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 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_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 */ 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 590facc514488..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 @@ -2008,7 +2250,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 +2293,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 } @@ -2237,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); @@ -2260,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); @@ -2271,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 */ @@ -2558,6 +2811,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); } @@ -2619,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. @@ -2643,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 && @@ -2815,385 +3077,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; - - /* Disable UE, HDSEL can only be written when UE=0 */ + case TIOCSSINGLEWIRE: + { + uint32_t cr1; + uint32_t cr1_ue; + irqstate_t flags; - stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1); + flags = enter_critical_section(); - /* Change the TX port to be open-drain/push-pull and enable/disable - * half-duplex mode. - */ + /* Get the original state of UE */ - uint32_t cr = stm32serial_getreg(priv, STM32_USART_CR3_OFFSET); + cr1 = stm32serial_getreg(priv, STM32_USART_CR1_OFFSET); + cr1_ue = cr1 & USART_CR1_UE; + cr1 &= ~USART_CR1_UE; - if ((arg & SER_SINGLEWIRE_ENABLED) != 0) - { - uint32_t gpio_val = GPIO_OPENDRAIN; + /* Disable UE, HDSEL can only be written when UE=0 */ - if ((arg & SER_SINGLEWIRE_PULL_MASK) == SER_SINGLEWIRE_PULLUP) - { - gpio_val |= GPIO_PULLUP; - } - else - { - gpio_val |= GPIO_FLOAT; - } + stm32serial_putreg(priv, STM32_USART_CR1_OFFSET, cr1); - if ((arg & SER_SINGLEWIRE_PULL_MASK) == SER_SINGLEWIRE_PULLDOWN) - { - gpio_val |= GPIO_PULLDOWN; - } - else - { - gpio_val |= GPIO_FLOAT; - } + /* Change the TX port to be open-drain/push-pull and enable/disable + * half-duplex mode. + */ - if (priv->tx_gpio != 0) - { - stm32_configgpio((priv->tx_gpio & - ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) | - gpio_val); - } + uint32_t cr = stm32serial_getreg(priv, STM32_USART_CR3_OFFSET); - 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 */ + + if (priv->tx_gpio != 0) + { + stm32_configgpio(priv->tx_gpio); + } - priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS; + priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS; - /* Enable further tx activity */ + /* Enable further tx activity */ - stm32serial_txint(dev, true); + stm32serial_txint(dev, true); - leave_critical_section(flags); - } - break; + 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 +4174,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 +4372,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) 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);