diff --git a/arch/arm/src/am335x/am335x_can.c b/arch/arm/src/am335x/am335x_can.c index 6620fe8d6c94d..27a4611ef9c10 100644 --- a/arch/arm/src/am335x/am335x_can.c +++ b/arch/arm/src/am335x/am335x_can.c @@ -27,9 +27,11 @@ #include #include +#include #include #include +#include #include #include @@ -205,6 +207,8 @@ static struct can_dev_s g_can1dev = }; #endif +static spinlock_t g_can_lock = SP_UNLOCKED; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -1079,7 +1083,8 @@ struct can_dev_s *am335x_can_initialize(int port) syslog(LOG_DEBUG, "CAN%d\n", port); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_can_lock); + sched_lock(); #ifdef CONFIG_AM335X_CAN0 if (port == 0) @@ -1109,11 +1114,13 @@ struct can_dev_s *am335x_can_initialize(int port) { canerr("Unsupported port: %d\n", port); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_can_lock, flags); + sched_unlock(); return NULL; } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_can_lock, flags); + sched_unlock(); return candev; } @@ -1124,7 +1131,8 @@ void am335x_can_uninitialize(struct can_dev_s *dev) DEBUGASSERT(dev); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_can_lock); + sched_lock(); #ifdef CONFIG_AM335X_CAN0 if (dev == &g_can0dev) @@ -1151,7 +1159,8 @@ void am335x_can_uninitialize(struct can_dev_s *dev) canerr("Not a CAN device: %p\n", dev); } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_can_lock, flags); + sched_unlock(); } #endif diff --git a/arch/arm/src/am335x/am335x_gpio.c b/arch/arm/src/am335x/am335x_gpio.c index 3875df2c58930..f0e5f8cb06edf 100644 --- a/arch/arm/src/am335x/am335x_gpio.c +++ b/arch/arm/src/am335x/am335x_gpio.c @@ -31,6 +31,7 @@ #include #include +#include #include "chip.h" #include "arm_internal.h" @@ -219,6 +220,8 @@ static const uint8_t *g_gpio_padctl[AM335X_GPIO_NPORTS] = g_gpio3_padctl, /* GPIO3 */ }; +static spinlock_t g_gpio_lock = SP_UNLOCKED; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -364,7 +367,7 @@ int am335x_gpio_config(gpio_pinset_t pinset) /* Configure the pin as an input initially to avoid any spurious outputs */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); /* Configure based upon the pin mode */ @@ -407,7 +410,7 @@ int am335x_gpio_config(gpio_pinset_t pinset) break; } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); return ret; } @@ -425,9 +428,9 @@ void am335x_gpio_write(gpio_pinset_t pinset, bool value) int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); am335x_gpio_setoutput(port, pin, value); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); } /**************************************************************************** @@ -445,9 +448,9 @@ bool am335x_gpio_read(gpio_pinset_t pinset) int pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; bool value; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); value = am335x_gpio_getinput(port, pin); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); return value; } diff --git a/arch/arm/src/am335x/am335x_i2c.c b/arch/arm/src/am335x/am335x_i2c.c index ba4b03a09a3bb..320bfb80ca66d 100644 --- a/arch/arm/src/am335x/am335x_i2c.c +++ b/arch/arm/src/am335x/am335x_i2c.c @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -185,6 +186,7 @@ struct am335x_i2c_priv_s int refs; /* Reference count */ mutex_t lock; /* Mutual exclusion mutex */ + spinlock_t spinlock; /* Spinlock */ #ifndef CONFIG_I2C_POLLED sem_t sem_isr; /* Interrupt wait semaphore */ #endif @@ -317,6 +319,7 @@ static struct am335x_i2c_priv_s am335x_i2c0_priv = .config = &am335x_i2c0_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -352,6 +355,7 @@ static struct am335x_i2c_priv_s am335x_i2c1_priv = .config = &am335x_i2c1_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -387,6 +391,7 @@ static struct am335x_i2c_priv_s am335x_i2c2_priv = .config = &am335x_i2c2_config, .refs = 0, .lock = NXMUTEX_INITIALIZER, + .spinlock = SP_UNLOCKED, #ifndef CONFIG_I2C_POLLED .sem_isr = SEM_INITIALIZER(0), #endif @@ -492,7 +497,7 @@ static inline int am335x_i2c_sem_waitdone(struct am335x_i2c_priv_s *priv) uint32_t regval; int ret; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); /* Enable Interrupts when master mode */ @@ -529,6 +534,8 @@ static inline int am335x_i2c_sem_waitdone(struct am335x_i2c_priv_s *priv) */ priv->intstate = INTSTATE_WAITING; + spin_unlock_irqrestore(&priv->spinlock, flags); + do { /* Wait until either the transfer is complete or the timeout expires */ @@ -551,6 +558,8 @@ static inline int am335x_i2c_sem_waitdone(struct am335x_i2c_priv_s *priv) } } + flags = spin_lock_irqsave(&priv->spinlock); + /* Loop until the interrupt level transfer is complete. */ while (priv->intstate != INTSTATE_DONE); @@ -563,7 +572,7 @@ static inline int am335x_i2c_sem_waitdone(struct am335x_i2c_priv_s *priv) am335x_i2c_putreg(priv, AM335X_I2C_IRQ_EN_CLR_OFFSET, I2C_ICR_CLEARMASK); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return ret; } #else @@ -992,7 +1001,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv) */ #ifdef CONFIG_I2C_POLLED - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); #endif /* Transmit a byte */ @@ -1001,7 +1010,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv) priv->dcnt--; #ifdef CONFIG_I2C_POLLED - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); #endif if ((priv->dcnt == 0) && ((priv->flags & I2C_M_NOSTOP) == 0)) { @@ -1026,7 +1035,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv) */ #ifdef CONFIG_I2C_POLLED - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); #endif /* Receive a byte */ @@ -1036,7 +1045,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv) priv->dcnt--; #ifdef CONFIG_I2C_POLLED - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); #endif if ((priv->msgc <= 0) && (priv->dcnt == 0)) { @@ -1100,7 +1109,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv) */ #ifdef CONFIG_I2C_POLLED - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); #endif /* Transmit a byte */ @@ -1109,7 +1118,7 @@ static int am335x_i2c_isr_process(struct am335x_i2c_priv_s *priv) priv->dcnt--; #ifdef CONFIG_I2C_POLLED - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); #endif if ((priv->dcnt == 0) && ((priv->flags & I2C_M_NOSTOP) == 0)) { diff --git a/arch/arm/src/am335x/am335x_irq.c b/arch/arm/src/am335x/am335x_irq.c index 9e9b52f91b52b..5fce7640be75d 100644 --- a/arch/arm/src/am335x/am335x_irq.c +++ b/arch/arm/src/am335x/am335x_irq.c @@ -29,6 +29,7 @@ #include #include +#include #include "arm_internal.h" #include "sctlr.h" @@ -36,6 +37,13 @@ #include "am335x_gpio.h" #include "am335x_irq.h" +/**************************************************************************** + * Private Data + ****************************************************************************/ +#ifdef CONFIG_ARCH_IRQPRIO +static spinlock_t g_irq_lock = SP_UNLOCKED; +#endif + /**************************************************************************** * Public Data ****************************************************************************/ @@ -328,7 +336,7 @@ int up_prioritize_irq(int irq, int priority) { /* These operations must be atomic */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_irq_lock); #if 0 // TODO /* Set the new priority */ @@ -340,7 +348,7 @@ int up_prioritize_irq(int irq, int priority) putreg32(regval, regaddr); #endif - leave_critical_section(flags); + spin_unlock_irqrestore(&g_irq_lock, flags); return OK; } diff --git a/arch/arm/src/am335x/am335x_serial.c b/arch/arm/src/am335x/am335x_serial.c index 927faf685f71c..d85637bec0bf5 100644 --- a/arch/arm/src/am335x/am335x_serial.c +++ b/arch/arm/src/am335x/am335x_serial.c @@ -39,6 +39,7 @@ #endif #include +#include #include #include #include @@ -76,13 +77,14 @@ struct up_dev_s { - uint32_t uartbase; /* Base address of UART registers */ - uint32_t baud; /* Configured baud */ - uint32_t ier; /* Saved IER value */ - uint8_t irq; /* IRQ associated with this UART */ - uint8_t parity; /* 0=none, 1=odd, 2=even */ - uint8_t bits; /* Number of bits (7 or 8) */ - bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */ + uint32_t uartbase; /* Base address of UART registers */ + uint32_t baud; /* Configured baud */ + uint32_t ier; /* Saved IER value */ + uint8_t irq; /* IRQ associated with this UART */ + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (7 or 8) */ + bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */ + spinlock_t spinlock; /* Spinlock */ }; /**************************************************************************** @@ -169,6 +171,7 @@ static struct up_dev_s g_uart0priv = .parity = CONFIG_UART0_PARITY, .bits = CONFIG_UART0_BITS, .stopbits2 = CONFIG_UART0_2STOP, + .spinlock = SP_UNLOCKED, }; static uart_dev_t g_uart0port = @@ -200,6 +203,7 @@ static struct up_dev_s g_uart1priv = .parity = CONFIG_UART1_PARITY, .bits = CONFIG_UART1_BITS, .stopbits2 = CONFIG_UART1_2STOP, + .spinlock = SP_UNLOCKED, }; static uart_dev_t g_uart1port = @@ -230,6 +234,7 @@ static struct up_dev_s g_uart2priv = .parity = CONFIG_UART2_PARITY, .bits = CONFIG_UART2_BITS, .stopbits2 = CONFIG_UART2_2STOP, + .spinlock = SP_UNLOCKED, }; static uart_dev_t g_uart2port = @@ -260,6 +265,7 @@ static struct up_dev_s g_uart3priv = .parity = CONFIG_UART3_PARITY, .bits = CONFIG_UART3_BITS, .stopbits2 = CONFIG_UART3_2STOP, + .spinlock = SP_UNLOCKED, }; static uart_dev_t g_uart3port = @@ -290,6 +296,7 @@ static struct up_dev_s g_uart4priv = .parity = CONFIG_UART4_PARITY, .bits = CONFIG_UART4_BITS, .stopbits2 = CONFIG_UART4_2STOP, + .spinlock = SP_UNLOCKED, }; static uart_dev_t g_uart4port = @@ -320,6 +327,7 @@ static struct up_dev_s g_uart5priv = .parity = CONFIG_UART5_PARITY, .bits = CONFIG_UART5_BITS, .stopbits2 = CONFIG_UART5_2STOP, + .spinlock = SP_UNLOCKED, }; static uart_dev_t g_uart5port = @@ -484,6 +492,10 @@ static uart_dev_t g_uart5port = # define UART5_ASSIGNED 1 #endif +/* Spinlock */ + +static spinlock_t g_gpio_lock = SP_UNLOCKED; + /**************************************************************************** * Inline Functions ****************************************************************************/ @@ -567,7 +579,7 @@ static inline void am335x_uart0config(void) /* Step 1: Enable power to UART0 */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); #warning Missing logic /* Step 2: Enable clocking to UART0 */ @@ -577,7 +589,7 @@ static inline void am335x_uart0config(void) am335x_gpio_config(GPIO_UART0_TXD); am335x_gpio_config(GPIO_UART0_RXD); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); }; #endif @@ -588,7 +600,7 @@ static inline void am335x_uart1config(void) /* Step 1: Enable power to UART1 */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); #warning Missing logic /* Step 2: Enable clocking to UART1 */ @@ -598,7 +610,7 @@ static inline void am335x_uart1config(void) am335x_gpio_config(GPIO_UART1_TXD); am335x_gpio_config(GPIO_UART1_RXD); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); }; #endif @@ -609,7 +621,7 @@ static inline void am335x_uart2config(void) /* Step 1: Enable power to UART2 */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); #warning Missing logic /* Step 2: Enable clocking on UART2 */ @@ -619,7 +631,7 @@ static inline void am335x_uart2config(void) am335x_gpio_config(GPIO_UART2_TXD); am335x_gpio_config(GPIO_UART2_RXD); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); }; #endif @@ -630,7 +642,7 @@ static inline void am335x_uart3config(void) /* Step 1: Enable power to UART3 */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); #warning Missing logic /* Step 2: Enable clocking to UART3 */ @@ -640,7 +652,7 @@ static inline void am335x_uart3config(void) am335x_gpio_config(GPIO_UART3_TXD); am335x_gpio_config(GPIO_UART3_RXD); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); }; #endif @@ -651,7 +663,7 @@ static inline void am335x_uart4config(void) /* Step 1: Enable power to UART4 */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); #warning Missing logic /* Step 2: Enable clocking to UART4 */ @@ -661,7 +673,7 @@ static inline void am335x_uart4config(void) am335x_gpio_config(GPIO_UART4_TXD); am335x_gpio_config(GPIO_UART4_RXD); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); }; #endif @@ -672,7 +684,7 @@ static inline void am335x_uart5config(void) /* Step 1: Enable power to UART5 */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); #warning Missing logic /* Step 2: Enable clocking to UART5 */ @@ -682,7 +694,7 @@ static inline void am335x_uart5config(void) am335x_gpio_config(GPIO_UART5_TXD); am335x_gpio_config(GPIO_UART5_RXD); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); }; #endif @@ -1029,18 +1041,18 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg) case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ { - irqstate_t flags = enter_critical_section(); + irqstate_t flags = spin_lock_irqsave(&priv->spinlock); up_enablebreaks(priv, true); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } break; case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ { irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); up_enablebreaks(priv, false); - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); } break; @@ -1204,13 +1216,15 @@ static void up_txint(struct uart_dev_s *dev, bool enable) struct up_dev_s *priv = (struct up_dev_s *)dev->priv; irqstate_t flags; - flags = enter_critical_section(); + flags = spin_lock_irqsave(&priv->spinlock); if (enable) { #ifndef CONFIG_SUPPRESS_SERIAL_INTS priv->ier |= UART_IER_THR; up_serialout(priv, AM335X_UART_IER_OFFSET, priv->ier); + spin_unlock_irqrestore(&priv->spinlock, flags); + /* Fake a TX interrupt here by just calling uart_xmitchars() with * interrupts disabled (note this may recurse). */ @@ -1222,9 +1236,9 @@ static void up_txint(struct uart_dev_s *dev, bool enable) { priv->ier &= ~UART_IER_THR; up_serialout(priv, AM335X_UART_IER_OFFSET, priv->ier); - } - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); + } } /**************************************************************************** diff --git a/arch/arm/src/armv6-m/arm_ramvec_attach.c b/arch/arm/src/armv6-m/arm_ramvec_attach.c index 221f47dcbb2c9..7f72a547f1468 100644 --- a/arch/arm/src/armv6-m/arm_ramvec_attach.c +++ b/arch/arm/src/armv6-m/arm_ramvec_attach.c @@ -31,11 +31,18 @@ #include #include +#include #include "ram_vectors.h" #ifdef CONFIG_ARCH_RAMVECTORS +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static spinlock_t g_ramvec_lock = SP_UNLOCKED; + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -68,7 +75,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector) * common exception handler. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_ramvec_lock); if (vector == NULL) { /* Disable the interrupt if we can before detaching it. We might @@ -87,7 +94,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector) /* Save the new vector in the vector table */ g_ram_vectors[irq] = vector; - leave_critical_section(flags); + spin_unlock_irqrestore(&g_ramvec_lock, flags); ret = OK; } diff --git a/arch/arm/src/armv7-a/Toolchain.defs b/arch/arm/src/armv7-a/Toolchain.defs index 31fce70b92ca4..38ea1511ceb7e 100644 --- a/arch/arm/src/armv7-a/Toolchain.defs +++ b/arch/arm/src/armv7-a/Toolchain.defs @@ -35,7 +35,7 @@ else ifeq ($(CONFIG_ARCH_CORTEXA9),y) endif ifeq ($(CONFIG_ARM_THUMB),y) - LLVM_ARCHTYPE := thumbv7 + LLVM_ARCHTYPE := thumbv7a else LLVM_ARCHTYPE := armv7a endif diff --git a/arch/arm/src/armv7-a/arm_l2cc_pl310.c b/arch/arm/src/armv7-a/arm_l2cc_pl310.c index 41bb356f02d39..0b36f2175f815 100644 --- a/arch/arm/src/armv7-a/arm_l2cc_pl310.c +++ b/arch/arm/src/armv7-a/arm_l2cc_pl310.c @@ -38,6 +38,7 @@ #include #include +#include #include "arm_internal.h" #include "barriers.h" @@ -225,6 +226,12 @@ #define PL310_GULP_SIZE 4096 +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static spinlock_t g_l2cc_lock = SP_UNLOCKED; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -262,6 +269,66 @@ static void pl310_flush_all(void) putreg32(0, L2CC_CSR); } +/**************************************************************************** + * Name: l2cc_disable_nolock + * + * Description: + * Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void l2cc_disable_nolock(void) +{ + /* Flush all ways using the Clean Invalidate Way Register (CIWR). */ + + pl310_flush_all(); + + /* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */ + + putreg32(0, L2CC_CR); + ARM_DSB(); + ARM_ISB(); +} + +/**************************************************************************** + * Name: l2cc_invalidate_all_nolock + * + * Description: + * Invalidate all ways using the Invalidate Way Register (IWR). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void l2cc_invalidate_all_nolock(void) +{ + /* Invalidate all ways by writing the bit mask of ways to be invalidated + * the Invalidate Way Register (IWR). + */ + + putreg32(PL310_WAY_MASK, L2CC_IWR); + + /* Wait for cache operation by way to complete */ + + while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0); + + /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and + * EB, are empty. + */ + + putreg32(0, L2CC_CSR); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -457,18 +524,18 @@ void l2cc_enable(void) /* Invalidate and enable the cache (must be disabled to do this!) */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); if ((getreg32(L2CC_CR) & L2CC_CR_L2CEN) != 0) { - l2cc_disable(); + l2cc_disable_nolock(); } - l2cc_invalidate_all(); + l2cc_invalidate_all_nolock(); putreg32(L2CC_CR_L2CEN, L2CC_CR); ARM_DSB(); ARM_ISB(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -489,17 +556,11 @@ void l2cc_disable(void) { irqstate_t flags; - /* Flush all ways using the Clean Invalidate Way Register (CIWR). */ + flags = spin_lock_irqsave(&g_l2cc_lock); - flags = enter_critical_section(); - pl310_flush_all(); + l2cc_disable_nolock(); - /* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */ - - putreg32(0, L2CC_CR); - ARM_DSB(); - ARM_ISB(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -525,9 +586,9 @@ void l2cc_sync(void) * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -548,27 +609,11 @@ void l2cc_invalidate_all(void) { irqstate_t flags; - /* Invalidate all ways */ - - flags = enter_critical_section(); - - /* Invalidate all ways by writing the bit mask of ways to be invalidated - * the Invalidate Way Register (IWR). - */ - - putreg32(PL310_WAY_MASK, L2CC_IWR); - - /* Wait for cache operation by way to complete */ - - while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0); + flags = spin_lock_irqsave(&g_l2cc_lock); - /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and - * EB, are empty. - */ - - putreg32(0, L2CC_CSR); + l2cc_invalidate_all_nolock(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -595,7 +640,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) /* Check if the start address is aligned with a cacheline */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); if ((startaddr & PL310_CACHE_LINE_MASK) != 0) { /* No.. align down and flush the cache line by writing the address to @@ -622,7 +667,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) putreg32(endaddr, L2CC_CIPALR); } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); /* Loop, invalidated the address range by cache line. Interrupts are re- * enabled momentarily every PL310_GULP_SIZE bytes. @@ -640,7 +685,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) /* Disable interrupts and invalidate the gulp */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); while (startaddr < gulpend) { /* Invalidate the cache line by writing the address to the @@ -656,16 +701,16 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) /* Enable interrupts momentarily */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -690,7 +735,7 @@ void l2cc_clean_all(void) * Ways Register (CWR). */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(PL310_WAY_MASK, L2CC_CWR); /* Wait for cache operation by way to complete */ @@ -702,7 +747,7 @@ void l2cc_clean_all(void) */ putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -758,7 +803,7 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr) /* Disable interrupts and clean the gulp */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); while (startaddr < gulpend) { /* Clean the cache line by writing the address to the Clean @@ -774,16 +819,16 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr) /* Enable interrupts momentarily */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -806,9 +851,9 @@ void l2cc_flush_all(void) /* Flush all ways using the Clean Invalidate Way Register (CIWR). */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); pl310_flush_all(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -864,7 +909,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr) /* Disable interrupts and flush the gulp */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); while (startaddr < gulpend) { /* Flush the cache line by writing the address to the Clean @@ -880,16 +925,16 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr) /* Enable interrupts momentarily */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } #endif /* CONFIG_ARMV7A_L2CC_PL310 */ diff --git a/arch/arm/src/armv7-m/arm_ramvec_attach.c b/arch/arm/src/armv7-m/arm_ramvec_attach.c index 16899e06299e6..ad331046bce65 100644 --- a/arch/arm/src/armv7-m/arm_ramvec_attach.c +++ b/arch/arm/src/armv7-m/arm_ramvec_attach.c @@ -31,11 +31,18 @@ #include #include +#include #include "ram_vectors.h" #ifdef CONFIG_ARCH_RAMVECTORS +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static spinlock_t g_ramvec_lock = SP_UNLOCKED; + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -68,7 +75,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector) * common exception handler. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_ramvec_lock); if (vector == NULL) { /* Disable the interrupt if we can before detaching it. We might @@ -87,7 +94,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector) /* Save the new vector in the vector table */ g_ram_vectors[irq] = vector; - leave_critical_section(flags); + spin_unlock_irqrestore(&g_ramvec_lock, flags); ret = OK; } diff --git a/arch/arm/src/armv7-r/arm_l2cc_pl310.c b/arch/arm/src/armv7-r/arm_l2cc_pl310.c index 1930c0b9ca764..33164ce5267de 100644 --- a/arch/arm/src/armv7-r/arm_l2cc_pl310.c +++ b/arch/arm/src/armv7-r/arm_l2cc_pl310.c @@ -38,6 +38,7 @@ #include #include +#include #include "arm_internal.h" #include "barriers.h" @@ -225,6 +226,12 @@ #define PL310_GULP_SIZE 4096 +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static volatile spinlock_t g_l2cc_lock = SP_UNLOCKED; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -262,6 +269,66 @@ static void pl310_flush_all(void) putreg32(0, L2CC_CSR); } +/**************************************************************************** + * Name: l2cc_disable_nolock + * + * Description: + * Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void l2cc_disable_nolock(void) +{ + /* Flush all ways using the Clean Invalidate Way Register (CIWR). */ + + pl310_flush_all(); + + /* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */ + + putreg32(0, L2CC_CR); + ARM_DSB(); + ARM_ISB(); +} + +/**************************************************************************** + * Name: l2cc_invalidate_all_nolock + * + * Description: + * Invalidate all ways using the Invalidate Way Register (IWR). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void l2cc_invalidate_all_nolock(void) +{ + /* Invalidate all ways by writing the bit mask of ways to be invalidated + * the Invalidate Way Register (IWR). + */ + + putreg32(PL310_WAY_MASK, L2CC_IWR); + + /* Wait for cache operation by way to complete */ + + while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0); + + /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and + * EB, are empty. + */ + + putreg32(0, L2CC_CSR); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -457,18 +524,18 @@ void l2cc_enable(void) /* Invalidate and enable the cache (must be disabled to do this!) */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); if ((getreg32(L2CC_CR) & L2CC_CR_L2CEN) != 0) { - l2cc_disable(); + l2cc_disable_nolock(); } - l2cc_invalidate_all(); + l2cc_invalidate_all_nolock(); putreg32(L2CC_CR_L2CEN, L2CC_CR); ARM_DSB(); ARM_ISB(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -489,17 +556,11 @@ void l2cc_disable(void) { irqstate_t flags; - /* Flush all ways using the Clean Invalidate Way Register (CIWR). */ + flags = spin_lock_irqsave(&g_l2cc_lock); - flags = enter_critical_section(); - pl310_flush_all(); + l2cc_disable_nolock(); - /* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */ - - putreg32(0, L2CC_CR); - ARM_DSB(); - ARM_ISB(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -525,9 +586,9 @@ void l2cc_sync(void) * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -548,27 +609,11 @@ void l2cc_invalidate_all(void) { irqstate_t flags; - /* Invalidate all ways */ - - flags = enter_critical_section(); - - /* Invalidate all ways by writing the bit mask of ways to be invalidated - * the Invalidate Way Register (IWR). - */ - - putreg32(PL310_WAY_MASK, L2CC_IWR); - - /* Wait for cache operation by way to complete */ - - while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0); + flags = spin_lock_irqsave(&g_l2cc_lock); - /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and - * EB, are empty. - */ - - putreg32(0, L2CC_CSR); + l2cc_invalidate_all_nolock(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -595,7 +640,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) /* Check if the start address is aligned with a cacheline */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); if ((startaddr & PL310_CACHE_LINE_MASK) != 0) { /* No.. align down and flush the cache line by writing the address to @@ -622,7 +667,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) putreg32(endaddr, L2CC_CIPALR); } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); /* Loop, invalidated the address range by cache line. Interrupts are re- * enabled momentarily every PL310_GULP_SIZE bytes. @@ -640,7 +685,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) /* Disable interrupts and invalidate the gulp */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); while (startaddr < gulpend) { /* Invalidate the cache line by writing the address to the @@ -656,16 +701,16 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) /* Enable interrupts momentarily */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -690,7 +735,7 @@ void l2cc_clean_all(void) * Ways Register (CWR). */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(PL310_WAY_MASK, L2CC_CWR); /* Wait for cache operation by way to complete */ @@ -702,7 +747,7 @@ void l2cc_clean_all(void) */ putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -758,7 +803,7 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr) /* Disable interrupts and clean the gulp */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); while (startaddr < gulpend) { /* Clean the cache line by writing the address to the Clean @@ -774,16 +819,16 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr) /* Enable interrupts momentarily */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -806,9 +851,9 @@ void l2cc_flush_all(void) /* Flush all ways using the Clean Invalidate Way Register (CIWR). */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); pl310_flush_all(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -864,7 +909,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr) /* Disable interrupts and flush the gulp */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); while (startaddr < gulpend) { /* Flush the cache line by writing the address to the Clean @@ -880,16 +925,16 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr) /* Enable interrupts momentarily */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } #endif /* CONFIG_ARMV7R_L2CC_PL310 */ diff --git a/arch/arm/src/armv8-m/arm_ramvec_attach.c b/arch/arm/src/armv8-m/arm_ramvec_attach.c index d882431db268e..a08ea3af21031 100644 --- a/arch/arm/src/armv8-m/arm_ramvec_attach.c +++ b/arch/arm/src/armv8-m/arm_ramvec_attach.c @@ -31,11 +31,18 @@ #include #include +#include #include "ram_vectors.h" #ifdef CONFIG_ARCH_RAMVECTORS +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static spinlock_t g_ramvec_lock = SP_UNLOCKED; + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -68,7 +75,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector) * common exception handler. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_ramvec_lock); if (vector == NULL) { /* Disable the interrupt if we can before detaching it. We might @@ -87,7 +94,7 @@ int arm_ramvec_attach(int irq, up_vector_t vector) /* Save the new vector in the vector table */ g_ram_vectors[irq] = vector; - leave_critical_section(flags); + spin_unlock_irqrestore(&g_ramvec_lock, flags); ret = OK; } diff --git a/arch/arm/src/armv8-r/arm_l2cc_pl310.c b/arch/arm/src/armv8-r/arm_l2cc_pl310.c index b9f4ba7ee4ead..5ed37c94013c4 100644 --- a/arch/arm/src/armv8-r/arm_l2cc_pl310.c +++ b/arch/arm/src/armv8-r/arm_l2cc_pl310.c @@ -38,6 +38,7 @@ #include #include +#include #include "arm_internal.h" #include "barriers.h" @@ -225,6 +226,12 @@ #define PL310_GULP_SIZE 4096 +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static volatile spinlock_t g_l2cc_lock = SP_UNLOCKED; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -262,6 +269,66 @@ static void pl310_flush_all(void) putreg32(0, L2CC_CSR); } +/**************************************************************************** + * Name: l2cc_disable_nolock + * + * Description: + * Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void l2cc_disable_nolock(void) +{ + /* Flush all ways using the Clean Invalidate Way Register (CIWR). */ + + pl310_flush_all(); + + /* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */ + + putreg32(0, L2CC_CR); + ARM_DSB(); + ARM_ISB(); +} + +/**************************************************************************** + * Name: l2cc_invalidate_all_nolock + * + * Description: + * Invalidate all ways using the Invalidate Way Register (IWR). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +static void l2cc_invalidate_all_nolock(void) +{ + /* Invalidate all ways by writing the bit mask of ways to be invalidated + * the Invalidate Way Register (IWR). + */ + + putreg32(PL310_WAY_MASK, L2CC_IWR); + + /* Wait for cache operation by way to complete */ + + while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0); + + /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and + * EB, are empty. + */ + + putreg32(0, L2CC_CSR); +} + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -457,18 +524,18 @@ void l2cc_enable(void) /* Invalidate and enable the cache (must be disabled to do this!) */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); if ((getreg32(L2CC_CR) & L2CC_CR_L2CEN) != 0) { - l2cc_disable(); + l2cc_disable_nolock(); } - l2cc_invalidate_all(); + l2cc_invalidate_all_nolock(); putreg32(L2CC_CR_L2CEN, L2CC_CR); ARM_DSB(); ARM_ISB(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -489,17 +556,11 @@ void l2cc_disable(void) { irqstate_t flags; - /* Flush all ways using the Clean Invalidate Way Register (CIWR). */ + flags = spin_lock_irqsave(&g_l2cc_lock); - flags = enter_critical_section(); - pl310_flush_all(); + l2cc_disable_nolock(); - /* Disable the L2CC-P310 L2 cache by clearing the Control Register (CR) */ - - putreg32(0, L2CC_CR); - ARM_DSB(); - ARM_ISB(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -525,9 +586,9 @@ void l2cc_sync(void) * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -548,27 +609,11 @@ void l2cc_invalidate_all(void) { irqstate_t flags; - /* Invalidate all ways */ - - flags = enter_critical_section(); - - /* Invalidate all ways by writing the bit mask of ways to be invalidated - * the Invalidate Way Register (IWR). - */ - - putreg32(PL310_WAY_MASK, L2CC_IWR); - - /* Wait for cache operation by way to complete */ - - while ((getreg32(L2CC_IWR) & PL310_WAY_MASK) != 0); + flags = spin_lock_irqsave(&g_l2cc_lock); - /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and - * EB, are empty. - */ - - putreg32(0, L2CC_CSR); + l2cc_invalidate_all_nolock(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -595,7 +640,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) /* Check if the start address is aligned with a cacheline */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); if ((startaddr & PL310_CACHE_LINE_MASK) != 0) { /* No.. align down and flush the cache line by writing the address to @@ -622,7 +667,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) putreg32(endaddr, L2CC_CIPALR); } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); /* Loop, invalidated the address range by cache line. Interrupts are re- * enabled momentarily every PL310_GULP_SIZE bytes. @@ -640,7 +685,7 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) /* Disable interrupts and invalidate the gulp */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); while (startaddr < gulpend) { /* Invalidate the cache line by writing the address to the @@ -656,16 +701,16 @@ void l2cc_invalidate(uintptr_t startaddr, uintptr_t endaddr) /* Enable interrupts momentarily */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -690,7 +735,7 @@ void l2cc_clean_all(void) * Ways Register (CWR). */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(PL310_WAY_MASK, L2CC_CWR); /* Wait for cache operation by way to complete */ @@ -702,7 +747,7 @@ void l2cc_clean_all(void) */ putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -758,7 +803,7 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr) /* Disable interrupts and clean the gulp */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); while (startaddr < gulpend) { /* Clean the cache line by writing the address to the Clean @@ -774,16 +819,16 @@ void l2cc_clean(uintptr_t startaddr, uintptr_t endaddr) /* Enable interrupts momentarily */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -806,9 +851,9 @@ void l2cc_flush_all(void) /* Flush all ways using the Clean Invalidate Way Register (CIWR). */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); pl310_flush_all(); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /**************************************************************************** @@ -864,7 +909,7 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr) /* Disable interrupts and flush the gulp */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); while (startaddr < gulpend) { /* Flush the cache line by writing the address to the Clean @@ -880,16 +925,16 @@ void l2cc_flush(uint32_t startaddr, uint32_t endaddr) /* Enable interrupts momentarily */ - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } /* Drain the STB. Operation complete when all buffers, LRB, LFB, STB, and * EB, are empty. */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_l2cc_lock); putreg32(0, L2CC_CSR); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_l2cc_lock, flags); } #endif /* CONFIG_ARMV8R_L2CC_PL310 */ diff --git a/arch/arm/src/cmake/armv6-m.cmake b/arch/arm/src/cmake/armv6-m.cmake index 32596ab689128..5d52da216da4f 100644 --- a/arch/arm/src/cmake/armv6-m.cmake +++ b/arch/arm/src/cmake/armv6-m.cmake @@ -21,3 +21,8 @@ # ############################################################################## add_compile_options(-mcpu=cortex-m0 -mthumb -mfloat-abi=soft) + +# LLVM Configuration +set(LLVM_ARCHTYPE thumbv6m) +set(LLVM_ABITYPE eabi) +set(LLVM_CPUTYPE cortex-m0) diff --git a/arch/arm/src/cmake/armv7-a.cmake b/arch/arm/src/cmake/armv7-a.cmake index 88ac27dfcd7d8..ddd02c324bf5f 100644 --- a/arch/arm/src/cmake/armv7-a.cmake +++ b/arch/arm/src/cmake/armv7-a.cmake @@ -24,24 +24,43 @@ set(PLATFORM_FLAGS) if(CONFIG_ARCH_CORTEXA5) list(APPEND PLATFORM_FLAGS -mcpu=cortex-a5) + set(LLVM_CPUTYPE cortex-a5) elseif(CONFIG_ARCH_CORTEXA7) list(APPEND PLATFORM_FLAGS -mcpu=cortex-a7) + set(LLVM_CPUTYPE cortex-a7) elseif(CONFIG_ARCH_CORTEXA8) list(APPEND PLATFORM_FLAGS -mcpu=cortex-a8) + set(LLVM_CPUTYPE cortex-a8) elseif(CONFIG_ARCH_CORTEXA9) list(APPEND PLATFORM_FLAGS -mcpu=cortex-a9) + set(LLVM_CPUTYPE cortex-a9) +endif() + +if(CONFIG_ARM_THUMB) + set(LLVM_ARCHTYPE thumbv7a) +else() + set(LLVM_ARCHTYPE armv7-a) +endif() + +if(CONFIG_ARCH_FPU) + set(LLVM_ABITYPE eabihf) +else() + set(LLVM_ABITYPE eabi) endif() if(NOT CONFIG_ARM_DPFPU32) set(ARCHFPUD16 -d16) endif() -# Cortex-A5 | -mfpu=vfpv4-fp16 | -mfpu=vfpv4-d16-fp16 | -mfpu=neon-fp16 -# Cortex-A7 | -mfpu=vfpv4 | -mfpu=vfpv4-d16 | -mfpu=neon-vfpv4 -# Cortex-A8 | -mfpu=vfpv3 | | -mfpu=neon (alias for -# neon-vfpv3) Cortex-A9 | -mfpu=vfpv3-fp16 | -mfpu=vfpv3-d16-fp16 | -# -mfpu=neon-fp16 Cortex-A15 | -mfpu=vfpv4 | | -# -mfpu=neon-vfpv4 +# ~~~ +# | Cortex | FPU Option 1 | FPU Option 2 | FPU Option 3 | +# |--------|--------------------|------------------------|-----------------------| +# | A5 | -mfpu=vfpv4-fp16 | -mfpu=vfpv4-d16-fp16 | -mfpu=neon-fp16 | +# | A7 | -mfpu=vfpv4 | -mfpu=vfpv4-d16 | -mfpu=neon-vfpv4 | +# | A8 | -mfpu=vfpv3 | | -mfpu=neon (alias for neon-vfpv3) | +# | A9 | -mfpu=vfpv3-fp16 | -mfpu=vfpv3-d16-fp16 | -mfpu=neon-fp16 | +# | A15 | -mfpu=vfpv4 | | -mfpu=neon-vfpv4 | +# ~~~ if(CONFIG_ARCH_FPU) if(CONFIG_ARM_FPU_ABI_SOFT) diff --git a/arch/arm/src/cmake/armv7-m.cmake b/arch/arm/src/cmake/armv7-m.cmake index 73ef08d18ca8f..1f6d121e78a1a 100644 --- a/arch/arm/src/cmake/armv7-m.cmake +++ b/arch/arm/src/cmake/armv7-m.cmake @@ -38,4 +38,23 @@ else() # gcc set(TOOLCHAIN_ARCH_FILE armv7-m_gcc) endif() +# LLVM Configuration +if(CONFIG_ARCH_CORTEXM3) + set(LLVM_ARCHTYPE thumbv7m) + set(LLVM_CPUTYPE cortex-m3) +else() + set(LLVM_ARCHTYPE thumbv7em) + if(CONFIG_ARCH_CORTEXM4) + set(LLVM_CPUTYPE cortex-m4) + elseif(CONFIG_ARCH_CORTEXM7) + set(LLVM_CPUTYPE cortex-m7) + endif() +endif() + +if(CONFIG_ARCH_FPU) + set(LLVM_ABITYPE eabihf) +else() + set(LLVM_ABITYPE eabi) +endif() + include(${TOOLCHAIN_ARCH_FILE}) diff --git a/arch/arm/src/cmake/armv8-m.cmake b/arch/arm/src/cmake/armv8-m.cmake index fef71a4984b92..71a8747e566df 100644 --- a/arch/arm/src/cmake/armv8-m.cmake +++ b/arch/arm/src/cmake/armv8-m.cmake @@ -22,6 +22,31 @@ set(PLATFORM_FLAGS) +# LLVM Configuration +if(CONFIG_ARCH_CORTEXM23) + set(LLVM_ARCHTYPE thumbv8m.base) + set(LLVM_CPUTYPE cortex-m23) +elseif(CONFIG_ARCH_CORTEXM33) + set(LLVM_ARCHTYPE thumbv8m.main) + set(LLVM_CPUTYPE cortex-m33) +elseif(CONFIG_ARCH_CORTEXM35P) + set(LLVM_ARCHTYPE thumbv8m.main) + set(LLVM_CPUTYPE cortex-m35p) +elseif(CONFIG_ARCH_CORTEXM55) + set(LLVM_ARCHTYPE thumbv8.1m.main) + set(LLVM_CPUTYPE cortex-m55) +elseif(CONFIG_ARCH_CORTEXM85) + set(LLVM_ARCHTYPE thumbv8.1m.main) + set(LLVM_CPUTYPE cortex-m85) +endif() + +# Set ABI type based on FPU configuration +if(CONFIG_ARCH_FPU) + set(LLVM_ABITYPE eabihf) +else() + set(LLVM_ABITYPE eabi) +endif() + if(CONFIG_ARM_DSP) set(EXTCPUFLAGS +dsp) endif() diff --git a/arch/arm/src/stm32h5/Kconfig b/arch/arm/src/stm32h5/Kconfig index 3a1e04d36ab02..4fd8583a4cf3f 100644 --- a/arch/arm/src/stm32h5/Kconfig +++ b/arch/arm/src/stm32h5/Kconfig @@ -299,6 +299,10 @@ config STM32H5_SPI_DMA bool default n +config STM32H5_TIM + bool + default n + # These are the peripheral selections proper config STM32H5_ADC1 @@ -477,8 +481,81 @@ config STM32H5_SPI6 select SPI select STM32H5_SPI -endmenu +menu "STM32H5 Timer Selection" + +config STM32H5_TIM1 + bool "TIM1" + default n + select STM32H5_TIM + +config STM32H5_TIM2 + bool "TIM2" + default n + select STM32H5_TIM + +config STM32H5_TIM3 + bool "TIM3" + default n + select STM32H5_TIM + +config STM32H5_TIM4 + bool "TIM4" + default n + select STM32H5_TIM + +config STM32H5_TIM5 + bool "TIM5" + default n + select STM32H5_TIM + +config STM32H5_TIM6 + bool "TIM6" + default n + select STM32H5_TIM + +config STM32H5_TIM7 + bool "TIM7" + default n + select STM32H5_TIM + +config STM32H5_TIM8 + bool "TIM8" + default n + select STM32H5_TIM + +config STM32H5_TIM12 + bool "TIM12" + default n + select STM32H5_TIM + +config STM32H5_TIM13 + bool "TIM13" + default n + select STM32H5_TIM + +config STM32H5_TIM14 + bool "TIM14" + default n + select STM32H5_TIM + +config STM32H5_TIM15 + bool "TIM15" + default n + select STM32H5_TIM + +config STM32H5_TIM16 + bool "TIM16" + default n + select STM32H5_TIM + +config STM32H5_TIM17 + bool "TIM17" + default n + select STM32H5_TIM +endmenu # STM32H5 Timer Selection + +endmenu config STM32H5_FLASH_PREFETCH bool "Enable FLASH Pre-fetch" @@ -661,6 +738,3038 @@ config STM32H5_SPI6_COMMTYPE endmenu # "SPI Configuration" +menu "Timer Configuration" + +if SCHED_TICKLESS + +config STM32H5_TICKLESS_TIMER + int "Tickless hardware timer" + default 2 + range 1 17 + ---help--- + If the Tickless OS feature is enabled, then one clock must be + assigned to provided the timer needed by the OS. + +config STM32H5_TICKLESS_CHANNEL + int "Tickless timer channel" + default 1 + range 1 4 + ---help--- + If the Tickless OS feature is enabled, the one clock must be + assigned to provided the free-running timer needed by the OS + and one channel on that clock is needed to handle intervals. + +endif # SCHED_TICKLESS + +config STM32H5_ONESHOT + bool "TIM one-shot wrapper" + default n + ---help--- + Enable a wrapper around the low level timer/counter functions to + support one-shot timer. + +config STM32H5_ONESHOT_MAXTIMERS + int "Maximum number of oneshot timers" + default 1 + range 1 8 + depends on STM32H5_ONESHOT + ---help--- + Determines the maximum number of oneshot timers that can be + supported. This setting pre-allocates some minimal support for each + of the timers and places an upper limit on the number of oneshot + timers that you can use. + +config STM32H5_PWM_LL_OPS + bool "PWM low-level operations" + default n + ---help--- + Enable low-level PWM ops. + +config STM32H5_TIM1_PWM + bool "TIM1 PWM" + default n + depends on STM32H5_TIM1 + select STM32H5_PWM + ---help--- + Reserve 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 STM32H5_TIM1 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM1_PWM + +config STM32H5_TIM1_MODE + int "TIM1 Mode" + default 0 + range 0 4 + ---help--- + Specifies the timer mode. + +config STM32H5_TIM1_LOCK + int "TIM1 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 1 lock level configuration + +config STM32H5_TIM1_TDTS + int "TIM1 t_DTS Division" + default 0 + range 0 2 + ---help--- + Timer 1 dead-time and sampling clock (t_DTS) division + +config STM32H5_TIM1_DEADTIME + int "TIM1 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 1 initial dead-time + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM1_CHANNEL1 + bool "TIM1 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM1_CHANNEL1 + +config STM32H5_TIM1_CH1MODE + int "TIM1 Channel 1 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM1_CH1OUT + bool "TIM1 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32H5_TIM1_CH1NOUT + bool "TIM1 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32H5_TIM1_CHANNEL1 + +config STM32H5_TIM1_CHANNEL2 + bool "TIM1 Channel 2" + default n + ---help--- + Enables channel 2. + +if STM32H5_TIM1_CHANNEL2 + +config STM32H5_TIM1_CH2MODE + int "TIM1 Channel 2 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM1_CH2OUT + bool "TIM1 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config STM32H5_TIM1_CH2NOUT + bool "TIM1 Channel 2 Complementary Output" + default n + ---help--- + Enables channel 2 Complementary Output. + +endif # STM32H5_TIM1_CHANNEL2 + +config STM32H5_TIM1_CHANNEL3 + bool "TIM1 Channel 3" + default n + ---help--- + Enables channel 3. + +if STM32H5_TIM1_CHANNEL3 + +config STM32H5_TIM1_CH3MODE + int "TIM1 Channel 3 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM1_CH3OUT + bool "TIM1 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +config STM32H5_TIM1_CH3NOUT + bool "TIM1 Channel 3 Complementary Output" + default n + ---help--- + Enables channel 3 Complementary Output. + +endif # STM32H5_TIM1_CHANNEL3 + +config STM32H5_TIM1_CHANNEL4 + bool "TIM1 Channel 4" + default n + ---help--- + Enables channel 4. + +if STM32H5_TIM1_CHANNEL4 + +config STM32H5_TIM1_CH4MODE + int "TIM1 Channel 4 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM1_CH4OUT + bool "TIM1 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM1_CHANNEL4 + +config STM32H5_TIM1_CHANNEL5 + bool "TIM1 Channel 5 (internal)" + default n + ---help--- + Enables channel 5 (not available externally) + +if STM32H5_TIM1_CHANNEL5 + +config STM32H5_TIM1_CH5MODE + int "TIM1 Channel 5 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM1_CH5OUT + bool "TIM1 Channel 5 Output" + default n + ---help--- + Enables channel 5 output. + +endif # STM32H5_TIM1_CHANNEL5 + +config STM32H5_TIM1_CHANNEL6 + bool "TIM1 Channel 6 (internal)" + default n + ---help--- + Enables channel 6 (not available externally) + +if STM32H5_TIM1_CHANNEL6 + +config STM32H5_TIM1_CH6MODE + int "TIM1 Channel 6 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM1_CH6OUT + bool "TIM1 Channel 6 Output" + default n + ---help--- + Enables channel 6 output. + +endif # STM32H5_TIM1_CHANNEL6 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM1_CHANNEL + int "TIM1 PWM Output Channel" + default 1 + range 1 4 + ---help--- + If TIM1 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +if STM32H5_TIM1_CHANNEL = 1 + +config STM32H5_TIM1_CH1OUT + bool "TIM1 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32H5_TIM1_CH1NOUT + bool "TIM1 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32H5_TIM1_CHANNEL = 1 + +if STM32H5_TIM1_CHANNEL = 2 + +config STM32H5_TIM1_CH2OUT + bool "TIM1 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config STM32H5_TIM1_CH2NOUT + bool "TIM1 Channel 2 Complementary Output" + default n + ---help--- + Enables channel 2 Complementary Output. + +endif # STM32H5_TIM1_CHANNEL = 2 + +if STM32H5_TIM1_CHANNEL = 3 + +config STM32H5_TIM1_CH3OUT + bool "TIM1 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +config STM32H5_TIM1_CH3NOUT + bool "TIM1 Channel 3 Complementary Output" + default n + ---help--- + Enables channel 3 Complementary Output. + +endif # STM32H5_TIM1_CHANNEL = 3 + +if STM32H5_TIM1_CHANNEL = 4 + +config STM32H5_TIM1_CH4OUT + bool "TIM1 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM1_CHANNEL = 4 + +config STM32H5_TIM1_CHMODE + int "TIM1 Channel Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM1_PWM + +config STM32H5_TIM2_PWM + bool "TIM2 PWM" + default n + depends on STM32H5_TIM2 + select STM32H5_PWM + ---help--- + Reserve 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 STM32H5_TIM2 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM2_PWM + +config STM32H5_TIM2_MODE + int "TIM2 Mode" + default 0 + range 0 4 + ---help--- + Specifies the timer mode. + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM2_CHANNEL1 + bool "TIM2 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM2_CHANNEL1 + +config STM32H5_TIM2_CH1MODE + int "TIM2 Channel 1 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM2_CH1OUT + bool "TIM2 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM2_CHANNEL1 + +config STM32H5_TIM2_CHANNEL2 + bool "TIM2 Channel 2" + default n + ---help--- + Enables channel 2. + +if STM32H5_TIM2_CHANNEL2 + +config STM32H5_TIM2_CH2MODE + int "TIM2 Channel 2 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM2_CH2OUT + bool "TIM2 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM2_CHANNEL2 + +config STM32H5_TIM2_CHANNEL3 + bool "TIM2 Channel 3" + default n + ---help--- + Enables channel 3. + +if STM32H5_TIM2_CHANNEL3 + +config STM32H5_TIM2_CH3MODE + int "TIM2 Channel 3 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM2_CH3OUT + bool "TIM2 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32H5_TIM2_CHANNEL3 + +config STM32H5_TIM2_CHANNEL4 + bool "TIM2 Channel 4" + default n + ---help--- + Enables channel 4. + +if STM32H5_TIM2_CHANNEL4 + +config STM32H5_TIM2_CH4MODE + int "TIM2 Channel 4 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM2_CH4OUT + bool "TIM2 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM2_CHANNEL4 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM2_CHANNEL + int "TIM2 PWM Output Channel" + default 1 + range 1 4 + ---help--- + If TIM2 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +if STM32H5_TIM2_CHANNEL = 1 + +config STM32H5_TIM2_CH1OUT + bool "TIM2 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM2_CHANNEL = 1 + +if STM32H5_TIM2_CHANNEL = 2 + +config STM32H5_TIM2_CH2OUT + bool "TIM2 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM2_CHANNEL = 2 + +if STM32H5_TIM2_CHANNEL = 3 + +config STM32H5_TIM2_CH3OUT + bool "TIM2 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32H5_TIM2_CHANNEL = 3 + +if STM32H5_TIM2_CHANNEL = 4 + +config STM32H5_TIM2_CH4OUT + bool "TIM2 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM2_CHANNEL = 4 + +config STM32H5_TIM2_CHMODE + int "TIM2 Channel Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM2_PWM + +config STM32H5_TIM3_PWM + bool "TIM3 PWM" + default n + depends on STM32H5_TIM3 + select STM32H5_PWM + ---help--- + Reserve timer 3 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 STM32H5_TIM3 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM3_PWM + +config STM32H5_TIM3_MODE + int "TIM3 Mode" + default 0 + range 0 4 + ---help--- + Specifies the timer mode. + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM3_CHANNEL1 + bool "TIM3 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM3_CHANNEL1 + +config STM32H5_TIM3_CH1MODE + int "TIM3 Channel 1 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM3_CH1OUT + bool "TIM3 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM3_CHANNEL1 + +config STM32H5_TIM3_CHANNEL2 + bool "TIM3 Channel 2" + default n + ---help--- + Enables channel 2. + +if STM32H5_TIM3_CHANNEL2 + +config STM32H5_TIM3_CH2MODE + int "TIM3 Channel 2 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM3_CH2OUT + bool "TIM3 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM3_CHANNEL2 + +config STM32H5_TIM3_CHANNEL3 + bool "TIM3 Channel 3" + default n + ---help--- + Enables channel 3. + +if STM32H5_TIM3_CHANNEL3 + +config STM32H5_TIM3_CH3MODE + int "TIM3 Channel 3 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM3_CH3OUT + bool "TIM3 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32H5_TIM3_CHANNEL3 + +config STM32H5_TIM3_CHANNEL4 + bool "TIM3 Channel 4" + default n + ---help--- + Enables channel 4. + +if STM32H5_TIM3_CHANNEL4 + +config STM32H5_TIM3_CH4MODE + int "TIM3 Channel 4 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM3_CH4OUT + bool "TIM3 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM3_CHANNEL4 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM3_CHANNEL + int "TIM3 PWM Output Channel" + default 1 + range 1 4 + ---help--- + If TIM3 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +if STM32H5_TIM3_CHANNEL = 1 + +config STM32H5_TIM3_CH1OUT + bool "TIM3 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM3_CHANNEL = 1 + +if STM32H5_TIM3_CHANNEL = 2 + +config STM32H5_TIM3_CH2OUT + bool "TIM3 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM3_CHANNEL = 2 + +if STM32H5_TIM3_CHANNEL = 3 + +config STM32H5_TIM3_CH3OUT + bool "TIM3 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32H5_TIM3_CHANNEL = 3 + +if STM32H5_TIM3_CHANNEL = 4 + +config STM32H5_TIM3_CH4OUT + bool "TIM3 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM3_CHANNEL = 4 + +config STM32H5_TIM3_CHMODE + int "TIM3 Channel Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM3_PWM + +config STM32H5_TIM4_PWM + bool "TIM4 PWM" + default n + depends on STM32H5_TIM4 + select STM32H5_PWM + ---help--- + Reserve timer 4 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 STM32H5_TIM4 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM4_PWM + +config STM32H5_TIM4_MODE + int "TIM4 Mode" + default 0 + range 0 4 + ---help--- + Specifies the timer mode. + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM4_CHANNEL1 + bool "TIM4 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM4_CHANNEL1 + +config STM32H5_TIM4_CH1MODE + int "TIM4 Channel 1 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM4_CH1OUT + bool "TIM4 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM4_CHANNEL1 + +config STM32H5_TIM4_CHANNEL2 + bool "TIM4 Channel 2" + default n + ---help--- + Enables channel 2. + +if STM32H5_TIM4_CHANNEL2 + +config STM32H5_TIM4_CH2MODE + int "TIM4 Channel 2 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM4_CH2OUT + bool "TIM4 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM4_CHANNEL2 + +config STM32H5_TIM4_CHANNEL3 + bool "TIM4 Channel 3" + default n + ---help--- + Enables channel 3. + +if STM32H5_TIM4_CHANNEL3 + +config STM32H5_TIM4_CH3MODE + int "TIM4 Channel 3 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM4_CH3OUT + bool "TIM4 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32H5_TIM4_CHANNEL3 + +config STM32H5_TIM4_CHANNEL4 + bool "TIM4 Channel 4" + default n + ---help--- + Enables channel 4. + +if STM32H5_TIM4_CHANNEL4 + +config STM32H5_TIM4_CH4MODE + int "TIM4 Channel 4 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM4_CH4OUT + bool "TIM4 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM4_CHANNEL4 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM4_CHANNEL + int "TIM4 PWM Output Channel" + default 1 + range 1 4 + ---help--- + If TIM4 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +if STM32H5_TIM4_CHANNEL = 1 + +config STM32H5_TIM4_CH1OUT + bool "TIM4 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM4_CHANNEL = 1 + +if STM32H5_TIM4_CHANNEL = 2 + +config STM32H5_TIM4_CH2OUT + bool "TIM4 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM4_CHANNEL = 2 + +if STM32H5_TIM4_CHANNEL = 3 + +config STM32H5_TIM4_CH3OUT + bool "TIM4 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32H5_TIM4_CHANNEL = 3 + +if STM32H5_TIM4_CHANNEL = 4 + +config STM32H5_TIM4_CH4OUT + bool "TIM4 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM4_CHANNEL = 4 + +config STM32H5_TIM4_CHMODE + int "TIM4 Channel Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM4_PWM + +config STM32H5_TIM5_PWM + bool "TIM5 PWM" + default n + depends on STM32H5_TIM5 + select STM32H5_PWM + ---help--- + Reserve timer 5 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 STM32H5_TIM5 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM5_PWM + +config STM32H5_TIM5_MODE + int "TIM5 Mode" + default 0 + range 0 4 + ---help--- + Specifies the timer mode. + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM5_CHANNEL1 + bool "TIM5 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM5_CHANNEL1 + +config STM32H5_TIM5_CH1MODE + int "TIM5 Channel 1 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM5_CH1OUT + bool "TIM5 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM5_CHANNEL1 + +config STM32H5_TIM5_CHANNEL2 + bool "TIM5 Channel 2" + default n + ---help--- + Enables channel 2. + +if STM32H5_TIM5_CHANNEL2 + +config STM32H5_TIM5_CH2MODE + int "TIM5 Channel 2 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM5_CH2OUT + bool "TIM5 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM5_CHANNEL2 + +config STM32H5_TIM5_CHANNEL3 + bool "TIM5 Channel 3" + default n + ---help--- + Enables channel 3. + +if STM32H5_TIM5_CHANNEL3 + +config STM32H5_TIM5_CH3MODE + int "TIM5 Channel 3 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM5_CH3OUT + bool "TIM5 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32H5_TIM5_CHANNEL3 + +config STM32H5_TIM5_CHANNEL4 + bool "TIM5 Channel 4" + default n + ---help--- + Enables channel 4. + +if STM32H5_TIM5_CHANNEL4 + +config STM32H5_TIM5_CH4MODE + int "TIM5 Channel 4 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM5_CH4OUT + bool "TIM5 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM5_CHANNEL4 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM5_CHANNEL + int "TIM5 PWM Output Channel" + default 1 + range 1 4 + ---help--- + If TIM5 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +if STM32H5_TIM5_CHANNEL = 1 + +config STM32H5_TIM5_CH1OUT + bool "TIM5 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM5_CHANNEL = 1 + +if STM32H5_TIM5_CHANNEL = 2 + +config STM32H5_TIM5_CH2OUT + bool "TIM5 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM5_CHANNEL = 2 + +if STM32H5_TIM5_CHANNEL = 3 + +config STM32H5_TIM5_CH3OUT + bool "TIM5 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +endif # STM32H5_TIM5_CHANNEL = 3 + +if STM32H5_TIM5_CHANNEL = 4 + +config STM32H5_TIM5_CH4OUT + bool "TIM5 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM5_CHANNEL = 4 + +config STM32H5_TIM5_CHMODE + int "TIM5 Channel Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM5_PWM + +config STM32H5_TIM8_PWM + bool "TIM8 PWM" + default n + depends on STM32H5_TIM8 + select STM32H5_PWM + ---help--- + Reserve timer 8 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 STM32H5_TIM8 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM8_PWM + +config STM32H5_TIM8_MODE + int "TIM8 Mode" + default 0 + range 0 4 + ---help--- + Specifies the timer mode. + +config STM32H5_TIM8_LOCK + int "TIM8 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 8 lock level configuration + +config STM32H5_TIM8_DEADTIME + int "TIM8 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 8 initial dead-time + +config STM32H5_TIM8_TDTS + int "TIM8 t_DTS Division" + default 0 + range 0 2 + ---help--- + Timer 8 dead-time and sampling clock (t_DTS) division + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM8_CHANNEL1 + bool "TIM8 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM8_CHANNEL1 + +config STM32H5_TIM8_CH1MODE + int "TIM8 Channel 1 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM8_CH1OUT + bool "TIM8 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32H5_TIM8_CH1NOUT + bool "TIM8 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32H5_TIM8_CHANNEL1 + +config STM32H5_TIM8_CHANNEL2 + bool "TIM8 Channel 2" + default n + ---help--- + Enables channel 2. + +if STM32H5_TIM8_CHANNEL2 + +config STM32H5_TIM8_CH2MODE + int "TIM8 Channel 2 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM8_CH2OUT + bool "TIM8 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config STM32H5_TIM8_CH2NOUT + bool "TIM8 Channel 2 Complementary Output" + default n + ---help--- + Enables channel 2 Complementary Output. + +endif # STM32H5_TIM8_CHANNEL2 + +config STM32H5_TIM8_CHANNEL3 + bool "TIM8 Channel 3" + default n + ---help--- + Enables channel 3. + +if STM32H5_TIM8_CHANNEL3 + +config STM32H5_TIM8_CH3MODE + int "TIM8 Channel 3 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM8_CH3OUT + bool "TIM8 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +config STM32H5_TIM8_CH3NOUT + bool "TIM8 Channel 3 Complementary Output" + default n + ---help--- + Enables channel 3 Complementary Output. + +endif # STM32H5_TIM8_CHANNEL3 + +config STM32H5_TIM8_CHANNEL4 + bool "TIM8 Channel 4" + default n + ---help--- + Enables channel 4. + +if STM32H5_TIM8_CHANNEL4 + +config STM32H5_TIM8_CH4MODE + int "TIM8 Channel 4 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM8_CH4OUT + bool "TIM8 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM8_CHANNEL4 + +config STM32H5_TIM8_CHANNEL5 + bool "TIM8 Channel 5 (internal)" + default n + ---help--- + Enables channel 5 (not available externally) + +if STM32H5_TIM8_CHANNEL5 + +config STM32H5_TIM8_CH5MODE + int "TIM8 Channel 5 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM8_CH5OUT + bool "TIM8 Channel 5 Output" + default n + ---help--- + Enables channel 5 output. + +endif # STM32H5_TIM8_CHANNEL5 + +config STM32H5_TIM8_CHANNEL6 + bool "TIM8 Channel 6 (internal)" + default n + ---help--- + Enables channel 6 (not available externally) + +if STM32H5_TIM8_CHANNEL6 + +config STM32H5_TIM8_CH6MODE + int "TIM8 Channel 6 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM8_CH6OUT + bool "TIM8 Channel 6 Output" + default n + ---help--- + Enables channel 6 output. + +endif # STM32H5_TIM8_CHANNEL6 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM8_CHANNEL + int "TIM8 PWM Output Channel" + default 1 + range 1 4 + ---help--- + If TIM8 is enabled for PWM usage, you also need specifies the timer output + channel {1,..,4} + +if STM32H5_TIM8_CHANNEL = 1 + +config STM32H5_TIM8_CH1OUT + bool "TIM8 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32H5_TIM8_CH1NOUT + bool "TIM8 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32H5_TIM8_CHANNEL = 1 + +if STM32H5_TIM8_CHANNEL = 2 + +config STM32H5_TIM8_CH2OUT + bool "TIM8 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config STM32H5_TIM8_CH2NOUT + bool "TIM8 Channel 2 Complementary Output" + default n + ---help--- + Enables channel 2 Complementary Output. + +endif # STM32H5_TIM8_CHANNEL = 2 + +if STM32H5_TIM8_CHANNEL = 3 + +config STM32H5_TIM8_CH3OUT + bool "TIM8 Channel 3 Output" + default n + ---help--- + Enables channel 3 output. + +config STM32H5_TIM8_CH3NOUT + bool "TIM8 Channel 3 Complementary Output" + default n + ---help--- + Enables channel 3 Complementary Output. + +endif # STM32H5_TIM8_CHANNEL = 3 + +if STM32H5_TIM8_CHANNEL = 4 + +config STM32H5_TIM8_CH4OUT + bool "TIM8 Channel 4 Output" + default n + ---help--- + Enables channel 4 output. + +endif # STM32H5_TIM8_CHANNEL = 4 + +config STM32H5_TIM8_CHMODE + int "TIM8 Channel Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM8_PWM + +config STM32H5_TIM12_PWM + bool "TIM12 PWM" + default n + depends on STM32H5_TIM12 + select STM32H5_PWM + ---help--- + Reserve timer 12 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 STM32H5_TIM12 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM12_PWM + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM12_CHANNEL1 + bool "TIM12 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM12_CHANNEL1 + +config STM32H5_TIM12_CH1MODE + int "TIM12 Channel 1 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM12_CH1OUT + bool "TIM12 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM12_CHANNEL1 + +config STM32H5_TIM12_CHANNEL2 + bool "TIM12 Channel 2" + default n + ---help--- + Enables channel 2. + +if STM32H5_TIM12_CHANNEL2 + +config STM32H5_TIM12_CH2MODE + int "TIM12 Channel 2 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM12_CH2OUT + bool "TIM12 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM12_CHANNEL2 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM12_CHANNEL + int "TIM12 PWM Output Channel" + default 1 + range 1 2 + ---help--- + If TIM12 is enabled for PWM usage, you also need specifies the timer output + channel {1,2} + +if STM32H5_TIM12_CHANNEL = 1 + +config STM32H5_TIM12_CH1OUT + bool "TIM12 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM12_CHANNEL = 1 + +if STM32H5_TIM12_CHANNEL = 2 + +config STM32H5_TIM12_CH2OUT + bool "TIM12 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM12_CHANNEL = 2 + +config STM32H5_TIM12_CHMODE + int "TIM12 Channel Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM12_PWM + +config STM32H5_TIM13_PWM + bool "TIM13 PWM" + default n + depends on STM32H5_TIM13 + select STM32H5_PWM + ---help--- + Reserve timer 13 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 STM32H5_TIM13 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM13_PWM + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM13_CHANNEL1 + bool "TIM13 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM13_CHANNEL1 + +config STM32H5_TIM13_CH1MODE + int "TIM13 Channel 1 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM13_CH1OUT + bool "TIM13 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM13_CHANNEL1 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM13_CHANNEL + int "TIM13 PWM Output Channel" + default 1 + range 1 1 + ---help--- + If TIM13 is enabled for PWM usage, you also need specifies the timer output + channel {1} + +if STM32H5_TIM13_CHANNEL = 1 + +config STM32H5_TIM13_CH1OUT + bool "TIM13 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM13_CHANNEL = 1 + +config STM32H5_TIM13_CHMODE + int "TIM13 Channel Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM13_PWM + +config STM32H5_TIM14_PWM + bool "TIM14 PWM" + default n + depends on STM32H5_TIM14 + select STM32H5_PWM + ---help--- + Reserve timer 14 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 STM32H5_TIM14 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM14_PWM + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM14_CHANNEL1 + bool "TIM14 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM14_CHANNEL1 + +config STM32H5_TIM14_CH1MODE + int "TIM14 Channel 1 Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM14_CH1OUT + bool "TIM14 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM14_CHANNEL1 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM14_CHANNEL + int "TIM14 PWM Output Channel" + default 1 + range 1 1 + ---help--- + If TIM14 is enabled for PWM usage, you also need specifies the timer output + channel {1} + +if STM32H5_TIM14_CHANNEL = 1 + +config STM32H5_TIM14_CH1OUT + bool "TIM14 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM14_CHANNEL = 1 + +config STM32H5_TIM14_CHMODE + int "TIM14 Channel Mode" + default 6 + range 0 11 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM14_PWM + +config STM32H5_TIM15_PWM + bool "TIM15 PWM" + default n + depends on STM32H5_TIM15 + select STM32H5_PWM + ---help--- + Reserve timer 15 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 STM32H5_TIM15 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM15_PWM + +config STM32H5_TIM15_LOCK + int "TIM15 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 15 lock level configuration + +config STM32H5_TIM15_TDTS + int "TIM15 t_DTS Division" + default 0 + range 0 2 + ---help--- + Timer 15 dead-time and sampling clock (t_DTS) division + +config STM32H5_TIM15_DEADTIME + int "TIM15 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 15 initial dead-time + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM15_CHANNEL1 + bool "TIM15 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM15_CHANNEL1 + +config STM32H5_TIM15_CH1MODE + int "TIM15 Channel 1 Mode" + default 6 + range 0 9 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM15_CH1OUT + bool "TIM15 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32H5_TIM15_CH1NOUT + bool "TIM15 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32H5_TIM15_CHANNEL1 + +config STM32H5_TIM15_CHANNEL2 + bool "TIM15 Channel 2" + default n + ---help--- + Enables channel 2. + +if STM32H5_TIM15_CHANNEL2 + +config STM32H5_TIM15_CH2MODE + int "TIM15 Channel 2 Mode" + default 6 + range 0 9 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM15_CH2OUT + bool "TIM15 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +endif # STM32H5_TIM15_CHANNEL2 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM15_CHANNEL + int "TIM15 PWM Output Channel" + default 1 + range 1 2 + ---help--- + If TIM15 is enabled for PWM usage, you also need specifies the timer output + channel {1,2} + +if STM32H5_TIM15_CHANNEL = 1 + +config STM32H5_TIM15_CH1OUT + bool "TIM15 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +config STM32H5_TIM15_CH1NOUT + bool "TIM15 Channel 1 Complementary Output" + default n + ---help--- + Enables channel 1 Complementary Output. + +endif # STM32H5_TIM15_CHANNEL = 1 + +if STM32H5_TIM15_CHANNEL = 2 + +config STM32H5_TIM15_CH2OUT + bool "TIM15 Channel 2 Output" + default n + ---help--- + Enables channel 2 output. + +config STM32H5_TIM15_CH2NOUT + bool "TIM15 Channel 2 Complementary Output" + default n + ---help--- + Enables channel 2 Complementary Output. + +endif # STM32H5_TIM15_CHANNEL = 2 + +config STM32H5_TIM15_CHMODE + int "TIM15 Channel Mode" + default 6 + range 0 9 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM15_PWM + +config STM32H5_TIM16_PWM + bool "TIM16 PWM" + default n + depends on STM32H5_TIM16 + select STM32H5_PWM + ---help--- + Reserve timer 16 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 STM32H5_TIM16 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM16_PWM + +config STM32H5_TIM16_LOCK + int "TIM16 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 16 lock level configuration + +config STM32H5_TIM16_TDTS + int "TIM16 t_DTS division" + default 0 + range 0 2 + ---help--- + Timer 16 dead-time and sampling clock (t_DTS) division + +config STM32H5_TIM16_DEADTIME + int "TIM16 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 16 initial dead-time + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM16_CHANNEL1 + bool "TIM16 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM16_CHANNEL1 + +config STM32H5_TIM16_CH1MODE + int "TIM16 Channel 1 Mode" + default 6 + range 0 7 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM16_CH1OUT + bool "TIM16 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM16_CHANNEL1 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM16_CHANNEL + int "TIM16 PWM Output Channel" + default 1 + range 1 1 + ---help--- + If TIM16 is enabled for PWM usage, you also need specifies the timer output + channel {1} + +if STM32H5_TIM16_CHANNEL = 1 + +config STM32H5_TIM16_CH1OUT + bool "TIM16 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM16_CHANNEL = 1 + +config STM32H5_TIM16_CHMODE + int "TIM16 Channel Mode" + default 6 + range 0 7 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM16_PWM + +config STM32H5_TIM17_PWM + bool "TIM17 PWM" + default n + depends on STM32H5_TIM17 + select STM32H5_PWM + ---help--- + Reserve timer 17 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 STM32H5_TIM17 + is defined then THIS following may also be defined to indicate that + the timer is intended to be used for pulsed output modulation. + +if STM32H5_TIM17_PWM + +config STM32H5_TIM17_LOCK + int "TIM17 Lock Level Configuration" + default 0 + range 0 3 + ---help--- + Timer 17 lock level configuration + +config STM32H5_TIM17_TDTS + int "TIM17 t_DTS Division" + default 0 + range 0 2 + ---help--- + Timer 17 dead-time and sampling clock (t_DTS) division + +config STM32H5_TIM17_DEADTIME + int "TIM17 Initial Dead-time" + default 0 + range 0 255 + ---help--- + Timer 17 initial dead-time + +if STM32H5_PWM_MULTICHAN + +config STM32H5_TIM17_CHANNEL1 + bool "TIM17 Channel 1" + default n + ---help--- + Enables channel 1. + +if STM32H5_TIM17_CHANNEL1 + +config STM32H5_TIM17_CH1MODE + int "TIM17 Channel 1 Mode" + default 6 + range 0 7 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +config STM32H5_TIM17_CH1OUT + bool "TIM17 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM17_CHANNEL1 + +endif # STM32H5_PWM_MULTICHAN + +if !STM32H5_PWM_MULTICHAN + +config STM32H5_TIM17_CHANNEL + int "TIM17 PWM Output Channel" + default 1 + range 1 1 + ---help--- + If TIM17 is enabled for PWM usage, you also need specifies the timer output + channel {1} + +if STM32H5_TIM17_CHANNEL = 1 + +config STM32H5_TIM17_CH1OUT + bool "TIM17 Channel 1 Output" + default n + ---help--- + Enables channel 1 output. + +endif # STM32H5_TIM17_CHANNEL = 1 + +config STM32H5_TIM17_CHMODE + int "TIM17 Channel Mode" + default 6 + range 0 7 + ---help--- + Specifies the channel mode. See enum stm32_pwm_chanmode_e in stm32_pwm.h. + +endif # !STM32H5_PWM_MULTICHAN + +endif # STM32H5_TIM17_PWM + +config STM32H5_PWM_MULTICHAN + bool "PWM Multiple Output Channels" + default n + depends on STM32H5_PWM + select ARCH_HAVE_PWM_MULTICHAN + ---help--- + Specifies that the PWM driver supports multiple output + channels per timer. + +config STM32H5_TIM1_ADC + bool "TIM1 ADC" + default n + depends on STM32H5_TIM1 && STM32H5_ADC + ---help--- + Reserve timer 1 for use by an ADC + + Timer devices may be used for different purposes. If STM32H5_TIM1 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM1" + default STM32H5_TIM1_ADC1 + depends on STM32H5_TIM1_ADC + +config STM32H5_TIM1_ADC1 + bool "Use TIM1 for ADC1" + depends on STM32H5_ADC1 + select STM32H5_HAVE_ADC1_TIMER + ---help--- + Reserve TIM1 to trigger ADC1 + +config STM32H5_TIM1_ADC2 + bool "Use TIM1 for ADC2" + depends on STM32H5_ADC2 + select STM32H5_HAVE_ADC2_TIMER + ---help--- + Reserve TIM1 to trigger ADC2 + +endchoice + +config STM32H5_TIM2_ADC + bool "TIM2 ADC" + default n + depends on STM32H5_TIM2 && STM32H5_ADC + ---help--- + Reserve timer 2 for use by an ADC + + Timer devices may be used for different purposes. If STM32H5_TIM2 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM2" + default STM32H5_TIM2_ADC1 + depends on STM32H5_TIM2_ADC + +config STM32H5_TIM2_ADC1 + bool "Use TIM2 for ADC1" + depends on STM32H5_ADC1 + select STM32H5_HAVE_ADC1_TIMER + ---help--- + Reserve TIM2 to trigger ADC1 + +config STM32H5_TIM2_ADC2 + bool "Use TIM2 for ADC2" + depends on STM32H5_ADC2 + select STM32H5_HAVE_ADC2_TIMER + ---help--- + Reserve TIM2 to trigger ADC2 + +endchoice + +config STM32H5_TIM3_ADC + bool "TIM3 ADC" + default n + depends on STM32H5_TIM3 && STM32H5_ADC + ---help--- + Reserve timer 3 for use by an ADC + + Timer devices may be used for different purposes. If STM32H5_TIM3 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM3" + default STM32H5_TIM3_ADC1 + depends on STM32H5_TIM3_ADC + +config STM32H5_TIM3_ADC1 + bool "Use TIM3 for ADC1" + depends on STM32H5_ADC1 + select STM32H5_HAVE_ADC1_TIMER + ---help--- + Reserve TIM3 to trigger ADC1 + +config STM32H5_TIM3_ADC2 + bool "Use TIM3 for ADC2" + depends on STM32H5_ADC2 + select STM32H5_HAVE_ADC2_TIMER + ---help--- + Reserve TIM3 to trigger ADC2 + +endchoice + +config STM32H5_TIM4_ADC + bool "TIM4 ADC" + default n + depends on STM32H5_TIM4 && STM32H5_ADC + ---help--- + Reserve timer 4 for use by ADC + + Timer devices may be used for different purposes. If STM32H5_TIM4 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM4" + default STM32H5_TIM4_ADC1 + depends on STM32H5_TIM4_ADC + +config STM32H5_TIM4_ADC1 + bool "Use TIM4 for ADC1" + depends on STM32H5_ADC1 + select STM32H5_HAVE_ADC1_TIMER + ---help--- + Reserve TIM4 to trigger ADC1 + +config STM32H5_TIM4_ADC2 + bool "Use TIM4 for ADC2" + depends on STM32H5_ADC2 + select STM32H5_HAVE_ADC2_TIMER + ---help--- + Reserve TIM4 to trigger ADC2 + +endchoice + +config STM32H5_TIM6_ADC + bool "TIM6 ADC" + default n + depends on STM32H5_TIM6 && STM32H5_ADC + ---help--- + Reserve timer 6 for use by ADC + + Timer devices may be used for different purposes. If STM32H5_TIM6 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM6" + default STM32H5_TIM6_ADC1 + depends on STM32H5_TIM6_ADC + +config STM32H5_TIM6_ADC1 + bool "Use TIM6 for ADC1" + depends on STM32H5_ADC1 + select STM32H5_HAVE_ADC1_TIMER + ---help--- + Reserve TIM6 to trigger ADC1 + +config STM32H5_TIM6_ADC2 + bool "Use TIM6 for ADC2" + depends on STM32H5_ADC2 + select STM32H5_HAVE_ADC2_TIMER + ---help--- + Reserve TIM6 to trigger ADC2 + +endchoice + +config STM32H5_TIM8_ADC + bool "TIM8 ADC" + default n + depends on STM32H5_TIM8 && STM32H5_ADC + ---help--- + Reserve timer 8 for use by ADC + + Timer devices may be used for different purposes. If STM32H5_TIM8 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM8" + default STM32H5_TIM8_ADC1 + depends on STM32H5_TIM8_ADC + +config STM32H5_TIM8_ADC1 + bool "Use TIM8 for ADC1" + depends on STM32H5_ADC1 + select STM32H5_HAVE_ADC1_TIMER + ---help--- + Reserve TIM8 to trigger ADC1 + +config STM32H5_TIM8_ADC2 + bool "Use TIM8 for ADC2" + depends on STM32H5_ADC2 + select STM32H5_HAVE_ADC2_TIMER + ---help--- + Reserve TIM8 to trigger ADC2 + +endchoice + +config STM32H5_TIM15_ADC + bool "TIM15 ADC" + default n + depends on STM32H5_TIM15 && STM32H5_ADC + ---help--- + Reserve timer 15 for use by ADC + + Timer devices may be used for different purposes. If STM32H5_TIM15 is + defined then the following may also be defined to indicate that the + timer is intended to be used for ADC conversion. Note that ADC usage + requires two definition: Not only do you have to assign the timer + for used by the ADC, but then you also have to configure which ADC + channel it is assigned to. + +choice + prompt "Select ADC for use with TIM15" + default STM32H5_TIM15_ADC1 + depends on STM32H5_TIM15_ADC + +config STM32H5_TIM15_ADC1 + bool "Use TIM15 for ADC1" + depends on STM32H5_ADC1 + select STM32H5_HAVE_ADC1_TIMER + ---help--- + Reserve TIM15 to trigger ADC1 + +config STM32H5_TIM15_ADC2 + bool "Use TIM15 for ADC2" + depends on STM32H5_ADC2 + select STM32H5_HAVE_ADC2_TIMER + ---help--- + Reserve TIM15 to trigger ADC2 + +endchoice + +config STM32H5_HAVE_ADC1_TIMER + bool + +config STM32H5_HAVE_ADC2_TIMER + bool + +config STM32H5_ADC1_SAMPLE_FREQUENCY + int "ADC1 Sampling Frequency" + default 100 + depends on STM32H5_HAVE_ADC1_TIMER + ---help--- + ADC1 sampling frequency. Default: 100Hz + +config STM32H5_ADC1_TIMTRIG + int "ADC1 Timer Trigger" + default 0 + range 0 4 + depends on STM32H5_HAVE_ADC1_TIMER + ---help--- + Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO + +config STM32H5_ADC2_SAMPLE_FREQUENCY + int "ADC2 Sampling Frequency" + default 100 + depends on STM32H5_HAVE_ADC2_TIMER + ---help--- + ADC2 sampling frequency. Default: 100Hz + +config STM32H5_ADC2_TIMTRIG + int "ADC2 Timer Trigger" + default 0 + range 0 4 + depends on STM32H5_HAVE_ADC2_TIMER + ---help--- + Values 0:CC1 1:CC2 2:CC3 3:CC4 4:TRGO + +config STM32H5_TIM1_CAP + bool "TIM1 Capture" + default n + depends on STM32H5_TIM1 + ---help--- + Reserve timer 1 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM2_CAP + bool "TIM2 Capture" + default n + depends on STM32H5_TIM2 + ---help--- + Reserve timer 2 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM3_CAP + bool "TIM3 Capture" + default n + depends on STM32H5_TIM3 + ---help--- + Reserve timer 3 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM4_CAP + bool "TIM4 Capture" + default n + depends on STM32H5_TIM4 + ---help--- + Reserve timer 4 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM5_CAP + bool "TIM5 Capture" + default n + depends on STM32H5_TIM5 + ---help--- + Reserve timer 5 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM8_CAP + bool "TIM8 Capture" + default n + depends on STM32H5_TIM8 + ---help--- + Reserve timer 8 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM12_CAP + bool "TIM12 Capture" + default n + depends on STM32H5_TIM12 + ---help--- + Reserve timer 12 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM13_CAP + bool "TIM13 Capture" + default n + depends on STM32H5_TIM13 + ---help--- + Reserve timer 13 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM14_CAP + bool "TIM14 Capture" + default n + depends on STM32H5_TIM14 + ---help--- + Reserve timer 14 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM15_CAP + bool "TIM15 Capture" + default n + depends on STM32H5_TIM15 + ---help--- + Reserve timer 15 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM16_CAP + bool "TIM16 Capture" + default n + depends on STM32H5_TIM16 + ---help--- + Reserve timer 16 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +config STM32H5_TIM17_CAP + bool "TIM14 Capture" + default n + depends on STM32H5_TIM17 + ---help--- + Reserve timer 17 for use by Capture + + Timer devices may be used for different purposes. One special purpose is + to capture input. + +menu "STM32 TIMx Outputs Configuration" + +config STM32H5_TIM1_CH1POL + int "TIM1 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH1OUT + ---help--- + TIM1 Channel 1 output polarity + +config STM32H5_TIM1_CH1IDLE + int "TIM1 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH1OUT + ---help--- + TIM1 Channel 1 output IDLE + +config STM32H5_TIM1_CH1NPOL + int "TIM1 Channel 1 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH1NOUT + ---help--- + TIM1 Channel 1 Complementary Output polarity + +config STM32H5_TIM1_CH1NIDLE + int "TIM1 Channel 1 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH1NOUT + ---help--- + TIM1 Channel 1 Complementary Output IDLE + +config STM32H5_TIM1_CH2POL + int "TIM1 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH2OUT + ---help--- + TIM1 Channel 2 output polarity + +config STM32H5_TIM1_CH2IDLE + int "TIM1 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH2OUT + ---help--- + TIM1 Channel 2 output IDLE + +config STM32H5_TIM1_CH2NPOL + int "TIM1 Channel 2 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH2NOUT + ---help--- + TIM1 Channel 2 Complementary Output polarity + +config STM32H5_TIM1_CH2NIDLE + int "TIM1 Channel 2 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH2NOUT + ---help--- + TIM1 Channel 2 Complementary Output IDLE + +config STM32H5_TIM1_CH3POL + int "TIM1 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH3OUT + ---help--- + TIM1 Channel 3 output polarity + +config STM32H5_TIM1_CH3IDLE + int "TIM1 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH3OUT + ---help--- + TIM1 Channel 3 output IDLE + +config STM32H5_TIM1_CH3NPOL + int "TIM1 Channel 3 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH3NOUT + ---help--- + TIM1 Channel 3 Complementary Output polarity + +config STM32H5_TIM1_CH3NIDLE + int "TIM1 Channel 3 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH3NOUT + ---help--- + TIM1 Channel 3 Complementary Output IDLE + +config STM32H5_TIM1_CH4POL + int "TIM1 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH4OUT + ---help--- + TIM1 Channel 4 output polarity + +config STM32H5_TIM1_CH4IDLE + int "TIM1 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH4OUT + ---help--- + TIM1 Channel 4 output IDLE + +config STM32H5_TIM1_CH5POL + int "TIM1 Channel 5 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH5OUT + ---help--- + TIM1 Channel 5 output polarity + +config STM32H5_TIM1_CH5IDLE + int "TIM1 Channel 5 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH5OUT + ---help--- + TIM1 Channel 5 output IDLE + +config STM32H5_TIM1_CH6POL + int "TIM1 Channel 6 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH6OUT + ---help--- + TIM1 Channel 6 output polarity + +config STM32H5_TIM1_CH6IDLE + int "TIM1 Channel 6 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM1_CH6OUT + ---help--- + TIM1 Channel 6 output IDLE + +config STM32H5_TIM2_CH1POL + int "TIM2 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM2_CH1OUT + ---help--- + TIM2 Channel 1 output polarity + +config STM32H5_TIM2_CH1IDLE + int "TIM2 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM2_CH1OUT + ---help--- + TIM2 Channel 1 output IDLE + +config STM32H5_TIM2_CH2POL + int "TIM2 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM2_CH2OUT + ---help--- + TIM2 Channel 2 output polarity + +config STM32H5_TIM2_CH2IDLE + int "TIM2 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM2_CH2OUT + ---help--- + TIM2 Channel 2 output IDLE + +config STM32H5_TIM2_CH3POL + int "TIM2 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM2_CH3OUT + ---help--- + TIM2 Channel 3 output polarity + +config STM32H5_TIM2_CH3IDLE + int "TIM2 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM2_CH3OUT + ---help--- + TIM2 Channel 3 output IDLE + +config STM32H5_TIM2_CH4POL + int "TIM2 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM2_CH4OUT + ---help--- + TIM2 Channel 4 output polarity + +config STM32H5_TIM2_CH4IDLE + int "TIM2 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM2_CH4OUT + ---help--- + TIM2 Channel 4 output IDLE + +config STM32H5_TIM3_CH1POL + int "TIM3 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM3_CH1OUT + ---help--- + TIM3 Channel 1 output polarity + +config STM32H5_TIM3_CH1IDLE + int "TIM3 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM3_CH1OUT + ---help--- + TIM3 Channel 1 output IDLE + +config STM32H5_TIM3_CH2POL + int "TIM3 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM3_CH2OUT + ---help--- + TIM3 Channel 2 output polarity + +config STM32H5_TIM3_CH2IDLE + int "TIM3 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM3_CH2OUT + ---help--- + TIM3 Channel 2 output IDLE + +config STM32H5_TIM3_CH3POL + int "TIM3 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM3_CH3OUT + ---help--- + TIM3 Channel 3 output polarity + +config STM32H5_TIM3_CH3IDLE + int "TIM3 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM3_CH3OUT + ---help--- + TIM3 Channel 3 output IDLE + +config STM32H5_TIM3_CH4POL + int "TIM3 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM3_CH4OUT + ---help--- + TIM3 Channel 4 output polarity + +config STM32H5_TIM3_CH4IDLE + int "TIM3 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM3_CH4OUT + ---help--- + TIM3 Channel 4 output IDLE + +config STM32H5_TIM4_CH1POL + int "TIM4 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM4_CH1OUT + ---help--- + TIM4 Channel 1 output polarity + +config STM32H5_TIM4_CH1IDLE + int "TIM4 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM4_CH1OUT + ---help--- + TIM4 Channel 1 output IDLE + +config STM32H5_TIM4_CH2POL + int "TIM4 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM4_CH2OUT + ---help--- + TIM4 Channel 2 output polarity + +config STM32H5_TIM4_CH2IDLE + int "TIM4 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM4_CH2OUT + ---help--- + TIM4 Channel 2 output IDLE + +config STM32H5_TIM4_CH3POL + int "TIM4 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM4_CH3OUT + ---help--- + TIM4 Channel 3 output polarity + +config STM32H5_TIM4_CH3IDLE + int "TIM4 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM4_CH3OUT + ---help--- + TIM4 Channel 3 output IDLE + +config STM32H5_TIM4_CH4POL + int "TIM4 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM4_CH4OUT + ---help--- + TIM4 Channel 4 output polarity + +config STM32H5_TIM4_CH4IDLE + int "TIM4 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM4_CH4OUT + ---help--- + TIM4 Channel 4 output IDLE + +config STM32H5_TIM5_CH1POL + int "TIM5 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM5_CH1OUT + ---help--- + TIM5 Channel 1 output polarity + +config STM32H5_TIM5_CH1IDLE + int "TIM5 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM5_CH1OUT + ---help--- + TIM5 Channel 1 output IDLE + +config STM32H5_TIM5_CH2POL + int "TIM5 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM5_CH2OUT + ---help--- + TIM5 Channel 2 output polarity + +config STM32H5_TIM5_CH2IDLE + int "TIM5 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM5_CH2OUT + ---help--- + TIM5 Channel 2 output IDLE + +config STM32H5_TIM5_CH3POL + int "TIM5 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM5_CH3OUT + ---help--- + TIM5 Channel 3 output polarity + +config STM32H5_TIM5_CH3IDLE + int "TIM5 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM5_CH3OUT + ---help--- + TIM5 Channel 3 output IDLE + +config STM32H5_TIM5_CH4POL + int "TIM5 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM5_CH4OUT + ---help--- + TIM5 Channel 4 output polarity + +config STM32H5_TIM5_CH4IDLE + int "TIM5 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM5_CH4OUT + ---help--- + TIM5 Channel 4 output IDLE + +config STM32H5_TIM8_CH1POL + int "TIM8 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH1OUT + ---help--- + TIM8 Channel 1 output polarity + +config STM32H5_TIM8_CH1IDLE + int "TIM8 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH1OUT + ---help--- + TIM8 Channel 1 output IDLE + +config STM32H5_TIM8_CH1NPOL + int "TIM8 Channel 1 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH1NOUT + ---help--- + TIM8 Channel 1 Complementary Output polarity + +config STM32H5_TIM8_CH1NIDLE + int "TIM8 Channel 1 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH1NOUT + ---help--- + TIM8 Channel 1 Complementary Output IDLE + +config STM32H5_TIM8_CH2POL + int "TIM8 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH2OUT + ---help--- + TIM8 Channel 2 output polarity + +config STM32H5_TIM8_CH2IDLE + int "TIM8 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH2OUT + ---help--- + TIM8 Channel 2 output IDLE + +config STM32H5_TIM8_CH2NPOL + int "TIM8 Channel 2 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH2NOUT + ---help--- + TIM8 Channel 2 Complementary Output polarity + +config STM32H5_TIM8_CH2NIDLE + int "TIM8 Channel 2 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH2NOUT + ---help--- + TIM8 Channel 2 Complementary Output IDLE + +config STM32H5_TIM8_CH3POL + int "TIM8 Channel 3 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH3OUT + ---help--- + TIM8 Channel 3 output polarity + +config STM32H5_TIM8_CH3IDLE + int "TIM8 Channel 3 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH3OUT + ---help--- + TIM8 Channel 3 output IDLE + +config STM32H5_TIM8_CH3NPOL + int "TIM8 Channel 3 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH3NOUT + ---help--- + TIM8 Channel 3 Complementary Output polarity + +config STM32H5_TIM8_CH3NIDLE + int "TIM8 Channel 3 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH3NOUT + ---help--- + TIM8 Channel 3 Complementary Output IDLE + +config STM32H5_TIM8_CH4POL + int "TIM8 Channel 4 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH4OUT + ---help--- + TIM8 Channel 4 output polarity + +config STM32H5_TIM8_CH4IDLE + int "TIM8 Channel 4 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH4OUT + ---help--- + TIM8 Channel 4 output IDLE + +config STM32H5_TIM8_CH5POL + int "TIM8 Channel 5 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH5OUT + ---help--- + TIM8 Channel 5 output polarity + +config STM32H5_TIM8_CH5IDLE + int "TIM8 Channel 5 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH5OUT + ---help--- + TIM8 Channel 5 output IDLE + +config STM32H5_TIM8_CH6POL + int "TIM8 Channel 6 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH6OUT + ---help--- + TIM8 Channel 6 output polarity + +config STM32H5_TIM8_CH6IDLE + int "TIM8 Channel 6 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM8_CH6OUT + ---help--- + TIM8 Channel 6 output IDLE + +config STM32H5_TIM12_CH1POL + int "TIM12 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM12_CH1OUT + ---help--- + TIM12 Channel 1 output polarity + +config STM32H5_TIM12_CH1IDLE + int "TIM12 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM12_CH1OUT + ---help--- + TIM12 Channel 1 output IDLE + +config STM32H5_TIM12_CH2POL + int "TIM12 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM12_CH2OUT + ---help--- + TIM12 Channel 2 output polarity + +config STM32H5_TIM12_CH2IDLE + int "TIM12 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM12_CH2OUT + ---help--- + TIM12 Channel 2 output IDLE + +config STM32H5_TIM13_CH1POL + int "TIM13 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM13_CH1OUT + ---help--- + TIM13 Channel 1 output polarity + +config STM32H5_TIM13_CH1IDLE + int "TIM13 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM13_CH1OUT + ---help--- + TIM13 Channel 1 output IDLE + +config STM32H5_TIM14_CH1POL + int "TIM14 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM14_CH1OUT + ---help--- + TIM14 Channel 1 output polarity + +config STM32H5_TIM14_CH1IDLE + int "TIM14 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM14_CH1OUT + ---help--- + TIM14 Channel 1 output IDLE + +config STM32H5_TIM15_CH1POL + int "TIM15 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM15_CH1OUT + ---help--- + TIM15 Channel 1 output polarity + +config STM32H5_TIM15_CH1IDLE + int "TIM15 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM15_CH1OUT + ---help--- + TIM15 Channel 1 output IDLE + +config STM32H5_TIM15_CH1NPOL + int "TIM15 Channel 1 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM15_CH1NOUT + ---help--- + TIM15 Channel 1 Complementary Output polarity + +config STM32H5_TIM15_CH1NIDLE + int "TIM15 Channel 1 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM15_CH1NOUT + ---help--- + TIM15 Channel 1 Complementary Output IDLE + +config STM32H5_TIM15_CH2POL + int "TIM15 Channel 2 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM15_CH2OUT + ---help--- + TIM15 Channel 2 output polarity + +config STM32H5_TIM15_CH2IDLE + int "TIM15 Channel 2 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM15_CH2OUT + ---help--- + TIM15 Channel 2 output IDLE + +config STM32H5_TIM15_CH2NPOL + int "TIM15 Channel 2 Complementary Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM15_CH2NOUT + ---help--- + TIM15 Channel 2 Complementary Output polarity + +config STM32H5_TIM15_CH2NIDLE + int "TIM15 Channel 2 Complementary Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM15_CH2NOUT + ---help--- + TIM15 Channel 2 Complementary Output IDLE + +config STM32H5_TIM16_CH1POL + int "TIM16 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM16_CH1OUT + ---help--- + TIM16 Channel 1 output polarity + +config STM32H5_TIM16_CH1IDLE + int "TIM16 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM16_CH1OUT + ---help--- + TIM16 Channel 1 output IDLE + +config STM32H5_TIM17_CH1POL + int "TIM17 Channel 1 Output polarity" + default 0 + range 0 1 + depends on STM32H5_TIM17_CH1OUT + ---help--- + TIM17 Channel 1 output polarity + +config STM32H5_TIM17_CH1IDLE + int "TIM17 Channel 1 Output IDLE" + default 0 + range 0 1 + depends on STM32H5_TIM17_CH1OUT + ---help--- + TIM17 Channel 1 output IDLE + +endmenu #STM32 TIMx Outputs Configuration + +endmenu # Timer Configuration + config STM32H5_SERIALDRIVER bool diff --git a/arch/arm/src/stm32h5/Make.defs b/arch/arm/src/stm32h5/Make.defs index 598d16cf5e240..96f055b5f999c 100644 --- a/arch/arm/src/stm32h5/Make.defs +++ b/arch/arm/src/stm32h5/Make.defs @@ -43,7 +43,7 @@ CHIP_CSRCS += stm32_idle.c endif ifeq ($(CONFIG_TIMER),y) -CHIP_CSRCS += stm32h5_tim_lowerhalf.c +CHIP_CSRCS += stm32_tim_lowerhalf.c endif ifeq ($(CONFIG_STM32H5_I2C),y) @@ -66,6 +66,10 @@ ifeq ($(CONFIG_STM32H5_QSPI1),y) CHIP_CSRCS += stm32_qspi.c endif +ifeq ($(CONFIG_STM32H5_TIM),y) +CHIP_CSRCS += stm32_tim.c +endif + # Required chip type specific files ifeq ($(CONFIG_STM32H5_STM32H5XXXX),y) diff --git a/arch/arm/src/stm32h5/stm32_tim.c b/arch/arm/src/stm32h5/stm32_tim.c new file mode 100644 index 0000000000000..b36dcae502c0a --- /dev/null +++ b/arch/arm/src/stm32h5/stm32_tim.c @@ -0,0 +1,1553 @@ +/**************************************************************************** + * arch/arm/src/stm32h5/stm32_tim.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "chip.h" +#include "arm_internal.h" +#include "stm32_rcc.h" +#include "stm32_gpio.h" +#include "stm32_tim.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Timer devices may be used for different purposes. Such special purposes + * include: + * + * - To generate modulated outputs for such things as motor control. If + * CONFIG_STM32H5_TIMn is defined then the CONFIG_STM32H5_TIMn_PWM may + * also be defined to indicate that the timer is intended to be used for + * pulsed output modulation. + * + * - To control periodic ADC input sampling. If CONFIG_STM32H5_TIMn is + * defined then CONFIG_STM32H5_TIMn_ADC may also be defined to indicate + * that timer "n" is intended to be used for that purpose. + * + * - To control periodic DAC outputs. If CONFIG_STM32H5_TIMn is defined + * then CONFIG_STM32H5_TIMn_DAC may also be defined to indicate that + * timer "n" is intended to be used for that purpose. + * + * - To use a Quadrature Encoder. If CONFIG_STM32H5_TIMn is defined then + * CONFIG_STM32H5_TIMn_QE may also be defined to indicate that timer "n" + * is intended to be used for that purpose. + * + * In any of these cases, the timer will not be used by this timer module. + */ + +#if defined(CONFIG_STM32H5_TIM1_PWM) || defined (CONFIG_STM32H5_TIM1_ADC) || \ + defined(CONFIG_STM32H5_TIM1_DAC) || defined(CONFIG_STM32H5_TIM1_QE) +# undef CONFIG_STM32H5_TIM1 +#endif + +#if defined(CONFIG_STM32H5_TIM2_PWM) || defined (CONFIG_STM32H5_TIM2_ADC) || \ + defined(CONFIG_STM32H5_TIM2_DAC) || defined(CONFIG_STM32H5_TIM2_QE) +# undef CONFIG_STM32H5_TIM2 +#endif + +#if defined(CONFIG_STM32H5_TIM3_PWM) || defined (CONFIG_STM32H5_TIM3_ADC) || \ + defined(CONFIG_STM32H5_TIM3_DAC) || defined(CONFIG_STM32H5_TIM3_QE) +# undef CONFIG_STM32H5_TIM3 +#endif + +#if defined(CONFIG_STM32H5_TIM4_PWM) || defined (CONFIG_STM32H5_TIM4_ADC) || \ + defined(CONFIG_STM32H5_TIM4_DAC) || defined(CONFIG_STM32H5_TIM4_QE) +# undef CONFIG_STM32H5_TIM4 +#endif + +#if defined(CONFIG_STM32H5_TIM5_PWM) || defined (CONFIG_STM32H5_TIM5_ADC) || \ + defined(CONFIG_STM32H5_TIM5_DAC) || defined(CONFIG_STM32H5_TIM5_QE) +# undef CONFIG_STM32H5_TIM5 +#endif + +#if defined(CONFIG_STM32H5_TIM6_PWM) || defined (CONFIG_STM32H5_TIM6_ADC) || \ + defined(CONFIG_STM32H5_TIM6_DAC) || defined(CONFIG_STM32H5_TIM6_QE) +# undef CONFIG_STM32H5_TIM6 +#endif + +#if defined(CONFIG_STM32H5_TIM7_PWM) || defined (CONFIG_STM32H5_TIM7_ADC) || \ + defined(CONFIG_STM32H5_TIM7_DAC) || defined(CONFIG_STM32H5_TIM7_QE) +# undef CONFIG_STM32H5_TIM7 +#endif + +#if defined(CONFIG_STM32H5_TIM8_PWM) || defined (CONFIG_STM32H5_TIM8_ADC) || \ + defined(CONFIG_STM32H5_TIM8_DAC) || defined(CONFIG_STM32H5_TIM8_QE) +# undef CONFIG_STM32H5_TIM8 +#endif + +#if defined(CONFIG_STM32H5_TIM12_PWM) || defined (CONFIG_STM32H5_TIM12_ADC) || \ + defined(CONFIG_STM32H5_TIM12_DAC) || defined(CONFIG_STM32H5_TIM12_QE) +# undef CONFIG_STM32H5_TIM12 +#endif + +#if defined(CONFIG_STM32H5_TIM13_PWM) || defined (CONFIG_STM32H5_TIM13_ADC) || \ + defined(CONFIG_STM32H5_TIM13_DAC) || defined(CONFIG_STM32H5_TIM13_QE) +# undef CONFIG_STM32H5_TIM13 +#endif + +#if defined(CONFIG_STM32H5_TIM14_PWM) || defined (CONFIG_STM32H5_TIM14_ADC) || \ + defined(CONFIG_STM32H5_TIM14_DAC) || defined(CONFIG_STM32H5_TIM14_QE) +# undef CONFIG_STM32H5_TIM14 +#endif + +#if defined(CONFIG_STM32H5_TIM15_PWM) || defined (CONFIG_STM32H5_TIM15_ADC) || \ + defined(CONFIG_STM32H5_TIM15_DAC) || defined(CONFIG_STM32H5_TIM15_QE) +# undef CONFIG_STM32H5_TIM15 +#endif + +#if defined(CONFIG_STM32H5_TIM16_PWM) || defined (CONFIG_STM32H5_TIM16_ADC) || \ + defined(CONFIG_STM32H5_TIM16_DAC) || defined(CONFIG_STM32H5_TIM16_QE) +# undef CONFIG_STM32H5_TIM16 +#endif + +#if defined(CONFIG_STM32H5_TIM17_PWM) || defined (CONFIG_STM32H5_TIM17_ADC) || \ + defined(CONFIG_STM32H5_TIM17_DAC) || defined(CONFIG_STM32H5_TIM17_QE) +# undef CONFIG_STM32H5_TIM17 +#endif + +#if defined(CONFIG_STM32H5_TIM1) +# if defined(GPIO_TIM1_CH1OUT) ||defined(GPIO_TIM1_CH2OUT)||\ + defined(GPIO_TIM1_CH3OUT) ||defined(GPIO_TIM1_CH4OUT)||\ + defined(GPIO_TIM1_CH5OUT) ||defined(GPIO_TIM1_CH6OUT) +# define HAVE_TIM1_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM2) +# if defined(GPIO_TIM2_CH1OUT) ||defined(GPIO_TIM2_CH2OUT)||\ + defined(GPIO_TIM2_CH3OUT) ||defined(GPIO_TIM2_CH4OUT) +# define HAVE_TIM2_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM3) +# if defined(GPIO_TIM3_CH1OUT) ||defined(GPIO_TIM3_CH2OUT)||\ + defined(GPIO_TIM3_CH3OUT) ||defined(GPIO_TIM3_CH4OUT) +# define HAVE_TIM3_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM4) +# if defined(GPIO_TIM4_CH1OUT) ||defined(GPIO_TIM4_CH2OUT)||\ + defined(GPIO_TIM4_CH3OUT) ||defined(GPIO_TIM4_CH4OUT) +# define HAVE_TIM4_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM5) +# if defined(GPIO_TIM5_CH1OUT) ||defined(GPIO_TIM5_CH2OUT)||\ + defined(GPIO_TIM5_CH3OUT) ||defined(GPIO_TIM5_CH4OUT) +# define HAVE_TIM5_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM8) +# if defined(GPIO_TIM8_CH1OUT) ||defined(GPIO_TIM8_CH2OUT)||\ + defined(GPIO_TIM8_CH3OUT) ||defined(GPIO_TIM8_CH4OUT)||\ + defined(GPIO_TIM8_CH5OUT) ||defined(GPIO_TIM8_CH6OUT) +# define HAVE_TIM8_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM12) +# if defined(GPIO_TIM12_CH1OUT) ||defined(GPIO_TIM12_CH2OUT) +# define HAVE_TIM12_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM13) +# if defined(GPIO_TIM13_CH1OUT) +# define HAVE_TIM13_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM14) +# if defined(GPIO_TIM14_CH1OUT) +# define HAVE_TIM14_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM15) +# if defined(GPIO_TIM15_CH1OUT) ||defined(GPIO_TIM15_CH2OUT) +# define HAVE_TIM15_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM16) +# if defined(GPIO_TIM16_CH1OUT) +# define HAVE_TIM16_GPIOCONFIG 1 +# endif +#endif + +#if defined(CONFIG_STM32H5_TIM17) +# if defined(GPIO_TIM17_CH1OUT) +# define HAVE_TIM17_GPIOCONFIG 1 +# endif +#endif + +/* This module then only compiles if there are enabled timers that are not + * intended for some other purpose. + */ + +#if defined(CONFIG_STM32H5_TIM1) || defined(CONFIG_STM32H5_TIM2) || \ + defined(CONFIG_STM32H5_TIM3) || defined(CONFIG_STM32H5_TIM4) || \ + defined(CONFIG_STM32H5_TIM5) || defined(CONFIG_STM32H5_TIM6) || \ + defined(CONFIG_STM32H5_TIM7) || defined(CONFIG_STM32H5_TIM8) || \ + defined(CONFIG_STM32H5_TIM12) || defined(CONFIG_STM32H5_TIM13) || \ + defined(CONFIG_STM32H5_TIM14) || defined(CONFIG_STM32H5_TIM15) || \ + defined(CONFIG_STM32H5_TIM16) || defined(CONFIG_STM32H5_TIM17) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* TIM Device Structure */ + +struct stm32_tim_priv_s +{ + const struct stm32_tim_ops_s *ops; + stm32_tim_mode_t mode; + uint32_t base; /* TIMn base address */ +}; + +/**************************************************************************** + * Private Function prototypes + ****************************************************************************/ + +/* Timer methods */ + +static void stm32_tim_enable(struct stm32_tim_dev_s *dev); +static void stm32_tim_disable(struct stm32_tim_dev_s *dev); +static int stm32_tim_setmode(struct stm32_tim_dev_s *dev, + stm32_tim_mode_t mode); +static int stm32_tim_setclock(struct stm32_tim_dev_s *dev, + uint32_t freq); +static void stm32_tim_setperiod(struct stm32_tim_dev_s *dev, + uint32_t period); +static uint32_t stm32_tim_getcounter(struct stm32_tim_dev_s *dev); +static void stm32_tim_setcounter(struct stm32_tim_dev_s *dev, + uint32_t count); +static int stm32_tim_getwidth(struct stm32_tim_dev_s *dev); +static int stm32_tim_setchannel(struct stm32_tim_dev_s *dev, + uint8_t channel, + stm32_tim_channel_t mode); +static int stm32_tim_setcompare(struct stm32_tim_dev_s *dev, + uint8_t channel, uint32_t compare); +static int stm32_tim_getcapture(struct stm32_tim_dev_s *dev, + uint8_t channel); +static int stm32_tim_setisr(struct stm32_tim_dev_s *dev, + xcpt_t handler, void *arg, int source); +static void stm32_tim_enableint(struct stm32_tim_dev_s *dev, + int source); +static void stm32_tim_disableint(struct stm32_tim_dev_s *dev, + int source); +static void stm32_tim_ackint(struct stm32_tim_dev_s *dev, + int source); +static int stm32_tim_checkint(struct stm32_tim_dev_s *dev, + int source); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct stm32_tim_ops_s stm32_tim_ops = +{ + .enable = &stm32_tim_enable, + .disable = &stm32_tim_disable, + .setmode = &stm32_tim_setmode, + .setclock = &stm32_tim_setclock, + .setperiod = &stm32_tim_setperiod, + .getcounter = &stm32_tim_getcounter, + .setcounter = &stm32_tim_setcounter, + .getwidth = &stm32_tim_getwidth, + .setchannel = &stm32_tim_setchannel, + .setcompare = &stm32_tim_setcompare, + .getcapture = &stm32_tim_getcapture, + .setisr = &stm32_tim_setisr, + .enableint = &stm32_tim_enableint, + .disableint = &stm32_tim_disableint, + .ackint = &stm32_tim_ackint, + .checkint = &stm32_tim_checkint, +}; + +#ifdef CONFIG_STM32H5_TIM1 +struct stm32_tim_priv_s stm32_tim1_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM1_BASE, +}; +#endif +#ifdef CONFIG_STM32H5_TIM2 +struct stm32_tim_priv_s stm32_tim2_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM2_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM3 +struct stm32_tim_priv_s stm32_tim3_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM3_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM4 +struct stm32_tim_priv_s stm32_tim4_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM4_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM5 +struct stm32_tim_priv_s stm32_tim5_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM5_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM6 +struct stm32_tim_priv_s stm32_tim6_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM6_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM7 +struct stm32_tim_priv_s stm32_tim7_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM7_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM8 +struct stm32_tim_priv_s stm32_tim8_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM8_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM12 +struct stm32_tim_priv_s stm32_tim12_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM12_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM13 +struct stm32_tim_priv_s stm32_tim13_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM13_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM14 +struct stm32_tim_priv_s stm32_tim14_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM14_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM15 +struct stm32_tim_priv_s stm32_tim15_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM15_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM16 +struct stm32_tim_priv_s stm32_tim16_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM16_BASE, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM17 +struct stm32_tim_priv_s stm32_tim17_priv = +{ + .ops = &stm32_tim_ops, + .mode = STM32_TIM_MODE_UNUSED, + .base = STM32_TIM17_BASE, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* Get a 16-bit register value by offset */ + +static inline uint16_t stm32_getreg16(struct stm32_tim_dev_s *dev, + uint8_t offset) +{ + return getreg16(((struct stm32_tim_priv_s *)dev)->base + offset); +} + +/* Put a 16-bit register value by offset */ + +static inline void stm32_putreg16(struct stm32_tim_dev_s *dev, + uint8_t offset, uint16_t value) +{ + putreg16(value, ((struct stm32_tim_priv_s *)dev)->base + offset); +} + +/* Modify a 16-bit register value by offset */ + +static inline void stm32_modifyreg16(struct stm32_tim_dev_s *dev, + uint8_t offset, uint16_t clearbits, + uint16_t setbits) +{ + modifyreg16(((struct stm32_tim_priv_s *)dev)->base + offset, clearbits, + setbits); +} + +/* Get a 32-bit register value by offset. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5. + */ + +static inline uint32_t stm32_getreg32(struct stm32_tim_dev_s *dev, + uint8_t offset) +{ + return getreg32(((struct stm32_tim_priv_s *)dev)->base + offset); +} + +/* Put a 32-bit register value by offset. This applies only for the STM32 F4 + * 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5. + */ + +static inline void stm32_putreg32(struct stm32_tim_dev_s *dev, + uint8_t offset, uint32_t value) +{ + putreg32(value, ((struct stm32_tim_priv_s *)dev)->base + offset); +} + +static void stm32_tim_reload_counter(struct stm32_tim_dev_s *dev) +{ + uint16_t val = stm32_getreg16(dev, STM32_GTIM_EGR_OFFSET); + val |= GTIM_EGR_UG; + stm32_putreg16(dev, STM32_GTIM_EGR_OFFSET, val); +} + +static void stm32_tim_enable(struct stm32_tim_dev_s *dev) +{ + uint16_t val = stm32_getreg16(dev, STM32_GTIM_CR1_OFFSET); + val |= GTIM_CR1_CEN; + stm32_tim_reload_counter(dev); + stm32_putreg16(dev, STM32_GTIM_CR1_OFFSET, val); +} + +static void stm32_tim_disable(struct stm32_tim_dev_s *dev) +{ + uint16_t val = stm32_getreg16(dev, STM32_GTIM_CR1_OFFSET); + val &= ~GTIM_CR1_CEN; + stm32_putreg16(dev, STM32_GTIM_CR1_OFFSET, val); +} + +/**************************************************************************** + * Name: stm32_tim_getwidth + ****************************************************************************/ + +static int stm32_tim_getwidth(struct stm32_tim_dev_s *dev) +{ + /* Only TIM2 and TIM5 timers may be 32-bits in width */ + + switch (((struct stm32_tim_priv_s *)dev)->base) + { +#if defined(CONFIG_STM32H5_TIM2) + case STM32_TIM2_BASE: + return 32; +#endif + +#if defined(CONFIG_STM32H5_TIM5) + case STM32_TIM5_BASE: + return 32; +#endif + + /* All others are 16-bit times */ + + default: + return 16; + } +} + +/**************************************************************************** + * Name: stm32_tim_getcounter + ****************************************************************************/ + +static uint32_t stm32_tim_getcounter(struct stm32_tim_dev_s *dev) +{ + DEBUGASSERT(dev != NULL); + return stm32_tim_getwidth(dev) > 16 ? + stm32_getreg32(dev, STM32_BTIM_CNT_OFFSET) : + (uint32_t)stm32_getreg16(dev, STM32_BTIM_CNT_OFFSET); +} + +/**************************************************************************** + * Name: stm32_tim_setcounter + ****************************************************************************/ + +static void stm32_tim_setcounter(struct stm32_tim_dev_s *dev, + uint32_t count) +{ + DEBUGASSERT(dev != NULL); + + if (stm32_tim_getwidth(dev) > 16) + { + stm32_putreg32(dev, STM32_BTIM_CNT_OFFSET, count); + } + else + { + stm32_putreg16(dev, STM32_BTIM_CNT_OFFSET, (uint16_t)count); + } +} + +/* Reset timer into system default state, but do not affect output/input + * pins + */ + +static void stm32_tim_reset(struct stm32_tim_dev_s *dev) +{ + ((struct stm32_tim_priv_s *)dev)->mode = STM32_TIM_MODE_DISABLED; + stm32_tim_disable(dev); +} + +#if defined(HAVE_TIM1_GPIOCONFIG)||defined(HAVE_TIM2_GPIOCONFIG)||\ + defined(HAVE_TIM3_GPIOCONFIG)||defined(HAVE_TIM4_GPIOCONFIG)||\ + defined(HAVE_TIM5_GPIOCONFIG)||defined(HAVE_TIM6_GPIOCONFIG)||\ + defined(HAVE_TIM7_GPIOCONFIG)||defined(HAVE_TIM8_GPIOCONFIG)||\ + defined(HAVE_TIM12_GPIOCONFIG)||defined(HAVE_TIM13_GPIOCONFIG)||\ + defined(HAVE_TIM14_GPIOCONFIG)||defined(HAVE_TIM15_GPIOCONFIG)||\ + defined(HAVE_TIM16_GPIOCONFIG)||defined(HAVE_TIM17_GPIOCONFIG) +static void stm32_tim_gpioconfig(uint32_t cfg, stm32_tim_channel_t mode) +{ + /* TODO: Add support for input capture and bipolar dual outputs for TIM8 */ + + if (mode & STM32_TIM_CH_MODE_MASK) + { + stm32_configgpio(cfg); + } + else + { + stm32_unconfiggpio(cfg); + } +} +#endif + +/**************************************************************************** + * Basic Functions + ****************************************************************************/ + +static int stm32_tim_setclock(struct stm32_tim_dev_s *dev, uint32_t freq) +{ + uint32_t freqin; + int prescaler; + + DEBUGASSERT(dev != NULL); + + /* Disable Timer? */ + + if (freq == 0) + { + stm32_tim_disable(dev); + return 0; + } + + /* Get the input clock frequency for this timer. These vary with + * different timer clock sources, MCU-specific timer configuration, and + * board-specific clock configuration. The correct input clock frequency + * must be defined in the board.h header file. + */ + + switch (((struct stm32_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32H5_TIM1 + case STM32_TIM1_BASE: + freqin = STM32_APB2_TIM1_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM2 + case STM32_TIM2_BASE: + freqin = STM32_APB1_TIM2_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM3 + case STM32_TIM3_BASE: + freqin = STM32_APB1_TIM3_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM4 + case STM32_TIM4_BASE: + freqin = STM32_APB1_TIM4_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM5 + case STM32_TIM5_BASE: + freqin = STM32_APB1_TIM5_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM6 + case STM32_TIM6_BASE: + freqin = STM32_APB1_TIM6_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM7 + case STM32_TIM7_BASE: + freqin = STM32_APB1_TIM7_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM8 + case STM32_TIM8_BASE: + freqin = STM32_APB2_TIM8_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM12 + case STM32_TIM12_BASE: + freqin = STM32_APB1_TIM12_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM13 + case STM32_TIM13_BASE: + freqin = STM32_APB1_TIM13_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM14 + case STM32_TIM14_BASE: + freqin = STM32_APB1_TIM14_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM15 + case STM32_TIM15_BASE: + freqin = STM32_APB2_TIM15_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM16 + case STM32_TIM16_BASE: + freqin = STM32_APB2_TIM16_CLKIN; + break; +#endif +#ifdef CONFIG_STM32H5_TIM17 + case STM32_TIM17_BASE: + freqin = STM32_APB2_TIM17_CLKIN; + break; +#endif + default: + return -EINVAL; + } + + /* Select a pre-scaler value for this timer using the input clock + * frequency. + */ + + prescaler = freqin / freq; + + /* We need to decrement value for '1', but only, if that will not to + * cause underflow. + */ + + if (prescaler > 0) + { + prescaler--; + } + + /* Check for overflow as well. */ + + if (prescaler > 0xffff) + { + prescaler = 0xffff; + } + + stm32_putreg16(dev, STM32_GTIM_PSC_OFFSET, prescaler); + stm32_tim_enable(dev); + + return prescaler; +} + +static void stm32_tim_setperiod(struct stm32_tim_dev_s *dev, + uint32_t period) +{ + DEBUGASSERT(dev != NULL); + stm32_putreg32(dev, STM32_GTIM_ARR_OFFSET, period); +} + +static int stm32_tim_setisr(struct stm32_tim_dev_s *dev, + xcpt_t handler, void *arg, int source) +{ + int vectorno; + + DEBUGASSERT(dev != NULL); + DEBUGASSERT(source == 0); + + switch (((struct stm32_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32H5_TIM1 + case STM32_TIM1_BASE: + vectorno = STM32_IRQ_TIM1_UP; + break; +#endif +#ifdef CONFIG_STM32H5_TIM2 + case STM32_TIM2_BASE: + vectorno = STM32_IRQ_TIM2; + break; +#endif +#ifdef CONFIG_STM32H5_TIM3 + case STM32_TIM3_BASE: + vectorno = STM32_IRQ_TIM3; + break; +#endif +#ifdef CONFIG_STM32H5_TIM4 + case STM32_TIM4_BASE: + vectorno = STM32_IRQ_TIM4; + break; +#endif +#ifdef CONFIG_STM32H5_TIM5 + case STM32_TIM5_BASE: + vectorno = STM32_IRQ_TIM5; + break; +#endif +#ifdef CONFIG_STM32H5_TIM6 + case STM32_TIM6_BASE: + vectorno = STM32_IRQ_TIM6; + break; +#endif +#ifdef CONFIG_STM32H5_TIM7 + case STM32_TIM7_BASE: + vectorno = STM32_IRQ_TIM7; + break; +#endif +#ifdef CONFIG_STM32H5_TIM8 + case STM32_TIM8_BASE: + vectorno = STM32_IRQ_TIM8_UP; + break; +#endif +#ifdef CONFIG_STM32H5_TIM12 + case STM32_TIM12_BASE: + vectorno = STM32_IRQ_TIM12; + break; +#endif +#ifdef CONFIG_STM32H5_TIM13 + case STM32_TIM13_BASE: + vectorno = STM32_IRQ_TIM13; + break; +#endif +#ifdef CONFIG_STM32H5_TIM14 + case STM32_TIM14_BASE: + vectorno = STM32_IRQ_TIM14; + break; +#endif +#ifdef CONFIG_STM32H5_TIM15 + case STM32_TIM15_BASE: + vectorno = STM32_IRQ_TIM15; + break; +#endif +#ifdef CONFIG_STM32H5_TIM16 + case STM32_TIM16_BASE: + vectorno = STM32_IRQ_TIM16; + break; +#endif +#ifdef CONFIG_STM32H5_TIM17 + case STM32_TIM17_BASE: + vectorno = STM32_IRQ_TIM17; + break; +#endif + + default: + return -EINVAL; + } + + /* Disable interrupt when callback is removed */ + + if (!handler) + { + up_disable_irq(vectorno); + irq_detach(vectorno); + return OK; + } + + /* Otherwise set callback and enable interrupt */ + + irq_attach(vectorno, handler, arg); + up_enable_irq(vectorno); + +#ifdef CONFIG_ARCH_IRQPRIO + /* Set the interrupt priority */ + + up_prioritize_irq(vectorno, NVIC_SYSH_PRIORITY_DEFAULT); +#endif + + return OK; +} + +static void stm32_tim_enableint(struct stm32_tim_dev_s *dev, int source) +{ + DEBUGASSERT(dev != NULL); + stm32_modifyreg16(dev, STM32_GTIM_DIER_OFFSET, 0, source); +} + +static void stm32_tim_disableint(struct stm32_tim_dev_s *dev, int source) +{ + DEBUGASSERT(dev != NULL); + stm32_modifyreg16(dev, STM32_GTIM_DIER_OFFSET, source, 0); +} + +static int stm32_tim_checkint(struct stm32_tim_dev_s *dev, int source) +{ + uint16_t regval = stm32_getreg16(dev, STM32_BTIM_SR_OFFSET); + return (regval & source) ? 1 : 0; +} + +static void stm32_tim_ackint(struct stm32_tim_dev_s *dev, int source) +{ + stm32_putreg16(dev, STM32_GTIM_SR_OFFSET, ~source); +} + +/**************************************************************************** + * General Functions + ****************************************************************************/ + +static int stm32_tim_setmode(struct stm32_tim_dev_s *dev, + stm32_tim_mode_t mode) +{ + uint16_t val = GTIM_CR1_CEN | GTIM_CR1_ARPE; + + DEBUGASSERT(dev != NULL); + + /* This function is not supported on basic timers. To enable or + * disable it, simply set its clock to valid frequency or zero. + */ + + if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM6_BASE || \ + ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM7_BASE) + { + return -EINVAL; + } + + /* Decode operational modes */ + + switch (mode & STM32_TIM_MODE_MASK) + { + case STM32_TIM_MODE_DISABLED: + val = 0; + break; + + case STM32_TIM_MODE_DOWN: + val |= GTIM_CR1_DIR; + + case STM32_TIM_MODE_UP: + break; + + case STM32_TIM_MODE_UPDOWN: + val |= GTIM_CR1_CENTER1; + + /* Our default: Interrupts are generated on compare, when counting + * down + */ + + break; + + case STM32_TIM_MODE_PULSE: + val |= GTIM_CR1_OPM; + break; + + default: + return -EINVAL; + } + + stm32_tim_reload_counter(dev); + stm32_putreg16(dev, STM32_GTIM_CR1_OFFSET, val); + + /* Advanced registers require Main Output Enable */ + + if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM1_BASE || + ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM8_BASE) + { + stm32_modifyreg16(dev, STM32_ATIM_BDTR_OFFSET, 0, ATIM_BDTR_MOE); + } + + return OK; +} + +static int stm32_tim_setchannel(struct stm32_tim_dev_s *dev, + uint8_t channel, stm32_tim_channel_t mode) +{ + uint16_t ccmr_orig = 0; + uint16_t ccmr_val = 0; + uint16_t ccmr_mask = 0xff; + uint16_t ccer_val = stm32_getreg16(dev, STM32_GTIM_CCER_OFFSET); + uint8_t ccmr_offset = STM32_GTIM_CCMR1_OFFSET; + + DEBUGASSERT(dev != NULL); + + /* Further we use range as 0..3; if channel=0 it will also overflow here */ + + if (--channel > 4) + { + return -EINVAL; + } + + /* Assume that channel is disabled and polarity is active high */ + + ccer_val &= ~(3 << GTIM_CCER_CCXBASE(channel)); + + /* This function is not supported on basic timers. To enable or + * disable it, simply set its clock to valid frequency or zero. + */ + + if (((struct stm32_tim_priv_s *)dev)->base == STM32_TIM6_BASE || \ + ((struct stm32_tim_priv_s *)dev)->base == STM32_TIM7_BASE) + { + return -EINVAL; + } + + /* Decode configuration */ + + switch (mode & STM32_TIM_CH_MODE_MASK) + { + case STM32_TIM_CH_DISABLED: + break; + + case STM32_TIM_CH_OUTTOGGLE: + ccmr_val = (GTIM_CCMR_MODE_OCREFTOG << GTIM_CCMR1_OC1M_SHIFT); + ccer_val |= GTIM_CCER_CC1E << GTIM_CCER_CCXBASE(channel); + break; + + case STM32_TIM_CH_OUTPWM: + ccmr_val = (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR1_OC1M_SHIFT) + + GTIM_CCMR1_OC1PE; + ccer_val |= GTIM_CCER_CC1E << GTIM_CCER_CCXBASE(channel); + break; + + default: + return -EINVAL; + } + + /* Set polarity */ + + if (mode & STM32_TIM_CH_POLARITY_NEG) + { + ccer_val |= GTIM_CCER_CC1P << GTIM_CCER_CCXBASE(channel); + } + + /* Define its position (shift) and get register offset */ + + if (channel & 1) + { + ccmr_val <<= 8; + ccmr_mask <<= 8; + } + + if (channel > 1) + { + ccmr_offset = STM32_GTIM_CCMR2_OFFSET; + } + + ccmr_orig = stm32_getreg16(dev, ccmr_offset); + ccmr_orig &= ~ccmr_mask; + ccmr_orig |= ccmr_val; + stm32_putreg16(dev, ccmr_offset, ccmr_orig); + stm32_putreg16(dev, STM32_GTIM_CCER_OFFSET, ccer_val); + + /* set GPIO */ + + switch (((struct stm32_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32H5_TIM1 + case STM32_TIM1_BASE: + switch (channel) + { +# if defined(GPIO_TIM1_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM1_CH1OUT, mode); break; +# endif +# if defined(GPIO_TIM1_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM1_CH2OUT, mode); break; +# endif +# if defined(GPIO_TIM1_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM1_CH3OUT, mode); break; +# endif +# if defined(GPIO_TIM1_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM1_CH4OUT, mode); break; +# endif +# if defined(GPIO_TIM1_CH5OUT) + case 4: + stm32_tim_gpioconfig(GPIO_TIM1_CH5OUT, mode); break; +# endif +# if defined(GPIO_TIM1_CH6OUT) + case 5: + stm32_tim_gpioconfig(GPIO_TIM1_CH6OUT, mode); break; +# endif + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32H5_TIM2 + case STM32_TIM2_BASE: + switch (channel) + { +# if defined(GPIO_TIM2_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM2_CH1OUT, mode); + break; +# endif +# if defined(GPIO_TIM2_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM2_CH2OUT, mode); + break; +# endif +# if defined(GPIO_TIM2_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM2_CH3OUT, mode); + break; +# endif +# if defined(GPIO_TIM2_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM2_CH4OUT, mode); + break; +#endif + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32H5_TIM3 + case STM32_TIM3_BASE: + switch (channel) + { +# if defined(GPIO_TIM3_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM3_CH1OUT, mode); + break; +# endif +# if defined(GPIO_TIM3_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM3_CH2OUT, mode); + break; +# endif +# if defined(GPIO_TIM3_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM3_CH3OUT, mode); + break; +# endif +# if defined(GPIO_TIM3_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM3_CH4OUT, mode); + break; +#endif + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32H5_TIM4 + case STM32_TIM4_BASE: + switch (channel) + { +# if defined(GPIO_TIM4_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM4_CH1OUT, mode); + break; +# endif +# if defined(GPIO_TIM4_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM4_CH2OUT, mode); + break; +# endif +# if defined(GPIO_TIM4_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM4_CH3OUT, mode); + break; +# endif +# if defined(GPIO_TIM4_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM4_CH4OUT, mode); + break; +# endif + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32H5_TIM5 + case STM32_TIM5_BASE: + switch (channel) + { +# if defined(GPIO_TIM5_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM5_CH1OUT, mode); + break; +# endif +# if defined(GPIO_TIM5_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM5_CH2OUT, mode); + break; +# endif +# if defined(GPIO_TIM5_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM5_CH3OUT, mode); + break; +# endif +# if defined(GPIO_TIM5_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM5_CH4OUT, mode); + break; +# endif + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32H5_TIM8 + case STM32_TIM8_BASE: + switch (channel) + { +# if defined(GPIO_TIM8_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM8_CH1OUT, mode); break; +# endif +# if defined(GPIO_TIM8_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM8_CH2OUT, mode); break; +# endif +# if defined(GPIO_TIM8_CH3OUT) + case 2: + stm32_tim_gpioconfig(GPIO_TIM8_CH3OUT, mode); break; +# endif +# if defined(GPIO_TIM8_CH4OUT) + case 3: + stm32_tim_gpioconfig(GPIO_TIM8_CH4OUT, mode); break; +# endif +# if defined(GPIO_TIM8_CH5OUT) + case 4: + stm32_tim_gpioconfig(GPIO_TIM8_CH5OUT, mode); break; +# endif +# if defined(GPIO_TIM8_CH6OUT) + case 5: + stm32_tim_gpioconfig(GPIO_TIM8_CH6OUT, mode); break; +# endif + default: + return -EINVAL; + } + break; +#endif + +#ifdef CONFIG_STM32H5_TIM12 + case STM32_TIM12_BASE: + switch (channel) + { +# if defined(GPIO_TIM12_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM12_CH1OUT, mode); + break; +# endif +# if defined(GPIO_TIM12_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM12_CH2OUT, mode); + break; +# endif + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32H5_TIM13 + case STM32_TIM13_BASE: + switch (channel) + { +# if defined(GPIO_TIM13_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM13_CH1OUT, mode); + break; +# endif + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32H5_TIM14 + case STM32_TIM14_BASE: + switch (channel) + { +# if defined(GPIO_TIM14_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM14_CH1OUT, mode); + break; +# endif + default: + return -EINVAL; + } + break; +#endif + +#ifdef CONFIG_STM32H5_TIM15 + case STM32_TIM15_BASE: + switch (channel) + { +# if defined(GPIO_TIM15_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM15_CH1OUT, mode); + break; +# endif +# if defined(GPIO_TIM15_CH2OUT) + case 1: + stm32_tim_gpioconfig(GPIO_TIM15_CH2OUT, mode); + break; +# endif + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32H5_TIM16 + case STM32_TIM16_BASE: + switch (channel) + { +# if defined(GPIO_TIM16_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM16_CH1OUT, mode); + break; +# endif + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32H5_TIM17 + case STM32_TIM17_BASE: + switch (channel) + { +# if defined(GPIO_TIM17_CH1OUT) + case 0: + stm32_tim_gpioconfig(GPIO_TIM17_CH1OUT, mode); + break; +# endif + default: + return -EINVAL; + } + break; +#endif + } + + return OK; +} + +static int stm32_tim_setcompare(struct stm32_tim_dev_s *dev, + uint8_t channel, uint32_t compare) +{ + DEBUGASSERT(dev != NULL); + + switch (channel) + { + case 1: + stm32_putreg32(dev, STM32_GTIM_CCR1_OFFSET, compare); + break; + + case 2: + stm32_putreg32(dev, STM32_GTIM_CCR2_OFFSET, compare); + break; + + case 3: + stm32_putreg32(dev, STM32_GTIM_CCR3_OFFSET, compare); + break; + + case 4: + stm32_putreg32(dev, STM32_GTIM_CCR4_OFFSET, compare); + break; + + default: + return -EINVAL; + } + + return OK; +} + +static int stm32_tim_getcapture(struct stm32_tim_dev_s *dev, + uint8_t channel) +{ + DEBUGASSERT(dev != NULL); + + switch (channel) + { + case 1: + return stm32_getreg32(dev, STM32_GTIM_CCR1_OFFSET); + + case 2: + return stm32_getreg32(dev, STM32_GTIM_CCR2_OFFSET); + + case 3: + return stm32_getreg32(dev, STM32_GTIM_CCR3_OFFSET); + + case 4: + return stm32_getreg32(dev, STM32_GTIM_CCR4_OFFSET); + } + + return -EINVAL; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +struct stm32_tim_dev_s *stm32_tim_init(int timer) +{ + struct stm32_tim_dev_s *dev = NULL; + + /* Get structure and enable power */ + + switch (timer) + { +#ifdef CONFIG_STM32H5_TIM1 + case 1: + dev = (struct stm32_tim_dev_s *)&stm32_tim1_priv; + modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM1EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM2 + case 2: + dev = (struct stm32_tim_dev_s *)&stm32_tim2_priv; + modifyreg32(STM32_RCC_APB1LENR, 0, RCC_APB1LENR_TIM2EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM3 + case 3: + dev = (struct stm32_tim_dev_s *)&stm32_tim3_priv; + modifyreg32(STM32_RCC_APB1LENR, 0, RCC_APB1LENR_TIM3EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM4 + case 4: + dev = (struct stm32_tim_dev_s *)&stm32_tim4_priv; + modifyreg32(STM32_RCC_APB1LENR, 0, RCC_APB1LENR_TIM4EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM5 + case 5: + dev = (struct stm32_tim_dev_s *)&stm32_tim5_priv; + modifyreg32(STM32_RCC_APB1LENR, 0, RCC_APB1LENR_TIM5EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM6 + case 6: + dev = (struct stm32_tim_dev_s *)&stm32_tim6_priv; + modifyreg32(STM32_RCC_APB1LENR, 0, RCC_APB1LENR_TIM6EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM7 + case 7: + dev = (struct stm32_tim_dev_s *)&stm32_tim7_priv; + modifyreg32(STM32_RCC_APB1LENR, 0, RCC_APB1LENR_TIM7EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM8 + case 8: + dev = (struct stm32_tim_dev_s *)&stm32_tim8_priv; + modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM8EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM12 + case 12: + dev = (struct stm32_tim_dev_s *)&stm32_tim12_priv; + modifyreg32(STM32_RCC_APB1LENR, 0, RCC_APB1LENR_TIM12EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM13 + case 13: + dev = (struct stm32_tim_dev_s *)&stm32_tim13_priv; + modifyreg32(STM32_RCC_APB1LENR, 0, RCC_APB1LENR_TIM13EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM14 + case 14: + dev = (struct stm32_tim_dev_s *)&stm32_tim14_priv; + modifyreg32(STM32_RCC_APB1LENR, 0, RCC_APB1LENR_TIM14EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM15 + case 15: + dev = (struct stm32_tim_dev_s *)&stm32_tim15_priv; + modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM15EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM16 + case 16: + dev = (struct stm32_tim_dev_s *)&stm32_tim16_priv; + modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM16EN); + break; +#endif +#ifdef CONFIG_STM32H5_TIM17 + case 17: + dev = (struct stm32_tim_dev_s *)&stm32_tim17_priv; + modifyreg32(STM32_RCC_APB2ENR, 0, RCC_APB2ENR_TIM17EN); + break; +#endif + default: + return NULL; + } + + /* Is device already allocated */ + + if (((struct stm32_tim_priv_s *)dev)->mode != STM32_TIM_MODE_UNUSED) + { + return NULL; + } + + stm32_tim_reset(dev); + + return dev; +} + +/* TODO: Detach interrupts, and close down all TIM Channels */ + +int stm32_tim_deinit(struct stm32_tim_dev_s * dev) +{ + DEBUGASSERT(dev != NULL); + + /* Disable power */ + + switch (((struct stm32_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32H5_TIM1 + case STM32_TIM1_BASE: + modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM1EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM2 + case STM32_TIM2_BASE: + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM2EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM3 + case STM32_TIM3_BASE: + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM3EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM4 + case STM32_TIM4_BASE: + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM4EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM5 + case STM32_TIM5_BASE: + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM5EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM6 + case STM32_TIM6_BASE: + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM6EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM7 + case STM32_TIM7_BASE: + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM7EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM8 + case STM32_TIM8_BASE: + modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM8EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM12 + case STM32_TIM12_BASE: + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM12EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM13 + case STM32_TIM13_BASE: + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM13EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM14 + case STM32_TIM14_BASE: + modifyreg32(STM32_RCC_APB1LENR, RCC_APB1LENR_TIM14EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM15 + case STM32_TIM15_BASE: + modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM15EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM16 + case STM32_TIM16_BASE: + modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM16EN, 0); + break; +#endif +#ifdef CONFIG_STM32H5_TIM17 + case STM32_TIM17_BASE: + modifyreg32(STM32_RCC_APB2ENR, RCC_APB2ENR_TIM17EN, 0); + break; +#endif + default: + return -EINVAL; + } + + /* Mark it as free */ + + ((struct stm32_tim_priv_s *)dev)->mode = STM32_TIM_MODE_UNUSED; + + return OK; +} + +#endif /* defined(CONFIG_STM32H5_TIM1 || ... || TIM17) */ diff --git a/arch/arm/src/stm32h5/stm32_tim.h b/arch/arm/src/stm32h5/stm32_tim.h new file mode 100644 index 0000000000000..b571fcb7159ba --- /dev/null +++ b/arch/arm/src/stm32h5/stm32_tim.h @@ -0,0 +1,223 @@ +/**************************************************************************** + * arch/arm/src/stm32h5/stm32_tim.h + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32H5_STM32_TIM_H +#define __ARCH_ARM_SRC_STM32H5_STM32_TIM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" +#include "hardware/stm32_tim.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helpers ******************************************************************/ + +#define STM32_TIM_ENABLE(d) ((d)->ops->enable(d)) +#define STM32_TIM_DISABLE(d) ((d)->ops->disable(d)) +#define STM32_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode)) +#define STM32_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq)) +#define STM32_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period)) +#define STM32_TIM_GETCOUNTER(d) ((d)->ops->getcounter(d)) +#define STM32_TIM_SETCOUNTER(d,c) ((d)->ops->setcounter(d,c)) +#define STM32_TIM_GETWIDTH(d) ((d)->ops->getwidth(d)) +#define STM32_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode)) +#define STM32_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp)) +#define STM32_TIM_GETCAPTURE(d,ch) ((d)->ops->getcapture(d,ch)) +#define STM32_TIM_SETISR(d,hnd,arg,s) ((d)->ops->setisr(d,hnd,arg,s)) +#define STM32_TIM_ENABLEINT(d,s) ((d)->ops->enableint(d,s)) +#define STM32_TIM_DISABLEINT(d,s) ((d)->ops->disableint(d,s)) +#define STM32_TIM_ACKINT(d,s) ((d)->ops->ackint(d,s)) +#define STM32_TIM_CHECKINT(d,s) ((d)->ops->checkint(d,s)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* TIM Device Structure */ + +struct stm32_tim_dev_s +{ + struct stm32_tim_ops_s *ops; +}; + +/* TIM Modes of Operation */ + +typedef enum +{ + STM32_TIM_MODE_UNUSED = -1, + + /* One of the following */ + + STM32_TIM_MODE_MASK = 0x0310, + STM32_TIM_MODE_DISABLED = 0x0000, + STM32_TIM_MODE_UP = 0x0100, + STM32_TIM_MODE_DOWN = 0x0110, + STM32_TIM_MODE_UPDOWN = 0x0200, + STM32_TIM_MODE_PULSE = 0x0300, + + /* One of the following */ + + STM32_TIM_MODE_CK_INT = 0x0000, +#if 0 + STM32_TIM_MODE_CK_INT_TRIG = 0x0400, + STM32_TIM_MODE_CK_EXT = 0x0800, + STM32_TIM_MODE_CK_EXT_TRIG = 0x0c00, + + /* Clock sources, OR'ed with CK_EXT */ + + STM32_TIM_MODE_CK_CHINVALID = 0x0000, + STM32_TIM_MODE_CK_CH1 = 0x0001, + STM32_TIM_MODE_CK_CH2 = 0x0002, + STM32_TIM_MODE_CK_CH3 = 0x0003, + STM32_TIM_MODE_CK_CH4 = 0x0004 +#endif + + /* Todo: external trigger block */ +} stm32_tim_mode_t; + +/* TIM Channel Modes */ + +typedef enum +{ + STM32_TIM_CH_DISABLED = 0x00, + + /* Common configuration */ + + STM32_TIM_CH_POLARITY_POS = 0x00, + STM32_TIM_CH_POLARITY_NEG = 0x01, + + /* MODES: */ + + STM32_TIM_CH_MODE_MASK = 0x0e, + + /* Output Compare Modes */ + + /* Enable standard PWM mode, active high when counter < compare */ + + STM32_TIM_CH_OUTPWM = 0x04, + + /* Toggle TIM_CHx output on UEV */ + + STM32_TIM_CH_OUTTOGGLE = 0x08, +#if 0 + STM32_TIM_CH_OUTCOMPARE = 0x06, + + /* TODO other modes ... as PWM capture, ENCODER and Hall Sensor */ + + STM32_TIM_CH_INCAPTURE = 0x10, + STM32_TIM_CH_INPWM = 0x20 + STM32_TIM_CH_DRIVE_OC - open collector mode +#endif +} stm32_tim_channel_t; + +/* TIM Operations */ + +struct stm32_tim_ops_s +{ + /* Basic Timers */ + + void (*enable)(struct stm32_tim_dev_s *dev); + void (*disable)(struct stm32_tim_dev_s *dev); + int (*setmode)(struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode); + int (*setclock)(struct stm32_tim_dev_s *dev, uint32_t freq); + void (*setperiod)(struct stm32_tim_dev_s *dev, uint32_t period); + uint32_t (*getcounter)(struct stm32_tim_dev_s *dev); + void (*setcounter)(struct stm32_tim_dev_s *dev, uint32_t count); + + /* General and Advanced Timers Adds */ + + int (*getwidth)(struct stm32_tim_dev_s *dev); + int (*setchannel)(struct stm32_tim_dev_s *dev, uint8_t channel, + stm32_tim_channel_t mode); + int (*setcompare)(struct stm32_tim_dev_s *dev, uint8_t channel, + uint32_t compare); + int (*getcapture)(struct stm32_tim_dev_s *dev, uint8_t channel); + + /* Timer interrupts */ + + int (*setisr)(struct stm32_tim_dev_s *dev, xcpt_t handler, void *arg, + int source); + void (*enableint)(struct stm32_tim_dev_s *dev, int source); + void (*disableint)(struct stm32_tim_dev_s *dev, int source); + void (*ackint)(struct stm32_tim_dev_s *dev, int source); + int (*checkint)(struct stm32_tim_dev_s *dev, int source); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Power-up timer and get its structure */ + +struct stm32_tim_dev_s *stm32_tim_init(int timer); + +/* Power-down timer, mark it as unused */ + +int stm32_tim_deinit(struct stm32_tim_dev_s *dev); + +/**************************************************************************** + * Name: stm32_timer_initialize + * + * Description: + * Bind the configuration timer to a timer lower half instance and + * register the timer drivers at 'devpath' + * + * Input Parameters: + * devpath - The full path to the timer device. This should be of the + * form /dev/timer0 + * timer - the timer number. + * + * Returned Values: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_TIMER +int stm32_timer_initialize(const char *devpath, int timer); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32H5_STM32_TIM_H */ diff --git a/arch/arm/src/stm32h5/stm32_tim_lowerhalf.c b/arch/arm/src/stm32h5/stm32_tim_lowerhalf.c new file mode 100644 index 0000000000000..b31f6771216e3 --- /dev/null +++ b/arch/arm/src/stm32h5/stm32_tim_lowerhalf.c @@ -0,0 +1,586 @@ +/**************************************************************************** + * arch/arm/src/stm32h5/stm32_tim_lowerhalf.c + * + * SPDX-License-Identifier: BSD-3-Clause + * SPDX-FileCopyrightText: 2023 Max Kriegleder. All rights reserved. + * SPDX-FileCopyrightText: 2015 Wail Khemir. All rights reserved. + * SPDX-FileCopyrightText: 2015 Omni Hoverboards Inc. All rights reserved. + * SPDX-FileContributor: Wail Khemir + * SPDX-FileContributor: Paul Alexander Patience + * SPDX-FileContributor: Max Kriegleder + * + * 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 "stm32_tim.h" + +#if defined(CONFIG_TIMER) && \ + (defined(CONFIG_STM32H5_TIM1) || defined(CONFIG_STM32H5_TIM2) || \ + defined(CONFIG_STM32H5_TIM3) || defined(CONFIG_STM32H5_TIM4) || \ + defined(CONFIG_STM32H5_TIM5) || defined(CONFIG_STM32H5_TIM6) || \ + defined(CONFIG_STM32H5_TIM7) || defined(CONFIG_STM32H5_TIM8) || \ + defined(CONFIG_STM32H5_TIM12) || defined(CONFIG_STM32H5_TIM13) || \ + defined(CONFIG_STM32H5_TIM14) || defined(CONFIG_STM32H5_TIM15) || \ + defined(CONFIG_STM32H5_TIM16) || defined(CONFIG_STM32H5_TIM17)) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define STM32_TIM1_RES 16 +#define STM32_TIM2_RES 32 +#define STM32_TIM3_RES 16 +#define STM32_TIM4_RES 16 +#define STM32_TIM5_RES 32 +#define STM32_TIM6_RES 16 +#define STM32_TIM7_RES 16 +#define STM32_TIM8_RES 16 +#define STM32_TIM12_RES 16 +#define STM32_TIM13_RES 16 +#define STM32_TIM14_RES 16 +#define STM32_TIM15_RES 16 +#define STM32_TIM16_RES 16 +#define STM32_TIM17_RES 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * timer_lowerhalf_s structure. + */ + +struct stm32_lowerhalf_s +{ + const struct timer_ops_s *ops; /* Lower half operations */ + struct stm32_tim_dev_s *tim; /* stm32 timer driver */ + tccb_t callback; /* Current user interrupt callback */ + void *arg; /* Argument passed to upper half callback */ + bool started; /* True: Timer has been started */ + const uint8_t resolution; /* Number of bits in the timer (16 or 32 bits) */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int stm32_timer_handler(int irq, void * context, void * arg); + +/* "Lower half" driver methods **********************************************/ + +static int stm32_start(struct timer_lowerhalf_s *lower); +static int stm32_stop(struct timer_lowerhalf_s *lower); +static int stm32_settimeout(struct timer_lowerhalf_s *lower, + uint32_t timeout); +static void stm32_setcallback(struct timer_lowerhalf_s *lower, + tccb_t callback, void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct timer_ops_s g_timer_ops = +{ + .start = stm32_start, + .stop = stm32_stop, + .getstatus = NULL, + .settimeout = stm32_settimeout, + .setcallback = stm32_setcallback, + .ioctl = NULL, +}; + +#ifdef CONFIG_STM32H5_TIM1 +static struct stm32_lowerhalf_s g_tim1_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM1_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM2 +static struct stm32_lowerhalf_s g_tim2_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM2_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM3 +static struct stm32_lowerhalf_s g_tim3_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM3_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM4 +static struct stm32_lowerhalf_s g_tim4_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM4_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM5 +static struct stm32_lowerhalf_s g_tim5_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM5_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM6 +static struct stm32_lowerhalf_s g_tim6_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM6_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM7 +static struct stm32_lowerhalf_s g_tim7_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM7_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM8 +static struct stm32_lowerhalf_s g_tim8_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM8_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM12 +static struct stm32_lowerhalf_s g_tim12_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM12_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM13 +static struct stm32_lowerhalf_s g_tim13_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM13_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM14 +static struct stm32_lowerhalf_s g_tim14_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM14_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM15 +static struct stm32_lowerhalf_s g_tim15_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM15_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM16 +static struct stm32_lowerhalf_s g_tim16_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM16_RES, +}; +#endif + +#ifdef CONFIG_STM32H5_TIM17 +static struct stm32_lowerhalf_s g_tim17_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32_TIM17_RES, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_timer_handler + * + * Description: + * timer interrupt handler + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int stm32_timer_handler(int irq, void * context, void * arg) +{ + struct stm32_lowerhalf_s *lower = (struct stm32_lowerhalf_s *) arg; + uint32_t next_interval_us = 0; + + STM32_TIM_ACKINT(lower->tim, ATIM_DIER_UIE); + + if (lower->callback(&next_interval_us, lower->arg)) + { + if (next_interval_us > 0) + { + STM32_TIM_SETPERIOD(lower->tim, next_interval_us); + } + } + else + { + stm32_stop((struct timer_lowerhalf_s *)lower); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_start + * + * Description: + * Start the timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_start(struct timer_lowerhalf_s *lower) +{ + struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower; + + if (!priv->started) + { + STM32_TIM_SETMODE(priv->tim, STM32_TIM_MODE_UP); + + if (priv->callback != NULL) + { + STM32_TIM_SETISR(priv->tim, stm32_timer_handler, priv, 0); + STM32_TIM_ENABLEINT(priv->tim, ATIM_DIER_UIE); + } + + priv->started = true; + return OK; + } + + /* Return EBUSY to indicate that the timer was already running */ + + return -EBUSY; +} + +/**************************************************************************** + * Name: stm32_stop + * + * Description: + * Stop the timer + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_stop(struct timer_lowerhalf_s *lower) +{ + struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower; + + if (priv->started) + { + STM32_TIM_SETMODE(priv->tim, STM32_TIM_MODE_DISABLED); + STM32_TIM_DISABLEINT(priv->tim, ATIM_DIER_UIE); + STM32_TIM_SETISR(priv->tim, NULL, NULL, 0); + priv->started = false; + return OK; + } + + /* Return ENODEV to indicate that the timer was not running */ + + return -ENODEV; +} + +/**************************************************************************** + * Name: stm32_settimeout + * + * Description: + * Set a new timeout value (and reset the timer) + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * timeout - The new timeout value in microseconds. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32_settimeout(struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower; + uint64_t maxtimeout; + + if (priv->started) + { + return -EPERM; + } + + maxtimeout = (1 << priv->resolution) - 1; + if (timeout > maxtimeout) + { + uint64_t freq = (maxtimeout * 1000000) / timeout; + STM32_TIM_SETCLOCK(priv->tim, freq); + STM32_TIM_SETPERIOD(priv->tim, maxtimeout); + } + else + { + STM32_TIM_SETCLOCK(priv->tim, 1000000); + STM32_TIM_SETPERIOD(priv->tim, timeout); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32_setcallback + * + * Description: + * Call this user provided timeout callback. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * callback - The new timer expiration function pointer. If this + * function pointer is NULL, then the reset-on-expiration + * behavior is restored, + * arg - Argument that will be provided in the callback + * + * Returned Value: + * The previous timer expiration function pointer or NULL is there was + * no previous function pointer. + * + ****************************************************************************/ + +static void stm32_setcallback(struct timer_lowerhalf_s *lower, + tccb_t callback, void *arg) +{ + struct stm32_lowerhalf_s *priv = (struct stm32_lowerhalf_s *)lower; + + irqstate_t flags = enter_critical_section(); + + /* Save the new callback */ + + priv->callback = callback; + priv->arg = arg; + + if (callback != NULL && priv->started) + { + STM32_TIM_SETISR(priv->tim, stm32_timer_handler, priv, 0); + STM32_TIM_ENABLEINT(priv->tim, ATIM_DIER_UIE); + } + else + { + STM32_TIM_DISABLEINT(priv->tim, ATIM_DIER_UIE); + STM32_TIM_SETISR(priv->tim, NULL, NULL, 0); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32_timer_initialize + * + * Description: + * Bind the configuration timer to a timer lower half instance and + * register the timer drivers at 'devpath' + * + * Input Parameters: + * devpath - The full path to the timer device. This should be of the + * form /dev/timer0 + * timer - the timer's number. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int stm32_timer_initialize(const char *devpath, int timer) +{ + struct stm32_lowerhalf_s *lower; + + switch (timer) + { +#ifdef CONFIG_STM32H5_TIM1 + case 1: + lower = &g_tim1_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM2 + case 2: + lower = &g_tim2_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM3 + case 3: + lower = &g_tim3_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM4 + case 4: + lower = &g_tim4_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM5 + case 5: + lower = &g_tim5_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM6 + case 6: + lower = &g_tim6_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM7 + case 7: + lower = &g_tim7_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM8 + case 8: + lower = &g_tim8_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM12 + case 12: + lower = &g_tim12_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM13 + case 13: + lower = &g_tim13_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32H5_TIM14 + case 14: + lower = &g_tim14_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32H5_TIM15 + case 15: + lower = &g_tim15_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32H5_TIM16 + case 16: + lower = &g_tim16_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32H5_TIM17 + case 17: + lower = &g_tim17_lowerhalf; + break; +#endif + + default: + return -ENODEV; + } + + /* Initialize the elements of lower half state structure */ + + lower->started = false; + lower->callback = NULL; + lower->tim = stm32_tim_init(timer); + + if (lower->tim == NULL) + { + return -EINVAL; + } + + /* Register the timer driver as /dev/timerX. The returned value from + * timer_register is a handle that could be used with timer_unregister(). + * REVISIT: The returned handle is discard here. + */ + + void *drvr = timer_register(devpath, + (struct timer_lowerhalf_s *)lower); + if (drvr == NULL) + { + /* The actual cause of the failure may have been a failure to allocate + * perhaps a failure to register the timer driver (such as if the + * 'depath' were not unique). We know here but we return EEXIST to + * indicate the failure (implying the non-unique devpath). + */ + + return -EEXIST; + } + + return OK; +} + +#endif /* CONFIG_TIMER */ diff --git a/arch/arm/src/stm32h5/stm32h5xx_rcc.c b/arch/arm/src/stm32h5/stm32h5xx_rcc.c index 18a051341ec44..b01905edb3c2b 100644 --- a/arch/arm/src/stm32h5/stm32h5xx_rcc.c +++ b/arch/arm/src/stm32h5/stm32h5xx_rcc.c @@ -355,60 +355,6 @@ static inline void rcc_enableapb1l(void) regval = getreg32(STM32_RCC_APB1LENR); -#ifdef CONFIG_STM32H5_TIM2 - /* Bit 0: TIM2 clock enable */ - - regval |= RCC_APB1LENR_TIM2EN; -#endif - -#ifdef CONFIG_STM32H5_TIM3 - /* Bit 1: TIM3 clock enable */ - - regval |= RCC_APB1LENR_TIM3EN; -#endif - -#ifdef CONFIG_STM32H5_TIM4 - /* Bit 2: TIM4 clock enable */ - - regval |= RCC_APB1LENR_TIM4EN; -#endif - -#ifdef CONFIG_STM32H5_TIM5 - /* Bit 3: TIM5 clock enable */ - - regval |= RCC_APB1LENR_TIM5EN; -#endif - -#ifdef CONFIG_STM32H5_TIM6 - /* Bit 4: TIM6 clock enable */ - - regval |= RCC_APB1LENR_TIM6EN; -#endif - -#ifdef CONFIG_STM32H5_TIM7 - /* Bit 5: TIM7 clock enable */ - - regval |= RCC_APB1LENR_TIM7EN; -#endif - -#ifdef CONFIG_STM32H5_TIM12 - /* Bit 5: TIM12 clock enable */ - - regval |= RCC_APB1LENR_TIM12EN; -#endif - -#ifdef CONFIG_STM32H5_TIM13 - /* Bit 5: TIM13 clock enable */ - - regval |= RCC_APB1LENR_TIM13EN; -#endif - -#ifdef CONFIG_STM32H5_TIM14 - /* Bit 5: TIM14 clock enable */ - - regval |= RCC_APB1LENR_TIM14EN; -#endif - #ifdef CONFIG_STM32H5_SPI2 /* Bit 14: SPI2 clock enable */ @@ -588,48 +534,18 @@ static inline void rcc_enableapb2(void) regval = getreg32(STM32_RCC_APB2ENR); -#ifdef CONFIG_STM32H5_TIM1 - /* TIM1 clock enable */ - - regval |= RCC_APB2ENR_TIM1EN; -#endif - #ifdef CONFIG_STM32H5_SPI1 /* SPI1 clock enable */ regval |= RCC_APB2ENR_SPI1EN; #endif -#ifdef CONFIG_STM32H5_TIM8 - /* TIM8 clock enable */ - - regval |= RCC_APB2ENR_TIM8EN; -#endif - #ifdef CONFIG_STM32H5_USART1 /* USART1 clock enable */ regval |= RCC_APB2ENR_USART1EN; #endif -#ifdef CONFIG_STM32H5_TIM15 - /* TIM15 clock enable */ - - regval |= RCC_APB2ENR_TIM15EN; -#endif - -#ifdef CONFIG_STM32H5_TIM16 - /* TIM16 clock enable */ - - regval |= RCC_APB2ENR_TIM16EN; -#endif - -#ifdef CONFIG_STM32H5_TIM17 - /* TIM17 clock enable */ - - regval |= RCC_APB2ENR_TIM17EN; -#endif - #ifdef CONFIG_STM32H5_SPI4 /* SPI4 clock enable */ diff --git a/arch/arm64/include/irq.h b/arch/arm64/include/irq.h index d3e1ece7f80f1..7467691a288a4 100644 --- a/arch/arm64/include/irq.h +++ b/arch/arm64/include/irq.h @@ -153,10 +153,11 @@ #define REG_SPSR (33) #define REG_SP_EL0 (34) #define REG_EXE_DEPTH (35) +#define REG_SCTLR_EL1 (36) /* In Armv8-A Architecture, the stack must align with 16 byte */ -#define ARM64_CONTEXT_REGS (36) +#define ARM64_CONTEXT_REGS (37) #define ARM64_CONTEXT_SIZE (8 * ARM64_CONTEXT_REGS) #ifdef CONFIG_ARCH_FPU diff --git a/arch/arm64/src/common/arm64_initialstate.c b/arch/arm64/src/common/arm64_initialstate.c index bc51df5750d90..ff2d9c5cffc48 100644 --- a/arch/arm64/src/common/arm64_initialstate.c +++ b/arch/arm64/src/common/arm64_initialstate.c @@ -86,6 +86,11 @@ void arm64_new_task(struct tcb_s * tcb) xcp->regs[REG_SPSR] = SPSR_MODE_EL1H; #endif + xcp->regs[REG_SCTLR_EL1] = read_sysreg(sctlr_el1); +#ifdef CONFIG_ARM64_MTE + xcp->regs[REG_SCTLR_EL1] |= SCTLR_TCF1_BIT; +#endif + #ifdef CONFIG_SUPPRESS_INTERRUPTS xcp->regs[REG_SPSR] |= (DAIF_IRQ_BIT | DAIF_FIQ_BIT); #endif /* CONFIG_SUPPRESS_INTERRUPTS */ diff --git a/arch/arm64/src/common/arm64_vector_table.S b/arch/arm64/src/common/arm64_vector_table.S index e98bd9b0baa34..a159bac2cf035 100644 --- a/arch/arm64/src/common/arm64_vector_table.S +++ b/arch/arm64/src/common/arm64_vector_table.S @@ -80,16 +80,17 @@ #endif stp \xreg0, \xreg1, [sp, #8 * REG_ELR] + mrs \xreg0, sctlr_el1 + str \xreg0, [sp, #8 * REG_SCTLR_EL1] + mrs \xreg0, sp_el0 mrs \xreg1, tpidrro_el0 - stp \xreg0, \xreg1, [sp, #8 * REG_SP_EL0] + stp \xreg0, \xreg1, [sp, #8 * REG_SP_EL0] /* Increment exception depth */ - mrs \xreg0, tpidrro_el0 - mov \xreg1, #1 - add \xreg0, \xreg0, \xreg1 - msr tpidrro_el0, \xreg0 + add \xreg1, \xreg1, #1 + msr tpidrro_el0, \xreg1 /* Save the FPU registers */ @@ -268,6 +269,9 @@ SECTION_FUNC(text, arm64_exit_exception) msr spsr_el1, x1 #endif + ldr x0, [sp, #8 * REG_SCTLR_EL1] + msr sctlr_el1, x0 + ldp x0, x1, [sp, #8 * REG_SP_EL0] msr sp_el0, x0 msr tpidrro_el0, x1 diff --git a/arch/arm64/src/common/arm64_vectors.S b/arch/arm64/src/common/arm64_vectors.S index bbc904b586133..a18e0a9838249 100644 --- a/arch/arm64/src/common/arm64_vectors.S +++ b/arch/arm64/src/common/arm64_vectors.S @@ -84,6 +84,9 @@ SECTION_FUNC(text, up_saveusercontext) #endif stp x4, x5, [x0, #8 * REG_ELR] + mrs x4, sctlr_el1 + str x4, [x0, #8 * REG_SCTLR_EL1] + ret /**************************************************************************** @@ -115,6 +118,8 @@ SECTION_FUNC(text, arm64_jump_to_user) and x0, x0, #~SPSR_MODE_MASK #orr x0, x0, #SPSR_MODE_EL0T # EL0T=0x00, out of range for orr str x0, [sp, #8 * REG_SPSR] + mrs x0, sctlr_el1 + str x0, [sp, #8 * REG_SCTLR_EL1] b arm64_exit_exception #endif diff --git a/arch/arm64/src/imx9/imx9_gpio.c b/arch/arm64/src/imx9/imx9_gpio.c index 5f6fe2d0fbd36..084cac7852ebd 100644 --- a/arch/arm64/src/imx9/imx9_gpio.c +++ b/arch/arm64/src/imx9/imx9_gpio.c @@ -33,6 +33,7 @@ #include #include +#include #include @@ -45,6 +46,10 @@ * Private Functions ****************************************************************************/ +/* Spinlock */ + +static spinlock_t g_gpio_lock = SP_UNLOCKED; + /**************************************************************************** * Name: imx9_gpio_dirout ****************************************************************************/ @@ -174,7 +179,7 @@ int imx9_config_gpio(gpio_pinset_t pinset) /* Configure the pin as an input initially to avoid any spurious outputs */ - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); /* Configure based upon the pin mode */ @@ -223,7 +228,7 @@ int imx9_config_gpio(gpio_pinset_t pinset) break; } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); return ret; } @@ -243,9 +248,9 @@ void imx9_gpio_write(gpio_pinset_t pinset, bool value) DEBUGASSERT((unsigned int)port < IMX9_GPIO_NPORTS); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); imx9_gpio_setoutput(port, pin, value); - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); } /**************************************************************************** @@ -265,7 +270,7 @@ bool imx9_gpio_read(gpio_pinset_t pinset) DEBUGASSERT((unsigned int)port < IMX9_GPIO_NPORTS); - flags = enter_critical_section(); + flags = spin_lock_irqsave(&g_gpio_lock); if ((pinset & (GPIO_OUTPUT)) == (GPIO_OUTPUT)) { value = imx9_gpio_get_pinstatus(port, pin); @@ -275,6 +280,6 @@ bool imx9_gpio_read(gpio_pinset_t pinset) value = imx9_gpio_getinput(port, pin); } - leave_critical_section(flags); + spin_unlock_irqrestore(&g_gpio_lock, flags); return value; } diff --git a/arch/arm64/src/imx9/imx9_lpi2c.c b/arch/arm64/src/imx9/imx9_lpi2c.c index cc04c0d6aa951..04585a6f6323a 100644 --- a/arch/arm64/src/imx9/imx9_lpi2c.c +++ b/arch/arm64/src/imx9/imx9_lpi2c.c @@ -2438,7 +2438,7 @@ int imx9_i2cbus_uninitialize(struct i2c_master_s *dev) if (--priv->refs > 0) { - leave_critical_section(flags); + spin_unlock_irqrestore(&priv->spinlock, flags); return OK; } diff --git a/arch/arm64/src/imx9/imx9_lpspi.c b/arch/arm64/src/imx9/imx9_lpspi.c index 0dd6af7fc2c6f..0a2e6e10919c4 100644 --- a/arch/arm64/src/imx9/imx9_lpspi.c +++ b/arch/arm64/src/imx9/imx9_lpspi.c @@ -1798,8 +1798,6 @@ struct spi_dev_s *imx9_lpspibus_initialize(int bus) { struct imx9_lpspidev_s *priv = NULL; - irqstate_t flags = enter_critical_section(); - #ifdef CONFIG_IMX9_LPSPI1 if (bus == 1) { @@ -2017,7 +2015,6 @@ struct spi_dev_s *imx9_lpspibus_initialize(int bus) else #endif { - leave_critical_section(flags); spierr("ERROR: Unsupported SPI bus: %d\n", bus); return NULL; } @@ -2061,7 +2058,6 @@ struct spi_dev_s *imx9_lpspibus_initialize(int bus) } #endif - leave_critical_section(flags); return (struct spi_dev_s *)priv; } diff --git a/arch/arm64/src/imx9/imx9_usbdev.c b/arch/arm64/src/imx9/imx9_usbdev.c index 3488f4b4eeaab..38c6416ad2402 100644 --- a/arch/arm64/src/imx9/imx9_usbdev.c +++ b/arch/arm64/src/imx9/imx9_usbdev.c @@ -2319,9 +2319,9 @@ static int imx9_epdisable(struct usbdev_ep_s *ep) /* Cancel any ongoing activity */ - spin_unlock_irqrestore(&privep->spinlock, flags); + imx9_cancelrequests(privep, -ESHUTDOWN); - leave_critical_section(flags); + spin_unlock_irqrestore(&privep->spinlock, flags); return OK; } diff --git a/arch/x86_64/src/intel64/intel64_tsc_tickless.c b/arch/x86_64/src/intel64/intel64_tsc_tickless.c index 2e417443304e0..4ec709ffef85b 100644 --- a/arch/x86_64/src/intel64/intel64_tsc_tickless.c +++ b/arch/x86_64/src/intel64/intel64_tsc_tickless.c @@ -57,6 +57,7 @@ #include #include +#include #ifdef CONFIG_SCHED_TICKLESS @@ -90,6 +91,7 @@ static uint32_t g_timer_active; static irqstate_t g_tmr_sync_count; static irqstate_t g_tmr_flags; +static spinlock_t g_tmr_lock = SP_UNLOCKED; /**************************************************************************** * Private Functions @@ -161,7 +163,7 @@ static inline void up_tmr_sync_up(void) { if (!g_tmr_sync_count) { - g_tmr_flags = enter_critical_section(); + g_tmr_flags = spin_lock_irqsave(&g_tmr_lock); } g_tmr_sync_count++; @@ -171,7 +173,7 @@ static inline void up_tmr_sync_down(void) { if (g_tmr_sync_count == 1) { - leave_critical_section(g_tmr_flags); + spin_unlock_irqrestore(&g_tmr_lock, g_tmr_flags); } if (g_tmr_sync_count > 0) diff --git a/boards/risc-v/esp32c6/esp32c6-devkitm/src/esp32c6_gpio.c b/boards/risc-v/esp32c6/esp32c6-devkitm/src/esp32c6_gpio.c index 4a7f3f4a59070..f4c02a4e0a3fc 100644 --- a/boards/risc-v/esp32c6/esp32c6-devkitm/src/esp32c6_gpio.c +++ b/boards/risc-v/esp32c6/esp32c6-devkitm/src/esp32c6_gpio.c @@ -484,7 +484,7 @@ int esp_gpio_init(void) /* Configure the pins that will be used as output */ esp_gpio_matrix_out(g_gpiooutputs[i], SIG_GPIO_OUT_IDX, 0, 0); - esp_configgpio(g_gpiooutputs[i], OUTPUT_FUNCTION_1 | INPUT_FUNCTION_1); + esp_configgpio(g_gpiooutputs[i], OUTPUT_FUNCTION_2 | INPUT_FUNCTION_2); esp_gpiowrite(g_gpiooutputs[i], 0); pincount++; @@ -503,7 +503,7 @@ int esp_gpio_init(void) /* Configure the pins that will be used as interrupt input */ - esp_configgpio(g_gpiointinputs[i], INPUT_FUNCTION_1 | PULLDOWN); + esp_configgpio(g_gpiointinputs[i], INPUT_FUNCTION_2 | PULLDOWN); pincount++; } diff --git a/boards/risc-v/qemu-rv/rv-virt/configs/citest64/defconfig b/boards/risc-v/qemu-rv/rv-virt/configs/citest64/defconfig index 3f0e9db20e14a..4a61f056a2ccb 100644 --- a/boards/risc-v/qemu-rv/rv-virt/configs/citest64/defconfig +++ b/boards/risc-v/qemu-rv/rv-virt/configs/citest64/defconfig @@ -76,6 +76,7 @@ CONFIG_START_YEAR=2021 CONFIG_SYMTAB_ORDEREDBYNAME=y CONFIG_SYSTEM_NSH=y CONFIG_SYSTEM_POPEN=y +CONFIG_SYSTEM_POPEN_STACKSIZE=3072 CONFIG_TESTING_GETPRIME=y CONFIG_TESTING_MM=y CONFIG_TESTING_OSTEST=y diff --git a/drivers/usbdev/cdcacm.c b/drivers/usbdev/cdcacm.c index 403ad6e230c89..d3cc8a5ad383c 100644 --- a/drivers/usbdev/cdcacm.c +++ b/drivers/usbdev/cdcacm.c @@ -2618,6 +2618,13 @@ static bool cdcuart_txempty(FAR struct uart_dev_s *dev) #endif flags = enter_critical_section(); + + if (dev->disconnected) + { + leave_critical_section(flags); + return true; + } + priv->ispolling = true; EP_POLL(ep); priv->ispolling = false; @@ -3012,6 +3019,10 @@ void cdcacm_uninitialize(FAR struct usbdevclass_driver_s *classdev) char devname[CDCACM_DEVNAME_SIZE]; int ret; + /* Disconnect in case we are connected */ + + cdcacm_disconnect(classdev, priv->usbdev); + #ifndef CONFIG_CDCACM_COMPOSITE usbdev_unregister(&drvr->drvr); #endif