From be0d6266419df73737ad41d8fc876a4ea216da18 Mon Sep 17 00:00:00 2001 From: Liam Howatt Date: Fri, 18 Sep 2026 16:26:30 -0400 Subject: [PATCH 1/4] arch/arm/stm32h5: Fix duplicate define STM32_OTP_BASE. STM32_OTP_BASE was defined independently in two separate contributions. Remove one. Signed-off-by: Liam Howatt --- arch/arm/src/stm32h5/hardware/stm32h5xxx_memorymap.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm/src/stm32h5/hardware/stm32h5xxx_memorymap.h b/arch/arm/src/stm32h5/hardware/stm32h5xxx_memorymap.h index d1e19f693d300..d36327ea3d231 100644 --- a/arch/arm/src/stm32h5/hardware/stm32h5xxx_memorymap.h +++ b/arch/arm/src/stm32h5/hardware/stm32h5xxx_memorymap.h @@ -65,10 +65,6 @@ #define STM32_SYSMEM_FSIZE 0x08FFF80C /* Size of Flash memory in Kbytes. */ #define STM32_SYSMEM_PACKAGE 0x08FFF80E /* Indicates the device's package type. */ -/* OTP Base Addresses *******************************************************/ - -#define STM32_OTP_BASE 0x08fff000 /* Base address of OTP Area */ - /* Peripheral Base Addresses ************************************************/ #define STM32_APB1_BASE 0x40000000 /* 0x40000000-0x4000fbff: APB1 */ From 72e13f645395de95fb46ca6fa1c2053704b85ebe Mon Sep 17 00:00:00 2001 From: Liam Howatt Date: Fri, 18 Sep 2026 11:08:01 -0400 Subject: [PATCH 2/4] arch/arm/stm32h5: Fix nxstyle issues in stm32_serial.c. Fix nxstyle issues in arch/arm/src/stm32h5/stm32_serial.c Signed-off-by: Liam Howatt --- arch/arm/src/stm32h5/stm32_serial.c | 755 ++++++++++++++-------------- 1 file changed, 380 insertions(+), 375 deletions(-) diff --git a/arch/arm/src/stm32h5/stm32_serial.c b/arch/arm/src/stm32h5/stm32_serial.c index 590facc514488..361c67872be78 100644 --- a/arch/arm/src/stm32h5/stm32_serial.c +++ b/arch/arm/src/stm32h5/stm32_serial.c @@ -2008,7 +2008,9 @@ static void stm32serial_pm_setsuspend(bool suspend) /* Already in desired state? */ if (suspend == g_serialpm.serial_suspended) - return; + { + return; + } g_serialpm.serial_suspended = suspend; @@ -2049,86 +2051,86 @@ static void stm32serial_setapbclock(struct uart_dev_s *dev, bool on) switch (priv->usartbase) { - default: - return; + default: + return; #ifdef CONFIG_STM32_LPUART1_SERIALDRIVER - case STM32_LPUART1_BASE: - rcc_en = RCC_APB3ENR_LPUART1EN ; - regaddr = STM32_RCC_APB3ENR; - break; + case STM32_LPUART1_BASE: + rcc_en = RCC_APB3ENR_LPUART1EN ; + regaddr = STM32_RCC_APB3ENR; + break; #endif #ifdef CONFIG_STM32_USART1_SERIALDRIVER - case STM32_USART1_BASE: - rcc_en = RCC_APB2ENR_USART1EN ; - regaddr = STM32_RCC_APB2ENR; - break; + case STM32_USART1_BASE: + rcc_en = RCC_APB2ENR_USART1EN ; + regaddr = STM32_RCC_APB2ENR; + break; #endif #ifdef CONFIG_STM32_USART2_SERIALDRIVER - case STM32_USART2_BASE: - rcc_en = RCC_APB1LENR_USART2EN; - regaddr = STM32_RCC_APB1LENR; - break; + case STM32_USART2_BASE: + rcc_en = RCC_APB1LENR_USART2EN; + regaddr = STM32_RCC_APB1LENR; + break; #endif #ifdef CONFIG_STM32_USART3_SERIALDRIVER - case STM32_USART3_BASE: - rcc_en = RCC_APB1LENR_USART3EN; - regaddr = STM32_RCC_APB1LENR; - break; + case STM32_USART3_BASE: + rcc_en = RCC_APB1LENR_USART3EN; + regaddr = STM32_RCC_APB1LENR; + break; #endif #ifdef CONFIG_STM32_UART4_SERIALDRIVER - case STM32_UART4_BASE: - rcc_en = RCC_APB1LENR_UART4EN; - regaddr = STM32_RCC_APB1LENR; - break; + case STM32_UART4_BASE: + rcc_en = RCC_APB1LENR_UART4EN; + regaddr = STM32_RCC_APB1LENR; + break; #endif #ifdef CONFIG_STM32_UART5_SERIALDRIVER - case STM32_UART5_BASE: - rcc_en = RCC_APB1LENR_UART5EN; - regaddr = STM32_RCC_APB1LENR; - break; + case STM32_UART5_BASE: + rcc_en = RCC_APB1LENR_UART5EN; + regaddr = STM32_RCC_APB1LENR; + break; #endif #ifdef CONFIG_STM32_USART6_SERIALDRIVER - case STM32_USART6_BASE: - rcc_en = RCC_APB1LENR_USART6EN; - regaddr = STM32_RCC_APB1LENR; - break; + case STM32_USART6_BASE: + rcc_en = RCC_APB1LENR_USART6EN; + regaddr = STM32_RCC_APB1LENR; + break; #endif #ifdef CONFIG_STM32_UART7_SERIALDRIVER - case STM32_UART7_BASE: - rcc_en = RCC_APB1LENR_UART7EN; - regaddr = STM32_RCC_APB1LENR; - break; + case STM32_UART7_BASE: + rcc_en = RCC_APB1LENR_UART7EN; + regaddr = STM32_RCC_APB1LENR; + break; #endif #ifdef CONFIG_STM32_UART8_SERIALDRIVER - case STM32_UART8_BASE: - rcc_en = RCC_APB1LENR_UART8EN; - regaddr = STM32_RCC_APB1LENR; - break; + case STM32_UART8_BASE: + rcc_en = RCC_APB1LENR_UART8EN; + regaddr = STM32_RCC_APB1LENR; + break; #endif #ifdef CONFIG_STM32_UART9_SERIALDRIVER - case STM32_UART9_BASE: - rcc_en = RCC_APB1HENR_UART9EN; - regaddr = STM32_RCC_APB1HENR; - break; + case STM32_UART9_BASE: + rcc_en = RCC_APB1HENR_UART9EN; + regaddr = STM32_RCC_APB1HENR; + break; #endif #ifdef CONFIG_STM32_USART10_SERIALDRIVER - case STM32_USART10_BASE: - rcc_en = RCC_APB1LENR_USART10EN; - regaddr = STM32_RCC_APB1LENR; - break; + case STM32_USART10_BASE: + rcc_en = RCC_APB1LENR_USART10EN; + regaddr = STM32_RCC_APB1LENR; + break; #endif #ifdef CONFIG_STM32_USART11_SERIALDRIVER - case STM32_USART11_BASE: - rcc_en = RCC_APB1LENR_USART11EN; - regaddr = STM32_RCC_APB1LENR; - break; + case STM32_USART11_BASE: + rcc_en = RCC_APB1LENR_USART11EN; + regaddr = STM32_RCC_APB1LENR; + break; #endif #ifdef CONFIG_STM32_UART12_SERIALDRIVER - case STM32_UART12_BASE: - rcc_en = RCC_APB1HENR_UART12EN; - regaddr = STM32_RCC_APB1HENR; - break; + case STM32_UART12_BASE: + rcc_en = RCC_APB1HENR_UART12EN; + regaddr = STM32_RCC_APB1HENR; + break; #endif } @@ -2558,6 +2560,7 @@ static void stm32serial_detach(struct uart_dev_s *dev) { struct stm32_serial_s *priv = (struct stm32_serial_s *)dev->priv; + up_disable_irq(priv->irq); irq_detach(priv->irq); } @@ -2815,385 +2818,387 @@ static int stm32serial_ioctl(struct file *filep, int cmd, switch (cmd) { #ifdef CONFIG_SERIAL_TIOCSERGSTRUCT - case TIOCSERGSTRUCT: - { - struct stm32_serial_s *user; + case TIOCSERGSTRUCT: + { + struct stm32_serial_s *user; - user = (struct stm32_serial_s *)arg; + user = (struct stm32_serial_s *)arg; - if (!user) - { - ret = -EINVAL; - } - else - { - memcpy(user, dev, sizeof(struct stm32_serial_s)); - } - } - break; + if (!user) + { + ret = -EINVAL; + } + else + { + memcpy(user, dev, sizeof(struct stm32_serial_s)); + } + } + break; #endif #ifdef CONFIG_STM32_USART_SINGLEWIRE - case TIOCSSINGLEWIRE: - { - uint32_t cr1; - uint32_t cr1_ue; - irqstate_t flags; - - flags = enter_critical_section(); - - /* Get the original state of UE */ - - cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); - cr1_ue = cr1 & USART_CR1_UE; - cr1 &= ~USART_CR1_UE; + case TIOCSSINGLEWIRE: + { + uint32_t cr1; + uint32_t cr1_ue; + irqstate_t flags; - /* Disable UE, HDSEL can only be written when UE=0 */ + flags = enter_critical_section(); - stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1); + /* Get the original state of UE */ - /* Change the TX port to be open-drain/push-pull and enable/disable - * half-duplex mode. - */ + cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); + cr1_ue = cr1 & USART_CR1_UE; + cr1 &= ~USART_CR1_UE; - uint32_t cr = stm32serial_getreg(priv, STM32_USART_CR3_OFFSET); + /* Disable UE, HDSEL can only be written when UE=0 */ - if ((arg & SER_SINGLEWIRE_ENABLED) != 0) - { - uint32_t gpio_val = GPIO_OPENDRAIN; + stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1); - if ((arg & SER_SINGLEWIRE_PULL_MASK) == SER_SINGLEWIRE_PULLUP) - { - gpio_val |= GPIO_PULLUP; - } - else - { - gpio_val |= GPIO_FLOAT; - } + /* Change the TX port to be open-drain/push-pull and enable/disable + * half-duplex mode. + */ - if ((arg & SER_SINGLEWIRE_PULL_MASK) == SER_SINGLEWIRE_PULLDOWN) - { - gpio_val |= GPIO_PULLDOWN; - } - else - { - gpio_val |= GPIO_FLOAT; - } + uint32_t cr = stm32serial_getreg(priv, STM32_USART_CR3_OFFSET); - if (priv->tx_gpio != 0) - { - stm32_configgpio((priv->tx_gpio & - ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) | - gpio_val); - } - - cr |= USART_CR3_HDSEL; - } - else - { - if (priv->tx_gpio != 0) - { - stm32_configgpio((priv->tx_gpio & - ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) | - GPIO_PUSHPULL); - } - - cr &= ~USART_CR3_HDSEL; - } + if ((arg & SER_SINGLEWIRE_ENABLED) != 0) + { + uint32_t gpio_val = GPIO_OPENDRAIN; + + if ((arg & SER_SINGLEWIRE_PULL_MASK) == SER_SINGLEWIRE_PULLUP) + { + gpio_val |= GPIO_PULLUP; + } + else + { + gpio_val |= GPIO_FLOAT; + } + + if ((arg & SER_SINGLEWIRE_PULL_MASK) == + SER_SINGLEWIRE_PULLDOWN) + { + gpio_val |= GPIO_PULLDOWN; + } + else + { + gpio_val |= GPIO_FLOAT; + } + + if (priv->tx_gpio != 0) + { + stm32_configgpio((priv->tx_gpio & + ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) | + gpio_val); + } + + cr |= USART_CR3_HDSEL; + } + else + { + if (priv->tx_gpio != 0) + { + stm32_configgpio((priv->tx_gpio & + ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) | + GPIO_PUSHPULL); + } + + cr &= ~USART_CR3_HDSEL; + } - stm32serial_putreg(priv, STM32_USART_CR3_OFFSET, cr); + stm32serial_putreg(priv, STM32_USART_CR3_OFFSET, cr); - /* Re-enable UE if appropriate */ + /* Re-enable UE if appropriate */ - stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1 | cr1_ue); - leave_critical_section(flags); - } - break; + stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1 | cr1_ue); + leave_critical_section(flags); + } + break; #endif #ifdef CONFIG_STM32_USART_INVERT - case TIOCSINVERT: - { - uint32_t cr1; - uint32_t cr1_ue; - irqstate_t flags; + case TIOCSINVERT: + { + uint32_t cr1; + uint32_t cr1_ue; + irqstate_t flags; - flags = enter_critical_section(); + flags = enter_critical_section(); - /* Get the original state of UE */ + /* Get the original state of UE */ - cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); - cr1_ue = cr1 & USART_CR1_UE; - cr1 &= ~USART_CR1_UE; + cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); + cr1_ue = cr1 & USART_CR1_UE; + cr1 &= ~USART_CR1_UE; - /* Disable UE, {R,T}XINV can only be written when UE=0 */ + /* Disable UE, {R,T}XINV can only be written when UE=0 */ - stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1); + stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1); - /* Enable/disable signal inversion. */ + /* Enable/disable signal inversion. */ - uint32_t cr = stm32serial_getreg(priv, STM32_USART_CR2_OFFSET); + uint32_t cr = stm32serial_getreg(priv, STM32_USART_CR2_OFFSET); - if (arg & SER_INVERT_ENABLED_RX) - { - cr |= USART_CR2_RXINV; - } - else - { - cr &= ~USART_CR2_RXINV; - } + if (arg & SER_INVERT_ENABLED_RX) + { + cr |= USART_CR2_RXINV; + } + else + { + cr &= ~USART_CR2_RXINV; + } - if (arg & SER_INVERT_ENABLED_TX) - { - cr |= USART_CR2_TXINV; - } - else - { - cr &= ~USART_CR2_TXINV; - } + if (arg & SER_INVERT_ENABLED_TX) + { + cr |= USART_CR2_TXINV; + } + else + { + cr &= ~USART_CR2_TXINV; + } - stm32serial_putreg(priv, STM32_USART_CR2_OFFSET, cr); + stm32serial_putreg(priv, STM32_USART_CR2_OFFSET, cr); - /* Re-enable UE if appropriate */ + /* Re-enable UE if appropriate */ - stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1 | cr1_ue); - leave_critical_section(flags); - } - break; + stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1 | cr1_ue); + leave_critical_section(flags); + } + break; #endif #ifdef CONFIG_STM32_USART_SWAP - case TIOCSSWAP: - { - uint32_t cr1; - uint32_t cr1_ue; - irqstate_t flags; + case TIOCSSWAP: + { + uint32_t cr1; + uint32_t cr1_ue; + irqstate_t flags; - flags = enter_critical_section(); + flags = enter_critical_section(); - /* Get the original state of UE */ + /* Get the original state of UE */ - cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); - cr1_ue = cr1 & USART_CR1_UE; - cr1 &= ~USART_CR1_UE; + cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); + cr1_ue = cr1 & USART_CR1_UE; + cr1 &= ~USART_CR1_UE; - /* Disable UE, SWAP can only be written when UE=0 */ + /* Disable UE, SWAP can only be written when UE=0 */ - stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1); + stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1); - /* Enable/disable Swap mode. */ + /* Enable/disable Swap mode. */ - uint32_t cr = stm32serial_getreg(priv, STM32_USART_CR2_OFFSET); + uint32_t cr = stm32serial_getreg(priv, STM32_USART_CR2_OFFSET); - if (arg == SER_SWAP_ENABLED) - { - cr |= USART_CR2_SWAP; - } - else - { - cr &= ~USART_CR2_SWAP; - } + if (arg == SER_SWAP_ENABLED) + { + cr |= USART_CR2_SWAP; + } + else + { + cr &= ~USART_CR2_SWAP; + } - stm32serial_putreg(priv, STM32_USART_CR2_OFFSET, cr); + stm32serial_putreg(priv, STM32_USART_CR2_OFFSET, cr); - /* Re-enable UE if appropriate */ + /* Re-enable UE if appropriate */ - stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1 | cr1_ue); - leave_critical_section(flags); - } - break; + stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1 | cr1_ue); + leave_critical_section(flags); + } + break; #endif #ifdef CONFIG_SERIAL_TERMIOS - case TCGETS: - { - struct termios *termiosp = (struct termios *)arg; + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; - if (!termiosp) - { - ret = -EINVAL; - break; - } + if (!termiosp) + { + ret = -EINVAL; + break; + } - cfsetispeed(termiosp, priv->baud); + cfsetispeed(termiosp, priv->baud); - /* Note that since we only support 8/9 bit modes and - * there is no way to report 9-bit mode, we always claim 8. - */ + /* Note that since we only support 8/9 bit modes and + * there is no way to report 9-bit mode, we always claim 8. + */ - termiosp->c_cflag = - ((priv->parity != 0) ? PARENB : 0) | - ((priv->parity == 1) ? PARODD : 0) | - ((priv->stopbits2) ? CSTOPB : 0) | + termiosp->c_cflag = + ((priv->parity != 0) ? PARENB : 0) | + ((priv->parity == 1) ? PARODD : 0) | + ((priv->stopbits2) ? CSTOPB : 0) | #ifdef CONFIG_SERIAL_OFLOWCONTROL - ((priv->oflow) ? CCTS_OFLOW : 0) | + ((priv->oflow) ? CCTS_OFLOW : 0) | #endif #ifdef CONFIG_SERIAL_IFLOWCONTROL - ((priv->iflow) ? CRTS_IFLOW : 0) | + ((priv->iflow) ? CRTS_IFLOW : 0) | #endif - CS8; + CS8; - /* TODO: CRTS_IFLOW, CCTS_OFLOW */ - } - break; + /* TODO: CRTS_IFLOW, CCTS_OFLOW */ + } + break; - case TCSETS: - { - struct termios *termiosp = (struct termios *)arg; + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; - if (!termiosp) - { - ret = -EINVAL; - break; - } + if (!termiosp) + { + ret = -EINVAL; + break; + } - /* Perform some sanity checks before accepting any changes */ + /* Perform some sanity checks before accepting any changes */ - if (((termiosp->c_cflag & CSIZE) != CS8) + if (((termiosp->c_cflag & CSIZE) != CS8) #ifdef CONFIG_SERIAL_OFLOWCONTROL - || ((termiosp->c_cflag & CCTS_OFLOW) && (priv->cts_gpio == 0)) + || ((termiosp->c_cflag & CCTS_OFLOW) && (priv->cts_gpio == 0)) #endif #ifdef CONFIG_SERIAL_IFLOWCONTROL - || ((termiosp->c_cflag & CRTS_IFLOW) && (priv->rts_gpio == 0)) + || ((termiosp->c_cflag & CRTS_IFLOW) && (priv->rts_gpio == 0)) #endif - ) - { - ret = -EINVAL; - break; - } + ) + { + ret = -EINVAL; + break; + } - if (termiosp->c_cflag & PARENB) - { - priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2; - } - else - { - priv->parity = 0; - } + if (termiosp->c_cflag & PARENB) + { + priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + } + else + { + priv->parity = 0; + } - priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0; + priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0; #ifdef CONFIG_SERIAL_OFLOWCONTROL - priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0; + priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0; #endif #ifdef CONFIG_SERIAL_IFLOWCONTROL - priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0; + priv->iflow = (termiosp->c_cflag & CRTS_IFLOW) != 0; #endif - /* Note that since there is no way to request 9-bit mode - * and no way to support 5/6/7-bit modes, we ignore them - * all here. - */ + /* Note that since there is no way to request 9-bit mode + * and no way to support 5/6/7-bit modes, we ignore them + * all here. + */ - /* Note that only cfgetispeed is used because we have knowledge - * that only one speed is supported. - */ + /* Note that only cfgetispeed is used because we have knowledge + * that only one speed is supported. + */ - priv->baud = cfgetispeed(termiosp); + priv->baud = cfgetispeed(termiosp); - /* Effect the changes immediately - note that we do not implement - * TCSADRAIN / TCSAFLUSH - */ + /* Effect the changes immediately - note that we do not implement + * TCSADRAIN / TCSAFLUSH + */ - stm32serial_setformat(dev); - } - break; + stm32serial_setformat(dev); + } + break; #endif /* CONFIG_SERIAL_TERMIOS */ #ifdef CONFIG_STM32_USART_BREAKS # ifdef CONFIG_STM32_SERIALBRK_BSDCOMPAT - case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ - { - irqstate_t flags; + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + { + irqstate_t flags; - flags = enter_critical_section(); + flags = enter_critical_section(); - /* Disable any further tx activity */ + /* Disable any further tx activity */ - priv->ie |= USART_CR1_IE_BREAK_INPROGRESS; + priv->ie |= USART_CR1_IE_BREAK_INPROGRESS; - stm32serial_txint(dev, false); + stm32serial_txint(dev, false); - /* Configure TX as a GPIO output pin and Send a break signal */ + /* Configure TX as a GPIO output pin and Send a break signal */ - if (priv->tx_gpio != 0) - { - uint32_t tx_break = GPIO_OUTPUT | - (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio); - stm32_configgpio(tx_break); - } + if (priv->tx_gpio != 0) + { + uint32_t tx_break = GPIO_OUTPUT | + (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio); - leave_critical_section(flags); - } - break; + stm32_configgpio(tx_break); + } - case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ - { - irqstate_t flags; + leave_critical_section(flags); + } + break; - flags = enter_critical_section(); + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + { + irqstate_t flags; - /* Configure TX back to U(S)ART */ + flags = enter_critical_section(); - if (priv->tx_gpio != 0) - { - stm32_configgpio(priv->tx_gpio); - } + /* Configure TX back to U(S)ART */ - priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS; + if (priv->tx_gpio != 0) + { + stm32_configgpio(priv->tx_gpio); + } - /* Enable further tx activity */ + priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS; - stm32serial_txint(dev, true); + /* Enable further tx activity */ - leave_critical_section(flags); - } - break; + stm32serial_txint(dev, true); + + leave_critical_section(flags); + } + break; # else - case TIOCSBRK: /* No BSD compatibility: Turn break on for M bit times */ - { - uint32_t cr1; - irqstate_t flags; - - flags = enter_critical_section(); - cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); - stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, - cr1 | USART_CR1_SBK); - leave_critical_section(flags); - } - break; - - case TIOCCBRK: /* No BSD compatibility: May turn off break too soon */ - { - uint32_t cr1; - irqstate_t flags; - - flags = enter_critical_section(); - cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); - stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, - cr1 & ~USART_CR1_SBK); - leave_critical_section(flags); - } - break; + case TIOCSBRK: /* No BSD compatibility: Turn break on for M bit times */ + { + uint32_t cr1; + irqstate_t flags; + + flags = enter_critical_section(); + cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); + stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, + cr1 | USART_CR1_SBK); + leave_critical_section(flags); + } + break; + + case TIOCCBRK: /* No BSD compatibility: May turn off break too soon */ + { + uint32_t cr1; + irqstate_t flags; + + flags = enter_critical_section(); + cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); + stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, + cr1 & ~USART_CR1_SBK); + leave_critical_section(flags); + } + break; # endif #endif #ifdef HAVE_RS485 - case TIOCSRS485: /* Set RS485 mode, arg: pointer to struct serial_rs485 */ - { - ret = stm32serial_set_rs485_mode( - priv, (const struct serial_rs485 *)((uintptr_t)arg)); - } - break; + case TIOCSRS485: /* Set RS485 mode, arg: pointer to struct serial_rs485 */ + { + ret = stm32serial_set_rs485_mode( + priv, (const struct serial_rs485 *)((uintptr_t)arg)); + } + break; - case TIOCGRS485: /* Get RS485 mode, arg: pointer to struct serial_rs485 */ - { - ret = stm32serial_get_rs485_mode( - priv, (struct serial_rs485 *)((uintptr_t)arg)); - } - break; -#endif - default: - ret = -ENOTTY; - break; + case TIOCGRS485: /* Get RS485 mode, arg: pointer to struct serial_rs485 */ + { + ret = stm32serial_get_rs485_mode( + priv, (struct serial_rs485 *)((uintptr_t)arg)); + } + break; +#endif + default: + ret = -ENOTTY; + break; } return ret; @@ -3910,62 +3915,62 @@ static int stm32serial_pmprepare(struct pm_callback_s *cb, int domain, switch (pmstate) { - case PM_NORMAL: - case PM_IDLE: - break; + case PM_NORMAL: + case PM_IDLE: + break; - case PM_STANDBY: - case PM_SLEEP: + case PM_STANDBY: + case PM_SLEEP: #ifdef SERIAL_HAVE_DMA - /* Flush Rx DMA buffers before checking state of serial device - * buffers. - */ + /* Flush Rx DMA buffers before checking state of serial device + * buffers. + */ - stm32_serial_dma_poll(); + stm32_serial_dma_poll(); #endif - /* Check if any of the active ports have data pending on Tx/Rx - * buffers. - */ + /* Check if any of the active ports have data pending on Tx/Rx + * buffers. + */ - for (n = 0; n < STM32_NLPUART + STM32_NUSART + STM32_NUART; n++) - { - struct stm32_serial_s *priv = g_uart_devs[n]; + for (n = 0; n < STM32_NLPUART + STM32_NUSART + STM32_NUART; n++) + { + struct stm32_serial_s *priv = g_uart_devs[n]; - if (!priv || !priv->initialized) - { - /* Not active, skip. */ + if (!priv || !priv->initialized) + { + /* Not active, skip. */ - continue; - } + continue; + } - if (priv->suspended) - { - /* Port already suspended, skip. */ + if (priv->suspended) + { + /* Port already suspended, skip. */ - continue; - } + continue; + } - /* Check if port has data pending (Rx & Tx). */ + /* Check if port has data pending (Rx & Tx). */ - if (priv->dev.xmit.head != priv->dev.xmit.tail) - { - return ERROR; - } + if (priv->dev.xmit.head != priv->dev.xmit.tail) + { + return ERROR; + } - if (priv->dev.recv.head != priv->dev.recv.tail) - { - return ERROR; - } - } - break; + if (priv->dev.recv.head != priv->dev.recv.tail) + { + return ERROR; + } + } + break; - default: + default: - /* Should not get here */ + /* Should not get here */ - break; + break; } return OK; @@ -4108,9 +4113,9 @@ void arm_serialinit(void) #ifdef SERIAL_HAVE_DMA void stm32_serial_dma_poll(void) { - irqstate_t flags; + irqstate_t flags; - flags = enter_critical_section(); + flags = enter_critical_section(); #ifdef CONFIG_LPUART1_RXDMA if (g_lpuart1priv.rxdma != NULL) From 807118ccb41386d99b94640d265cc4be33f613e5 Mon Sep 17 00:00:00 2001 From: Liam Howatt Date: Fri, 18 Sep 2026 14:34:18 -0400 Subject: [PATCH 3/4] arch/arm/stm32h5: Add USART wake from low power. Support USART waking from low power modes, allow keeping HSI running in STOP mode, allow specifying clock source for USARTs, add some missing register and field definitions. stm32 common Kconfigs: Add common STM32 UART config options USARTx_WAKE_FROM_LOW_POWER and USARTx_WUS for USART to cause wake up from low power modes. stm32h5 board configs: Allow board.h to choose the clock source of each USART. Allow board.h to express that HSI should continue running in low power modes. stm32h5 RCC: Set the clock source for each USART if specified in the board configs (STM32_RCC_CCIPR1_USARTxSEL). Keep HSI on in STOP mode if specified in the board configs (STM32_BOARD_HSIKERON_ENABLE). stm32h5 serial driver: Use the new USARTx_WAKE_FROM_LOW_POWER and USARTx_WUS in stm32h5 serial driver to wake from low power modes. Use the USART clock source specified by board configs. Enable FIFOs. Clear UE bit before initialization. Co-authored-by: Javier Casas Co-authored-by: daniellizewski Signed-off-by: Liam Howatt --- arch/arm/src/common/stm32/Kconfig.have | 3 + arch/arm/src/common/stm32/Kconfig.uart | 280 ++++++++++++++++ arch/arm/src/stm32h5/Kconfig | 1 + .../arm/src/stm32h5/hardware/stm32h5xxx_rcc.h | 34 +- .../src/stm32h5/hardware/stm32h5xxx_uart.h | 33 +- arch/arm/src/stm32h5/stm32_serial.c | 299 ++++++++++++++++-- arch/arm/src/stm32h5/stm32h5xx_rcc.c | 94 ++++++ 7 files changed, 706 insertions(+), 38 deletions(-) diff --git a/arch/arm/src/common/stm32/Kconfig.have b/arch/arm/src/common/stm32/Kconfig.have index 829b51534d036..cb7fa87d3faf6 100644 --- a/arch/arm/src/common/stm32/Kconfig.have +++ b/arch/arm/src/common/stm32/Kconfig.have @@ -1069,6 +1069,9 @@ config STM32_HAVE_USART_H5 config STM32_HAVE_USART_RXFIFO_THRESHOLD bool +config STM32_HAVE_USART_WUS + bool + config STM32_HAVE_USART_UNCONFIG_ON_CLOSE bool default y if ARCH_CHIP_STM32H5 diff --git a/arch/arm/src/common/stm32/Kconfig.uart b/arch/arm/src/common/stm32/Kconfig.uart index 78ee35c0e34d3..679b076ec2bce 100644 --- a/arch/arm/src/common/stm32/Kconfig.uart +++ b/arch/arm/src/common/stm32/Kconfig.uart @@ -1227,6 +1227,286 @@ config UART8_RXFIFO_THRES endif # STM32_UART8 +config USART1_WAKE_FROM_LOW_POWER + bool "USART1 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS && STM32_USART && STM32_USART1_SERIALDRIVER + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config USART1_WUS + int "USART1 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on USART1_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +config USART2_WAKE_FROM_LOW_POWER + bool "USART2 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS && STM32_USART && STM32_USART2_SERIALDRIVER + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config USART2_WUS + int "USART2 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on USART2_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +if STM32_USART3 + +config USART3_WAKE_FROM_LOW_POWER + bool "USART3 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config USART3_WUS + int "USART3 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on USART3_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_USART3 + +if STM32_UART4 + +config UART4_WAKE_FROM_LOW_POWER + bool "UART4 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config UART4_WUS + int "UART4 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on UART4_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_UART4 + +if STM32_UART5 + +config UART5_WAKE_FROM_LOW_POWER + bool "UART5 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config UART5_WUS + int "UART5 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on UART5_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_UART5 + +if STM32_USART6 + +config USART6_WAKE_FROM_LOW_POWER + bool "USART6 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config USART6_WUS + int "USART6 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on USART6_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_USART6 + +if STM32_UART7 + +config UART7_WAKE_FROM_LOW_POWER + bool "UART7 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config UART7_WUS + int "UART7 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on UART7_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_UART7 + +if STM32_UART8 + +config UART8_WAKE_FROM_LOW_POWER + bool "UART8 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config UART8_WUS + int "UART8 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on UART8_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_UART8 + +if STM32_UART9 + +config UART9_WAKE_FROM_LOW_POWER + bool "UART9 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config UART9_WUS + int "UART9 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on UART9_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_UART9 + +if STM32_USART10 + +config USART10_WAKE_FROM_LOW_POWER + bool "USART10 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config USART10_WUS + int "USART10 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on USART10_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_USART10 + +if STM32_USART11 + +config USART11_WAKE_FROM_LOW_POWER + bool "USART11 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config USART11_WUS + int "USART11 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on USART11_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_USART11 + +if STM32_UART12 + +config UART12_WAKE_FROM_LOW_POWER + bool "UART12 Enable wake from low power mode" + default n + depends on STM32_HAVE_USART_WUS + ---help--- + Enable the wake from low power mode interrupt. + NOTE: The UART must be clocked from a clock source which is not disabled during stop + for this to work + +config UART12_WUS + int "UART12 Wake from low power interrupt selection" + default 2 + range 0 3 + depends on UART12_WAKE_FROM_LOW_POWER + ---help--- + 0 = WUF active on address match (as defined by ADD[7:0] and ADDM7) + 1 = Reserved. + 2 = WUF active on start bit detection + 3 = WUF active on RXNE/RXFNE. + +endif # STM32_UART12 + config STM32_USART_INVERT bool "Signal Invert Support" depends on STM32_USART diff --git a/arch/arm/src/stm32h5/Kconfig b/arch/arm/src/stm32h5/Kconfig index 8aba6121e9b3d..09a0a520970fa 100644 --- a/arch/arm/src/stm32h5/Kconfig +++ b/arch/arm/src/stm32h5/Kconfig @@ -29,6 +29,7 @@ config STM32_H5_PERIPHERALS select STM32_HAVE_USBDRD_HOST select STM32_HAVE_ADC_H5 select STM32_HAVE_USART_H5 + select STM32_HAVE_USART_WUS select STM32_HAVE_I2C_H5 select STM32_HAVE_CRC select STM32_HAVE_IP_WDG_M3M4_V1 diff --git a/arch/arm/src/stm32h5/hardware/stm32h5xxx_rcc.h b/arch/arm/src/stm32h5/hardware/stm32h5xxx_rcc.h index d9fb24d703e75..29415266db52f 100644 --- a/arch/arm/src/stm32h5/hardware/stm32h5xxx_rcc.h +++ b/arch/arm/src/stm32h5/hardware/stm32h5xxx_rcc.h @@ -823,7 +823,7 @@ #define RCC_CCIPR1_USART1SEL_SHIFT (0) #define RCC_CCIPR1_USART1SEL_MASK (7 << RCC_CCIPR1_USART1SEL_SHIFT) -# define RCC_CCIPR1_USART1SEL_RCCPCLK1 (0 << RCC_CCIPR1_USART1SEL_SHIFT) +# define RCC_CCIPR1_USART1SEL_RCCPCLK2 (0 << RCC_CCIPR1_USART1SEL_SHIFT) # define RCC_CCIPR1_USART1SEL_PLL2QCK (1 << RCC_CCIPR1_USART1SEL_SHIFT) # define RCC_CCIPR1_USART1SEL_PLL3QCK (2 << RCC_CCIPR1_USART1SEL_SHIFT) # define RCC_CCIPR1_USART1SEL_HSIKERCK (3 << RCC_CCIPR1_USART1SEL_SHIFT) @@ -866,14 +866,14 @@ # define RCC_CCIPR1_UART5SEL_CSIKERCK (4 << RCC_CCIPR1_UART5SEL_SHIFT) # define RCC_CCIPR1_UART5SEL_LSECK (5 << RCC_CCIPR1_UART5SEL_SHIFT) -#define RCC_CCIPR1_UART6SEL_SHIFT (15) -#define RCC_CCIPR1_UART6SEL_MASK (7 << RCC_CCIPR1_UART6SEL_SHIFT) -# define RCC_CCIPR1_UART6SEL_RCCPCLK1 (0 << RCC_CCIPR1_UART6SEL_SHIFT) -# define RCC_CCIPR1_UART6SEL_PLL2QCK (1 << RCC_CCIPR1_UART6SEL_SHIFT) -# define RCC_CCIPR1_UART6SEL_PLL3QCK (2 << RCC_CCIPR1_UART6SEL_SHIFT) -# define RCC_CCIPR1_UART6SEL_HSIKERCK (3 << RCC_CCIPR1_UART6SEL_SHIFT) -# define RCC_CCIPR1_UART6SEL_CSIKERCK (4 << RCC_CCIPR1_UART6SEL_SHIFT) -# define RCC_CCIPR1_UART6SEL_LSECK (5 << RCC_CCIPR1_UART6SEL_SHIFT) +#define RCC_CCIPR1_USART6SEL_SHIFT (15) +#define RCC_CCIPR1_USART6SEL_MASK (7 << RCC_CCIPR1_USART6SEL_SHIFT) +# define RCC_CCIPR1_USART6SEL_RCCPCLK1 (0 << RCC_CCIPR1_USART6SEL_SHIFT) +# define RCC_CCIPR1_USART6SEL_PLL2QCK (1 << RCC_CCIPR1_USART6SEL_SHIFT) +# define RCC_CCIPR1_USART6SEL_PLL3QCK (2 << RCC_CCIPR1_USART6SEL_SHIFT) +# define RCC_CCIPR1_USART6SEL_HSIKERCK (3 << RCC_CCIPR1_USART6SEL_SHIFT) +# define RCC_CCIPR1_USART6SEL_CSIKERCK (4 << RCC_CCIPR1_USART6SEL_SHIFT) +# define RCC_CCIPR1_USART6SEL_LSECK (5 << RCC_CCIPR1_USART6SEL_SHIFT) #define RCC_CCIPR1_UART7SEL_SHIFT (18) #define RCC_CCIPR1_UART7SEL_MASK (7 << RCC_CCIPR1_UART7SEL_SHIFT) @@ -924,14 +924,14 @@ # define RCC_CCIPR2_USART11SEL_CSIKERCK (4 << RCC_CCIPR2_USART11SEL_SHIFT) # define RCC_CCIPR2_USART11SEL_LSECK (5 << RCC_CCIPR2_USART11SEL_SHIFT) -#define RCC_CCIPR2_USART12SEL_SHIFT (4) -#define RCC_CCIPR2_USART12SEL_MASK (7 << RCC_CCIPR2_USART12SEL_SHIFT) -# define RCC_CCIPR2_USART12SEL_RCCPCLK1 (0 << RCC_CCIPR2_USART12SEL_SHIFT) -# define RCC_CCIPR2_USART12SEL_PLL2QCK (1 << RCC_CCIPR2_USART12SEL_SHIFT) -# define RCC_CCIPR2_USART12SEL_PLL3QCK (2 << RCC_CCIPR2_USART12SEL_SHIFT) -# define RCC_CCIPR2_USART12SEL_HSIKERCK (3 << RCC_CCIPR2_USART12SEL_SHIFT) -# define RCC_CCIPR2_USART12SEL_CSIKERCK (4 << RCC_CCIPR2_USART12SEL_SHIFT) -# define RCC_CCIPR2_USART12SEL_LSECK (5 << RCC_CCIPR2_USART12SEL_SHIFT) +#define RCC_CCIPR2_UART12SEL_SHIFT (4) +#define RCC_CCIPR2_UART12SEL_MASK (7 << RCC_CCIPR2_UART12SEL_SHIFT) +# define RCC_CCIPR2_UART12SEL_RCCPCLK1 (0 << RCC_CCIPR2_UART12SEL_SHIFT) +# define RCC_CCIPR2_UART12SEL_PLL2QCK (1 << RCC_CCIPR2_UART12SEL_SHIFT) +# define RCC_CCIPR2_UART12SEL_PLL3QCK (2 << RCC_CCIPR2_UART12SEL_SHIFT) +# define RCC_CCIPR2_UART12SEL_HSIKERCK (3 << RCC_CCIPR2_UART12SEL_SHIFT) +# define RCC_CCIPR2_UART12SEL_CSIKERCK (4 << RCC_CCIPR2_UART12SEL_SHIFT) +# define RCC_CCIPR2_UART12SEL_LSECK (5 << RCC_CCIPR2_UART12SEL_SHIFT) #define RCC_CCIPR2_LPTIM1SEL_SHIFT (8) #define RCC_CCIPR2_LPTIM1SEL_MASK (7 << RCC_CCIPR2_LPTIM1SEL_SHIFT) diff --git a/arch/arm/src/stm32h5/hardware/stm32h5xxx_uart.h b/arch/arm/src/stm32h5/hardware/stm32h5xxx_uart.h index 3e9cf17197605..06bde190cf3e1 100644 --- a/arch/arm/src/stm32h5/hardware/stm32h5xxx_uart.h +++ b/arch/arm/src/stm32h5/hardware/stm32h5xxx_uart.h @@ -277,14 +277,19 @@ #define USART_CR1_RTOIE (1 << 26) /* Bit 26: Receiver timeout interrupt enable */ #define USART_CR1_EOBIE (1 << 27) /* Bit 27: End of block interrupt enable */ #define USART_CR1_M1 (1 << 28) /* Bit 28: Word length */ +#define USART_CR1_FIFOEN (1 << 29) /* Bit 29: FIFO EN */ +#define USART_CR1_TXFEIE (1 << 30) /* Bit 30: TX FIFO empty interrupt enable */ +#define USART_CR1_RXFFIE (1 << 31) /* Bit 31: RX FIFO full interrupt enable */ #define USART_CR1_ALLINTS (USART_CR1_IDLEIE|USART_CR1_RXNEIE| \ USART_CR1_TCIE|USART_CR1_TXEIE| \ USART_CR1_PEIE|USART_CR1_CMIE| \ - USART_CR1_RTOIE|USART_CR1_EOBIE) + USART_CR1_RTOIE|USART_CR1_EOBIE| \ + USART_CR1_TXFEIE|USART_CR1_RXFFIE) #define LPUART_CR1_ALLINTS \ (USART_CR1_IDLEIE | USART_CR1_RXNEIE | USART_CR1_TCIE | \ USART_CR1_TXEIE | USART_CR1_PEIE | USART_CR1_CMIE | \ + USART_CR1_TXFEIE | USART_CR1_RXFFIE | \ USART_CR1_TXFEIE | USART_CR1_RXFFIE) /* Control register 2 */ @@ -350,6 +355,27 @@ #define USART_CR3_WUS_START (2 << USART_CR3_WUS_SHIFT) /* 10: WUF active on Start bit detection */ #define USART_CR3_WUS_RXNE (3 << USART_CR3_WUS_SHIFT) /* 11: WUF active on RXNE */ #define USART_CR3_WUFIE (1 << 22) /* Bit 22: Wakeup from Stop mode interrupt enable */ +#define USART_CR3_TXFTIE (1 << 23) /* Bit 23: TXFIFO threshold interrupt enable */ +#define USART_CR3_TCBGTIE (1 << 24) /* Bit 24: Transmission Complete before guard time, interrupt enable */ +#define USART_CR3_RXFTCFG_SHIFT (25) /* Bits 25-27: Receive FIFO threshold configuration */ +#define USART_CR3_RXFTCFG_MASK (7 << USART_CR3_RXFTCFG_SHIFT) +#define USART_CR3_RXFTIE (1 << 28) /* Bit 28: RXFIFO threshold interrupt enable */ +#define USART_CR3_TXFTCFG_SHIFT (29) /* Bits 29-31: Transmit FIFO threshold configuration */ +#define USART_CR3_TXFTCFG_MASK (7 << USART_CR3_TXFTCFG_SHIFT) + +#define USART_CR3_TXFTCFG_0 (0) /* TX FIFO reaches 1/8 depth */ +#define USART_CR3_TXFTCFG_1 (1) /* TX FIFO reaches 1/4 depth */ +#define USART_CR3_TXFTCFG_2 (2) /* TX FIFO reaches 1/2 depth */ +#define USART_CR3_TXFTCFG_3 (3) /* TX FIFO reaches 3/4 depth */ +#define USART_CR3_TXFTCFG_4 (4) /* TX FIFO reaches 7/8 depth */ +#define USART_CR3_TXFTCFG_5 (5) /* TX FIFO reaches full depth */ + +#define USART_CR3_RXFTCFG_0 (0) /* RX FIFO reaches 1/8 depth */ +#define USART_CR3_RXFTCFG_1 (1) /* RX FIFO reaches 1/4 depth */ +#define USART_CR3_RXFTCFG_2 (2) /* RX FIFO reaches 1/2 depth */ +#define USART_CR3_RXFTCFG_3 (3) /* RX FIFO reaches 3/4 depth */ +#define USART_CR3_RXFTCFG_4 (4) /* RX FIFO reaches 7/8 depth */ +#define USART_CR3_RXFTCFG_5 (5) /* RX FIFO reaches full depth */ /* Baud Rate Register */ @@ -396,6 +422,11 @@ #define USART_ISR_WUF (1 << 20) /* Bit 20: Wakeup from Stop mode Flag */ #define USART_ISR_TEACK (1 << 21) /* Bit 21: Transmit enable acknowledge Flag */ #define USART_ISR_REACK (1 << 22) /* Bit 22: Receive enable acknowledge Flag */ +#define USART_ISR_TXFE (1 << 23) /* Bit 23: TXFIFO empty */ +#define USART_ISR_RXFF (1 << 24) /* Bit 24: RXFIFO full */ +#define USART_ISR_TCBGT (1 << 25) /* Bit 25: Transmission complete before guard time flag */ +#define USART_ISR_RXFT (1 << 26) /* Bit 26: RXFIFO threshold reached */ +#define USART_ISR_TXFT (1 << 27) /* Bit 27: TXFIFO threshold reached */ /* ICR */ diff --git a/arch/arm/src/stm32h5/stm32_serial.c b/arch/arm/src/stm32h5/stm32_serial.c index 361c67872be78..08dc366471f45 100644 --- a/arch/arm/src/stm32h5/stm32_serial.c +++ b/arch/arm/src/stm32h5/stm32_serial.c @@ -150,6 +150,198 @@ #ifdef USE_SERIALDRIVER #ifdef HAVE_UART +#if !defined STM32_RCC_CCIPR1_USART1SEL || STM32_RCC_CCIPR1_USART1SEL == RCC_CCIPR1_USART1SEL_RCCPCLK2 +# define STM32_USART1_FREQUENCY STM32_PCLK2_FREQUENCY +#elif STM32_RCC_CCIPR1_USART1SEL == RCC_CCIPR1_USART1SEL_PLL2QCK +# define STM32_USART1_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART1SEL == RCC_CCIPR1_USART1SEL_PLL3QCK +# define STM32_USART1_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART1SEL == RCC_CCIPR1_USART1SEL_HSIKERCK +# define STM32_USART1_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART1SEL == RCC_CCIPR1_USART1SEL_CSIKERCK +# define STM32_USART1_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART1SEL == RCC_CCIPR1_USART1SEL_LSECK +# define STM32_USART1_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported USART1 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR1_USART2SEL || STM32_RCC_CCIPR1_USART2SEL == RCC_CCIPR1_USART2SEL_RCCPCLK1 +# define STM32_USART2_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR1_USART2SEL == RCC_CCIPR1_USART2SEL_PLL2QCK +# define STM32_USART2_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART2SEL == RCC_CCIPR1_USART2SEL_PLL3QCK +# define STM32_USART2_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART2SEL == RCC_CCIPR1_USART2SEL_HSIKERCK +# define STM32_USART2_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART2SEL == RCC_CCIPR1_USART2SEL_CSIKERCK +# define STM32_USART2_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART2SEL == RCC_CCIPR1_USART2SEL_LSECK +# define STM32_USART2_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported USART2 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR1_USART3SEL || STM32_RCC_CCIPR1_USART3SEL == RCC_CCIPR1_USART3SEL_RCCPCLK1 +# define STM32_USART3_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR1_USART3SEL == RCC_CCIPR1_USART3SEL_PLL2QCK +# define STM32_USART3_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART3SEL == RCC_CCIPR1_USART3SEL_PLL3QCK +# define STM32_USART3_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART3SEL == RCC_CCIPR1_USART3SEL_HSIKERCK +# define STM32_USART3_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART3SEL == RCC_CCIPR1_USART3SEL_CSIKERCK +# define STM32_USART3_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART3SEL == RCC_CCIPR1_USART3SEL_LSECK +# define STM32_USART3_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported USART3 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR1_UART4SEL || STM32_RCC_CCIPR1_UART4SEL == RCC_CCIPR1_UART4SEL_RCCPCLK1 +# define STM32_UART4_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR1_UART4SEL == RCC_CCIPR1_UART4SEL_PLL2QCK +# define STM32_UART4_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART4SEL == RCC_CCIPR1_UART4SEL_PLL3QCK +# define STM32_UART4_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART4SEL == RCC_CCIPR1_UART4SEL_HSIKERCK +# define STM32_UART4_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART4SEL == RCC_CCIPR1_UART4SEL_CSIKERCK +# define STM32_UART4_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART4SEL == RCC_CCIPR1_UART4SEL_LSECK +# define STM32_UART4_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported UART4 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR1_UART5SEL || STM32_RCC_CCIPR1_UART5SEL == RCC_CCIPR1_UART5SEL_RCCPCLK1 +# define STM32_UART5_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR1_UART5SEL == RCC_CCIPR1_UART5SEL_PLL2QCK +# define STM32_UART5_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART5SEL == RCC_CCIPR1_UART5SEL_PLL3QCK +# define STM32_UART5_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART5SEL == RCC_CCIPR1_UART5SEL_HSIKERCK +# define STM32_UART5_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART5SEL == RCC_CCIPR1_UART5SEL_CSIKERCK +# define STM32_UART5_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART5SEL == RCC_CCIPR1_UART5SEL_LSECK +# define STM32_UART5_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported UART5 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR1_USART6SEL || STM32_RCC_CCIPR1_USART6SEL == RCC_CCIPR1_USART6SEL_RCCPCLK1 +# define STM32_USART6_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR1_USART6SEL == RCC_CCIPR1_USART6SEL_PLL2QCK +# define STM32_USART6_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART6SEL == RCC_CCIPR1_USART6SEL_PLL3QCK +# define STM32_USART6_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART6SEL == RCC_CCIPR1_USART6SEL_HSIKERCK +# define STM32_USART6_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART6SEL == RCC_CCIPR1_USART6SEL_CSIKERCK +# define STM32_USART6_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART6SEL == RCC_CCIPR1_USART6SEL_LSECK +# define STM32_USART6_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported USART6 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR1_UART7SEL || STM32_RCC_CCIPR1_UART7SEL == RCC_CCIPR1_UART7SEL_RCCPCLK1 +# define STM32_UART7_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR1_UART7SEL == RCC_CCIPR1_UART7SEL_PLL2QCK +# define STM32_UART7_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART7SEL == RCC_CCIPR1_UART7SEL_PLL3QCK +# define STM32_UART7_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART7SEL == RCC_CCIPR1_UART7SEL_HSIKERCK +# define STM32_UART7_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART7SEL == RCC_CCIPR1_UART7SEL_CSIKERCK +# define STM32_UART7_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART7SEL == RCC_CCIPR1_UART7SEL_LSECK +# define STM32_UART7_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported UART7 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR1_UART8SEL || STM32_RCC_CCIPR1_UART8SEL == RCC_CCIPR1_UART8SEL_RCCPCLK1 +# define STM32_UART8_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR1_UART8SEL == RCC_CCIPR1_UART8SEL_PLL2QCK +# define STM32_UART8_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART8SEL == RCC_CCIPR1_UART8SEL_PLL3QCK +# define STM32_UART8_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART8SEL == RCC_CCIPR1_UART8SEL_HSIKERCK +# define STM32_UART8_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART8SEL == RCC_CCIPR1_UART8SEL_CSIKERCK +# define STM32_UART8_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART8SEL == RCC_CCIPR1_UART8SEL_LSECK +# define STM32_UART8_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported UART8 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR1_UART9SEL || STM32_RCC_CCIPR1_UART9SEL == RCC_CCIPR1_UART9SEL_RCCPCLK1 +# define STM32_UART9_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR1_UART9SEL == RCC_CCIPR1_UART9SEL_PLL2QCK +# define STM32_UART9_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART9SEL == RCC_CCIPR1_UART9SEL_PLL3QCK +# define STM32_UART9_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_UART9SEL == RCC_CCIPR1_UART9SEL_HSIKERCK +# define STM32_UART9_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART9SEL == RCC_CCIPR1_UART9SEL_CSIKERCK +# define STM32_UART9_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_UART9SEL == RCC_CCIPR1_UART9SEL_LSECK +# define STM32_UART9_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported UART9 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR1_USART10SEL || STM32_RCC_CCIPR1_USART10SEL == RCC_CCIPR1_USART10SEL_RCCPCLK1 +# define STM32_USART10_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR1_USART10SEL == RCC_CCIPR1_USART10SEL_PLL2QCK +# define STM32_USART10_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART10SEL == RCC_CCIPR1_USART10SEL_PLL3QCK +# define STM32_USART10_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR1_USART10SEL == RCC_CCIPR1_USART10SEL_HSIKERCK +# define STM32_USART10_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART10SEL == RCC_CCIPR1_USART10SEL_CSIKERCK +# define STM32_USART10_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR1_USART10SEL == RCC_CCIPR1_USART10SEL_LSECK +# define STM32_USART10_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported USART10 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR2_USART11SEL || STM32_RCC_CCIPR2_USART11SEL == RCC_CCIPR2_USART11SEL_RCCPCLK1 +# define STM32_USART11_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR2_USART11SEL == RCC_CCIPR2_USART11SEL_PLL2QCK +# define STM32_USART11_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR2_USART11SEL == RCC_CCIPR2_USART11SEL_PLL3QCK +# define STM32_USART11_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR2_USART11SEL == RCC_CCIPR2_USART11SEL_HSIKERCK +# define STM32_USART11_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR2_USART11SEL == RCC_CCIPR2_USART11SEL_CSIKERCK +# define STM32_USART11_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR2_USART11SEL == RCC_CCIPR2_USART11SEL_LSECK +# define STM32_USART11_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported USART11 Clock Selection" +#endif + +#if !defined STM32_RCC_CCIPR2_UART12SEL || STM32_RCC_CCIPR2_UART12SEL == RCC_CCIPR2_UART12SEL_RCCPCLK1 +# define STM32_UART12_FREQUENCY STM32_PCLK1_FREQUENCY +#elif STM32_RCC_CCIPR2_UART12SEL == RCC_CCIPR2_UART12SEL_PLL2QCK +# define STM32_UART12_FREQUENCY STM32_PLL2Q_FREQUENCY +#elif STM32_RCC_CCIPR2_UART12SEL == RCC_CCIPR2_UART12SEL_PLL3QCK +# define STM32_UART12_FREQUENCY STM32_PLL3Q_FREQUENCY +#elif STM32_RCC_CCIPR2_UART12SEL == RCC_CCIPR2_UART12SEL_HSIKERCK +# define STM32_UART12_FREQUENCY STM32_HSI_FREQUENCY +#elif STM32_RCC_CCIPR2_UART12SEL == RCC_CCIPR2_UART12SEL_CSIKERCK +# define STM32_UART12_FREQUENCY STM32_CSI_FREQUENCY +#elif STM32_RCC_CCIPR2_UART12SEL == RCC_CCIPR2_UART12SEL_LSECK +# define STM32_UART12_FREQUENCY STM32_LSE_FREQUENCY +#else +# error "Unsupported UART12 Clock Selection" +#endif + /**************************************************************************** * Private Types ****************************************************************************/ @@ -157,8 +349,8 @@ struct stm32_serial_s { struct uart_dev_s dev; /* Generic UART device */ - uint16_t ie; /* Saved interrupt mask bits value */ - uint16_t sr; /* Saved status bits */ + uint32_t ie; /* Saved interrupt mask bits value */ + uint32_t sr; /* Saved status bits */ /* Has been initialized and HW is setup. */ @@ -194,7 +386,7 @@ struct stm32_serial_s const uint32_t baud; /* Configured baud */ #endif const uint8_t irq; /* IRQ associated with this USART */ - const uint32_t apbclock; /* PCLK 1 or 2 frequency */ + const uint32_t apbclock; /* Peripheral kernel clock frequency */ const uint32_t usartbase; /* Base address of USART registers */ const uint32_t tx_gpio; /* U[S]ART TX GPIO pin configuration */ const uint32_t rx_gpio; /* U[S]ART RX GPIO pin configuration */ @@ -228,6 +420,8 @@ struct stm32_serial_s const uint8_t unconfigure; /* Unconfigure pins on close */ const bool islpuart; /* Is this device a Low Power UART? */ spinlock_t lock; + const bool wakefromlowpower; /* Enable interrupt to wake from low power mode */ + const uint8_t wus; /* Wake from low power configuration. USART_CR3_WUS_* */ }; /**************************************************************************** @@ -536,7 +730,7 @@ static struct stm32_serial_s g_usart1priv = .bits = CONFIG_USART1_BITS, .stopbits2 = CONFIG_USART1_2STOP, .baud = CONFIG_USART1_BAUD, - .apbclock = STM32_PCLK2_FREQUENCY, + .apbclock = STM32_USART1_FREQUENCY, .usartbase = STM32_USART1_BASE, .tx_gpio = GPIO_USART1_TX, .rx_gpio = GPIO_USART1_RX, @@ -576,6 +770,10 @@ static struct stm32_serial_s g_usart1priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_USART1_WAKE_FROM_LOW_POWER) && defined(CONFIG_USART1_WUS) + .wakefromlowpower = true, + .wus = CONFIG_USART1_WUS, +#endif }; #endif @@ -613,7 +811,7 @@ static struct stm32_serial_s g_usart2priv = .bits = CONFIG_USART2_BITS, .stopbits2 = CONFIG_USART2_2STOP, .baud = CONFIG_USART2_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_USART2_FREQUENCY, .usartbase = STM32_USART2_BASE, .tx_gpio = GPIO_USART2_TX, .rx_gpio = GPIO_USART2_RX, @@ -653,6 +851,10 @@ static struct stm32_serial_s g_usart2priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_USART2_WAKE_FROM_LOW_POWER) && defined(CONFIG_USART2_WUS) + .wakefromlowpower = true, + .wus = CONFIG_USART2_WUS, +#endif }; #endif @@ -690,7 +892,7 @@ static struct stm32_serial_s g_usart3priv = .bits = CONFIG_USART3_BITS, .stopbits2 = CONFIG_USART3_2STOP, .baud = CONFIG_USART3_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_USART3_FREQUENCY, .usartbase = STM32_USART3_BASE, .tx_gpio = GPIO_USART3_TX, .rx_gpio = GPIO_USART3_RX, @@ -730,6 +932,10 @@ static struct stm32_serial_s g_usart3priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_USART3_WAKE_FROM_LOW_POWER) && defined(CONFIG_USART3_WUS) + .wakefromlowpower = true, + .wus = CONFIG_USART3_WUS, +#endif }; #endif @@ -775,7 +981,7 @@ static struct stm32_serial_s g_uart4priv = .rts_gpio = GPIO_UART4_RTS, # endif .baud = CONFIG_UART4_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_UART4_FREQUENCY, .usartbase = STM32_UART4_BASE, .tx_gpio = GPIO_UART4_TX, .rx_gpio = GPIO_UART4_RX, @@ -807,6 +1013,10 @@ static struct stm32_serial_s g_uart4priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_UART4_WAKE_FROM_LOW_POWER) && defined(CONFIG_UART4_WUS) + .wakefromlowpower = true, + .wus = CONFIG_UART4_WUS, +#endif }; #endif @@ -852,7 +1062,7 @@ static struct stm32_serial_s g_uart5priv = .rts_gpio = GPIO_UART5_RTS, # endif .baud = CONFIG_UART5_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_UART5_FREQUENCY, .usartbase = STM32_UART5_BASE, .tx_gpio = GPIO_UART5_TX, .rx_gpio = GPIO_UART5_RX, @@ -884,6 +1094,10 @@ static struct stm32_serial_s g_uart5priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_UART5_WAKE_FROM_LOW_POWER) && defined(CONFIG_UART5_WUS) + .wakefromlowpower = true, + .wus = CONFIG_UART5_WUS, +#endif }; #endif @@ -921,7 +1135,7 @@ static struct stm32_serial_s g_usart6priv = .bits = CONFIG_USART6_BITS, .stopbits2 = CONFIG_USART6_2STOP, .baud = CONFIG_USART6_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_USART6_FREQUENCY, .usartbase = STM32_USART6_BASE, .tx_gpio = GPIO_USART6_TX, .rx_gpio = GPIO_USART6_RX, @@ -961,6 +1175,10 @@ static struct stm32_serial_s g_usart6priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_USART6_WAKE_FROM_LOW_POWER) && defined(CONFIG_USART6_WUS) + .wakefromlowpower = true, + .wus = CONFIG_USART6_WUS, +#endif }; #endif @@ -1006,7 +1224,7 @@ static struct stm32_serial_s g_uart7priv = .rts_gpio = GPIO_UART7_RTS, # endif .baud = CONFIG_UART7_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_UART7_FREQUENCY, .usartbase = STM32_UART7_BASE, .tx_gpio = GPIO_UART7_TX, .rx_gpio = GPIO_UART7_RX, @@ -1038,6 +1256,10 @@ static struct stm32_serial_s g_uart7priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_UART7_WAKE_FROM_LOW_POWER) && defined(CONFIG_UART7_WUS) + .wakefromlowpower = true, + .wus = CONFIG_UART7_WUS, +#endif }; #endif @@ -1083,7 +1305,7 @@ static struct stm32_serial_s g_uart8priv = .rts_gpio = GPIO_UART8_RTS, # endif .baud = CONFIG_UART8_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_UART8_FREQUENCY, .usartbase = STM32_UART8_BASE, .tx_gpio = GPIO_UART8_TX, .rx_gpio = GPIO_UART8_RX, @@ -1115,6 +1337,10 @@ static struct stm32_serial_s g_uart8priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_UART8_WAKE_FROM_LOW_POWER) && defined(CONFIG_UART8_WUS) + .wakefromlowpower = true, + .wus = CONFIG_UART8_WUS, +#endif }; #endif @@ -1160,7 +1386,7 @@ static struct stm32_serial_s g_uart9priv = .rts_gpio = GPIO_UART9_RTS, # endif .baud = CONFIG_UART9_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_UART9_FREQUENCY, .usartbase = STM32_UART9_BASE, .tx_gpio = GPIO_UART9_TX, .rx_gpio = GPIO_UART9_RX, @@ -1192,6 +1418,10 @@ static struct stm32_serial_s g_uart9priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_UART9_WAKE_FROM_LOW_POWER) && defined(CONFIG_UART9_WUS) + .wakefromlowpower = true, + .wus = CONFIG_UART9_WUS, +#endif }; #endif @@ -1229,7 +1459,7 @@ static struct stm32_serial_s g_usart10priv = .bits = CONFIG_USART10_BITS, .stopbits2 = CONFIG_USART10_2STOP, .baud = CONFIG_USART10_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_USART10_FREQUENCY, .usartbase = STM32_USART10_BASE, .tx_gpio = GPIO_USART10_TX, .rx_gpio = GPIO_USART10_RX, @@ -1269,6 +1499,10 @@ static struct stm32_serial_s g_usart10priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_USART10_WAKE_FROM_LOW_POWER) && defined(CONFIG_USART10_WUS) + .wakefromlowpower = true, + .wus = CONFIG_USART10_WUS, +#endif }; #endif @@ -1306,7 +1540,7 @@ static struct stm32_serial_s g_usart11priv = .bits = CONFIG_USART11_BITS, .stopbits2 = CONFIG_USART11_2STOP, .baud = CONFIG_USART11_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_USART11_FREQUENCY, .usartbase = STM32_USART11_BASE, .tx_gpio = GPIO_USART11_TX, .rx_gpio = GPIO_USART11_RX, @@ -1346,6 +1580,10 @@ static struct stm32_serial_s g_usart11priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_USART11_WAKE_FROM_LOW_POWER) && defined(CONFIG_USART11_WUS) + .wakefromlowpower = true, + .wus = CONFIG_USART11_WUS, +#endif }; #endif @@ -1391,7 +1629,7 @@ static struct stm32_serial_s g_uart12priv = .rts_gpio = GPIO_UART12_RTS, # endif .baud = CONFIG_UART12_BAUD, - .apbclock = STM32_PCLK1_FREQUENCY, + .apbclock = STM32_UART12_FREQUENCY, .usartbase = STM32_UART12_BASE, .tx_gpio = GPIO_UART12_TX, .rx_gpio = GPIO_UART12_RX, @@ -1423,6 +1661,10 @@ static struct stm32_serial_s g_uart12priv = USART_UNCONFIGURE_DIR #endif , +#if defined(CONFIG_UART12_WAKE_FROM_LOW_POWER) && defined(CONFIG_UART12_WUS) + .wakefromlowpower = true, + .wus = CONFIG_UART12_WUS, +#endif }; #endif @@ -2239,19 +2481,21 @@ static int stm32serial_setup(struct uart_dev_s *dev) /* Configure CR1 */ - /* Clear TE, REm and all interrupt enable bits */ + /* Clear UE, TE, RE, and all interrupt enable bits */ regval = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); #ifdef CONFIG_STM32_LPUART1 if (priv->islpuart == true) { - regval &= ~(USART_CR1_TE | USART_CR1_RE | LPUART_CR1_ALLINTS); + regval &= ~(USART_CR1_UE | USART_CR1_TE | USART_CR1_RE | + LPUART_CR1_ALLINTS); } else #endif { - regval &= ~(USART_CR1_TE | USART_CR1_RE | USART_CR1_ALLINTS); + regval &= ~(USART_CR1_UE | USART_CR1_TE | USART_CR1_RE | + USART_CR1_ALLINTS); } stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, regval); @@ -2262,7 +2506,13 @@ static int stm32serial_setup(struct uart_dev_s *dev) regval = stm32serial_getreg(priv, STM32_USART_CR3_OFFSET); regval &= ~(USART_CR3_CTSIE | USART_CR3_CTSE | USART_CR3_RTSE | - USART_CR3_EIE); + USART_CR3_EIE | USART_CR3_WUFIE); + + if (priv->wakefromlowpower) + { + regval |= USART_CR3_WUFIE; + regval |= (priv->wus << USART_CR3_WUS_SHIFT); + } stm32serial_putreg(priv, STM32_USART_CR3_OFFSET, regval); @@ -2273,7 +2523,8 @@ static int stm32serial_setup(struct uart_dev_s *dev) /* Enable Rx, Tx, and the USART */ regval = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); - regval |= (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE); + regval |= (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE | + USART_CR1_FIFOEN); stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, regval); #endif /* CONFIG_SUPPRESS_UART_CONFIG */ @@ -2622,6 +2873,7 @@ static int stm32serial_interrupt(int irq, void *context, void *arg) * " " USART_ISR_NE Noise Error * " " USART_ISR_ORE Overrun Error Detected * USART_CR3_CTSIE USART_ISR_CTS CTS flag (not used) + * USART_CR3_WUFIE USART_ISR_WUF wake up from low power * * NOTE: Some of these status bits must be cleared by explicitly * writing one to the ICR register: USART_ICR_CTSCF, USART_ICR_LBDCF. @@ -2646,6 +2898,13 @@ static int stm32serial_interrupt(int irq, void *context, void *arg) } #endif + /* Wake up from low power mode interrupt */ + + if ((priv->sr & USART_ISR_WUF) != 0) + { + stm32serial_putreg(priv, STM32_USART_ICR_OFFSET, USART_ICR_WUCF); + } + /* Handle incoming, receive bytes. */ if ((priv->sr & USART_ISR_RXNE) != 0 && diff --git a/arch/arm/src/stm32h5/stm32h5xx_rcc.c b/arch/arm/src/stm32h5/stm32h5xx_rcc.c index 049d9cdb46496..b73b90aa9ce04 100644 --- a/arch/arm/src/stm32h5/stm32h5xx_rcc.c +++ b/arch/arm/src/stm32h5/stm32h5xx_rcc.c @@ -706,6 +706,91 @@ static inline void rcc_enableapb3(void) static inline void rcc_enableccip(void) { + /* Configure UART source clock */ +#if defined(STM32_RCC_CCIPR1_USART1SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_USART1SEL_MASK; + regval |= STM32_RCC_CCIPR1_USART1SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR1_USART2SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_USART2SEL_MASK; + regval |= STM32_RCC_CCIPR1_USART2SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR1_USART3SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_USART3SEL_MASK; + regval |= STM32_RCC_CCIPR1_USART3SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR1_UART4SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_UART4SEL_MASK; + regval |= STM32_RCC_CCIPR1_UART4SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR1_UART5SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_UART5SEL_MASK; + regval |= STM32_RCC_CCIPR1_UART5SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR1_USART6SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_USART6SEL_MASK; + regval |= STM32_RCC_CCIPR1_USART6SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR1_UART7SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_UART7SEL_MASK; + regval |= STM32_RCC_CCIPR1_UART7SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR1_UART8SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_UART8SEL_MASK; + regval |= STM32_RCC_CCIPR1_UART8SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR1_UART9SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_UART9SEL_MASK; + regval |= STM32_RCC_CCIPR1_UART9SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR1_USART10SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR1); + + regval &= ~RCC_CCIPR1_USART10SEL_MASK; + regval |= STM32_RCC_CCIPR1_USART10SEL; + putreg32(regval, STM32_RCC_CCIPR1); +#endif +#if defined(STM32_RCC_CCIPR2_USART11SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR2); + + regval &= ~RCC_CCIPR2_USART11SEL_MASK; + regval |= STM32_RCC_CCIPR2_USART11SEL; + putreg32(regval, STM32_RCC_CCIPR2); +#endif +#if defined(STM32_RCC_CCIPR2_UART12SEL) + uint32_t regval = getreg32(STM32_RCC_CCIPR2); + + regval &= ~RCC_CCIPR2_UART12SEL_MASK; + regval |= STM32_RCC_CCIPR2_UART12SEL; + putreg32(regval, STM32_RCC_CCIPR2); +#endif } /**************************************************************************** @@ -876,6 +961,9 @@ void stm32_stdclockconfig(void) regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_HSION; /* Enable HSI */ +#ifdef STM32_BOARD_HSIKERON_ENABLE + regval |= RCC_CR_HSIKERON; /* Keep HSI on during stop mode */ +#endif #if defined(STM32_BOARD_HSIDIV) regval &= ~RCC_CR_HSIDIV_MASK; @@ -1025,6 +1113,12 @@ void stm32_stdclockconfig(void) regval |= RCC_CR_PLL2ON; putreg32(regval, STM32_RCC_CR); + /* Wait until PLL2 is ready */ + + while ((getreg32(STM32_RCC_CR) & RCC_CR_PLL2RDY) == 0) + { + } + #ifdef STM32_PLLCFG_PLL2FRACR regval = STM32_PLLCFG_PLL2FRACR; putreg32(regval, STM32_RCC_PLL2FRACR); From 5d347151507386448f2dab923ec32b1c555fe657 Mon Sep 17 00:00:00 2001 From: Liam Howatt Date: Fri, 18 Sep 2026 16:12:24 -0400 Subject: [PATCH 4/4] Documentation/stm32h5: board.h clock defines. Document the board.h keep-HSI-running-in-stop-mode define STM32_BOARD_HSIKERON_ENABLE and the USART clock source selection defines. Signed-off-by: Liam Howatt --- Documentation/platforms/arm/stm32h5/index.rst | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Documentation/platforms/arm/stm32h5/index.rst b/Documentation/platforms/arm/stm32h5/index.rst index ac6f0b71ab0c5..ee1768faf9bc3 100644 --- a/Documentation/platforms/arm/stm32h5/index.rst +++ b/Documentation/platforms/arm/stm32h5/index.rst @@ -135,6 +135,26 @@ of the block size and count when partitioning the OTP area for their needs. ``len`` is the number of bytes - not words. It has no alignment requirement. ``offset`` is the offset in bytes. It must be a multiple of 4. +Clocks +------ + +``STM32_BOARD_HSIKERON_ENABLE`` can be defined in board.h to keep HSI running in +STOP mode. This can be used to keep a peripheral clocked by HSI running in +STOP mode. + +``STM32_RCC_CCIPR1_U[S]ARTxSEL`` (e.g. ``STM32_RCC_CCIPR1_USART3SEL``) can be defined as one of + +- ``RCC_CCIPR1_U[S]ARTxSEL_RCCPCLK1`` +- ``RCC_CCIPR1_U[S]ARTxSEL_PLL2QCK`` +- ``RCC_CCIPR1_U[S]ARTxSEL_PLL3QCK`` +- ``RCC_CCIPR1_U[S]ARTxSEL_HSIKERCK`` +- ``RCC_CCIPR1_U[S]ARTxSEL_CSIKERCK`` +- ``RCC_CCIPR1_U[S]ARTxSEL_LSECK`` + +E.g. ``RCC_CCIPR1_USART3SEL_HSIKERCK`` in board.h to select the clock source for that USART. +The clock source is set in RCC initialization. Only stm32_serial.c is aware of this setting. +TODO: Make stm32_lowputc.c aware of this clock source setting too. + References ================= [RM0481] Reference Manual: STM32H523/33xx, STM32H562/63xx, and STM32H573xx ArmĀ® -based 32-bit MCUs