diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3d6e64dda8..8061da504c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -430,6 +430,21 @@ config ARCH_CHIP_STM32U5 ---help--- STMicro STM32 U5 architectures (ARM Cortex-M33). +config ARCH_CHIP_STM32WL5 + bool "STMicro STM32 WL5" + select ARCH_CORTEXM4 + select ARCH_HAVE_MPU + select ARCH_HAVE_FETCHADD + select ARCH_HAVE_I2CRESET + select ARCH_HAVE_HEAPCHECK + select ARCH_HAVE_PROGMEM + select ARCH_HAVE_SPI_BITORDER + select ARCH_HAVE_TICKLESS + select ARM_HAVE_MPU_UNIFIED + select ARMV7M_HAVE_STACKCHECK + ---help--- + STMicro STM32WL5 architectures (dual CPU ARM Cortex-M4 Cortex-M0). + config ARCH_CHIP_STR71X bool "STMicro STR71x" select ARCH_ARM7TDMI @@ -852,6 +867,7 @@ config ARCH_CHIP default "stm32l4" if ARCH_CHIP_STM32L4 default "stm32l5" if ARCH_CHIP_STM32L5 default "stm32u5" if ARCH_CHIP_STM32U5 + default "stm32wl5" if ARCH_CHIP_STM32WL5 default "str71x" if ARCH_CHIP_STR71X default "tms570" if ARCH_CHIP_TMS570 default "xmc4" if ARCH_CHIP_XMC4 @@ -1236,6 +1252,9 @@ endif if ARCH_CHIP_STM32U5 source "arch/arm/src/stm32u5/Kconfig" endif +if ARCH_CHIP_STM32WL5 +source "arch/arm/src/stm32wl5/Kconfig" +endif if ARCH_CHIP_STR71X source "arch/arm/src/str71x/Kconfig" endif diff --git a/arch/arm/include/stm32wl5/chip.h b/arch/arm/include/stm32wl5/chip.h new file mode 100644 index 0000000000..89866b89f2 --- /dev/null +++ b/arch/arm/include/stm32wl5/chip.h @@ -0,0 +1,68 @@ +/**************************************************************************** + * arch/arm/include/stm32wl5/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_INCLUDE_STM32WL5_CHIP_H +#define __ARCH_ARM_INCLUDE_STM32WL5_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +#if defined(CONFIG_STM32WL5_STM32WL5XXX) +# define STM32WL5_SRAM1_SIZE (32*1024) /* 32kB SRAM1 on AHB bus Matrix */ +# define STM32WL5_SRAM2_SIZE (32*1024) /* 32kB SRAM2 on AHB bus Matrix */ +#else +# error "Unsupported STM32L5 chip" +#endif + +#if defined(CONFIG_STM32WL5_STM32WL5XXX_CPU1) +# define STM32WL5_NATIM 1 /* One advanced timer TIM1 */ +# define STM32WL5_NGTIM32 1 /* 32-bit general timer TIM2 with DMA */ +# define STM32WL5_NGTIM16 2 /* 16-bit general timers TIM16 and 17 with DMA */ +# define STM32WL5_NLPTIM 3 /* Three low-power timer, LPTIM1-3 */ +# define STM32WL5_NRNG 1 /* Random number generator (RNG) */ +# define STM32WL5_NUSART 2 /* USART 1-2 */ +# define STM32WL5_NLPUART 1 /* LPUART 1 */ +# define STM32WL5_NSPI 2 /* SPI1 and SPI2S2 (spi2 shared with i2s) */ +# define STM32WL5_NI2C 3 /* I2C1-3 */ +# define STM32WL5_NDMA 2 /* Two DMA channels DMA1-2 */ +# define STM32WL5_NPORTS 4 /* GPIO{A,B,C,H} */ +# define STM32WL5_NADC 1 /* ADC1 */ +# define STM32WL5_NDAC 1 /* DAC1 */ +# define STM32WL5_NCRC 1 /* CRC1 */ +# define STM32WL5_NCOMP 1 /* COMP1 */ +#endif /* CONFIG_STM32WL5_STM32WL5XXX */ + +/* NVIC priority levels *****************************************************/ + +/* 16 Programmable interrupt levels */ + +#define NVIC_SYSH_PRIORITY_MIN 0xf0 /* All bits set in minimum priority */ +#define NVIC_SYSH_PRIORITY_DEFAULT 0x80 /* Midpoint is the default */ +#define NVIC_SYSH_PRIORITY_MAX 0x00 /* Zero is maximum priority */ +#define NVIC_SYSH_PRIORITY_STEP 0x10 /* Four bits of interrupt priority used */ + +#endif /* __ARCH_ARM_INCLUDE_STM32WL5_CHIP_H */ diff --git a/arch/arm/include/stm32wl5/irq.h b/arch/arm/include/stm32wl5/irq.h new file mode 100644 index 0000000000..a5132a7f84 --- /dev/null +++ b/arch/arm/include/stm32wl5/irq.h @@ -0,0 +1,103 @@ +/**************************************************************************** + * arch/arm/include/stm32wl5/irq.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, + * only indirectly through nuttx/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_STM32WL5_IRQ_H +#define __ARCH_ARM_INCLUDE_STM32WL5_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* IRQ numbers. The IRQ number corresponds vector number and hence map + * directly to bits in the NVIC. This does, however, waste several words of + * memory in the IRQ to handle mapping tables. + */ + +/* Processor Exceptions (vectors 0-15) */ + +#define STM32WL5_IRQ_RESERVED (0) /* Reserved vector (only used with CONFIG_DEBUG_FEATURES) */ + /* Vector 0: Reset stack pointer value */ + /* Vector 1: Reset (not handler as an IRQ) */ +#define STM32WL5_IRQ_NMI (2) /* Vector 2: Non-Maskable Interrupt (NMI) */ +#define STM32WL5_IRQ_HARDFAULT (3) /* Vector 3: Hard fault */ +#define STM32WL5_IRQ_MEMFAULT (4) /* Vector 4: Memory management (MPU) */ +#define STM32WL5_IRQ_BUSFAULT (5) /* Vector 5: Bus fault */ +#define STM32WL5_IRQ_USAGEFAULT (6) /* Vector 6: Usage fault */ + /* Vectors 7-10: Reserved */ +#define STM32WL5_IRQ_SVCALL (11) /* Vector 11: SVC call */ +#define STM32WL5_IRQ_DBGMONITOR (12) /* Vector 12: Debug Monitor */ + /* Vector 13: Reserved */ +#define STM32WL5_IRQ_PENDSV (14) /* Vector 14: Pendable system service request */ +#define STM32WL5_IRQ_SYSTICK (15) /* Vector 15: System tick */ + +/* External interrupts (vectors >= 16). These definitions are + * chip-specific + */ + +#define STM32WL5_IRQ_FIRST (16) /* Vector number of the first external interrupt */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#if defined(CONFIG_STM32WL5_STM32WL5XXX_CPU1) +# include +#else +# error "Unsupported STM32 L5 chip" +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_STM32WL5_IRQ_H */ diff --git a/arch/arm/include/stm32wl5/stm32wl5xxx_cpu1_irq.h b/arch/arm/include/stm32wl5/stm32wl5xxx_cpu1_irq.h new file mode 100644 index 0000000000..878d996c45 --- /dev/null +++ b/arch/arm/include/stm32wl5/stm32wl5xxx_cpu1_irq.h @@ -0,0 +1,151 @@ +/**************************************************************************** + * arch/arm/include/stm32wl5/stm32wl5xxx_cpu1_irq.h + + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* This file should never be included directly but, rather, only indirectly + * through arch/irq.h + */ + +#ifndef __ARCH_ARM_INCLUDE_STM32WL5_STM32WL5XXX_CPU1_IRQ_H +#define __ARCH_ARM_INCLUDE_STM32WL5_STM32WL5XXX_CPU1_IRQ_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Prototypes + ****************************************************************************/ + +/* IRQ numbers. The IRQ number corresponds vector number and hence map + * directly to bits in the NVIC. This does, however, waste several words of + * memory in the IRQ to handle mapping tables. + * + * Processor Exceptions (vectors 0-15). These common definitions can be + * found in the file nuttx/arch/arm/include/stm32wl5/irq.h which includes + * this file + * + * External interrupts (vectors >= 16) + */ + +#define STM32WL5_IRQ_WWDG (STM32WL5_IRQ_FIRST + 0) /* 0: Window watchdog early wakeup */ +#define STM32WL5_IRQ_PVD (STM32WL5_IRQ_FIRST + 1) /* 1: PVD through EXTI[16] */ +#define STM32WL5_IRQ_PVM (STM32WL5_IRQ_FIRST + 1) /* 1: PVM through EXTI[34] */ +#define STM32WL5_IRQ_TAMPER (STM32WL5_IRQ_FIRST + 2) /* 2: Tamper */ +#define STM32WL5_IRQ_LSE_CSS (STM32WL5_IRQ_FIRST + 2) /* 2: LSECSS */ +#define STM32WL5_IRQ_RTC_STAMP (STM32WL5_IRQ_FIRST + 2) /* 2: timestamp */ +#define STM32WL5_IRQ_RTC_SSRU (STM32WL5_IRQ_FIRST + 2) /* 2: RTC SSR underflow */ +#define STM32WL5_IRQ_RTC_WKUP (STM32WL5_IRQ_FIRST + 3) /* 3: RTC wakeup interrupt */ +#define STM32WL5_IRQ_FLASH (STM32WL5_IRQ_FIRST + 4) /* 4: Flash memory global interrupt and Flash memory ECC single error interrupt */ +#define STM32WL5_IRQ_RCC (STM32WL5_IRQ_FIRST + 5) /* 5: RCC global interrupt */ +#define STM32WL5_IRQ_EXTI0 (STM32WL5_IRQ_FIRST + 6) /* 6: EXTI line 0 interrupt through EXTI[0] */ +#define STM32WL5_IRQ_EXTI1 (STM32WL5_IRQ_FIRST + 7) /* 7: EXTI line 1 interrupt through EXTI[1] */ +#define STM32WL5_IRQ_EXTI2 (STM32WL5_IRQ_FIRST + 8) /* 8: EXTI line 2 interrupt through EXTI[2] */ +#define STM32WL5_IRQ_EXTI3 (STM32WL5_IRQ_FIRST + 9) /* 9: EXTI line 3 interrupt through EXTI[3] */ +#define STM32WL5_IRQ_EXTI4 (STM32WL5_IRQ_FIRST + 10) /* 10: EXTI line 4 interrupt through EXTI[4] */ +#define STM32WL5_IRQ_DMA1CH1 (STM32WL5_IRQ_FIRST + 11) /* 11: DMA1 channel 1 non-secure interrupt */ +#define STM32WL5_IRQ_DMA1CH2 (STM32WL5_IRQ_FIRST + 12) /* 12: DMA1 channel 2 non-secure interrupt */ +#define STM32WL5_IRQ_DMA1CH3 (STM32WL5_IRQ_FIRST + 13) /* 13: DMA1 channel 3 non-secure interrupt */ +#define STM32WL5_IRQ_DMA1CH4 (STM32WL5_IRQ_FIRST + 14) /* 14: DMA1 channel 4 non-secure interrupt */ +#define STM32WL5_IRQ_DMA1CH5 (STM32WL5_IRQ_FIRST + 15) /* 15: DMA1 channel 5 non-secure interrupt */ +#define STM32WL5_IRQ_DMA1CH6 (STM32WL5_IRQ_FIRST + 16) /* 16: DMA1 channel 6 non-secure interrupt */ +#define STM32WL5_IRQ_DMA1CH7 (STM32WL5_IRQ_FIRST + 17) /* 17: DMA1 channel 7 non-secure interrupt */ +#define STM32WL5_IRQ_ADC (STM32WL5_IRQ_FIRST + 18) /* 18: ADC global interrupt */ +#define STM32WL5_IRQ_DAC (STM32WL5_IRQ_FIRST + 19) /* 19: DAC global interrupt */ +#define STM32WL5_IRQ_C2SEV (STM32WL5_IRQ_FIRST + 20) /* 20: CPU2 SEV through EXTI[40] */ +#define STM32WL5_IRQ_PWRC2H (STM32WL5_IRQ_FIRST + 20) /* 20: PWR CPU2 HOLD wakeup */ +#define STM32WL5_IRQ_COMP (STM32WL5_IRQ_FIRST + 21) /* 21: COMP2 and COMP1 interrupt through EXTI[22:21] */ +#define STM32WL5_IRQ_EXTI95 (STM32WL5_IRQ_FIRST + 22) /* 22: EXTI line [9:5] interrupt through EXTI[9:5] */ +#define STM32WL5_IRQ_TIM1BRK (STM32WL5_IRQ_FIRST + 23) /* 23: Timer 1 break interrupt */ +#define STM32WL5_IRQ_TIM1UP (STM32WL5_IRQ_FIRST + 24) /* 24: Timer 1 Update */ +#define STM32WL5_IRQ_TIM1TRG_COM (STM32WL5_IRQ_FIRST + 25) /* 25: Timer 1 trigger and communication */ +#define STM32WL5_IRQ_TIM1CC (STM32WL5_IRQ_FIRST + 26) /* 26: Timer 1 capture compare interrupt */ +#define STM32WL5_IRQ_TIM2 (STM32WL5_IRQ_FIRST + 27) /* 27: Timer 2 global interrupt */ +#define STM32WL5_IRQ_TIM16 (STM32WL5_IRQ_FIRST + 28) /* 28: Timer 16 global interrupt */ +#define STM32WL5_IRQ_TIM17 (STM32WL5_IRQ_FIRST + 29) /* 29: Timer 17 global interrupt */ +#define STM32WL5_IRQ_I2C1EV (STM32WL5_IRQ_FIRST + 30) /* 30: I2C1 event interrupt */ +#define STM32WL5_IRQ_I2C1ER (STM32WL5_IRQ_FIRST + 31) /* 31: I2C1 error interrupt */ +#define STM32WL5_IRQ_I2C2EV (STM32WL5_IRQ_FIRST + 32) /* 32: I2C2 event interrupt */ +#define STM32WL5_IRQ_I2C2ER (STM32WL5_IRQ_FIRST + 33) /* 33: I2C2 error interrupt */ +#define STM32WL5_IRQ_SPI1 (STM32WL5_IRQ_FIRST + 34) /* 34: SPI1 global interrupt */ +#define STM32WL5_IRQ_SPI2S2 (STM32WL5_IRQ_FIRST + 35) /* 35: SPI2S2 global interrupt */ +#define STM32WL5_IRQ_USART1 (STM32WL5_IRQ_FIRST + 36) /* 36: USART1 global interrupt */ +#define STM32WL5_IRQ_USART2 (STM32WL5_IRQ_FIRST + 37) /* 37: USART2 global interrupt */ +#define STM32WL5_IRQ_LPUART1 (STM32WL5_IRQ_FIRST + 38) /* 38: LPUART1 global interrupt */ +#define STM32WL5_IRQ_LPTIM1 (STM32WL5_IRQ_FIRST + 39) /* 39: LP timer 1 global interrupt */ +#define STM32WL5_IRQ_LPTIM2 (STM32WL5_IRQ_FIRST + 40) /* 40: LP timer 2 global interrupt */ +#define STM32WL5_IRQ_EXTI1510 (STM32WL5_IRQ_FIRST + 41) /* 41: EXTI line [15:10] interrupt through EXTI[15:10] (IMR1[31:26]) */ +#define STM32WL5_IRQ_RTCALRM (STM32WL5_IRQ_FIRST + 42) /* 42: RTC alarms A and B interrupt */ +#define STM32WL5_IRQ_LPTIM3 (STM32WL5_IRQ_FIRST + 43) /* 43: LP timer 3 global interrupt */ + /* 44: Reserved */ +#define STM32WL5_IRQ_IPCC_C1_RX_IT (STM32WL5_IRQ_FIRST + 45) /* 45: IPCC CPU1 RX occupied interrupt */ +#define STM32WL5_IRQ_IPCC_C1_TX_IT (STM32WL5_IRQ_FIRST + 46) /* 46: IPCC CPU1 TX free interrupt */ +#define STM32WL5_IRQ_HSEM (STM32WL5_IRQ_FIRST + 47) /* 47: Semaphore interrupt 0 to CPU1 */ +#define STM32WL5_IRQ_I2C3EV (STM32WL5_IRQ_FIRST + 48) /* 48: I2C3 event interrupt */ +#define STM32WL5_IRQ_I2C3ER (STM32WL5_IRQ_FIRST + 49) /* 49: I2C3 error interrupt */ +#define STM32WL5_IRQ_RADIO (STM32WL5_IRQ_FIRST + 50) /* 50: Radio */ +#define STM32WL5_IRQ_RFBUSY (STM32WL5_IRQ_FIRST + 50) /* 50: RFBUSY interrupt through EXTI[45] */ +#define STM32WL5_IRQ_AES (STM32WL5_IRQ_FIRST + 51) /* 51: AES global interrupt */ +#define STM32WL5_IRQ_RNG (STM32WL5_IRQ_FIRST + 52) /* 52: True random number generator interrupt */ +#define STM32WL5_IRQ_PKA (STM32WL5_IRQ_FIRST + 53) /* 53: Private key accelerator interrupt */ +#define STM32WL5_IRQ_DMA2CH1 (STM32WL5_IRQ_FIRST + 54) /* 54: DMA2 channel 1 non-secure interrupt */ +#define STM32WL5_IRQ_DMA2CH2 (STM32WL5_IRQ_FIRST + 55) /* 55: DMA2 channel 2 non-secure interrupt */ +#define STM32WL5_IRQ_DMA2CH3 (STM32WL5_IRQ_FIRST + 56) /* 56: DMA2 channel 3 non-secure interrupt */ +#define STM32WL5_IRQ_DMA2CH4 (STM32WL5_IRQ_FIRST + 57) /* 57: DMA2 channel 4 non-secure interrupt */ +#define STM32WL5_IRQ_DMA2CH5 (STM32WL5_IRQ_FIRST + 58) /* 58: DMA2 channel 5 non-secure interrupt */ +#define STM32WL5_IRQ_DMA2CH6 (STM32WL5_IRQ_FIRST + 59) /* 59: DMA2 channel 6 non-secure interrupt */ +#define STM32WL5_IRQ_DMA2CH7 (STM32WL5_IRQ_FIRST + 60) /* 60: DMA2 channel 7 non-secure interrupt */ +#define STM32WL5_IRQ_DMAMUX1_OVR (STM32WL5_IRQ_FIRST + 61) /* 61: DMAMUX1 overrun interrupt */ + +#define STM32WL5_IRQ_NEXTINTS 62 + +/* (EXTI interrupts do not use IRQ numbers) */ + +#define NR_IRQS (STM32WL5_IRQ_FIRST + STM32WL5_IRQ_NEXTINTS) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#undef EXTERN +#ifdef __cplusplus +} +#endif +#endif + +#endif /* __ARCH_ARM_INCLUDE_STM32WL5_STM32WL5XXX_CPU1_IRQ_H */ diff --git a/arch/arm/src/stm32wl5/Kconfig b/arch/arm/src/stm32wl5/Kconfig new file mode 100644 index 0000000000..750051cfdc --- /dev/null +++ b/arch/arm/src/stm32wl5/Kconfig @@ -0,0 +1,223 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if ARCH_CHIP_STM32WL5 + +comment "STM32WL5 Configuration Options" + +choice + prompt "STM32 WL5 Chip Selection" + default ARCH_CHIP_STM32WL55JC_CPU1 + depends on ARCH_CHIP_STM32WL5 + +config ARCH_CHIP_STM32WL55JC_CPU1 + bool "STM32WL55JC (cpu1)" + select STM32WL5_STM32WL5XXX_CPU1 + select STM32WL5_STM32WL5XXX + select STM32WL5_FLASH_CONFIG_C + ---help--- + STM32 WL5 Cortex M4 (cpu1), 256kiB FLASH, 64kiB SRAM + +config ARCH_CHIP_STM32WL55JC_CPU2 + bool "STM32WL55JC (cpu2)" + select STM32WL5_STM32WL5XXX_CPU2 + select STM32WL5_STM32WL5XXX + select STM32WL5_FLASH_CONFIG_C + ---help--- + STM32 WL5 Cortex M0 (cpu2), 256kiB FLASH, 64kiB SRAM + + +endchoice # STM32 WL5 Chip Selection + +# Chip product lines + +config STM32WL5_STM32WL5XXX + bool + +config STM32WL5_STM32WL5XXX_CPU1 + bool + default y + select STM32WL5_HAVE_USART1 + select STM32WL5_HAVE_USART2 + select STM32WL5_HAVE_LPUART1 + + +comment "STM32WL5 Peripherals" + +menu "STM32WL5 Peripheral Support" + +choice + prompt "Override Flash Size Designator" + depends on ARCH_CHIP_STM32WL5 + default STM32WL5_FLASH_OVERRIDE_DEFAULT + ---help--- + STM32WL5 series parts numbering (sans the package type) ends with a letter + that designates the FLASH size. + + Designator Size in KiB + 8 64 + B 128 + C 256 + E 512 + G 1024 + I 2048 + + This configuration option defaults to using the configuration based on that designator + or the default smaller size if there is no last character designator is present in the + STM32 Chip Selection. + + Examples: + If the STM32WL55JC is chosen, the Flash configuration would be 'C', if a variant of + the part with a 1024 KiB Flash is released in the future one could simply select + the 'G' designator here. + + If an STM32WL5xxx Series parts is chosen the default Flash configuration will be set + herein and can be changed. + +config STM32WL5_FLASH_OVERRIDE_DEFAULT + bool "Default" + +config STM32WL5_FLASH_OVERRIDE_8 + bool "8 64 KB" + +config STM32WL5_FLASH_OVERRIDE_B + bool "B 128 KB" + +config STM32WL5_FLASH_OVERRIDE_C + bool "C 256 KB" + +config STM32WL5_FLASH_OVERRIDE_E + bool "E 512 KB" + +config STM32WL5_FLASH_OVERRIDE_G + bool "G 1024 KB" + +endchoice # "Override Flash Size Designator" + +# Flash configurations + +config STM32WL5_FLASH_CONFIG_8 + bool + default n + +config STM32WL5_FLASH_CONFIG_B + bool + default n + +config STM32WL5_FLASH_CONFIG_C + bool + default n + +config STM32WL5_FLASH_CONFIG_E + bool + default n + +config STM32WL5_FLASH_CONFIG_G + bool + default n + +# These "hidden" settings determine whether a peripheral option is available +# for the selected MCU + +config STM32WL5_HAVE_USART1 + bool + default n + +config STM32WL5_HAVE_USART2 + bool + default n + +config STM32WL5_HAVE_LPUART1 + bool + default n + +# These "hidden" settings are the OR of individual peripheral selections +# indicating that the general capability is required. + +config STM32WL5_USART + bool + default n + + +# These are the peripheral selections proper + +comment "APB1 Peripherals" + +config STM32WL5_USART2 + bool "USART2" + default n + depends on STM32WL5_HAVE_USART2 + select ARCH_HAVE_SERIAL_TERMIOS + select STM32WL5_USART + +config STM32WL5_LPUART1 + bool "LPUART1" + default n + depends on STM32WL5_HAVE_LPUART1 + select ARCH_HAVE_SERIAL_TERMIOS + select STM32WL5_USART + +comment "APB2 Peripherals" + +config STM32WL5_SYSCFG + bool "SYSCFG" + default y + +config STM32WL5_USART1 + bool "USART1" + default n + depends on STM32WL5_HAVE_USART1 + select ARCH_HAVE_SERIAL_TERMIOS + select STM32WL5_USART + + +endmenu # STM32WL5 Peripheral Support + + +config STM32WL5_SERIALDRIVER + bool + +menu "[LP]U[S]ART Configuration" + depends on STM32WL5_USART + +choice + prompt "USART1 Driver Configuration" + default STM32WL5_USART1_SERIALDRIVER + depends on STM32WL5_USART1 + +config STM32WL5_USART1_SERIALDRIVER + bool "Standard serial driver" + select USART1_SERIALDRIVER + select STM32WL5_SERIALDRIVER + +endchoice # USART1 Driver Configuration + +choice + prompt "USART2 Driver Configuration" + default STM32WL5_USART2_SERIALDRIVER + depends on STM32WL5_USART2 + +config STM32WL5_USART2_SERIALDRIVER + bool "Standard serial driver" + select USART2_SERIALDRIVER + select STM32WL5_SERIALDRIVER + +endchoice # USART2 Driver Configuration + +choice + prompt "LPUART1 Driver Configuration" + default STM32WL5_LPUART1_SERIALDRIVER + depends on STM32WL5_LPUART1 + +config STM32WL5_LPUART1_SERIALDRIVER + bool "Standard serial driver" + select LPUART1_SERIALDRIVER + select STM32WL5_SERIALDRIVER + +endchoice # LPUART1 Driver Configuration + +endmenu # [LP]U[S]ART Configuration + +endif # ARCH_CHIP_STM32WL5 diff --git a/arch/arm/src/stm32wl5/Make.defs b/arch/arm/src/stm32wl5/Make.defs new file mode 100644 index 0000000000..b7917433a2 --- /dev/null +++ b/arch/arm/src/stm32wl5/Make.defs @@ -0,0 +1,34 @@ +############################################################################ +# arch/arm/src/stm32wl5/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +# The start-up, "head", file. Only common vectors are support so there +# isn't one. + +# Common ARM and Cortex-M4 files (copied from stm32/Make.defs) + +include armv7-m/Make.defs + +# Required STM32WL5 files + +CHIP_CSRCS = stm32wl5_allocateheap.c stm32wl5_exti_gpio.c stm32wl5_gpio.c +CHIP_CSRCS += stm32wl5_irq.c stm32wl5_lowputc.c stm32wl5_rcc.c +CHIP_CSRCS += stm32wl5_serial.c stm32wl5_start.c stm32wl5_waste.c stm32wl5_uid.c +CHIP_CSRCS += stm32wl5_lse.c stm32wl5_lsi.c stm32wl5_idle.c +CHIP_CSRCS += stm32wl5_pwr.c stm32wl5_tim.c stm32wl5_flash.c stm32wl5_timerisr.c diff --git a/arch/arm/src/stm32wl5/README.txt b/arch/arm/src/stm32wl5/README.txt new file mode 100644 index 0000000000..b869081690 --- /dev/null +++ b/arch/arm/src/stm32wl5/README.txt @@ -0,0 +1,48 @@ +This is a port of NuttX to the STM32WL5 Family. + +Used development board is Nucleo WL55JC. + +Most code is copied and adapted from STM32L4 and STM32L5 ports. + +There are only two chips in family, STM32WL55 and STM32WL54. Only difference +between them is that STM32WL55 has LORA radio while WL54 does not. + +STM32WL5 is a dual CPU (not core!) platform. Separate code must be generated +for both of them. + +Only CPU0 has access to radio, but other peripherals are shared. CPU1 can +initialize all hardware (except for radio and CPU0 specific registers). + +TODO list +--------- + +IRQs : OK +GPIO : OK +EXTI : TODO +HSE : OK +PLL : OK @ 48MHz +HSI : Not tested +MSI : Not tested +LSE : Not tested +RCC : All registers defined, not all peripherals enabled +SYSCFG : All registers defined, remapping not tested +USART : OK +LPUART : Partial OK + OK - full speed with HSE + TODO - low power mode with LSE +DMA : TODO +SRAM2 : TODO +SPI : TODO +I2C : TODO +RTC : TODO +Timers : TODO +PM : TODO +AES : TODO +RNG : TODO +CRC : TODO +WWDG : TODO +IWDG : TODO +ADC : TODO +DAC : TODO +CPU0<->CPU1 : TODO +Radio@CPU0 : TODO diff --git a/arch/arm/src/stm32wl5/chip.h b/arch/arm/src/stm32wl5/chip.h new file mode 100644 index 0000000000..3688e6b330 --- /dev/null +++ b/arch/arm/src/stm32wl5/chip.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/chip.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_CHIP_H +#define __ARCH_ARM_SRC_STM32WL5_CHIP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/* Include the memory map and the chip definitions file. + * Other chip hardware files should then include this file for the proper + * setup. + */ + +#include +#include +#include "hardware/stm32wl5_pinmap.h" +#include "hardware/stm32wl5_memorymap.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* If the common ARMv7-M vector handling logic is used, then it expects the + * following definition in this file that provides the number of supported + * external interrupts which, for this architecture, is provided in the + * arch/stm32wl5/chip.h header file. + */ + +#define ARMV7M_PERIPHERAL_INTERRUPTS STM32WL5_IRQ_NEXTINTS + +/* Cache line sizes (in bytes) for the STM32WL5 */ + +#define ARMV7M_DCACHE_LINESIZE 0 /* no cache */ +#define ARMV7M_ICACHE_LINESIZE 0 /* no cache */ + +#endif /* __ARCH_ARM_SRC_STM32WL5_CHIP_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_exti.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_exti.h new file mode 100644 index 0000000000..9b9b211196 --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_exti.h @@ -0,0 +1,106 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_exti.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_EXTI_H +#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_EXTI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define STM32WL5_EXTI_RTSR1_OFFSET 0x0000 /* Rising Trigger Selection 1 */ +#define STM32WL5_EXTI_FTSR1_OFFSET 0x0004 /* Falling Trigger Selection 1 */ +#define STM32WL5_EXTI_SWIER1_OFFSET 0x0008 /* Software Interrupt Event 1 */ +#define STM32WL5_EXTI_PR1_OFFSET 0x000c /* Pending 1 */ +#define STM32WL5_EXTI_RTSR2_OFFSET 0x0020 /* Rising Trigger Selection 2 */ +#define STM32WL5_EXTI_FTSR2_OFFSET 0x0024 /* Falling Trigger Selection 2 */ +#define STM32WL5_EXTI_SWIER2_OFFSET 0x0028 /* Software Interrupt Event 2 */ +#define STM32WL5_EXTI_PR2_OFFSET 0x002c /* Pending 2 */ +#define STM32WL5_EXTI_C1IMR1_OFFSET 0x0080 /* CPU Wakeup with Interrupt Mask 1 for cpu1 */ +#define STM32WL5_EXTI_C1EMR1_OFFSET 0x0084 /* CPU Wakeup with Event Mask 1 for cpu1 */ +#define STM32WL5_EXTI_C1IMR2_OFFSET 0x0090 /* CPU Wakeup with Interrupt Mask 2 for cpu1 */ +#define STM32WL5_EXTI_C1EMR2_OFFSET 0x0094 /* CPU Wakeup with Event Mask 2 for cpu1 */ +#define STM32WL5_EXTI_C2IMR1_OFFSET 0x00c0 /* CPU Wakeup with Interrupt Mask 1 for cpu2 */ +#define STM32WL5_EXTI_C2EMR1_OFFSET 0x00c4 /* CPU Wakeup with Event Mask 1 for cpu2 */ +#define STM32WL5_EXTI_C2IMR2_OFFSET 0x00d0 /* CPU Wakeup with Interrupt Mask 2 for cpu2 */ +#define STM32WL5_EXTI_C2EMR2_OFFSET 0x00d4 /* CPU Wakeup with Event Mask 2 for cpu2 */ + +/* Register Addresses *******************************************************/ + +#define STM32WL5_EXTI_RTSR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_RTSR1_OFFSET) +#define STM32WL5_EXTI_FTSR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_FTSR1_OFFSET) +#define STM32WL5_EXTI_SWIER1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_SWIER1_OFFSET) +#define STM32WL5_EXTI_PR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_PR1_OFFSET) +#define STM32WL5_EXTI_RTSR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_RTSR2_OFFSET) +#define STM32WL5_EXTI_FTSR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_FTSR2_OFFSET) +#define STM32WL5_EXTI_SWIER2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_SWIER2_OFFSET) +#define STM32WL5_EXTI_PR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_PR2_OFFSET) +#define STM32WL5_EXTI_C1IMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1IMR1_OFFSET) +#define STM32WL5_EXTI_C1EMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1EMR1_OFFSET) +#define STM32WL5_EXTI_C1IMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1IMR2_OFFSET) +#define STM32WL5_EXTI_C1EMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C1EMR2_OFFSET) +#define STM32WL5_EXTI_C2IMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2IMR1_OFFSET) +#define STM32WL5_EXTI_C2EMR1 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2EMR1_OFFSET) +#define STM32WL5_EXTI_C2IMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2IMR2_OFFSET) +#define STM32WL5_EXTI_C2EMR2 (STM32WL5_EXTI_BASE+STM32WL5_EXTI_C2EMR2_OFFSET) + +/* Register Bitfield Definitions ********************************************/ + +/* EXTI lines > 15 are associated with internal devices: */ + +#define EXTI1_PVD (1 << 16) /* EXTI line 16: PVD output */ +#define EXTI1_RTC (1 << 17) /* EXTI line 17: RTC */ +#define EXTI1_SSRU (1 << 18) /* EXTI line 18: RTC underflow */ +#define EXTI1_TAMP (1 << 19) /* EXTI line 19: TAMP */ +#define EXTI1_WKUP (1 << 20) /* EXTI line 20: RTC wakeup */ +#define EXTI1_COMP1 (1 << 21) /* EXTI line 21: COMP1 output */ +#define EXTI1_COMP2 (1 << 22) /* EXTI line 22: COMP2 output */ +#define EXTI1_I2C1 (1 << 23) /* EXTI line 23: I2C1 wakeup */ +#define EXTI1_I2C2 (1 << 24) /* EXTI line 24: I2C2 wakeup */ +#define EXTI1_I2C3 (1 << 25) /* EXTI line 25: I2C3 wakeup */ +#define EXTI1_USART1 (1 << 26) /* EXTI line 26: USART1 wakeup */ +#define EXTI1_USART2 (1 << 27) /* EXTI line 27: USART2 wakeup */ +#define EXTI1_LPUART1 (1 << 28) /* EXTI line 28: LPUART1 wakeup */ +#define EXTI1_LPTIM1 (1 << 29) /* EXTI line 29: LPTIM1 */ +#define EXTI1_LPTIM2 (1 << 30) /* EXTI line 30: LPTIM2 */ +#define EXTI1_LPTIM3 (1 << 31) /* EXTI line 31: LPTIM3 */ +#define EXTI2_PVM3 (1 << 3) /* EXTI line 34: PVM3 wakeup */ +#define EXTI2_C1IPCC (1 << 5) /* EXTI line 36: IPCC cpu1 RX occupied */ +#define EXTI2_C2IPCC (1 << 6) /* EXTI line 37: IPCC cpu1 RX occupied */ +#define EXTI2_C1HSEM (1 << 7) /* EXTI line 38: Semaphore irq 0 with cpu1 */ +#define EXTI2_C2HSEM (1 << 8) /* EXTI line 39: Semaphore irq 1 with cpu2 */ +#define EXTI2_C2SEV (1 << 9) /* EXTI line 40: CPU2 SEV line */ +#define EXTI2_C1SEV (1 << 10) /* EXTI line 41: CPU1 SEV line */ +#define EXTI2_FLASH (1 << 11) /* EXTI line 42: Flash ECC */ +#define EXTI2_HSE32CSS (1 << 12) /* EXTI line 43: RCC HSE32 CSS interrupt */ +#define EXTI2_RADIOIRQ (1 << 13) /* EXTI line 44: Radio interrupt */ +#define EXTI2_RADIOBSY (1 << 14) /* EXTI line 45: Radio busy wakeup */ +#define EXTI2_CDBGPWRUPREQ (1 << 15) /* EXTI line 46: Debug power-up request wakup */ + +#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_EXTI_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h new file mode 100644 index 0000000000..757f7e689a --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h @@ -0,0 +1,304 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_flash.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_FLASH_H +#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_FLASH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Flash size is known from the chip selection: + * + * When CONFIG_STM32WL5_FLASH_OVERRIDE_DEFAULT is set the + * CONFIG_STM32WL5_FLASH_CONFIG_x selects the default FLASH size based + * on the chip part number. This value can be overridden with + * CONFIG_STM32WL5_FLASH_OVERRIDE_x. For example: + * + * Parts STM32WL5xx8 have 64KiB of FLASH + * Parts STM32WL5xxB have 128KiB of FLASH + * Parts STM32WL5xxC have 256KiB of FLASH + * + * STM32WL5xxx has only single bank flash and page size 2KiB + */ + +#define _K(x) ((x)*1024) + +#if !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_DEFAULT) && \ + !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_8) && \ + !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_B) && \ + !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_C) && \ + !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_E) && \ + !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_G) && \ + !defined(CONFIG_STM32WL5_FLASH_CONFIG_8) && \ + !defined(CONFIG_STM32WL5_FLASH_CONFIG_B) && \ + !defined(CONFIG_STM32WL5_FLASH_CONFIG_C) && \ + !defined(CONFIG_STM32WL5_FLASH_CONFIG_E) && \ + !defined(CONFIG_STM32WL5_FLASH_CONFIG_G) +# define CONFIG_STM32WL5_FLASH_OVERRIDE_E +# warning "Flash size not defined defaulting to 512KiB (E)" +#endif + +/* Override of the Flash has been chosen */ + +#if !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_DEFAULT) +# undef CONFIG_STM32WL5_FLASH_CONFIG_8 +# undef CONFIG_STM32WL5_FLASH_CONFIG_B +# undef CONFIG_STM32WL5_FLASH_CONFIG_C +# undef CONFIG_STM32WL5_FLASH_CONFIG_E +# undef CONFIG_STM32WL5_FLASH_CONFIG_G +# if defined(CONFIG_STM32WL5_FLASH_OVERRIDE_8) +# define CONFIG_STM32WL5_FLASH_CONFIG_8 +# elif defined(CONFIG_STM32WL5_FLASH_OVERRIDE_B) +# define CONFIG_STM32WL5_FLASH_CONFIG_B +# elif defined(CONFIG_STM32WL5_FLASH_OVERRIDE_C) +# define CONFIG_STM32WL5_FLASH_CONFIG_C +# elif defined(CONFIG_STM32WL5_FLASH_OVERRIDE_E) +# define CONFIG_STM32WL5_FLASH_CONFIG_E +# elif defined(CONFIG_STM32WL5_FLASH_OVERRIDE_G) +# define CONFIG_STM32WL5_FLASH_CONFIG_G +# endif +#endif + +/* Define the valid configuration */ + +#if defined(CONFIG_STM32WL5_FLASH_CONFIG_8) /* 64 kB */ +# define STM32WL5_FLASH_NPAGES 32 +# define STM32WL5_FLASH_PAGESIZE 2048 +#elif defined(CONFIG_STM32WL5_FLASH_CONFIG_B) /* 128 kB */ +# define STM32WL5_FLASH_NPAGES 64 +# define STM32WL5_FLASH_PAGESIZE 2048 +#elif defined(CONFIG_STM32WL5_FLASH_CONFIG_C) /* 256 kB */ +# define STM32WL5_FLASH_NPAGES 128 +# define STM32WL5_FLASH_PAGESIZE 2048 +#elif defined(CONFIG_STM32WL5_FLASH_CONFIG_E) /* 512 kB */ +# define STM32WL5_FLASH_NPAGES 256 +# define STM32WL5_FLASH_PAGESIZE 2048 +#elif defined(CONFIG_STM32WL5_FLASH_CONFIG_G) /* 1 MB */ +# define STM32WL5_FLASH_NPAGES 512 +# define STM32WL5_FLASH_PAGESIZE 2048 +#else +# error "unknown flash configuration!" +#endif + +#define STM32WL5_FLASH_SIZE (STM32WL5_FLASH_NPAGES * STM32WL5_FLASH_PAGESIZE) + +/* Register Offsets *********************************************************/ + +#define STM32WL5_FLASH_ACR_OFFSET 0x0000 +#define STM32WL5_FLASH_ACR2_OFFSET 0x0004 +#define STM32WL5_FLASH_KEYR_OFFSET 0x0008 +#define STM32WL5_FLASH_OPTKEYR_OFFSET 0x000c +#define STM32WL5_FLASH_SR_OFFSET 0x0010 +#define STM32WL5_FLASH_CR_OFFSET 0x0014 +#define STM32WL5_FLASH_ECCR_OFFSET 0x0018 +#define STM32WL5_FLASH_OPTR_OFFSET 0x0020 +#define STM32WL5_FLASH_PCROP1ASR_OFFSET 0x0024 +#define STM32WL5_FLASH_PCROP1AER_OFFSET 0x0028 +#define STM32WL5_FLASH_WRP1AR_OFFSET 0x002c +#define STM32WL5_FLASH_WRP1BR_OFFSET 0x0030 +#define STM32WL5_FLASH_PCROP1BSR_OFFSET 0x0034 +#define STM32WL5_FLASH_PCROP1BER_OFFSET 0x0038 +#define STM32WL5_FLASH_IPCCBR_OFFSET 0x003c +#define STM32WL5_FLASH_C2ACR_OFFSET 0x005c +#define STM32WL5_FLASH_C2SR_OFFSET 0x0060 +#define STM32WL5_FLASH_C2CR_OFFSET 0x0064 +#define STM32WL5_FLASH_SFR_OFFSET 0x0080 +#define STM32WL5_FLASH_SRRVR_OFFSET 0x0084 + +/* Register Addresses *******************************************************/ + +#define STM32WL5_FLASH_ACR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_ACR_OFFSET) +#define STM32WL5_FLASH_ACR2 (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_ACR2_OFFSET) +#define STM32WL5_FLASH_KEYR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_KEYR_OFFSET) +#define STM32WL5_FLASH_OPTKEYR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_OPTKEYR_OFFSET) +#define STM32WL5_FLASH_SR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_SR_OFFSET) +#define STM32WL5_FLASH_CR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_CR_OFFSET) +#define STM32WL5_FLASH_ECCR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_ECCR_OFFSET) +#define STM32WL5_FLASH_OPTR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_OPTR_OFFSET) +#define STM32WL5_FLASH_PCROP1ASR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1ASR_OFFSET) +#define STM32WL5_FLASH_PCROP1AER (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1AER_OFFSET) +#define STM32WL5_FLASH_WRP1AR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_WRP1AR_OFFSET) +#define STM32WL5_FLASH_WRP1BR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_WRP1BR_OFFSET) +#define STM32WL5_FLASH_PCROP1BSR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1BSR_OFFSET) +#define STM32WL5_FLASH_PCROP1BER (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_PCROP1BER_OFFSET) +#define STM32WL5_FLASH_IPCCBR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_IPCCBR_OFFSET) +#define STM32WL5_FLASH_C2ACR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_C2ACR_OFFSET) +#define STM32WL5_FLASH_C2SR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_C2SR_OFFSET) +#define STM32WL5_FLASH_C2CR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_C2CR_OFFSET) +#define STM32WL5_FLASH_SFR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_SFR_OFFSET) +#define STM32WL5_FLASH_SRRVR (STM32WL5_FLASHIF_BASE+STM32WL5_FLASH_SRRVR_OFFSET) + +/* Register Bitfield Definitions ********************************************/ + +/* Flash Access Control Register (ACR) */ + +#define FLASH_ACR_LATENCY_SHIFT (0) +#define FLASH_ACR_LATENCY_MASK (7 << FLASH_ACR_LATENCY_SHIFT) +# define FLASH_ACR_LATENCY(n) ((n) << FLASH_ACR_LATENCY_SHIFT) /* n wait states, for Vcore range 1 and 2. */ +# define FLASH_ACR_LATENCY_0 (0 << FLASH_ACR_LATENCY_SHIFT) /* 000: Zero wait states */ +# define FLASH_ACR_LATENCY_1 (1 << FLASH_ACR_LATENCY_SHIFT) /* 001: One wait state */ +# define FLASH_ACR_LATENCY_2 (2 << FLASH_ACR_LATENCY_SHIFT) /* 010: Two wait states */ + +#define FLASH_ACR_PRFTEN (1 << 8) /* Bit 8: Prefetch enable */ +#define FLASH_ACR_ICEN (1 << 9) /* Bit 9: Instruction cache enable */ +#define FLASH_ACR_DCEN (1 << 10) /* Bit 10: Data cache enable */ +#define FLASH_ACR_ICRST (1 << 11) /* Bit 11: Instruction cache reset */ +#define FLASH_ACR_DCRST (1 << 12) /* Bit 12: Data cache reset */ +#define FLASH_ACR_PES (1 << 15) /* Bit 15: Suspend flash program */ +#define FLASH_ACR_EMPTY (1 << 16) /* Bit 16: Is user flash empty */ + +/* Flash Access Control Register 2 (ACR2) */ + +#define FLASH_ACR2_PRIVMODE (1 << 0) /* Bit 0: Enable flash priviliged access mode */ +#define FLASH_ACR2_HDPADIS (1 << 1) /* Bit 1: Disable user flash hide protection area access */ +#define FLASH_ACR2_C2SWDBGEN (1 << 2) /* Bit 2: Enable cpu2 debug access */ + +/* Flash Status Register (SR) */ + +#define FLASH_SR_EOP (1 << 0) /* Bit 0: End of operation */ +#define FLASH_SR_OPERR (1 << 1) /* Bit 1: Operation error */ +#define FLASH_SR_PROGERR (1 << 3) /* Bit 3: Programming error */ +#define FLASH_SR_WRPERR (1 << 4) /* Bit 4: Write protection error */ +#define FLASH_SR_PGAERR (1 << 5) /* Bit 5: Programming alignment error */ +#define FLASH_SR_SIZERR (1 << 6) /* Bit 6: Size error */ +#define FLASH_SR_PGSERR (1 << 7) /* Bit 7: Programming sequence error */ +#define FLASH_SR_MISERR (1 << 8) /* Bit 8: Fast programming data miss error */ +#define FLASH_SR_FASTERR (1 << 9) /* Bit 9: Fast programming error */ +#define FLASH_SR_OPTNV (1 << 13) /* Bit 13: User option OPTVAL indication */ +#define FLASH_SR_RDERR (1 << 14) /* Bit 14: PCROP read error */ +#define FLASH_SR_OPTVERR (1 << 15) /* Bit 15: Option validity error */ +#define FLASH_SR_BSY (1 << 16) /* Bit 16: Busy */ +#define FLASH_SR_CFGBSY (1 << 18) /* Bit 18: Program or erase configuration busy */ +#define FLASH_SR_PESD (1 << 19) /* Bit 19: Program or erase operation suspended */ + +/* Flash Control Register (CR) */ + +#define FLASH_CR_PG (1 << 0) /* Bit 0 : Program Page */ +#define FLASH_CR_PER (1 << 1) /* Bit 1 : Page Erase */ +#define FLASH_CR_MER (1 << 2) /* Bit 2 : Mass Erase */ + +#define FLASH_CR_PNB_SHIFT (3) /* Bits 3-9: Page number */ +#define FLASH_CR_PNB_MASK (0x7F << FLASH_CR_PNB_SHIFT) +#define FLASH_CR_PNB(n) ((n) << FLASH_CR_PNB_SHIFT) /* Page n, n=0..127 */ + +#define FLASH_CR_START (1 << 16) /* Bit 16: Start Erase */ +#define FLASH_CR_OPTSTRT (1 << 17) /* Bit 17: Options modification Start */ +#define FLASH_CR_FSTPG (1 << 23) /* Bit 23: Fast programming */ +#define FLASH_CR_EOPIE (1 << 24) /* Bit 24: End of operation interrupt enable */ +#define FLASH_CR_ERRIE (1 << 25) /* Bit 25: Error interrupt enable */ +#define FLASH_CR_RDERRIE (1 << 26) /* Bit 26: PCROP read error interrupt enable */ +#define FLASH_CR_OBL_LAUNCH (1 << 27) /* Bit 27: Option Byte Loading */ +#define FLASH_CR_OPTLOCK (1 << 30) /* Bit 30: Option Lock */ +#define FLASH_CR_LOCK (1 << 31) /* Bit 31: Lock */ + +/* Flash ECC Register (ECCR) */ + +#define FLASH_ECCR_ADDR_ECC_SHIFT (0) /* Bits 0-15: Read protect */ +# define FLASH_ECCR_ADDR_ECC_MASK (0xffff << FLASH_ECCR_ADDR_ECC_SHIFT) +#define FLASH_ECCR_SYSF_ECC (1 << 20) /* Bit 20: System Flash ECC fail */ +#define FLASH_ECCR_ECCCIE (1 << 24) /* Bit 24: ECC correction interrupt enable */ +#define FLASH_ECCR_CPUID_SHIFT (26) +# define FLASH_ECCR_CPUID_MASK (0x7 << FLASH_ECCR_CPUID_SHIFT) +# define FLASH_ECCR_CPUID_CPU1 (0x0 << FLASH_ECCR_CPUID_SHIFT) /* 000: cpu1 access caused ECC failure */ +# define FLASH_ECCR_CPUID_CPU2 (0x1 << FLASH_ECCR_CPUID_SHIFT) /* 001: cpu2 access caused ECC failure */ + +#define FLASH_ECCR_ECCC (1 << 30) /* Bit 30: ECC correction */ +#define FLASH_ECCR_ECCD (1 << 31) /* Bit 31: ECC detection */ + +/* Flash Option Register (OPTR) */ + +#define FLASH_OPTR_RDP_SHIFT (0) /* Bits 0-7: Read Protection Level */ +#define FLASH_OPTR_RDP_MASK (0xFF << FLASH_OPTR_RDP_SHIFT) +#define FLASH_OPTR_RDP_NONE (0xAA << FLASH_OPTR_RDP_SHIFT) +#define FLASH_OPTR_RDP_CHIP (0xCC << FLASH_OPTR_RDP_SHIFT) /* WARNING, CANNOT BE REVERSED !! */ + +#define FLASH_OPTR_ESE (1 << 8) /* Bit 8: System security flag */ + +#define FLASH_OPTR_BORLEV_SHIFT (9) /* Bits 9-11: BOR reset Level */ +#define FLASH_OPTR_BORLEV_MASK (7 << FLASH_OPTR_BORLEV_SHIFT) +#define FLASH_OPTR_VBOR0 (0 << FLASH_OPTR_BORLEV_SHIFT) /* 000: BOR Level 0 (1.7 V) */ +#define FLASH_OPTR_VBOR1 (1 << FLASH_OPTR_BORLEV_SHIFT) /* 001: BOR Level 1 (2.0 V) */ +#define FLASH_OPTR_VBOR2 (2 << FLASH_OPTR_BORLEV_SHIFT) /* 010: BOR Level 2 (2.2 V) */ +#define FLASH_OPTR_VBOR3 (3 << FLASH_OPTR_BORLEV_SHIFT) /* 011: BOR Level 3 (2.5 V) */ +#define FLASH_OPTR_VBOR4 (4 << FLASH_OPTR_BORLEV_SHIFT) /* 100: BOR Level 4 (2.8 V) */ + +#define FLASH_OPTR_NRST_STOP (1 << 12) /* Bit 12: Generate reset when entering the Stop mode */ +#define FLASH_OPTR_NRST_STDBY (1 << 13) /* Bit 13: Generate reset when entering the Standby mode */ +#define FLASH_OPTR_NRST_SHDW (1 << 14) /* Bit 14: Generate reset when entering the Shutdown mode */ +#define FLASH_OPTR_IWDG_SW (1 << 16) /* Bit 16: Independent watchdog selection */ +#define FLASH_OPTR_IWDG_STOP (1 << 17) /* Bit 17: Independent watchdog counter freeze in Stop mode */ +#define FLASH_OPTR_IWDG_STDBY (1 << 18) /* Bit 18: Independent watchdog counter freeze in Standby mode*/ +#define FLASH_OPTR_WWDG_SW (1 << 19) /* Bit 19: Window watchdog selection */ +#define FLASH_OPTR_NBOOT1 (1 << 23) /* Bit 23: Boot configuration */ +#define FLASH_OPTR_SRAM2_PE (1 << 24) /* Bit 24: SRAM2 parity check enable */ +#define FLASH_OPTR_SRAM_RST (1 << 25) /* Bit 25: SRAM1/2 Erase when system reset */ +#define FLASH_OPTR_NSWBOOT0 (1 << 26) /* Bit 26: Software BOOT0 */ +#define FLASH_OPTR_NBOOT0 (1 << 27) /* Bit 27: nBOOT0 option bit */ + +#define FLASH_OPTR_C1BOOT_LOCK (1 << 30) /* Bit 30: Enable cpu1 boot lock */ +#define FLASH_OPTR_C2BOOT_LOCK (1 << 31) /* Bit 31: Enable cpu2 boot lock */ + +/* Flash CPU2 Access Control Register (C2ACR) */ + +#define FLASH_C2ACR_PRFTEN (1 << 8) /* Bit 8: Enable cpu2 prefetch */ +#define FLASH_C2ACR_ICEN (1 << 9) /* Bit 9: Enable cpu2 instruction cache */ +#define FLASH_C2ACR_ICRST (1 << 11) /* Bit 11: Reset cpu2 instruction cache */ +#define FLASH_C2ACR_PES (1 << 15) /* Bit 15: Suspend cpu2 flash program/erase */ + +/* Flash CPU2 Status Register (C2SR) */ + +#define FLASH_C2SR_EOP (1 << 0) /* Bit 0: End of operation flag */ +#define FLASH_C2SR_OPERR (1 << 1) /* Bit 1: Operation */ +#define FLASH_C2SR_PROGERR (1 << 3) /* Bit 3: Programming */ +#define FLASH_C2SR_WRPERR (1 << 4) /* Bit 4: Write protection */ +#define FLASH_C2SR_PGAERR (1 << 5) /* Bit 5: Programming alignment */ +#define FLASH_C2SR_SIZERR (1 << 6) /* Bit 6: Size */ +#define FLASH_C2SR_PGSERR (1 << 7) /* Bit 7: Programming sequence */ +#define FLASH_C2SR_MISSERR (1 << 8) /* Bit 8: Fast programming data miss */ +#define FLASH_C2SR_FASTERR (1 << 9) /* Bit 9: Fast programming */ +#define FLASH_C2SR_RDERR (1 << 14) /* Bit 14: PCROP read */ +#define FLASH_C2SR_BSY (1 << 16) /* Bit 16: Busy flag */ +#define FLASH_C2SR_CFGBSY (1 << 18) /* Bit 18: Program or erase configuration busy */ +#define FLASH_C2SR_PESD (1 << 19) /* Bit 19: Program/erase operation suspended */ + +/* Flash CPU2 Control Register (C2CR) */ + +#define FLASH_C2CR_PG (1 << 0) /* Bit 0 : Program Page */ +#define FLASH_C2CR_PER (1 << 1) /* Bit 1 : Page Erase */ +#define FLASH_C2CR_MER (1 << 2) /* Bit 2 : Mass Erase */ + +#define FLASH_C2CR_PNB_SHIFT (3) /* Bits 3-9: Page number */ +#define FLASH_C2CR_PNB_MASK (0x7F << FLASH_C2CR_PNB_SHIFT) +#define FLASH_C2CR_PNB(n) ((n) << FLASH_C2CR_PNB_SHIFT) /* Page n, n=0..127 */ + +#define FLASH_C2CR_START (1 << 16) /* Bit 16: Start Erase */ +#define FLASH_C2CR_FSTPG (1 << 18) /* Bit 23: Fast programming */ +#define FLASH_C2CR_EOPIE (1 << 24) /* Bit 24: End of operation interrupt enable */ +#define FLASH_C2CR_ERRIE (1 << 25) /* Bit 25: Error interrupt enable */ +#define FLASH_C2CR_RDERRIE (1 << 26) /* Bit 26: PCROP read error interrupt enable */ + +#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_FLASH_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_gpio.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_gpio.h new file mode 100644 index 0000000000..35eb196329 --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_gpio.h @@ -0,0 +1,299 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_gpio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_GPIO_H +#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define STM32WL5_GPIO_MODER_OFFSET 0x0000 /* GPIO port mode register */ +#define STM32WL5_GPIO_OTYPER_OFFSET 0x0004 /* GPIO port output type register */ +#define STM32WL5_GPIO_OSPEED_OFFSET 0x0008 /* GPIO port output speed register */ +#define STM32WL5_GPIO_PUPDR_OFFSET 0x000c /* GPIO port pull-up/pull-down register */ +#define STM32WL5_GPIO_IDR_OFFSET 0x0010 /* GPIO port input data register */ +#define STM32WL5_GPIO_ODR_OFFSET 0x0014 /* GPIO port output data register */ +#define STM32WL5_GPIO_BSRR_OFFSET 0x0018 /* GPIO port bit set/reset register */ +#define STM32WL5_GPIO_LCKR_OFFSET 0x001c /* GPIO port configuration lock register */ +#define STM32WL5_GPIO_AFRL_OFFSET 0x0020 /* GPIO alternate function low register */ +#define STM32WL5_GPIO_AFRH_OFFSET 0x0024 /* GPIO alternate function high register */ +#define STM32WL5_GPIO_BRR_OFFSET 0x0028 /* GPIO port bit reset register */ + +/* Register Addresses *******************************************************/ + +#define STM32WL5_GPIOA_MODER (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_MODER_OFFSET) +#define STM32WL5_GPIOA_OTYPER (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_OTYPER_OFFSET) +#define STM32WL5_GPIOA_OSPEED (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_OSPEED_OFFSET) +#define STM32WL5_GPIOA_PUPDR (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_PUPDR_OFFSET) +#define STM32WL5_GPIOA_IDR (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_IDR_OFFSET) +#define STM32WL5_GPIOA_ODR (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_ODR_OFFSET) +#define STM32WL5_GPIOA_BSRR (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_BSRR_OFFSET) +#define STM32WL5_GPIOA_LCKR (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_LCKR_OFFSET) +#define STM32WL5_GPIOA_AFRL (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_AFRL_OFFSET) +#define STM32WL5_GPIOA_AFRH (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_AFRH_OFFSET) +#define STM32WL5_GPIOA_BRR (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_BRR_OFFSET) +#define STM32WL5_GPIOA_ASCR (STM32WL5_GPIOA_BASE+STM32WL5_GPIO_ASCR_OFFSET) + +#define STM32WL5_GPIOB_MODER (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_MODER_OFFSET) +#define STM32WL5_GPIOB_OTYPER (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_OTYPER_OFFSET) +#define STM32WL5_GPIOB_OSPEED (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_OSPEED_OFFSET) +#define STM32WL5_GPIOB_PUPDR (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_PUPDR_OFFSET) +#define STM32WL5_GPIOB_IDR (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_IDR_OFFSET) +#define STM32WL5_GPIOB_ODR (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_ODR_OFFSET) +#define STM32WL5_GPIOB_BSRR (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_BSRR_OFFSET) +#define STM32WL5_GPIOB_LCKR (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_LCKR_OFFSET) +#define STM32WL5_GPIOB_AFRL (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_AFRL_OFFSET) +#define STM32WL5_GPIOB_AFRH (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_AFRH_OFFSET) +#define STM32WL5_GPIOB_BRR (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_BRR_OFFSET) +#define STM32WL5_GPIOB_ASCR (STM32WL5_GPIOB_BASE+STM32WL5_GPIO_ASCR_OFFSET) + +#define STM32WL5_GPIOC_MODER (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_MODER_OFFSET) +#define STM32WL5_GPIOC_OTYPER (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_OTYPER_OFFSET) +#define STM32WL5_GPIOC_OSPEED (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_OSPEED_OFFSET) +#define STM32WL5_GPIOC_PUPDR (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_PUPDR_OFFSET) +#define STM32WL5_GPIOC_IDR (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_IDR_OFFSET) +#define STM32WL5_GPIOC_ODR (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_ODR_OFFSET) +#define STM32WL5_GPIOC_BSRR (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_BSRR_OFFSET) +#define STM32WL5_GPIOC_LCKR (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_LCKR_OFFSET) +#define STM32WL5_GPIOC_AFRL (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_AFRL_OFFSET) +#define STM32WL5_GPIOC_AFRH (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_AFRH_OFFSET) +#define STM32WL5_GPIOC_BRR (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_BRR_OFFSET) +#define STM32WL5_GPIOC_ASCR (STM32WL5_GPIOC_BASE+STM32WL5_GPIO_ASCR_OFFSET) + +#define STM32WL5_GPIOH_MODER (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_MODER_OFFSET) +#define STM32WL5_GPIOH_OTYPER (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_OTYPER_OFFSET) +#define STM32WL5_GPIOH_OSPEED (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_OSPEED_OFFSET) +#define STM32WL5_GPIOH_PUPDR (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_PUPDR_OFFSET) +#define STM32WL5_GPIOH_IDR (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_IDR_OFFSET) +#define STM32WL5_GPIOH_ODR (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_ODR_OFFSET) +#define STM32WL5_GPIOH_BSRR (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_BSRR_OFFSET) +#define STM32WL5_GPIOH_LCKR (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_LCKR_OFFSET) +#define STM32WL5_GPIOH_AFRL (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_AFRL_OFFSET) +#define STM32WL5_GPIOH_AFRH (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_AFRH_OFFSET) +#define STM32WL5_GPIOH_BRR (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_BRR_OFFSET) +#define STM32WL5_GPIOH_ASCR (STM32WL5_GPIOH_BASE+STM32WL5_GPIO_ASCR_OFFSET) + +/* Register Bitfield Definitions ********************************************/ + +/* GPIO port mode register */ + +#define GPIO_MODER_INPUT (0) /* Input */ +#define GPIO_MODER_OUTPUT (1) /* General purpose output mode */ +#define GPIO_MODER_ALT (2) /* Alternate mode */ +#define GPIO_MODER_ANALOG (3) /* Analog mode */ + +#define GPIO_MODER_SHIFT(n) ((n) << 1) +#define GPIO_MODER_MASK(n) (3 << GPIO_MODER_SHIFT(n)) + +#define GPIO_MODER0_SHIFT (0) +#define GPIO_MODER0_MASK (3 << GPIO_MODER0_SHIFT) +#define GPIO_MODER1_SHIFT (2) +#define GPIO_MODER1_MASK (3 << GPIO_MODER1_SHIFT) +#define GPIO_MODER2_SHIFT (4) +#define GPIO_MODER2_MASK (3 << GPIO_MODER2_SHIFT) +#define GPIO_MODER3_SHIFT (6) +#define GPIO_MODER3_MASK (3 << GPIO_MODER3_SHIFT) +#define GPIO_MODER4_SHIFT (8) +#define GPIO_MODER4_MASK (3 << GPIO_MODER4_SHIFT) +#define GPIO_MODER5_SHIFT (10) +#define GPIO_MODER5_MASK (3 << GPIO_MODER5_SHIFT) +#define GPIO_MODER6_SHIFT (12) +#define GPIO_MODER6_MASK (3 << GPIO_MODER6_SHIFT) +#define GPIO_MODER7_SHIFT (14) +#define GPIO_MODER7_MASK (3 << GPIO_MODER7_SHIFT) +#define GPIO_MODER8_SHIFT (16) +#define GPIO_MODER8_MASK (3 << GPIO_MODER8_SHIFT) +#define GPIO_MODER9_SHIFT (18) +#define GPIO_MODER9_MASK (3 << GPIO_MODER9_SHIFT) +#define GPIO_MODER10_SHIFT (20) +#define GPIO_MODER10_MASK (3 << GPIO_MODER10_SHIFT) +#define GPIO_MODER11_SHIFT (22) +#define GPIO_MODER11_MASK (3 << GPIO_MODER11_SHIFT) +#define GPIO_MODER12_SHIFT (24) +#define GPIO_MODER12_MASK (3 << GPIO_MODER12_SHIFT) +#define GPIO_MODER13_SHIFT (26) +#define GPIO_MODER13_MASK (3 << GPIO_MODER13_SHIFT) +#define GPIO_MODER14_SHIFT (28) +#define GPIO_MODER14_MASK (3 << GPIO_MODER14_SHIFT) +#define GPIO_MODER15_SHIFT (30) +#define GPIO_MODER15_MASK (3 << GPIO_MODER15_SHIFT) + +/* GPIO port output type register */ + +#define GPIO_OTYPER_PP(n) (0) /* 0=Output push-pull */ +#define GPIO_OTYPER_OD(n) (1 << (n)) /* 1=Output open-drain */ + +/* GPIO port output speed register */ + +#define GPIO_OSPEED_2MHz (0) /* 2 MHz Low speed */ +#define GPIO_OSPEED_25MHz (1) /* 25 MHz Medium speed */ +#define GPIO_OSPEED_50MHz (2) /* 50 MHz High speed */ +#define GPIO_OSPEED_100MHz (3) /* 100 MHz Very High speed on 30 pF (80 MHz Output max speed on 15 pF) */ + +#define GPIO_OSPEED_SHIFT(n) ((n) << 1) +#define GPIO_OSPEED_MASK(n) (3 << GPIO_OSPEED_SHIFT(n)) + +#define GPIO_OSPEED0_SHIFT (0) +#define GPIO_OSPEED0_MASK (3 << GPIO_OSPEED0_SHIFT) +#define GPIO_OSPEED1_SHIFT (2) +#define GPIO_OSPEED1_MASK (3 << GPIO_OSPEED1_SHIFT) +#define GPIO_OSPEED2_SHIFT (4) +#define GPIO_OSPEED2_MASK (3 << GPIO_OSPEED2_SHIFT) +#define GPIO_OSPEED3_SHIFT (6) +#define GPIO_OSPEED3_MASK (3 << GPIO_OSPEED3_SHIFT) +#define GPIO_OSPEED4_SHIFT (8) +#define GPIO_OSPEED4_MASK (3 << GPIO_OSPEED4_SHIFT) +#define GPIO_OSPEED5_SHIFT (10) +#define GPIO_OSPEED5_MASK (3 << GPIO_OSPEED5_SHIFT) +#define GPIO_OSPEED6_SHIFT (12) +#define GPIO_OSPEED6_MASK (3 << GPIO_OSPEED6_SHIFT) +#define GPIO_OSPEED7_SHIFT (14) +#define GPIO_OSPEED7_MASK (3 << GPIO_OSPEED7_SHIFT) +#define GPIO_OSPEED8_SHIFT (16) +#define GPIO_OSPEED8_MASK (3 << GPIO_OSPEED8_SHIFT) +#define GPIO_OSPEED9_SHIFT (18) +#define GPIO_OSPEED9_MASK (3 << GPIO_OSPEED9_SHIFT) +#define GPIO_OSPEED10_SHIFT (20) +#define GPIO_OSPEED10_MASK (3 << GPIO_OSPEED10_SHIFT) +#define GPIO_OSPEED11_SHIFT (22) +#define GPIO_OSPEED11_MASK (3 << GPIO_OSPEED11_SHIFT) +#define GPIO_OSPEED12_SHIFT (24) +#define GPIO_OSPEED12_MASK (3 << GPIO_OSPEED12_SHIFT) +#define GPIO_OSPEED13_SHIFT (26) +#define GPIO_OSPEED13_MASK (3 << GPIO_OSPEED13_SHIFT) +#define GPIO_OSPEED14_SHIFT (28) +#define GPIO_OSPEED14_MASK (3 << GPIO_OSPEED14_SHIFT) +#define GPIO_OSPEED15_SHIFT (30) +#define GPIO_OSPEED15_MASK (3 << GPIO_OSPEED15_SHIFT) + +/* GPIO port pull-up/pull-down register */ + +#define GPIO_PUPDR_NONE (0) /* No pull-up, pull-down */ +#define GPIO_PUPDR_PULLUP (1) /* Pull-up */ +#define GPIO_PUPDR_PULLDOWN (2) /* Pull-down */ + +#define GPIO_PUPDR_SHIFT(n) ((n) << 1) +#define GPIO_PUPDR_MASK(n) (3 << GPIO_PUPDR_SHIFT(n)) + +#define GPIO_PUPDR0_SHIFT (0) +#define GPIO_PUPDR0_MASK (3 << GPIO_PUPDR0_SHIFT) +#define GPIO_PUPDR1_SHIFT (2) +#define GPIO_PUPDR1_MASK (3 << GPIO_PUPDR1_SHIFT) +#define GPIO_PUPDR2_SHIFT (4) +#define GPIO_PUPDR2_MASK (3 << GPIO_PUPDR2_SHIFT) +#define GPIO_PUPDR3_SHIFT (6) +#define GPIO_PUPDR3_MASK (3 << GPIO_PUPDR3_SHIFT) +#define GPIO_PUPDR4_SHIFT (8) +#define GPIO_PUPDR4_MASK (3 << GPIO_PUPDR4_SHIFT) +#define GPIO_PUPDR5_SHIFT (10) +#define GPIO_PUPDR5_MASK (3 << GPIO_PUPDR5_SHIFT) +#define GPIO_PUPDR6_SHIFT (12) +#define GPIO_PUPDR6_MASK (3 << GPIO_PUPDR6_SHIFT) +#define GPIO_PUPDR7_SHIFT (14) +#define GPIO_PUPDR7_MASK (3 << GPIO_PUPDR7_SHIFT) +#define GPIO_PUPDR8_SHIFT (16) +#define GPIO_PUPDR8_MASK (3 << GPIO_PUPDR8_SHIFT) +#define GPIO_PUPDR9_SHIFT (18) +#define GPIO_PUPDR9_MASK (3 << GPIO_PUPDR9_SHIFT) +#define GPIO_PUPDR10_SHIFT (20) +#define GPIO_PUPDR10_MASK (3 << GPIO_PUPDR10_SHIFT) +#define GPIO_PUPDR11_SHIFT (22) +#define GPIO_PUPDR11_MASK (3 << GPIO_PUPDR11_SHIFT) +#define GPIO_PUPDR12_SHIFT (24) +#define GPIO_PUPDR12_MASK (3 << GPIO_PUPDR12_SHIFT) +#define GPIO_PUPDR13_SHIFT (26) +#define GPIO_PUPDR13_MASK (3 << GPIO_PUPDR13_SHIFT) +#define GPIO_PUPDR14_SHIFT (28) +#define GPIO_PUPDR14_MASK (3 << GPIO_PUPDR14_SHIFT) +#define GPIO_PUPDR15_SHIFT (30) +#define GPIO_PUPDR15_MASK (3 << GPIO_PUPDR15_SHIFT) + +/* GPIO port input data register */ + +#define GPIO_IDR(n) (1 << (n)) + +/* GPIO port output data register */ + +#define GPIO_ODR(n) (1 << (n)) + +/* GPIO port bit set/reset register */ + +#define GPIO_BSRR_SET(n) (1 << (n)) +#define GPIO_BSRR_RESET(n) (1 << ((n)+16)) + +/* GPIO port configuration lock register */ + +#define GPIO_LCKR(n) (1 << (n)) +#define GPIO_LCKK (1 << 16) /* Lock key */ + +/* GPIO alternate function low/high register */ + +#define GPIO_AFR_SHIFT(n) ((n) << 2) +#define GPIO_AFR_MASK(n) (15 << GPIO_AFR_SHIFT(n)) + +#define GPIO_AFRL0_SHIFT (0) +#define GPIO_AFRL0_MASK (15 << GPIO_AFRL0_SHIFT) +#define GPIO_AFRL1_SHIFT (4) +#define GPIO_AFRL1_MASK (15 << GPIO_AFRL1_SHIFT) +#define GPIO_AFRL2_SHIFT (8) +#define GPIO_AFRL2_MASK (15 << GPIO_AFRL2_SHIFT) +#define GPIO_AFRL3_SHIFT (12) +#define GPIO_AFRL3_MASK (15 << GPIO_AFRL3_SHIFT) +#define GPIO_AFRL4_SHIFT (16) +#define GPIO_AFRL4_MASK (15 << GPIO_AFRL4_SHIFT) +#define GPIO_AFRL5_SHIFT (20) +#define GPIO_AFRL5_MASK (15 << GPIO_AFRL5_SHIFT) +#define GPIO_AFRL6_SHIFT (24) +#define GPIO_AFRL6_MASK (15 << GPIO_AFRL6_SHIFT) +#define GPIO_AFRL7_SHIFT (28) +#define GPIO_AFRL7_MASK (15 << GPIO_AFRL7_SHIFT) + +#define GPIO_AFRH8_SHIFT (0) +#define GPIO_AFRH8_MASK (15 << GPIO_AFRH8_SHIFT) +#define GPIO_AFRH9_SHIFT (4) +#define GPIO_AFRH9_MASK (15 << GPIO_AFRH9_SHIFT) +#define GPIO_AFRH10_SHIFT (8) +#define GPIO_AFRH10_MASK (15 << GPIO_AFRH10_SHIFT) +#define GPIO_AFRH11_SHIFT (12) +#define GPIO_AFRH11_MASK (15 << GPIO_AFRH11_SHIFT) +#define GPIO_AFRH12_SHIFT (16) +#define GPIO_AFRH12_MASK (15 << GPIO_AFRH12_SHIFT) +#define GPIO_AFRH13_SHIFT (20) +#define GPIO_AFRH13_MASK (15 << GPIO_AFRH13_SHIFT) +#define GPIO_AFRH14_SHIFT (24) +#define GPIO_AFRH14_MASK (15 << GPIO_AFRH14_SHIFT) +#define GPIO_AFRH15_SHIFT (28) +#define GPIO_AFRH15_MASK (15 << GPIO_AFRH15_SHIFT) + +/* GPIO port analog switch control register */ + +#define GPIO_ASCR(n) (1 << (n)) + +#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_GPIO_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_memorymap.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_memorymap.h new file mode 100644 index 0000000000..b6ececc4e9 --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_memorymap.h @@ -0,0 +1,167 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_memorymap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_MEMORYMAP_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_MEMORYMAP_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* STM32WL5XXX Address Blocks ***********************************************/ + +#define STM32WL5_CODE_BASE 0x00000000 /* 0x0000 0000-0x1fff ffff: 512Mb code block */ +#define STM32WL5_SRAM_BASE 0x20000000 /* 0x2000 0000-0x3fff ffff: 512Mb sram block (48k to 256k) */ +#define STM32WL5_PERIPH_BASE 0x40000000 /* 0x4000 0000-0x5fff ffff: 512Mb peripheral block */ + /* 0x6000 0000-0xdfff ffff: 2048Mb (not used) */ +#define STM32WL5_CORTEX_BASE 0xe0000000 /* 0xe000 0000-0xffff ffff: 512Mb Cortex-M4/M0 block */ + +#define STM32WL5_REGION_MASK 0xf0000000 +#define STM32WL5_IS_SRAM(a) ((((uint32_t)(a)) & STM32WL5_REGION_MASK) == STM32WL5_SRAM_BASE) + +/* Code Base Addresses ******************************************************/ + +#define STM32WL5_BOOT_BASE 0x00000000 /* 0x0000 0000-0x0003 ffff: Aliased boot memory */ + /* 0x0004 0000-0x07ff ffff: Reserved */ +#define STM32WL5_FLASH_BASE 0x08000000 /* 0x0800 0000-0x0803 ffff: FLASH memory */ + /* 0x0804 0000-0x0fff ffff: Reserved */ +#define STM32WL5_FLASH_MASK 0xf8000000 /* Test if addr in FLASH */ + /* 0x1000 0000-0x1ffe 6fff: Reserved */ +#define STM32WL5_SYSMEM_BASE 0x1fff0000 /* 0x1fff 0000-0x1fff 6fff: System memory */ +#define STM32WL5_OTP_BASE 0x1fff7000 /* 0x1fff 7000-0x1fff 73ff: 1k otp memory */ +#define STM32WL5_ENGI_BASE 0x1fff7400 /* 0x1fff 7400-0x1fff 77ff: 1k engi flash */ +#define STM32WL5_OPTION_BASE 0x1fff7800 /* 0x1fff 7800-0x1fff 7fff: 2k flash user options */ + /* 0x1fff 8000-0x1fff ffff: reserved */ +#define STM32WL5_SRAM2_BASE 0x20008000 /* 0x2000 8000-0x2000 ffff: 32k SRAM2 */ + +/* System Memory Addresses **************************************************/ + +#define STM32WL5_SYSMEM_PACKAGE 0x1fff7500 /* This bitfield indicates the package + * type. + * 0: UFBGA73 + * 2: WLCSP59 + * 10: UFQFPN48 + */ +#define STM32WL5_SYSMEM_UID 0x1fff7590 /* The 96-bit unique device identifier */ +#define STM32WL5_SYSMEM_FSIZE 0x1fff75E0 /* This bitfield indicates the size of + * the device Flash memory expressed in + * Kbytes. Example: 0x0400 corresponds + * to 1024 Kbytes. + */ + +/* SRAM Base Addresses ******************************************************/ + +#define STM32WL5_SRAMBB_BASE 0x22000000 /* 0x22000000- : SRAM bit-band region */ + +/* Peripheral Base Addresses ************************************************/ + +#define STM32WL5_APB1_BASE 0x40000000 /* 0x4000 0000-0x4000 b3ff: APB1 */ + /* 0x4000 B400-0x4000 ffff: Reserved */ +#define STM32WL5_APB2_BASE 0x40010000 /* 0x4001 0000-0x4001 4bff: APB2 */ + /* 0x4001 4c00-0x4001 ffff: Reserved */ +#define STM32WL5_AHB1_BASE 0x40020000 /* 0x4002 0000-0x425f ffff: APB1 */ + /* 0x4260 0000-0x47ff ffff: Reserved */ +#define STM32WL5_AHB2_BASE 0x48000000 /* 0x4800 0000-0x4800 1fff: AHB2 */ + /* 0x4800 2000-0x57ff ffff: Reserved */ +#define STM32WL5_AHB3_BASE 0x58000000 /* 0x5800 0000-0x5800 4bff: AHB3 */ + /* 0x5800 40c0-0x5800 ffff: Reserved */ + +/* Radio Base Addresses *****************************************************/ + +#define STM32WL5_APB3_BASE 0x58010000 /* 0x5801 0000-0x5801 03ff: APB3 */ + /* 0x5801 0400-0x5801 ffff: Reserved */ + +/* in datasheet order */ + +/* APB1 Base Addresses ******************************************************/ + +#define STM32WL5_TAMP_BASE 0x4000B000 +#define STM32WL5_LPTIM3_BASE 0x40009800 +#define STM32WL5_LPTIM2_BASE 0x40009400 +#define STM32WL5_LPUART1_BASE 0x40008000 +#define STM32WL5_LPTIM1_BASE 0x40007C00 +#define STM32WL5_DAC_BASE 0x40007400 +#define STM32WL5_I2C3_BASE 0x40005C00 +#define STM32WL5_I2C2_BASE 0x40005800 +#define STM32WL5_I2C1_BASE 0x40005400 +#define STM32WL5_USART2_BASE 0x40004400 +#define STM32WL5_SPI2S2_BASE 0x40003800 +#define STM32WL5_IWDG_BASE 0x40003000 +#define STM32WL5_WWDG_BASE 0x40002C00 +#define STM32WL5_RTC_BASE 0x40002800 +#define STM32WL5_TIM2_BASE 0x40000000 + +/* APB2 Base Addresses ******************************************************/ + +#define STM32WL5_TIM17_BASE 0x40014800 +#define STM32WL5_TIM16_BASE 0x40014400 +#define STM32WL5_USART1_BASE 0x40013800 +#define STM32WL5_SPI1_BASE 0x40013000 +#define STM32WL5_TIM1_BASE 0x40012C00 +#define STM32WL5_ADC_BASE 0x40012400 +#define STM32WL5_COMP_BASE 0x40010200 +#define STM32WL5_SYSCFG2_BASE 0x40010100 +#define STM32WL5_VREFBUF_BASE 0x40010030 +#define STM32WL5_SYSCFG_BASE 0x40010000 + +/* AHB1 Base Addresses ******************************************************/ + +#define STM32WL5_CRC_BASE 0x40023000 +#define STM32WL5_DMAMUX1_BASE 0x40200800 +#define STM32WL5_DMA2_BASE 0x40200400 +#define STM32WL5_DMA1_BASE 0x40020000 + +/* AHB2 Base Addresses ******************************************************/ + +#define STM32WL5_GPIOH_BASE 0x48001C00 +#define STM32WL5_GPIOC_BASE 0x48000800 +#define STM32WL5_GPIOB_BASE 0x48000400 +#define STM32WL5_GPIOA_BASE 0x48000000 + +/* AHB3 Base Addresses ******************************************************/ + +#define STM32WL5_GTZC_TZIC_BASE 0x58004800 +#define STM32WL5_GTZC_TZSC_BASE 0x58004400 +#define STM32WL5_FLASHIF_BASE 0x58004000 +#define STM32WL5_PKA2_BASE 0x58003400 +#define STM32WL5_PKARAM_BASE 0x58002400 +#define STM32WL5_PKA_BASE 0x58002000 +#define STM32WL5_AES_BASE 0x58001800 +#define STM32WL5_HSEM_BASE 0x58001400 +#define STM32WL5_RNG_BASE 0x58001000 +#define STM32WL5_IPCC_BASE 0x58000C00 +#define STM32WL5_EXTI_BASE 0x58000800 +#define STM32WL5_PWR_BASE 0x58000400 +#define STM32WL5_RCC_BASE 0x58000000 + +/* APB3 Base Addresses ******************************************************/ + +#define STM32WL5_SUBGHZSPI_BASE 0x58010000 + +/* Cortex-M4 Base Addresses *************************************************/ + +/* Other registers -- see armv7-m/nvic.h for standard Cortex-M3 registers in + * this address range + */ + +#define STM32WL5_SCS_BASE 0xe000e000 +#define STM32WL5_DEBUGMCU_BASE 0xe0042000 + +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_MEMORYMAP_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_pinmap.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_pinmap.h new file mode 100644 index 0000000000..65419b4ae7 --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_pinmap.h @@ -0,0 +1,332 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_pinmap.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_PINMAP_H +#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_PINMAP_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Alternate Pin Functions. All members of the STM32WL5xxx family share the + * same pin multiplexing (although they may differ in the pins physically + * available). + * + * Alternative pin selections are provided with a numeric suffix like _1, _2, + * etc. Drivers, however, will use the pin selection without the numeric + * suffix. Additional definitions are required in the board.h file. For + * example, if CAN1_RX connects vis PA11 on some board, then the following + * definitions should appear in the board.h header file for that board: + * + * #define GPIO_CAN1_RX GPIO_CAN1_RX_1 + * + * The driver will then automatically configure PA11 as the CAN1 RX pin. + */ + +/* WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! WARNING!!! + * Additional effort is required to select specific GPIO options such as + * frequency, open-drain/push-pull, and pull-up/down! Just the basics are + * defined for most pins in this file. + */ + +/* Eventout */ + +#define GPIO_CM4_EVENTOUT_1 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN0) +#define GPIO_CM4_EVENTOUT_2 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN1) +#define GPIO_CM4_EVENTOUT_3 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN10) +#define GPIO_CM4_EVENTOUT_4 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN11) +#define GPIO_CM4_EVENTOUT_5 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN12) +#define GPIO_CM4_EVENTOUT_6 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN13) +#define GPIO_CM4_EVENTOUT_7 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN14) +#define GPIO_CM4_EVENTOUT_8 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN15) +#define GPIO_CM4_EVENTOUT_9 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN2) +#define GPIO_CM4_EVENTOUT_10 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN3) +#define GPIO_CM4_EVENTOUT_11 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN4) +#define GPIO_CM4_EVENTOUT_12 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN5) +#define GPIO_CM4_EVENTOUT_13 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN6) +#define GPIO_CM4_EVENTOUT_14 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN7) +#define GPIO_CM4_EVENTOUT_15 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN8) +#define GPIO_CM4_EVENTOUT_16 (GPIO_ALT|GPIO_AF15|GPIO_PORTA|GPIO_PIN9) +#define GPIO_CM4_EVENTOUT_17 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN0) +#define GPIO_CM4_EVENTOUT_18 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN1) +#define GPIO_CM4_EVENTOUT_19 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN10) +#define GPIO_CM4_EVENTOUT_20 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN11) +#define GPIO_CM4_EVENTOUT_21 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN12) +#define GPIO_CM4_EVENTOUT_22 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN13) +#define GPIO_CM4_EVENTOUT_23 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN14) +#define GPIO_CM4_EVENTOUT_24 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN15) +#define GPIO_CM4_EVENTOUT_25 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN2) +#define GPIO_CM4_EVENTOUT_26 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN3) +#define GPIO_CM4_EVENTOUT_27 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN4) +#define GPIO_CM4_EVENTOUT_28 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN5) +#define GPIO_CM4_EVENTOUT_29 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN6) +#define GPIO_CM4_EVENTOUT_30 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN7) +#define GPIO_CM4_EVENTOUT_31 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN8) +#define GPIO_CM4_EVENTOUT_32 (GPIO_ALT|GPIO_AF15|GPIO_PORTB|GPIO_PIN9) +#define GPIO_CM4_EVENTOUT_33 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN0) +#define GPIO_CM4_EVENTOUT_34 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN1) +#define GPIO_CM4_EVENTOUT_35 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN13) +#define GPIO_CM4_EVENTOUT_36 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN14) +#define GPIO_CM4_EVENTOUT_37 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN15) +#define GPIO_CM4_EVENTOUT_38 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN2) +#define GPIO_CM4_EVENTOUT_39 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN3) +#define GPIO_CM4_EVENTOUT_40 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN4) +#define GPIO_CM4_EVENTOUT_41 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN5) +#define GPIO_CM4_EVENTOUT_42 (GPIO_ALT|GPIO_AF15|GPIO_PORTC|GPIO_PIN6) +#define GPIO_CM4_EVENTOUT_43 (GPIO_ALT|GPIO_AF15|GPIO_PORTH|GPIO_PIN3) + +/* COMP */ + +#define GPIO_COMP1_OUT_1 (GPIO_ALT|GPIO_AF12|GPIO_PORTA|GPIO_PIN0) +#define GPIO_COMP1_OUT_2 (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN0) +#define GPIO_COMP1_OUT_3 (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN10) +#define GPIO_COMP2_OUT_1 (GPIO_ALT|GPIO_AF12|GPIO_PORTA|GPIO_PIN2) +#define GPIO_COMP2_OUT_2 (GPIO_ALT|GPIO_AF12|GPIO_PORTA|GPIO_PIN7) +#define GPIO_COMP2_OUT_3 (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN11) +#define GPIO_COMP2_OUT_4 (GPIO_ALT|GPIO_AF12|GPIO_PORTB|GPIO_PIN5) + +/* DEBUG */ + +#define GPIO_DEBUG_PWR_LDORDY_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN2) +#define GPIO_DEBUG_PWR_REGLP1S_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN0) +#define GPIO_DEBUG_PWR_REGLP2S_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN1) +#define GPIO_DEBUG_RF_DTB1_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN3) +#define GPIO_DEBUG_RF_HSE32RDY_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN10) +#define GPIO_DEBUG_RF_LDORDY_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN4) +#define GPIO_DEBUG_RF_NRESET_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN11) +#define GPIO_DEBUG_RF_SMPSRDY_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTB|GPIO_PIN2) +#define GPIO_DEBUG_SUBGHZSPI_MISOOUT_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN6) +#define GPIO_DEBUG_SUBGHZSPI_MOSIOUT_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN7) +#define GPIO_DEBUG_SUBGHZSPI_NSSOUT_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN4) +#define GPIO_DEBUG_SUBGHZSPI_SCKOUT_1 (GPIO_ALT|GPIO_AF13|GPIO_PORTA|GPIO_PIN5) + +/* I2C */ + +#define GPIO_I2C1_SCL_1 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN9) +#define GPIO_I2C1_SCL_2 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN6) +#define GPIO_I2C1_SCL_3 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN8) +#define GPIO_I2C1_SDA_1 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN10) +#define GPIO_I2C1_SDA_2 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN7) +#define GPIO_I2C1_SDA_3 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN9) +#define GPIO_I2C1_SMBA_1 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN1) +#define GPIO_I2C1_SMBA_2 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN14) +#define GPIO_I2C1_SMBA_3 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN5) + +#define GPIO_I2C2_SCL_1 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN12) +#define GPIO_I2C2_SCL_2 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN15) +#define GPIO_I2C2_SDA_1 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN11) +#define GPIO_I2C2_SDA_2 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN15) +#define GPIO_I2C2_SMBA_1 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN13) +#define GPIO_I2C2_SMBA_2 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN6) + +#define GPIO_I2C3_SCL_1 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN7) +#define GPIO_I2C3_SCL_2 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2C3_SCL_3 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN13) +#define GPIO_I2C3_SCL_4 (GPIO_ALT|GPIO_AF4 |GPIO_PORTC|GPIO_PIN0) +#define GPIO_I2C3_SDA_1 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN11) +#define GPIO_I2C3_SDA_2 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN14) +#define GPIO_I2C3_SDA_3 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN4) +#define GPIO_I2C3_SDA_4 (GPIO_ALT|GPIO_AF4 |GPIO_PORTC|GPIO_PIN1) +#define GPIO_I2C3_SMBA_1 (GPIO_ALT|GPIO_AF4 |GPIO_PORTA|GPIO_PIN0) +#define GPIO_I2C3_SMBA_2 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN12) +#define GPIO_I2C3_SMBA_3 (GPIO_ALT|GPIO_AF4 |GPIO_PORTB|GPIO_PIN2) + +/* I2S */ + +#define GPIO_I2S2_CK_1 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN8) +#define GPIO_I2S2_CK_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN9) +#define GPIO_I2S2_CK_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN10) +#define GPIO_I2S2_CK_4 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN13) +#define GPIO_I2S2_MCK_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTB|GPIO_PIN14) +#define GPIO_I2S2_MCK_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN3) +#define GPIO_I2S2_MCK_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTC|GPIO_PIN6) +#define GPIO_I2S2_SD_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTC|GPIO_PIN1) +#define GPIO_I2S2_SD_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN10) +#define GPIO_I2S2_SD_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN15) +#define GPIO_I2S2_SD_4 (GPIO_ALT|GPIO_AF5 |GPIO_PORTC|GPIO_PIN3) +#define GPIO_I2S2_WS_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTA|GPIO_PIN9) +#define GPIO_I2S2_WS_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN12) +#define GPIO_I2S2_WS_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN9) +#define GPIO_I2S_CKIN_1 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN0) + +/* IR */ + +#define GPIO_IR_OUT_1 (GPIO_ALT|GPIO_AF8 |GPIO_PORTA|GPIO_PIN13) +#define GPIO_IR_OUT_2 (GPIO_ALT|GPIO_AF8 |GPIO_PORTB|GPIO_PIN9) + +/* JTAG */ + +#define GPIO_JTCK_SWCLK_1 (GPIO_ALT|GPIO_AF0 |GPIO_PORTA|GPIO_PIN14) +#define GPIO_JTDI_1 (GPIO_ALT|GPIO_AF0 |GPIO_PORTA|GPIO_PIN15) +#define GPIO_JTDO_1 (GPIO_ALT|GPIO_AF0 |GPIO_PORTB|GPIO_PIN3) +#define GPIO_JTMS_SWDIO_1 (GPIO_ALT|GPIO_AF0 |GPIO_PORTA|GPIO_PIN13) +#define GPIO_NJTRST_1 (GPIO_ALT|GPIO_AF0 |GPIO_PORTB|GPIO_PIN4) + +/* Radio */ + +#define GPIO_RF_BUSY_1 (GPIO_ALT|GPIO_AF6 |GPIO_PORTA|GPIO_PIN12) +#define GPIO_RF_IRQ0_1 (GPIO_ALT|GPIO_AF6 |GPIO_PORTB|GPIO_PIN3) +#define GPIO_RF_IRQ1_1 (GPIO_ALT|GPIO_AF6 |GPIO_PORTB|GPIO_PIN5) +#define GPIO_RF_IRQ2_1 (GPIO_ALT|GPIO_AF6 |GPIO_PORTB|GPIO_PIN8) + +/* RTC */ + +#define GPIO_RTC_OUT_1 (GPIO_ALT|GPIO_AF0 |GPIO_PORTA|GPIO_PIN4) +#define GPIO_RTC_REFIN_1 (GPIO_ALT|GPIO_AF0 |GPIO_PORTA|GPIO_PIN10) + +/* SPI */ + +#define GPIO_SPI1_MISO_1 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN11) +#define GPIO_SPI1_MISO_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN6) +#define GPIO_SPI1_MISO_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN4) +#define GPIO_SPI1_MOSI_1 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN12) +#define GPIO_SPI1_MOSI_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN7) +#define GPIO_SPI1_MOSI_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN5) +#define GPIO_SPI1_NSS_1 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN15) +#define GPIO_SPI1_NSS_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN4) +#define GPIO_SPI1_NSS_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN2) +#define GPIO_SPI1_SCK_1 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN1) +#define GPIO_SPI1_SCK_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN5) +#define GPIO_SPI1_SCK_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN3) + +#define GPIO_SPI2_MISO_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTA|GPIO_PIN5) +#define GPIO_SPI2_MISO_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN14) +#define GPIO_SPI2_MISO_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTC|GPIO_PIN2) +#define GPIO_SPI2_MOSI_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTC|GPIO_PIN1) +#define GPIO_SPI2_MOSI_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN10) +#define GPIO_SPI2_MOSI_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN15) +#define GPIO_SPI2_MOSI_4 (GPIO_ALT|GPIO_AF5 |GPIO_PORTC|GPIO_PIN3) +#define GPIO_SPI2_NSS_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTA|GPIO_PIN9) +#define GPIO_SPI2_NSS_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN12) +#define GPIO_SPI2_NSS_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN9) +#define GPIO_SPI2_SCK_1 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN8) +#define GPIO_SPI2_SCK_2 (GPIO_ALT|GPIO_AF5 |GPIO_PORTA|GPIO_PIN9) +#define GPIO_SPI2_SCK_3 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN10) +#define GPIO_SPI2_SCK_4 (GPIO_ALT|GPIO_AF5 |GPIO_PORTB|GPIO_PIN13) + +/* TIM */ + +#define GPIO_TIM16_BKIN_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN5) +#define GPIO_TIM16_CH1N_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN6) +#define GPIO_TIM16_CH1_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM16_CH1_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM17_BKIN_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN10) +#define GPIO_TIM17_BKIN_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN4) +#define GPIO_TIM17_CH1N_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN7) +#define GPIO_TIM17_CH1_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM17_CH1_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM1_BKIN2_1 (GPIO_ALT|GPIO_AF12|GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_BKIN2_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_BKIN_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM1_BKIN_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN12) +#define GPIO_TIM1_BKIN_3 (GPIO_ALT|GPIO_AF12|GPIO_PORTA|GPIO_PIN6) +#define GPIO_TIM1_BKIN_4 (GPIO_ALT|GPIO_AF3 |GPIO_PORTB|GPIO_PIN12) +#define GPIO_TIM1_BKIN_5 (GPIO_ALT|GPIO_AF3 |GPIO_PORTB|GPIO_PIN7) +#define GPIO_TIM1_CH1N_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN7) +#define GPIO_TIM1_CH1N_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN13) +#define GPIO_TIM1_CH1_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN8) +#define GPIO_TIM1_CH2N_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN14) +#define GPIO_TIM1_CH2N_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN8) +#define GPIO_TIM1_CH2_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN9) +#define GPIO_TIM1_CH3N_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN15) +#define GPIO_TIM1_CH3N_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN9) +#define GPIO_TIM1_CH3_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN10) +#define GPIO_TIM1_CH4_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN11) +#define GPIO_TIM1_ETR_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN12) + +#define GPIO_TIM2_CH1_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_CH1_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_CH1_3 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN5) +#define GPIO_TIM2_CH2_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN1) +#define GPIO_TIM2_CH2_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN3) +#define GPIO_TIM2_CH3_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN2) +#define GPIO_TIM2_CH3_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN10) +#define GPIO_TIM2_CH4_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN3) +#define GPIO_TIM2_CH4_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN11) +#define GPIO_TIM2_ETR_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN0) +#define GPIO_TIM2_ETR_2 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN15) +#define GPIO_TIM2_ETR_3 (GPIO_ALT|GPIO_AF2 |GPIO_PORTA|GPIO_PIN5) + +#define GPIO_LPTIM1_ETR_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN6) +#define GPIO_LPTIM1_ETR_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTC|GPIO_PIN3) +#define GPIO_LPTIM1_IN1_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN5) +#define GPIO_LPTIM1_IN1_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTC|GPIO_PIN0) +#define GPIO_LPTIM1_IN2_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN7) +#define GPIO_LPTIM1_IN2_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTC|GPIO_PIN2) +#define GPIO_LPTIM1_OUT_1 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN14) +#define GPIO_LPTIM1_OUT_2 (GPIO_ALT|GPIO_AF1 |GPIO_PORTA|GPIO_PIN4) +#define GPIO_LPTIM1_OUT_3 (GPIO_ALT|GPIO_AF1 |GPIO_PORTB|GPIO_PIN2) +#define GPIO_LPTIM1_OUT_4 (GPIO_ALT|GPIO_AF1 |GPIO_PORTC|GPIO_PIN1) + +#define GPIO_LPTIM2_ETR_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN5) +#define GPIO_LPTIM2_ETR_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTC|GPIO_PIN3) +#define GPIO_LPTIM2_IN1_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTB|GPIO_PIN1) +#define GPIO_LPTIM2_IN1_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTC|GPIO_PIN0) +#define GPIO_LPTIM2_OUT_1 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN4) +#define GPIO_LPTIM2_OUT_2 (GPIO_ALT|GPIO_AF14|GPIO_PORTA|GPIO_PIN8) + +#define GPIO_LPTIM3_ETR_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTA|GPIO_PIN11) +#define GPIO_LPTIM3_IN1_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTA|GPIO_PIN12) +#define GPIO_LPTIM3_OUT_1 (GPIO_ALT|GPIO_AF3 |GPIO_PORTA|GPIO_PIN1) + +/* USART */ + +#define GPIO_USART1_CK_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN8) +#define GPIO_USART1_CK_2 (GPIO_ALT|GPIO_AF7 |GPIO_PORTB|GPIO_PIN5) +#define GPIO_USART1_CTS_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN11) +#define GPIO_USART1_CTS_2 (GPIO_ALT|GPIO_AF7 |GPIO_PORTB|GPIO_PIN4) +#define GPIO_USART1_RTS_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN12) +#define GPIO_USART1_RTS_2 (GPIO_ALT|GPIO_AF7 |GPIO_PORTB|GPIO_PIN3) +#define GPIO_USART1_RX_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN10) +#define GPIO_USART1_RX_2 (GPIO_ALT|GPIO_AF7 |GPIO_PORTB|GPIO_PIN7) +#define GPIO_USART1_TX_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN9) +#define GPIO_USART1_TX_2 (GPIO_ALT|GPIO_AF7 |GPIO_PORTB|GPIO_PIN6) + +#define GPIO_USART2_CK_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN4) +#define GPIO_USART2_CTS_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN0) +#define GPIO_USART2_RTS_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN1) +#define GPIO_USART2_RX_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN3) +#define GPIO_USART2_TX_1 (GPIO_ALT|GPIO_AF7 |GPIO_PORTA|GPIO_PIN2) + +#define GPIO_LPUART1_CTS_1 (GPIO_ALT|GPIO_AF8 |GPIO_PORTA|GPIO_PIN6) +#define GPIO_LPUART1_CTS_2 (GPIO_ALT|GPIO_AF8 |GPIO_PORTB|GPIO_PIN13) +#define GPIO_LPUART1_RTS_1 (GPIO_ALT|GPIO_AF8 |GPIO_PORTA|GPIO_PIN1) +#define GPIO_LPUART1_RTS_2 (GPIO_ALT|GPIO_AF8 |GPIO_PORTB|GPIO_PIN12) +#define GPIO_LPUART1_RTS_DE_1 (GPIO_ALT|GPIO_AF8 |GPIO_PORTB|GPIO_PIN1) +#define GPIO_LPUART1_RX_1 (GPIO_ALT|GPIO_AF8 |GPIO_PORTA|GPIO_PIN3) +#define GPIO_LPUART1_RX_2 (GPIO_ALT|GPIO_AF8 |GPIO_PORTB|GPIO_PIN10) +#define GPIO_LPUART1_RX_3 (GPIO_ALT|GPIO_AF8 |GPIO_PORTC|GPIO_PIN0) +#define GPIO_LPUART1_TX_1 (GPIO_ALT|GPIO_AF8 |GPIO_PORTA|GPIO_PIN2) +#define GPIO_LPUART1_TX_2 (GPIO_ALT|GPIO_AF8 |GPIO_PORTB|GPIO_PIN11) +#define GPIO_LPUART1_TX_3 (GPIO_ALT|GPIO_AF8 |GPIO_PORTC|GPIO_PIN1) + +/* Misc */ + +#define GPIO_LSCO_1 (GPIO_ALT|GPIO_AF0 |GPIO_PORTA|GPIO_PIN2) +#define GPIO_MCO_1 (GPIO_ALT|GPIO_AF0 |GPIO_PORTA|GPIO_PIN8) + +#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_PINMAP_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_pwr.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_pwr.h new file mode 100644 index 0000000000..ecd3860685 --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_pwr.h @@ -0,0 +1,198 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_pwr.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_PWR_H +#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_PWR_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define STM32WL5_PWR_CR1_OFFSET 0x0000 /* Power control register 1 */ +#define STM32WL5_PWR_CR2_OFFSET 0x0004 /* Power control register 2 */ +#define STM32WL5_PWR_CR3_OFFSET 0x0008 /* Power control register 3 */ +#define STM32WL5_PWR_CR4_OFFSET 0x000C /* Power control register 4 */ +#define STM32WL5_PWR_SR1_OFFSET 0x0010 /* Power status register 1 */ +#define STM32WL5_PWR_SR2_OFFSET 0x0014 /* Power status register 2 */ +#define STM32WL5_PWR_SCR_OFFSET 0x0018 /* Power status clear register */ +#define STM32WL5_PWR_CR5_OFFSET 0x001C /* Power control register 5 */ +#define STM32WL5_PWR_PUCRA_OFFSET 0x0020 /* Power Port A pull-up control register */ +#define STM32WL5_PWR_PDCRA_OFFSET 0x0024 /* Power Port A pull-down control register */ +#define STM32WL5_PWR_PUCRB_OFFSET 0x0028 /* Power Port B pull-up control register */ +#define STM32WL5_PWR_PDCRB_OFFSET 0x002C /* Power Port B pull-down control register */ +#define STM32WL5_PWR_PUCRC_OFFSET 0x0030 /* Power Port C pull-up control register */ +#define STM32WL5_PWR_PDCRC_OFFSET 0x0034 /* Power Port C pull-down control register */ +#define STM32WL5_PWR_PUCRH_OFFSET 0x0058 /* Power Port H pull-up control register */ +#define STM32WL5_PWR_PDCRH_OFFSET 0x005C /* Power Port H pull-down control register */ +#define STM32WL5_PWR_C2CR1_OFFSET 0x0080 /* Power control register 1 for cpu2 */ +#define STM32WL5_PWR_C2CR3_OFFSET 0x0084 /* Power control register 3 for cpu2 */ +#define STM32WL5_PWR_EXTSCR_OFFSET 0x0088 /* Power extended status */ +#define STM32WL5_PWR_SECCFGR_OFFSET 0x0088 /* Power security configuration */ +#define STM32WL5_PWR_SUBGHZSPICR_OFFSET 0x0088 /* Power sub-ghz spi radio control */ +#define STM32WL5_PWR_RSSCMDR_OFFSET 0x0088 /* Power RSS command */ + +/* Register Addresses *******************************************************/ + +#define STM32WL5_PWR_CR1 (STM32WL5_PWR_BASE+STM32WL5_PWR_CR1_OFFSET) +#define STM32WL5_PWR_CR2 (STM32WL5_PWR_BASE+STM32WL5_PWR_CR2_OFFSET) +#define STM32WL5_PWR_CR3 (STM32WL5_PWR_BASE+STM32WL5_PWR_CR3_OFFSET) +#define STM32WL5_PWR_CR4 (STM32WL5_PWR_BASE+STM32WL5_PWR_CR4_OFFSET) +#define STM32WL5_PWR_SR1 (STM32WL5_PWR_BASE+STM32WL5_PWR_SR1_OFFSET) +#define STM32WL5_PWR_SR2 (STM32WL5_PWR_BASE+STM32WL5_PWR_SR2_OFFSET) +#define STM32WL5_PWR_SCR (STM32WL5_PWR_BASE+STM32WL5_PWR_SCR_OFFSET) +#define STM32WL5_PWR_CR5 (STM32WL5_PWR_BASE+STM32WL5_PWR_CR5_OFFSET) +#define STM32WL5_PWR_PUCRA (STM32WL5_PWR_BASE+STM32WL5_PWR_PUCRA_OFFSET) +#define STM32WL5_PWR_PDCRA (STM32WL5_PWR_BASE+STM32WL5_PWR_PDCRA_OFFSET) +#define STM32WL5_PWR_PUCRB (STM32WL5_PWR_BASE+STM32WL5_PWR_PUCRB_OFFSET) +#define STM32WL5_PWR_PDCRB (STM32WL5_PWR_BASE+STM32WL5_PWR_PDCRB_OFFSET) +#define STM32WL5_PWR_PUCRC (STM32WL5_PWR_BASE+STM32WL5_PWR_PUCRC_OFFSET) +#define STM32WL5_PWR_PDCRC (STM32WL5_PWR_BASE+STM32WL5_PWR_PDCRC_OFFSET) +#define STM32WL5_PWR_PUCRH (STM32WL5_PWR_BASE+STM32WL5_PWR_PUCRH_OFFSET) +#define STM32WL5_PWR_PDCRH (STM32WL5_PWR_BASE+STM32WL5_PWR_PDCRH_OFFSET) +#define STM32WL5_PWR_C2CR1 (STM32WL5_PWR_BASE+STM32WL5_PWR_C2CR1_OFFSET) +#define STM32WL5_PWR_C2CR3 (STM32WL5_PWR_BASE+STM32WL5_PWR_C2CR3_OFFSET) +#define STM32WL5_PWR_EXTSCR (STM32WL5_PWR_BASE+STM32WL5_PWR_EXTSCR_OFFSET) +#define STM32WL5_PWR_SECCFGR (STM32WL5_PWR_BASE+STM32WL5_PWR_SECCFGR_OFFSET) +#define STM32WL5_PWR_SUBGHZSPICR (STM32WL5_PWR_BASE+STM32WL5_PWR_SUBGHZSPICR_OFFSET) +#define STM32WL5_PWR_RSSCMDR (STM32WL5_PWR_BASE+STM32WL5_PWR_RSSCMDR_OFFSET) + +/* Register Bitfield Definitions ********************************************/ + +/* Power control register 1 */ + +#define PWR_CR1_LPMS_SHIFT 0 +#define PWR_CR1_LPMS_MASK (7 << PWR_CR1_LPMS_SHIFT) /* Bits 0-2: Low-power mode selection */ +# define PWR_CR1_LPMS_STOP1MR (0 << PWR_CR1_LPMS_SHIFT) /* Stop 1 mode with main regulator (MR) */ +# define PWR_CR1_LPMS_STOP1LPR (1 << PWR_CR1_LPMS_SHIFT) /* Stop 1 mode with low-power regulator (LPR) */ +# define PWR_CR1_LPMS_STOP2 (2 << PWR_CR1_LPMS_SHIFT) /* 010: Stop 2 mode */ +# define PWR_CR1_LPMS_STANDBY (3 << PWR_CR1_LPMS_SHIFT) /* 011: Standby mode */ +# define PWR_CR1_LPMS_SHUTDOWN (4 << PWR_CR1_LPMS_SHIFT) /* 1xx: Shutdown mode */ + +#define PWR_CR1_SUBGHZSPIPINSEL (1 << 3) /* Spi nss source select for radio */ +#define PWR_CR1_FPDR (1 << 4) /* Flash in power-down mode when system in lprun mode */ +#define PWR_CR1_FPDS (1 << 5) /* Flash in power-down mode when system in lpsleep mode (cpu1 only) */ + /* Bit 6-7: Reserved */ +#define PWR_CR1_DBP (1 << 8) /* Disable Backup domain write protection */ + +#define PWR_CR1_VOS_SHIFT 9 +#define PWR_CR1_VOS_MASK (3 << PWR_CR1_VOS_SHIFT) /* Bits 9-10: Voltage scaling range selection */ +#define PWR_CR1_VOS_RANGE1 (1 << PWR_CR1_VOS_SHIFT) /* 01: Range 1 */ +#define PWR_CR1_VOS_RANGE2 (2 << PWR_CR1_VOS_SHIFT) /* 10: Range 2 */ + +#define PWR_CR1_LPR (1 << 14) /* Bit 14: Low-power run */ + +/* Power control register 2 */ + +#define PWR_CR2_PVDE (1 << 0) /* Bit 0: Power voltage detector enable */ +#define PWR_CR2_PLS_SHIFT 1 +#define PWR_CR2_PLS_MASK (7 << PWR_CR2_PLS_SHIFT) /* Bits 1-3: Power voltage detector level selection */ +# define PWR_CR2_PLS_2000mv (0 << PWR_CR2_PLS_SHIFT) /* 000: VPVD0 around 2.0V */ +# define PWR_CR2_PLS_2200mv (1 << PWR_CR2_PLS_SHIFT) /* 001: VPVD1 around 2.2V */ +# define PWR_CR2_PLS_2400mv (2 << PWR_CR2_PLS_SHIFT) /* 010: VPVD2 around 2.4V */ +# define PWR_CR2_PLS_2500mv (3 << PWR_CR2_PLS_SHIFT) /* 011: VPVD3 around 2.5V */ +# define PWR_CR2_PLS_2600mv (4 << PWR_CR2_PLS_SHIFT) /* 100: VPVD4 around 2.6V */ +# define PWR_CR2_PLS_2800mv (5 << PWR_CR2_PLS_SHIFT) /* 101: VPVD5 around 2.8V */ +# define PWR_CR2_PLS_2900mv (6 << PWR_CR2_PLS_SHIFT) /* 110: VPVD6 around 2.9V */ +# define PWR_CR2_PLS_EXT (7 << PWR_CR2_PLS_SHIFT) /* 111: External input analog voltage PVD_IN */ + + /* Bit 4-5: Reserved */ +#define PWR_CR2_PVME3 (1 << 6) /* Bit 6: Peripheral voltage monitoring 3 enable (VDDA vs 1.62V) */ + +/* Power control register 3 */ + +#define PWR_CR3_EWUP1 (1 << 0) /* Bit 0: Enable Wakeup pin WKUP1 */ +#define PWR_CR3_EWUP2 (1 << 1) /* Bit 1: Enable Wakeup pin WKUP2 */ +#define PWR_CR3_EWUP3 (1 << 2) /* Bit 2: Enable Wakeup pin WKUP3 */ +#define PWR_CR3_ULPEN (1 << 7) /* Bit 7: Ultra low power mode enable */ +#define PWR_CR3_EWPVD (1 << 8) /* Bit 8: PVD enabled while radio is active */ +#define PWR_CR3_RRS (1 << 9) /* Bit 9: SRAM2 retention in Standby mode */ +#define PWR_CR3_APC (1 << 10) /* Bit 10: Apply pull-up and pull-down configuration */ +#define PWR_CR3_EWRFBUSY (1 << 11) /* Bit 11: Radio busy wakeup from standby for cpu1 */ +#define PWR_CR3_EWRFIRQ (1 << 13) /* Bit 13: Radio IRQ[2:0] wakeup for cpu1 */ +#define PWR_CR3_EC2H (1 << 14) /* Bit 14: Enable cpu2 interrupt to cpu1 */ +#define PWR_CR3_EIWUL (1 << 15) /* Bit 15: Enable internal wakeup line for cpu1 */ + +/* Power control register 4 */ + +#define PWR_CR4_WP1 (1 << 0) /* Bit 0: Wakeup pin WKUP1 polarity */ +#define PWR_CR4_WP2 (1 << 1) /* Bit 1: Wakeup pin WKUP2 polarity */ +#define PWR_CR4_WP3 (1 << 2) /* Bit 2: Wakeup pin WKUP3 polarity */ +#define PWR_CR4_VBE (1 << 8) /* Bit 8: Vbat battery charging enable */ +#define PWR_CR4_VBRS (1 << 9) /* Bit 9: Vbat battery charging resistor selection */ +#define PWR_CR4_WRFBUSYP (1 << 11) /* Bit 11: Radio event detection on failling edge */ +#define PWR_CR4_C2BOOT (1 << 15) /* Bit 15: Boot cpu2 after reset if event is available */ + +# define PWR_CR4_VBRS_5k 0 /* 0: 5k resistor */ +# define PWR_CR4_VBRS_1k5 PWR_CR4_VBRS /* 1: 1k5 resistor */ + +/* Power control register 5 */ + +#define PWR_CR5_RFEOLEN (1 << 14) /* Bit 14: Enable radio end-of-life detector */ +#define PWR_CR5_SMPSEN (1 << 15) /* Bit 15: Enable SMPS step-down converter */ + +/* Power status register 1 */ + +#define PWR_SR1_WUF1 (1 << 0) /* Bit 0: Wakeup flag 1 */ +#define PWR_SR1_WUF2 (1 << 1) /* Bit 1: Wakeup flag 2 */ +#define PWR_SR1_WUF3 (1 << 2) /* Bit 2: Wakeup flag 3 */ +#define PWR_SR1_WPVDF (1 << 8) /* Bit 8: Wakup PVD flag */ +#define PWR_SR1_WRFBUSYF (1 << 11) /* Bit 11: Radio busy wakup flag */ +#define PWR_SR1_C2HF (1 << 14) /* Bit 14: Cpu2 hold interrupt flag */ +#define PWR_SR1_WUFI (1 << 15) /* Bit 15: Wakeup internal flag */ + +/* Power status register 2 */ + +#define PVR_SR2_C2BOOTS (1 << 0) /* Bit 0: CPU2 booted from a C2BOOT request */ +#define PVR_SR2_RFBUSYS (1 << 1) /* Bit 1: Radio busy signal high (radio is busy) */ +#define PVR_SR2_RFBUSYMS (1 << 2) /* Bit 2: Radio busy masked signal high */ +#define PVR_SR2_SMPSRDY (1 << 3) /* Bit 3: SMPS step-down converter is ready */ +#define PVR_SR2_LDORDY (1 << 4) /* Bit 4: LDO is ready */ +#define PVR_SR2_RFEOLF (1 << 5) /* Bit 5: Supply voltage below radio end-of-life low level */ +#define PVR_SR2_REGMRS (1 << 6) /* Bit 6: Main regulator supplied through LDO or SMPS */ +#define PVR_SR2_FLASHRDY (1 << 7) /* Bit 7: Flash memory is ready */ +#define PWR_SR2_REGLPS (1 << 8) /* Bit 8: Low power regulator started */ +#define PWR_SR2_REGLPF (1 << 9) /* Bit 9: Low power regulator flag */ +#define PWR_SR2_VOSF (1 << 10) /* Bit 10: Voltage scaling flag */ +#define PWR_SR2_PVDO (1 << 11) /* Bit 11: Power voltage detector output */ +#define PWR_SR2_PVMO3 (1 << 14) /* Bit 14: Peripheral voltage monitoring output 3 (VDDA vs 1.62V) */ + +/* Power status clear register */ + +#define PWR_SCR_CWUF1 (1 << 0) /* Bit 0: Clear wakeup flag 1 */ +#define PWR_SCR_CWUF2 (1 << 1) /* Bit 1: Clear wakeup flag 2 */ +#define PWR_SCR_CWUF3 (1 << 2) /* Bit 2: Clear wakeup flag 3 */ +#define PWRC_SCR_CWPVDF (1 << 8) /* Bit 8: Clear wakeup PVD */ +#define PWRC_SCR_CWRFBUSYF (1 << 11) /* Bit 11: Clear wakeup radio */ +#define PWRC_SCR_CC2HF (1 << 14) /* Bit 14: Clear wakeup cpu2 */ + +/* Port X pull-up/down registers have one bit per port line, + * with a few exceptions + */ + +#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_PWR_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h new file mode 100644 index 0000000000..c730a3d4c0 --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h @@ -0,0 +1,671 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_rcc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_RCC_H +#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_RCC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define STM32WL5_RCC_CR_OFFSET 0x0000 /* Clock control register */ +#define STM32WL5_RCC_ICSCR_OFFSET 0x0004 /* Internal clock sources calibration register */ +#define STM32WL5_RCC_CFGR_OFFSET 0x0008 /* Clock configuration register */ +#define STM32WL5_RCC_PLLCFG_OFFSET 0x000c /* PLL configuration register */ +#define STM32WL5_RCC_CIER_OFFSET 0x0018 /* Clock interrupt enable register */ +#define STM32WL5_RCC_CIFR_OFFSET 0x001c /* Clock interrupt flag register */ +#define STM32WL5_RCC_CICR_OFFSET 0x0020 /* Clock interrupt clear register */ +#define STM32WL5_RCC_AHB1RSTR_OFFSET 0x0028 /* AHB1 peripheral reset register */ +#define STM32WL5_RCC_AHB2RSTR_OFFSET 0x002c /* AHB2 peripheral reset register */ +#define STM32WL5_RCC_AHB3RSTR_OFFSET 0x0030 /* AHB3 peripheral reset register */ +#define STM32WL5_RCC_APB1RSTR1_OFFSET 0x0038 /* APB1 Peripheral reset register 1 */ +#define STM32WL5_RCC_APB1RSTR2_OFFSET 0x003c /* APB1 Peripheral reset register 2 */ +#define STM32WL5_RCC_APB2RSTR_OFFSET 0x0040 /* APB2 Peripheral reset register */ +#define STM32WL5_RCC_AHB1ENR_OFFSET 0x0048 /* AHB1 Peripheral Clock enable register */ +#define STM32WL5_RCC_AHB2ENR_OFFSET 0x004c /* AHB2 Peripheral Clock enable register */ +#define STM32WL5_RCC_AHB3ENR_OFFSET 0x0050 /* AHB3 Peripheral Clock enable register */ +#define STM32WL5_RCC_APB1ENR1_OFFSET 0x0058 /* APB1 Peripheral Clock enable register 1 */ +#define STM32WL5_RCC_APB1ENR2_OFFSET 0x005c /* APB1 Peripheral Clock enable register 2 */ +#define STM32WL5_RCC_APB2ENR_OFFSET 0x0060 /* APB2 Peripheral Clock enable register */ +#define STM32WL5_RCC_AHB1SMENR_OFFSET 0x0068 /* RCC AHB1 low power mode peripheral clock enable register */ +#define STM32WL5_RCC_AHB2SMENR_OFFSET 0x006c /* RCC AHB2 low power mode peripheral clock enable register */ +#define STM32WL5_RCC_AHB3SMENR_OFFSET 0x0070 /* RCC AHB3 low power mode peripheral clock enable register */ +#define STM32WL5_RCC_APB1SMENR1_OFFSET 0x0078 /* RCC APB1 low power mode peripheral clock enable register 1 */ +#define STM32WL5_RCC_APB1SMENR2_OFFSET 0x007c /* RCC APB1 low power mode peripheral clock enable register 2 */ +#define STM32WL5_RCC_APB2SMENR_OFFSET 0x0080 /* RCC APB2 low power mode peripheral clock enable register */ +#define STM32WL5_RCC_CCIPR_OFFSET 0x0088 /* Peripherals independent clock configuration register 1 */ +#define STM32WL5_RCC_BDCR_OFFSET 0x0090 /* Backup domain control register */ +#define STM32WL5_RCC_CSR_OFFSET 0x0094 /* Control/status register */ +#define STM32WL5_RCC_EXTCFGR_OFFSET 0x0108 +#define STM32WL5_RCC_C2AHB1ENR_OFFSET 0x0148 /* CPU2 AHB1 Peripheral Clock enable register */ +#define STM32WL5_RCC_C2AHB2ENR_OFFSET 0x014c /* CPU2 AHB2 Peripheral Clock enable register */ +#define STM32WL5_RCC_C2AHB3ENR_OFFSET 0x0150 /* CPU2 AHB3 Peripheral Clock enable register */ +#define STM32WL5_RCC_C2APB1ENR1_OFFSET 0x0158 /* CPU2 APB1 Peripheral Clock enable register 1 */ +#define STM32WL5_RCC_C2APB1ENR2_OFFSET 0x015c /* CPU2 APB1 Peripheral Clock enable register 2 */ +#define STM32WL5_RCC_C2APB2ENR_OFFSET 0x0160 /* CPU2 APB2 Peripheral Clock enable register */ +#define STM32WL5_RCC_C2APB3ENR_OFFSET 0x0164 /* CPU2 APB3 Peripheral Clock enable register */ +#define STM32WL5_RCC_C2AHB1SMENR_OFFSET 0x0168 /* CPU2 RCC AHB1 low power mode peripheral clock enable register */ +#define STM32WL5_RCC_C2AHB2SMENR_OFFSET 0x016c /* CPU2 RCC AHB2 low power mode peripheral clock enable register */ +#define STM32WL5_RCC_C2AHB3SMENR_OFFSET 0x0170 /* CPU2 RCC AHB3 low power mode peripheral clock enable register */ +#define STM32WL5_RCC_C2APB1SMENR1_OFFSET 0x0178 /* CPU2 RCC APB1 low power mode peripheral clock enable register 1 */ +#define STM32WL5_RCC_C2APB1SMENR2_OFFSET 0x017c /* CPU2 RCC APB1 low power mode peripheral clock enable register 2 */ +#define STM32WL5_RCC_C2APB2SMENR_OFFSET 0x0180 /* CPU2 RCC APB2 low power mode peripheral clock enable register */ +#define STM32WL5_RCC_C2APB3SMENR_OFFSET 0x0184 /* CPU2 RCC APB3 low power mode peripheral clock enable register */ + +/* Register Addresses *******************************************************/ + +#define STM32WL5_RCC_CR (STM32WL5_RCC_BASE + STM32WL5_RCC_CR_OFFSET) +#define STM32WL5_RCC_ICSCR (STM32WL5_RCC_BASE + STM32WL5_RCC_ICSCR_OFFSET) +#define STM32WL5_RCC_CFGR (STM32WL5_RCC_BASE + STM32WL5_RCC_CFGR_OFFSET) +#define STM32WL5_RCC_PLLCFG (STM32WL5_RCC_BASE + STM32WL5_RCC_PLLCFG_OFFSET) +#define STM32WL5_RCC_CIER (STM32WL5_RCC_BASE + STM32WL5_RCC_CIER_OFFSET) +#define STM32WL5_RCC_CIFR (STM32WL5_RCC_BASE + STM32WL5_RCC_CIFR_OFFSET) +#define STM32WL5_RCC_CICR (STM32WL5_RCC_BASE + STM32WL5_RCC_CICR_OFFSET) +#define STM32WL5_RCC_AHB1RSTR (STM32WL5_RCC_BASE + STM32WL5_RCC_AHB1RSTR_OFFSET) +#define STM32WL5_RCC_AHB2RSTR (STM32WL5_RCC_BASE + STM32WL5_RCC_AHB2RSTR_OFFSET) +#define STM32WL5_RCC_AHB3RSTR (STM32WL5_RCC_BASE + STM32WL5_RCC_AHB3RSTR_OFFSET) +#define STM32WL5_RCC_APB1RSTR1 (STM32WL5_RCC_BASE + STM32WL5_RCC_APB1RSTR1_OFFSET) +#define STM32WL5_RCC_APB1RSTR2 (STM32WL5_RCC_BASE + STM32WL5_RCC_APB1RSTR2_OFFSET) +#define STM32WL5_RCC_APB2RSTR (STM32WL5_RCC_BASE + STM32WL5_RCC_APB2RSTR_OFFSET) +#define STM32WL5_RCC_AHB1ENR (STM32WL5_RCC_BASE + STM32WL5_RCC_AHB1ENR_OFFSET) +#define STM32WL5_RCC_AHB2ENR (STM32WL5_RCC_BASE + STM32WL5_RCC_AHB2ENR_OFFSET) +#define STM32WL5_RCC_AHB3ENR (STM32WL5_RCC_BASE + STM32WL5_RCC_AHB3ENR_OFFSET) +#define STM32WL5_RCC_APB1ENR1 (STM32WL5_RCC_BASE + STM32WL5_RCC_APB1ENR1_OFFSET) +#define STM32WL5_RCC_APB1ENR2 (STM32WL5_RCC_BASE + STM32WL5_RCC_APB1ENR2_OFFSET) +#define STM32WL5_RCC_APB2ENR (STM32WL5_RCC_BASE + STM32WL5_RCC_APB2ENR_OFFSET) +#define STM32WL5_RCC_AHB1SMENR (STM32WL5_RCC_BASE + STM32WL5_RCC_AHB1SMENR_OFFSET) +#define STM32WL5_RCC_AHB2SMENR (STM32WL5_RCC_BASE + STM32WL5_RCC_AHB2SMENR_OFFSET) +#define STM32WL5_RCC_AHB3SMENR (STM32WL5_RCC_BASE + STM32WL5_RCC_AHB3SMENR_OFFSET) +#define STM32WL5_RCC_APB1SMENR1 (STM32WL5_RCC_BASE + STM32WL5_RCC_APB1SMENR1_OFFSET) +#define STM32WL5_RCC_APB1SMENR2 (STM32WL5_RCC_BASE + STM32WL5_RCC_APB1SMENR2_OFFSET) +#define STM32WL5_RCC_APB2SMENR (STM32WL5_RCC_BASE + STM32WL5_RCC_APB2SMENR_OFFSET) +#define STM32WL5_RCC_CCIPR (STM32WL5_RCC_BASE + STM32WL5_RCC_CCIPR_OFFSET) +#define STM32WL5_RCC_BDCR (STM32WL5_RCC_BASE + STM32WL5_RCC_BDCR_OFFSET) +#define STM32WL5_RCC_CSR (STM32WL5_RCC_BASE + STM32WL5_RCC_CSR_OFFSET) +#define STM32WL5_RCC_EXTCFGR (STM32WL5_RCC_BASE + STM32WL5_RCC_EXTCFGR_OFFSET) +#define STM32WL5_RCC_C2AHB1ENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2AHB1ENR_OFFSET) +#define STM32WL5_RCC_C2AHB2ENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2AHB2ENR_OFFSET) +#define STM32WL5_RCC_C2AHB3ENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2AHB3ENR_OFFSET) +#define STM32WL5_RCC_C2APB1ENR1 (STM32WL5_RCC_BASE + STM32WL5_RCC_C2APB1ENR1_OFFSET) +#define STM32WL5_RCC_C2APB1ENR2 (STM32WL5_RCC_BASE + STM32WL5_RCC_C2APB1ENR2_OFFSET) +#define STM32WL5_RCC_C2APB2ENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2APB2ENR_OFFSET) +#define STM32WL5_RCC_C2APB3ENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2APB3ENR_OFFSET) +#define STM32WL5_RCC_C2AHB1SMENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2AHB1SMENR_OFFSET) +#define STM32WL5_RCC_C2AHB2SMENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2AHB2SMENR_OFFSET) +#define STM32WL5_RCC_C2AHB3SMENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2AHB3SMENR_OFFSET) +#define STM32WL5_RCC_C2APB1SMENR1 (STM32WL5_RCC_BASE + STM32WL5_RCC_C2APB1SMENR1_OFFSET) +#define STM32WL5_RCC_C2APB1SMENR2 (STM32WL5_RCC_BASE + STM32WL5_RCC_C2APB1SMENR2_OFFSET) +#define STM32WL5_RCC_C2APB2SMENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2APB2SMENR_OFFSET) +#define STM32WL5_RCC_C2APB3SMENR (STM32WL5_RCC_BASE + STM32WL5_RCC_C2APB3SMENR_OFFSET) + +/* Register Bitfield Definitions ********************************************/ + +/* Clock control register */ + +#define RCC_CR_MSION (1 << 0) /* Bit 0: Internal Multi Speed clock enable */ +#define RCC_CR_MSIRDY (1 << 1) /* Bit 1: Internal Multi Speed clock ready flag */ +#define RCC_CR_MSIPLLEN (1 << 2) /* Bit 2: MSI clock PLL enable */ +#define RCC_CR_MSIRGSEL (1 << 3) /* Bit 3: MSI clock range selection */ +#define RCC_CR_MSIRANGE_SHIFT (4) /* Bits 7-4: MSI clock range */ +#define RCC_CR_MSIRANGE_MASK (0x0f << RCC_CR_MSIRANGE_SHIFT) +# define RCC_CR_MSIRANGE_100K (0 << RCC_CR_MSIRANGE_SHIFT) /* 0000: around 100 kHz */ +# define RCC_CR_MSIRANGE_200K (1 << RCC_CR_MSIRANGE_SHIFT) /* 0001: around 200 kHz */ +# define RCC_CR_MSIRANGE_400K (2 << RCC_CR_MSIRANGE_SHIFT) /* 0010: around 400 kHz */ +# define RCC_CR_MSIRANGE_800K (3 << RCC_CR_MSIRANGE_SHIFT) /* 0011: around 800 kHz */ +# define RCC_CR_MSIRANGE_1M (4 << RCC_CR_MSIRANGE_SHIFT) /* 0100: around 1 MHz */ +# define RCC_CR_MSIRANGE_2M (5 << RCC_CR_MSIRANGE_SHIFT) /* 0101: around 2 MHz */ +# define RCC_CR_MSIRANGE_4M (6 << RCC_CR_MSIRANGE_SHIFT) /* 0110: around 4 MHz */ +# define RCC_CR_MSIRANGE_8M (7 << RCC_CR_MSIRANGE_SHIFT) /* 0111: around 8 MHz */ +# define RCC_CR_MSIRANGE_16M (8 << RCC_CR_MSIRANGE_SHIFT) /* 1000: around 16 MHz */ +# define RCC_CR_MSIRANGE_24M (9 << RCC_CR_MSIRANGE_SHIFT) /* 1001: around 24 MHz */ +# define RCC_CR_MSIRANGE_32M (10 << RCC_CR_MSIRANGE_SHIFT) /* 1010: around 32 MHz */ +# define RCC_CR_MSIRANGE_48M (11 << RCC_CR_MSIRANGE_SHIFT) /* 1011: around 48 MHz */ + +#define RCC_CR_HSION (1 << 8) /* Bit 8: Internal High Speed clock enable */ +#define RCC_CR_HSIKERON (1 << 9) /* Bit 9: HSI16 always enable for peripheral kernels */ +#define RCC_CR_HSIRDY (1 << 10) /* Bit 10: Internal High Speed clock ready flag */ +#define RCC_CR_HSIASFS (1 << 11) /* Bit 11: HSI automatic start from stop */ + +#define RCC_CR_HSEON (1 << 16) /* Bit 16: External High Speed clock enable */ +#define RCC_CR_HSERDY (1 << 17) /* Bit 17: External High Speed clock ready flag */ +#define RCC_CR_CSSON (1 << 19) /* Bit 19: Clock Security System enable */ +#define RCC_CR_HSEPRE (1 << 20) /* Bit 20: HSE prescaller */ +#define RCC_CR_HSEBYPPWR (1 << 21) /* Bit 21: Enable HSE VDDTCXO */ +#define RCC_CR_PLLON (1 << 24) /* Bit 24: PLL enable */ +#define RCC_CR_PLLRDY (1 << 25) /* Bit 25: PLL clock ready flag */ + +/* Internal Clock Sources Calibration */ + +#define RCC_CR_HSITRIM_SHIFT (24) /* Bits 30-24: Internal High Speed clock trimming */ +#define RCC_CR_HSITRIM_MASK (0x7f << RCC_CR_HSITRIM_SHIFT) +#define RCC_CR_HSICAL_SHIFT (16) /* Bits 23-16: Internal High Speed clock Calibration */ +#define RCC_CR_HSICAL_MASK (0xff << RCC_CR_HSICAL_SHIFT) +#define RCC_CR_MSITRIM_SHIFT (8) /* Bits 15-8: Internal Multi Speed clock trimming */ +#define RCC_CR_MSITRIM_MASK (0xff << RCC_CR_MSITRIM_SHIFT) +#define RCC_CR_MSICAL_SHIFT (0) /* Bits 7-0: Internal Multi Speed clock Calibration */ +#define RCC_CR_MSICAL_MASK (0xff << RCC_CR_MSICAL_SHIFT) + +/* Clock configuration register */ + +#define RCC_CFGR_SW_SHIFT (0) /* Bits 0-1: System clock Switch */ +#define RCC_CFGR_SW_MASK (3 << RCC_CFGR_SW_SHIFT) +# define RCC_CFGR_SW_MSI (0 << RCC_CFGR_SW_SHIFT) /* 00: MSI selected as system clock */ +# define RCC_CFGR_SW_HSI16 (1 << RCC_CFGR_SW_SHIFT) /* 01: HSI16 selected as system clock */ +# define RCC_CFGR_SW_HSE (2 << RCC_CFGR_SW_SHIFT) /* 10: HSE selected as system clock */ +# define RCC_CFGR_SW_PLL (3 << RCC_CFGR_SW_SHIFT) /* 11: PLL selected as system clock */ + +#define RCC_CFGR_SWS_SHIFT (2) /* Bits 2-3: System Clock Switch Status */ +#define RCC_CFGR_SWS_MASK (3 << RCC_CFGR_SWS_SHIFT) +# define RCC_CFGR_SWS_MSI (0 << RCC_CFGR_SWS_SHIFT) /* 00: MSI oscillator used as system clock */ +# define RCC_CFGR_SWS_HSI16 (1 << RCC_CFGR_SWS_SHIFT) /* 01: HSI16 oscillator used as system clock */ +# define RCC_CFGR_SWS_HSE (2 << RCC_CFGR_SWS_SHIFT) /* 10: HSE oscillator used as system clock */ +# define RCC_CFGR_SWS_PLL (3 << RCC_CFGR_SWS_SHIFT) /* 11: PLL used as system clock */ + +#define RCC_CFGR_HPRE_SHIFT (4) /* Bits 4-7: AHB prescaler */ +#define RCC_CFGR_HPRE_MASK (0x0f << RCC_CFGR_HPRE_SHIFT) +# define RCC_CFGR_HPRE_SYSCLK ( 0 << RCC_CFGR_HPRE_SHIFT) /* not-listed: SYSCLK not divided */ +# define RCC_CFGR_HPRE_SYSCLK_3 ( 1 << RCC_CFGR_HPRE_SHIFT) /* 0001: SYSCLK divided by 3 */ +# define RCC_CFGR_HPRE_SYSCLK_5 ( 2 << RCC_CFGR_HPRE_SHIFT) /* 0010: SYSCLK divided by 5 */ +# define RCC_CFGR_HPRE_SYSCLK_6 ( 5 << RCC_CFGR_HPRE_SHIFT) /* 0101: SYSCLK divided by 6 */ +# define RCC_CFGR_HPRE_SYSCLK_10 ( 6 << RCC_CFGR_HPRE_SHIFT) /* 0110: SYSCLK divided by 10 */ +# define RCC_CFGR_HPRE_SYSCLK_32 ( 7 << RCC_CFGR_HPRE_SHIFT) /* 0111: SYSCLK divided by 32 */ +# define RCC_CFGR_HPRE_SYSCLK_2 ( 8 << RCC_CFGR_HPRE_SHIFT) /* 1000: SYSCLK divided by 2 */ +# define RCC_CFGR_HPRE_SYSCLK_4 ( 9 << RCC_CFGR_HPRE_SHIFT) /* 1001: SYSCLK divided by 4 */ +# define RCC_CFGR_HPRE_SYSCLK_8 (10 << RCC_CFGR_HPRE_SHIFT) /* 1010: SYSCLK divided by 8 */ +# define RCC_CFGR_HPRE_SYSCLK_16 (11 << RCC_CFGR_HPRE_SHIFT) /* 1011: SYSCLK divided by 16 */ +# define RCC_CFGR_HPRE_SYSCLK_64 (12 << RCC_CFGR_HPRE_SHIFT) /* 1100: SYSCLK divided by 64 */ +# define RCC_CFGR_HPRE_SYSCLK_128 (13 << RCC_CFGR_HPRE_SHIFT) /* 1101: SYSCLK divided by 128 */ +# define RCC_CFGR_HPRE_SYSCLK_256 (14 << RCC_CFGR_HPRE_SHIFT) /* 1110: SYSCLK divided by 256 */ +# define RCC_CFGR_HPRE_SYSCLK_512 (15 << RCC_CFGR_HPRE_SHIFT) /* 1111: SYSCLK divided by 512 */ + +#define RCC_CFGR_PPRE1_SHIFT (8) /* Bits 8-10: APB Low speed prescaler (APB1) */ +#define RCC_CFGR_PPRE1_MASK (7 << RCC_CFGR_PPRE1_SHIFT) +# define RCC_CFGR_PPRE1_HCLK (0 << RCC_CFGR_PPRE1_SHIFT) /* 0xx: HCLK not divided */ +# define RCC_CFGR_PPRE1_HCLK_2 (4 << RCC_CFGR_PPRE1_SHIFT) /* 100: HCLK divided by 2 */ +# define RCC_CFGR_PPRE1_HCLK_4 (5 << RCC_CFGR_PPRE1_SHIFT) /* 101: HCLK divided by 4 */ +# define RCC_CFGR_PPRE1_HCLK_8 (6 << RCC_CFGR_PPRE1_SHIFT) /* 110: HCLK divided by 8 */ +# define RCC_CFGR_PPRE1_HCLK_16 (7 << RCC_CFGR_PPRE1_SHIFT) /* 111: HCLK divided by 16 */ + +#define RCC_CFGR_PPRE2_SHIFT (11) /* Bits 11-13: APB High speed prescaler (APB2) */ +#define RCC_CFGR_PPRE2_MASK (7 << RCC_CFGR_PPRE2_SHIFT) +# define RCC_CFGR_PPRE2_HCLK (0 << RCC_CFGR_PPRE2_SHIFT) /* 0xx: HCLK not divided */ +# define RCC_CFGR_PPRE2_HCLK_2 (4 << RCC_CFGR_PPRE2_SHIFT) /* 100: HCLK divided by 2 */ +# define RCC_CFGR_PPRE2_HCLK_4 (5 << RCC_CFGR_PPRE2_SHIFT) /* 101: HCLK divided by 4 */ +# define RCC_CFGR_PPRE2_HCLK_8 (6 << RCC_CFGR_PPRE2_SHIFT) /* 110: HCLK divided by 8 */ +# define RCC_CFGR_PPRE2_HCLK_16 (7 << RCC_CFGR_PPRE2_SHIFT) /* 111: HCLK divided by 16 */ + +#define RCC_CFGR_STOPWUCK (1 << 15) /* Bit 15: Wakeup from Stop and CSS backup clock selection */ +# define RCC_CFGR_STOPWUCK_MSI (0 << 15) /* 0: MSI */ +# define RCC_CFGR_STOPWUCK_HSI16 (1 << 15) /* 1: HSI16 */ + +#define RCC_CFGR_HPREF (1 << 16) /* Bit 16: HCLK1 prescaler flag (cpu1, ahb1, ahb2) */ +# define RCC_CFGR_HPREF_OFF (0 << 16) /* 0: Prescaller value not applied */ +# define RCC_CFGR_HPREF_ON (1 << 16) /* 1: Prescaller value applied */ + +#define RCC_CFGR_PPRE1F (1 << 17) /* Bit 17: PCLK1 prescaler flag (apb1) */ +# define RCC_CFGR_PPRE1F_OFF (0 << 17) /* 0: Prescaller value not applied */ +# define RCC_CFGR_PPRE1F_ON (1 << 17) /* 1: Prescaller value applied */ + +#define RCC_CFGR_PPRE2F (1 << 18) /* Bit 18: PCLK2 prescaler flag (apb2) */ +# define RCC_CFGR_PPRE2F_OFF (0 << 18) /* 0: Prescaller value not applied */ +# define RCC_CFGR_PPRE2F_ON (1 << 18) /* 1: Prescaller value applied */ + +#define RCC_CFGR_MCOSEL_SHIFT (24) /* Bits 24-27: Microcontroller Clock Output */ +#define RCC_CFGR_MCOSEL_MASK (0x0f << RCC_CFGR_MCOSEL_SHIFT) +# define RCC_CFGR_MCOSEL_NONE (0 << RCC_CFGR_MCOSEL_SHIFT) /* 0000: Disabled */ +# define RCC_CFGR_MCOSEL_SYSCLK (1 << RCC_CFGR_MCOSEL_SHIFT) /* 0001: SYSCLK system clock selected */ +# define RCC_CFGR_MCOSEL_MSI (2 << RCC_CFGR_MCOSEL_SHIFT) /* 0010: MSI clock selected */ +# define RCC_CFGR_MCOSEL_HSI16 (3 << RCC_CFGR_MCOSEL_SHIFT) /* 0011: HSI16 clock selected */ +# define RCC_CFGR_MCOSEL_HSE (4 << RCC_CFGR_MCOSEL_SHIFT) /* 0100: HSE clock selected */ +# define RCC_CFGR_MCOSEL_PLL (5 << RCC_CFGR_MCOSEL_SHIFT) /* 0101: Main PLL selected */ +# define RCC_CFGR_MCOSEL_LSI (6 << RCC_CFGR_MCOSEL_SHIFT) /* 0110: LSI clock selected */ +# define RCC_CFGR_MCOSEL_LSE (7 << RCC_CFGR_MCOSEL_SHIFT) /* 0111: LSE clock selected */ +# define RCC_CFGR_MCOSEL_HSI48 (8 << RCC_CFGR_MCOSEL_SHIFT) /* 1000: HSI48 clock selected */ + +#define RCC_CFGR_MCOPRE_SHIFT (28) /* Bits 28-30: MCO prescaler */ +#define RCC_CFGR_MCOPRE_MASK (7 << RCC_CFGR_MCOPRE_SHIFT) +# define RCC_CFGR_MCOPRE_NONE (0 << RCC_CFGR_MCOPRE_SHIFT) /* 000: no division */ +# define RCC_CFGR_MCOPRE_DIV2 (1 << RCC_CFGR_MCOPRE_SHIFT) /* 001: division by 2 */ +# define RCC_CFGR_MCOPRE_DIV4 (2 << RCC_CFGR_MCOPRE_SHIFT) /* 010: division by 4 */ +# define RCC_CFGR_MCOPRE_DIV8 (3 << RCC_CFGR_MCOPRE_SHIFT) /* 011: division by 8 */ +# define RCC_CFGR_MCOPRE_DIV16 (4 << RCC_CFGR_MCOPRE_SHIFT) /* 100: division by 16 */ + +/* PLL configuration register */ + +#define RCC_PLLCFG_PLLSRC_SHIFT (0) /* Bit 0-1: Main PLL(PLL) and audio PLLs (PLLSAIx) entry clock source */ +#define RCC_PLLCFG_PLLSRC_MASK (3 << RCC_PLLCFG_PLLSRC_SHIFT) +# define RCC_PLLCFG_PLLSRC_NONE (0 << RCC_PLLCFG_PLLSRC_SHIFT) /* 000: No clock sent to PLLs */ +# define RCC_PLLCFG_PLLSRC_MSI (1 << RCC_PLLCFG_PLLSRC_SHIFT) /* 001: MSI selected as PLL source */ +# define RCC_PLLCFG_PLLSRC_HSI16 (2 << RCC_PLLCFG_PLLSRC_SHIFT) /* 010: HSI16 selected as PLL source */ +# define RCC_PLLCFG_PLLSRC_HSE (3 << RCC_PLLCFG_PLLSRC_SHIFT) /* 011: HSE selected as PLL source */ + +#define RCC_PLLCFG_PLLM_SHIFT (4) /* Bits 4-6: Main PLL (PLL) input clock divider */ +#define RCC_PLLCFG_PLLM_MASK (0x07 << RCC_PLLCFG_PLLM_SHIFT) +# define RCC_PLLCFG_PLLM(n) ((n-1) << RCC_PLLCFG_PLLM_SHIFT) /* m = 1..8 */ + +#define RCC_PLLCFG_PLLN_SHIFT (8) /* Bits 8-14: Main PLL (PLL) VCO multiplier */ +#define RCC_PLLCFG_PLLN_MASK (0x7f << RCC_PLLCFG_PLLN_SHIFT) +# define RCC_PLLCFG_PLLN(n) ((n) << RCC_PLLCFG_PLLN_SHIFT) /* n = 6..127 */ + +#define RCC_PLLCFG_PLLPEN (1 << 16) /* Bit 16: Main PLL PLLSAI3CLK output enable */ + +#define RCC_PLLCFG_PLLP_SHIFT (17) /* Bit 17-21: Main PLL div factor for PLLPCLK */ +#define RCC_PLLCFG_PLLP_MASK (0x1f << RCC_PLLCFG_PLLP_SHIFT) +# define RCC_PLLCFG_PLLP (((n)-1) << RCC_PLLCFG_PLLP_SHIFT) /* 2..32 */ + +#define RCC_PLLCFG_PLLQEN (1 << 24) /* Bit 24: Main PLL PLLQCLK output enable */ + +#define RCC_PLLCFG_PLLQ_SHIFT (25) /* Bits 25-27: Main PLL division factor for PLLQCLK (48 MHz clock) */ +#define RCC_PLLCFG_PLLQ_MASK (3 << RCC_PLLCFG_PLLQ_SHIFT) +# define RCC_PLLCFG_PLLQ(n) (((n)-1) << RCC_PLLCFG_PLLQ_SHIFT) /* n=2..8 */ + +#define RCC_PLLCFG_PLLREN (1 << 28) /* Bit 24: Main PLL PLLRCLK output enable */ + +#define RCC_PLLCFG_PLLR_SHIFT (29) /* Bits 29-31: Main PLL division factor for PLLRCLK */ +#define RCC_PLLCFG_PLLR_MASK (3 << RCC_PLLCFG_PLLR_SHIFT) +# define RCC_PLLCFG_PLLR(n) (((n)-1) << RCC_PLLCFG_PLLR_SHIFT) /* n=2..8 */ + +/* Clock interrupt enable register */ + +#define RCC_CIER_LSIRDYIE (1 << 0) /* Bit 0: LSI Ready Interrupt Enable */ +#define RCC_CIER_LSERDYIE (1 << 1) /* Bit 1: LSE Ready Interrupt Enable */ +#define RCC_CIER_MSIRDYIE (1 << 2) /* Bit 2: MSI Ready Interrupt Enable */ +#define RCC_CIER_HSIRDYIE (1 << 3) /* Bit 3: HSI Ready Interrupt Enable */ +#define RCC_CIER_HSERDYIE (1 << 4) /* Bit 4: HSE Ready Interrupt Enable */ +#define RCC_CIER_PLLRDYIE (1 << 5) /* Bit 5: PLL Ready Interrupt Enable */ +#define RCC_CIER_PLESCCIE (1 << 9) /* Bit 9: LSE clock security system Interrupt Enable */ + +/* Clock interrupt flag register */ + +#define RCC_CIFR_LSIRDYIF (1 << 0) /* Bit 0: LSI Ready Interrupt Flag */ +#define RCC_CIFR_LSERDYIF (1 << 1) /* Bit 1: LSE Ready Interrupt Flag */ +#define RCC_CIFR_MSIRDYIF (1 << 2) /* Bit 2: MSI Ready Interrupt Flag */ +#define RCC_CIFR_HSIRDYIF (1 << 3) /* Bit 3: HSI Ready Interrupt Flag */ +#define RCC_CIFR_HSERDYIF (1 << 4) /* Bit 4: HSE Ready Interrupt Flag */ +#define RCC_CIFR_PLLRDYIF (1 << 5) /* Bit 5: PLL Ready Interrupt Flag */ +#define RCC_CIFR_CSSF (1 << 8) /* Bit 8: Clock Security System Interrupt Flag */ +#define RCC_CIFR_LSECSSF (1 << 9) /* Bit 9: LSE CSS (clock security system) Interrupt Flag */ + +/* Clock interrupt clear register */ + +#define RCC_CICR_LSIRDYIC (1 << 0) /* Bit 0: LSI Ready Interrupt Clear */ +#define RCC_CICR_LSERDYIC (1 << 1) /* Bit 1: LSE Ready Interrupt Clear */ +#define RCC_CICR_MSIRDYIC (1 << 2) /* Bit 2: MSI Ready Interrupt Clear */ +#define RCC_CICR_HSIRDYIC (1 << 3) /* Bit 3: HSI Ready Interrupt Clear */ +#define RCC_CICR_HSERDYIC (1 << 4) /* Bit 4: HSE Ready Interrupt Clear */ +#define RCC_CICR_PLLRDYIC (1 << 5) /* Bit 5: PLL Ready Interrupt Clear */ +#define RCC_CICR_CSSC (1 << 8) /* Bit 8: Clock Security System Interrupt Clear */ +#define RCC_CICR_ LSECSSC (1 << 9) /* Bit 9: LSE CSS Interrupt Clear */ + +/* AHB1 peripheral reset register */ + +#define RCC_AHB1RSTR_DMA1RST (1 << 0) /* Bit 0: DMA1 reset */ +#define RCC_AHB1RSTR_DMA2RST (1 << 1) /* Bit 1: DMA2 reset */ +#define RCC_AHB1RSTR_DMAMUX1RST (1 << 2) /* Bit 2: DMAMUX1 reset */ +#define RCC_AHB1RSTR_CRCRST (1 << 12) /* Bit 12: CRC reset */ + +/* AHB2 peripheral reset register */ + +#define RCC_AHB2RSTR_GPIORST(n) (1 << (n)) +#define RCC_AHB2RSTR_GPIOARST (1 << 0) /* Bit 0: IO port A reset */ +#define RCC_AHB2RSTR_GPIOBRST (1 << 1) /* Bit 1: IO port B reset */ +#define RCC_AHB2RSTR_GPIOCRST (1 << 2) /* Bit 2: IO port C reset */ +#define RCC_AHB2RSTR_GPIOHRST (1 << 7) /* Bit 7: IO port H reset */ + +/* AHB3 peripheral reset register */ + +#define RCC_AHB3RSTR_PKARST (1 << 16) /* Bit 16: PKA reset */ +#define RCC_AHB3RSTR_AESRST (1 << 17) /* Bit 16: AES reset */ +#define RCC_AHB3RSTR_RNGRST (1 << 18) /* Bit 16: RNG reset */ +#define RCC_AHB3RSTR_HSEMRST (1 << 19) /* Bit 16: HSEM reset */ +#define RCC_AHB3RSTR_IPCCRST (1 << 20) /* Bit 16: IPCC reset */ +#define RCC_AHB3RSTR_FLASHRST (1 << 25) /* Bit 16: FLASH reset */ + +/* APB1 Peripheral reset register 1 */ + +#define RCC_APB1RSTR1_TIM2RST (1 << 0) /* Bit 0: TIM2 reset */ +#define RCC_APB1RSTR1_SPI2RST (1 << 14) /* Bit 14: SPI2 reset */ +#define RCC_APB1RSTR1_USART2RST (1 << 17) /* Bit 17: USART2 reset */ +#define RCC_APB1RSTR1_I2C1RST (1 << 21) /* Bit 21: I2C1 reset */ +#define RCC_APB1RSTR1_I2C2RST (1 << 22) /* Bit 22: I2C2 reset */ +#define RCC_APB1RSTR1_I2C3RST (1 << 23) /* Bit 23: I2C3 reset */ +#define RCC_APB1RSTR1_DAC1RST (1 << 29) /* Bit 29: DAC1 reset */ +#define RCC_APB1RSTR1_LPTIM1RST (1 << 31) /* Bit 31: Low-power Timer 1 reset */ + +/* APB1 Peripheral reset register 2 */ + +#define RCC_APB1RSTR2_LPUART1RST (1 << 0) /* Bit 0: Low-power UART 1 reset */ +#define RCC_APB1RSTR2_LPTIM2RST (1 << 5) /* Bit 5: Low-power Timer 2 reset */ +#define RCC_APB1RSTR2_LPTIM3RST (1 << 6) /* Bit 6: Low-power Timer 3 reset */ + +/* APB2 Peripheral reset register */ + +#define RCC_APB2RSTR_ACDRST (1 << 9) /* Bit 9: ADC1 reset */ +#define RCC_APB2RSTR_TIM1RST (1 << 11) /* Bit 11: TIM1 reset */ +#define RCC_APB2RSTR_SPI1RST (1 << 12) /* Bit 12: SPI1 reset */ +#define RCC_APB2RSTR_USART1RST (1 << 14) /* Bit 14: USART1 reset */ +#define RCC_APB2RSTR_TIM16RST (1 << 17) /* Bit 17: TIM16 reset */ +#define RCC_APB2RSTR_TIM17RST (1 << 18) /* Bit 18: TIM17 reset */ + +/* APB3 Peripheral reset register */ + +#define RCC_APB3RSTR_SUBGHZSPIRST (1 << 0) /* Bit 9: SUBGHZSPI reset */ + +/* AHB1 Peripheral Clock enable register */ + +#define RCC_AHB1ENR_DMA1EN (1 << 0) /* Bit 0: DMA1 enable */ +#define RCC_AHB1ENR_DMA2EN (1 << 1) /* Bit 1: DMA2 enable */ +#define RCC_AHB1ENR_DMAMUX1EN (1 << 2) /* Bit 2: DMAMUX1 enable */ +#define RCC_AHB1ENR_CRCEN (1 << 12) /* Bit 12: CRC enable */ + +/* AHB2 Peripheral Clock enable register */ + +#define RCC_AHB2ENR_GPIOEN(n) (1 << (n)) +#define RCC_AHB2ENR_GPIOAEN (1 << 0) /* Bit 0: IO port A enable */ +#define RCC_AHB2ENR_GPIOBEN (1 << 1) /* Bit 1: IO port B enable */ +#define RCC_AHB2ENR_GPIOCEN (1 << 2) /* Bit 2: IO port C enable */ +#define RCC_AHB2ENR_GPIOHEN (1 << 7) /* Bit 7: IO port H enable */ + +/* AHB3 Peripheral Clock enable register */ + +#define RCC_AHB3ENR_PKAEN (1 << 16) /* Bit 16: PKA clock enable */ +#define RCC_AHB3ENR_AESEN (1 << 17) /* Bit 17: AES Cryptographic module enable */ +#define RCC_AHB3ENR_RNGEN (1 << 18) /* Bit 18: Random number generator module enable */ +#define RCC_AHB3ENR_HSEMEN (1 << 19) /* Bit 19: HSEM enable */ +#define RCC_AHB3ENR_IPCCEN (1 << 20) /* Bit 20: IPCC enable */ +#define RCC_AHB3ENR_FLASHEN (1 << 25) /* Bit 25: FLASH enable */ + +/* APB1 Peripheral Clock enable register 1 */ + +#define RCC_APB1ENR1_TIM2EN (1 << 0) /* Bit 0: TIM2 enable */ +#define RCC_APB1ENR1_RTCAPBEN (1 << 10) /* Bit 10: RTC APB clock enable */ +#define RCC_APB1ENR1_WWDGEN (1 << 11) /* Bit 11: Windowed Watchdog enable */ +#define RCC_APB1ENR1_SPI2EN (1 << 14) /* Bit 14: SPI2 enable */ +#define RCC_APB1ENR1_USART2EN (1 << 17) /* Bit 17: USART2 enable */ +#define RCC_APB1ENR1_I2C1EN (1 << 21) /* Bit 21: I2C1 enable */ +#define RCC_APB1ENR1_I2C2EN (1 << 22) /* Bit 22: I2C2 enable */ +#define RCC_APB1ENR1_I2C3EN (1 << 23) /* Bit 23: I2C3 enable */ +#define RCC_APB1ENR1_DAC1EN (1 << 29) /* Bit 29: DAC1 enable */ +#define RCC_APB1ENR1_LPTIM1EN (1 << 31) /* Bit 31: Low-power Timer 1 enable */ + +/* APB1 Peripheral Clock enable register 2 */ + +#define RCC_APB1ENR2_LPUART1EN (1 << 0) /* Bit 0: Low-power UART 1 enable */ +#define RCC_APB1ENR2_LPTIM2EN (1 << 5) /* Bit 5: Low-power Timer 2 enable */ +#define RCC_APB1ENR2_LPTIM3EN (1 << 6) /* Bit 6: Low-power Timer 3 enable */ + +/* APB2 Peripheral Clock enable register */ + +#define RCC_APB2ENR_ADC1EN (1 << 9) /* Bit 9: ADC1 enable */ +#define RCC_APB2ENR_TIM1EN (1 << 11) /* Bit 11: TIM1 enable */ +#define RCC_APB2ENR_SPI1EN (1 << 12) /* Bit 12: SPI1 enable */ +#define RCC_APB2ENR_USART1EN (1 << 14) /* Bit 14: USART1 enable */ +#define RCC_APB2ENR_TIM16EN (1 << 17) /* Bit 17: TIM16 enable */ +#define RCC_APB2ENR_TIM17EN (1 << 18) /* Bit 18: TIM17 enable */ + +/* APB3 Peripheral Clock enable register */ + +#define RCC_APB3ENR_SUBGHZSPIEN (1 << 0) /* Bit 0: SUBGHZSPI enable */ + +/* RCC AHB1 Sleep and Stop modes peripheral clock enable register */ + +#define RCC_AHB1SMENR_DMA1SMEN (1 << 0) /* Bit 0: DMA1 enable during Sleep mode */ +#define RCC_AHB1SMENR_DMA2SMEN (1 << 1) /* Bit 1: DMA2 enable during Sleep mode */ +#define RCC_AHB1SMENR_DMAMUX1SMEN (1 << 2) /* Bit 2: DMAMUX1 enable during Sleep mode */ +#define RCC_AHB1SMENR_CRCSMEN (1 << 12) /* Bit 12: CRC enable during Sleep mode */ + +/* RCC AHB2 low power mode peripheral clock enable register */ + +#define RCC_AHB2SMENR_GPIOASMEN (1 << 0) /* Bit 0: IO port A enable during Sleep mode */ +#define RCC_AHB2SMENR_GPIOBSMEN (1 << 1) /* Bit 1: IO port B enable during Sleep mode */ +#define RCC_AHB2SMENR_GPIOCSMEN (1 << 2) /* Bit 2: IO port C enable during Sleep mode */ +#define RCC_AHB2SMENR_GPIOHSMEN (1 << 7) /* Bit 7: IO port H enable during Sleep mode */ + +/* RCC AHB3 low power mode peripheral clock enable register */ + +#define RCC_AHB2SMENR_PKASMEN (1 << 16) /* Bit 16: PKA enable during cpu1 sleep mode */ +#define RCC_AHB2SMENR_AESSMEN (1 << 17) /* Bit 17: AES Cryptographic module enable during cpu1 Sleep mode */ +#define RCC_AHB2SMENR_RNGSMEN (1 << 18) /* Bit 18: Random number generator module enable during cpu1 Sleep mode */ +#define RCC_AHB2SMENR_SRAM1SMEN (1 << 23) /* Bit 23: SRAM1 enable during cpu1 Sleep mode */ +#define RCC_AHB2SMENR_SRAM2SMEN (1 << 24) /* Bit 24: SRAM2 enable during cpu1 Sleep mode */ +#define RCC_AHB2SMENR_FLASHSMEN (1 << 25) /* Bit 25: FLASH enable during cpu1 Sleep mode */ + +/* RCC APB1 low power mode peripheral clock enable register 1 */ + +#define RCC_APB1SMENR1_TIM2SMEN (1 << 0) /* Bit 0: TIM2 enable during Sleep mode */ +#define RCC_APB1SMENR1_RTCAPBSMEN (1 << 10) /* Bit 10: RTC APB clock enable during Sleep mode */ +#define RCC_APB1SMENR1_WWDGSMEN (1 << 11) /* Bit 11: Windowed Watchdog enable during Sleep mode */ +#define RCC_APB1SMENR1_SPI2SMEN (1 << 14) /* Bit 14: SPI2 enable during Sleep mode */ +#define RCC_APB1SMENR1_USART2SMEN (1 << 17) /* Bit 17: USART2 enable during Sleep mode */ +#define RCC_APB1SMENR1_I2C1SMEN (1 << 21) /* Bit 21: I2C1 enable during Sleep mode */ +#define RCC_APB1SMENR1_I2C2SMEN (1 << 22) /* Bit 22: I2C2 enable during Sleep mode */ +#define RCC_APB1SMENR1_I2C3SMEN (1 << 23) /* Bit 23: I2C3 enable during Sleep mode */ +#define RCC_APB1SMENR1_DAC1SMEN (1 << 29) /* Bit 29: DAC1 enable during Sleep mode */ +#define RCC_APB1SMENR1_LPTIM1SMEN (1 << 31) /* Bit 31: Low-power Timer 1 enable during Sleep mode */ + +/* RCC APB1 low power modeperipheral clock enable register 2 */ + +#define RCC_APB1SMENR2_LPUART1SMEN (1 << 0) /* Bit 0: Low-power UART 1 enable during Sleep mode */ +#define RCC_APB1SMENR2_LPTIM2SMEN (1 << 5) /* Bit 5: Low-power Timer 2 enable during Sleep mode */ +#define RCC_APB1SMENR2_LPTIM3SMEN (1 << 6) /* Bit 6: Low-power Timer 3 enable during Sleep mode */ + +/* RCC APB2 low power mode peripheral clock enable register */ + +#define RCC_APB2SMENR_ADC1SMEN (1 << 9) /* Bit 9: ADC1 enable during Sleep mode */ +#define RCC_APB2SMENR_TIM1SMEN (1 << 11) /* Bit 11: TIM1 enable during Sleep mode */ +#define RCC_APB2SMENR_SPI1SMEN (1 << 12) /* Bit 12: SPI1 enable during Sleep mode */ +#define RCC_APB2SMENR_USART1SMEN (1 << 14) /* Bit 14: USART1 enable during Sleep mode */ +#define RCC_APB2SMENR_TIM16SMEN (1 << 17) /* Bit 17: TIM16 enable during Sleep mode */ +#define RCC_APB2SMENR_TIM17SMEN (1 << 18) /* Bit 18: TIM17 enable during Sleep mode */ + +/* RCC APB3 low power mode peripheral clock enable register */ + +#define RCC_APB3SMENR_SUBGHZSPISMEN (1 << 0) /* Bit 0: SUBGHZSPI enable during Sleep mode */ + +/* Peripheral Independent Clock Configuration register */ + +#define RCC_CCIPR_USART1SEL_SHIFT (0) +#define RCC_CCIPR_USART1SEL_MASK (3 << RCC_CCIPR_USART1SEL_SHIFT) +# define RCC_CCIPR_USART1SEL_PCLK1 (0 << RCC_CCIPR_USART1SEL_SHIFT) +# define RCC_CCIPR_USART1SEL_SYSCLK (1 << RCC_CCIPR_USART1SEL_SHIFT) +# define RCC_CCIPR_USART1SEL_HSI16 (2 << RCC_CCIPR_USART1SEL_SHIFT) +# define RCC_CCIPR_USART1SEL_LSE (3 << RCC_CCIPR_USART1SEL_SHIFT) + +#define RCC_CCIPR_USART2SEL_SHIFT (2) +#define RCC_CCIPR_USART2SEL_MASK (3 << RCC_CCIPR_USART2SEL_SHIFT) +# define RCC_CCIPR_USART2SEL_PCLK1 (0 << RCC_CCIPR_USART2SEL_SHIFT) +# define RCC_CCIPR_USART2SEL_SYSCLK (1 << RCC_CCIPR_USART2SEL_SHIFT) +# define RCC_CCIPR_USART2SEL_HSI16 (2 << RCC_CCIPR_USART2SEL_SHIFT) +# define RCC_CCIPR_USART2SEL_LSE (3 << RCC_CCIPR_USART2SEL_SHIFT) + +#define RCC_CCIPR_SPI2S2SEL_SHIFT (8) +#define RCC_CCIPR_SPI2S2SEL_MASK (3 << RCC_CCIPR_SPI2S2SEL_SHIFT) +# define RCC_CCIPR_SPI2S2SEL_PCLK1 (0 << RCC_CCIPR_SPI2S2SEL_SHIFT) +# define RCC_CCIPR_SPI2S2SEL_SYSCLK (1 << RCC_CCIPR_SPI2S2SEL_SHIFT) +# define RCC_CCIPR_SPI2S2SEL_HSI16 (2 << RCC_CCIPR_SPI2S2SEL_SHIFT) +# define RCC_CCIPR_SPI2S2SEL_LSE (3 << RCC_CCIPR_SPI2S2SEL_SHIFT) + +#define RCC_CCIPR_LPUART1SEL_SHIFT (10) +#define RCC_CCIPR_LPUART1SEL_MASK (3 << RCC_CCIPR_LPUART1SEL_SHIFT) +# define RCC_CCIPR_LPUART1SEL_PCLK1 (0 << RCC_CCIPR_LPUART1SEL_SHIFT) +# define RCC_CCIPR_LPUART1SEL_SYSCLK (1 << RCC_CCIPR_LPUART1SEL_SHIFT) +# define RCC_CCIPR_LPUART1SEL_HSI16 (2 << RCC_CCIPR_LPUART1SEL_SHIFT) +# define RCC_CCIPR_LPUART1SEL_LSE (3 << RCC_CCIPR_LPUART1SEL_SHIFT) + +#define RCC_CCIPR_I2C1SEL_SHIFT (12) +#define RCC_CCIPR_I2C1SEL_MASK (3 << RCC_CCIPR_I2C1SEL_SHIFT) +# define RCC_CCIPR_I2C1SEL_PCLK1 (0 << RCC_CCIPR_I2C1SEL_SHIFT) +# define RCC_CCIPR_I2C1SEL_SYSCLK (1 << RCC_CCIPR_I2C1SEL_SHIFT) +# define RCC_CCIPR_I2C1SEL_HSI16 (2 << RCC_CCIPR_I2C1SEL_SHIFT) + +#define RCC_CCIPR_I2C2SEL_SHIFT (14) +#define RCC_CCIPR_I2C2SEL_MASK (3 << RCC_CCIPR_I2C2SEL_SHIFT) +# define RCC_CCIPR_I2C2SEL_PCLK1 (0 << RCC_CCIPR_I2C2SEL_SHIFT) +# define RCC_CCIPR_I2C2SEL_SYSCLK (1 << RCC_CCIPR_I2C2SEL_SHIFT) +# define RCC_CCIPR_I2C2SEL_HSI16 (2 << RCC_CCIPR_I2C2SEL_SHIFT) + +#define RCC_CCIPR_I2C3SEL_SHIFT (16) +#define RCC_CCIPR_I2C3SEL_MASK (3 << RCC_CCIPR_I2C3SEL_SHIFT) +# define RCC_CCIPR_I2C3SEL_PCLK1 (0 << RCC_CCIPR_I2C3SEL_SHIFT) +# define RCC_CCIPR_I2C3SEL_SYSCLK (1 << RCC_CCIPR_I2C3SEL_SHIFT) +# define RCC_CCIPR_I2C3SEL_HSI16 (2 << RCC_CCIPR_I2C3SEL_SHIFT) + +#define RCC_CCIPR_LPTIM1SEL_SHIFT (18) +#define RCC_CCIPR_LPTIM1SEL_MASK (3 << RCC_CCIPR_LPTIM1SEL_SHIFT) +# define RCC_CCIPR_LPTIM1SEL_PCLK1 (0 << RCC_CCIPR_LPTIM1SEL_SHIFT) +# define RCC_CCIPR_LPTIM1SEL_LSI (1 << RCC_CCIPR_LPTIM1SEL_SHIFT) +# define RCC_CCIPR_LPTIM1SEL_HSI16 (2 << RCC_CCIPR_LPTIM1SEL_SHIFT) +# define RCC_CCIPR_LPTIM1SEL_LSE (3 << RCC_CCIPR_LPTIM1SEL_SHIFT) + +#define RCC_CCIPR_LPTIM2SEL_SHIFT (20) +#define RCC_CCIPR_LPTIM2SEL_MASK (3 << RCC_CCIPR_LPTIM2SEL_SHIFT) +# define RCC_CCIPR_LPTIM2SEL_PCLK1 (0 << RCC_CCIPR_LPTIM2SEL_SHIFT) +# define RCC_CCIPR_LPTIM2SEL_LSI (1 << RCC_CCIPR_LPTIM2SEL_SHIFT) +# define RCC_CCIPR_LPTIM2SEL_HSI16 (2 << RCC_CCIPR_LPTIM2SEL_SHIFT) +# define RCC_CCIPR_LPTIM2SEL_LSE (3 << RCC_CCIPR_LPTIM2SEL_SHIFT) + +#define RCC_CCIPR_LPTIM3SEL_SHIFT (22) +#define RCC_CCIPR_LPTIM3SEL_MASK (3 << RCC_CCIPR_SAI1SEL_SHIFT) +# define RCC_CCIPR_LPTIM3SEL_PCLK1 (0 << RCC_CCIPR_SAI1SEL_SHIFT) +# define RCC_CCIPR_LPTIM3SEL_LSI (1 << RCC_CCIPR_SAI1SEL_SHIFT) +# define RCC_CCIPR_LPTIM3SEL_HSI16 (2 << RCC_CCIPR_SAI1SEL_SHIFT) +# define RCC_CCIPR_LPTIM3SEL_LSE (3 << RCC_CCIPR_SAI1SEL_SHIFT) + +#define RCC_CCIPR_ADCSEL_SHIFT (28) +#define RCC_CCIPR_ADCSEL_MASK (3 << RCC_CCIPR_ADCSEL_SHIFT) +# define RCC_CCIPR_ADCSEL_NONE (0 << RCC_CCIPR_ADCSEL_SHIFT) +# define RCC_CCIPR_ADCSEL_HSI16 (1 << RCC_CCIPR_ADCSEL_SHIFT) +# define RCC_CCIPR_ADCSEL_PLLADC1CLK (2 << RCC_CCIPR_ADCSEL_SHIFT) +# define RCC_CCIPR_ADCSEL_SYSCLK (3 << RCC_CCIPR_ADCSEL_SHIFT) + +#define RCC_CCIPR_RNGSEL_SHIFT (30) +#define RCC_CCIPR_RNGSEL_MASK (3 << RCC_CCIPR_RNGSEL_SHIFT) +# define RCC_CCIPR_RNGSEL_NONE (0 << RCC_CCIPR_RNGSEL_SHIFT) +# define RCC_CCIPR_RNGSEL_HSI16 (1 << RCC_CCIPR_RNGSEL_SHIFT) +# define RCC_CCIPR_RNGSEL_PLLRNG1CLK (2 << RCC_CCIPR_RNGSEL_SHIFT) +# define RCC_CCIPR_RNGSEL_SYSCLK (3 << RCC_CCIPR_RNGSEL_SHIFT) + +/* Backup domain control register */ + +#define RCC_BDCR_LSEON (1 << 0) /* Bit 0: External Low Speed oscillator enable */ +#define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */ +#define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */ + +#define RCC_BDCR_LSEDRV_SHIFT (3) /* Bits 3-4: LSE oscillator drive capability */ +#define RCC_BDCR_LSEDRV_MASK (3 << RCC_BDCR_LSEDRV_SHIFT) +# define RCC_BDCR_LSEDRV_LOW (0 << RCC_BDCR_LSEDRV_SHIFT) /* 00: Lower driving capability */ +# define RCC_BDCR_LSEDRV_MEDLO (1 << RCC_BDCR_LSEDRV_SHIFT) /* 01: Medium Low driving capability */ +# define RCC_BDCR_LSEDRV_MEDHI (2 << RCC_BDCR_LSEDRV_SHIFT) /* 10: Medium High driving capability*/ +# define RCC_BDCR_LSEDRV_HIGH (3 << RCC_BDCR_LSEDRV_SHIFT) /* 11: Higher driving capability */ + +#define RCC_BDCR_LSECSSON (1 << 5) /* Bit 5: CSS on LSE enable */ +#define RCC_BDCR_LSECSSD (1 << 6) /* Bit 6: CSS on LSE failure Detection */ +#define RCC_BDCR_LSESYSEN (1 << 7) /* Bit 7: LSE system clock (LSESYS) enable */ + +#define RCC_BDCR_RTCSEL_SHIFT (8) /* Bits 9:8: RTC clock source selection */ +#define RCC_BDCR_RTCSEL_MASK (3 << RCC_BDCR_RTCSEL_SHIFT) +# define RCC_BDCR_RTCSEL_NOCLK (0 << RCC_BDCR_RTCSEL_SHIFT) /* 00: No clock */ +# define RCC_BDCR_RTCSEL_LSE (1 << RCC_BDCR_RTCSEL_SHIFT) /* 01: LSE oscillator clock used as RTC clock */ +# define RCC_BDCR_RTCSEL_LSI (2 << RCC_BDCR_RTCSEL_SHIFT) /* 10: LSI oscillator clock used as RTC clock */ +# define RCC_BDCR_RTCSEL_HSE (3 << RCC_BDCR_RTCSEL_SHIFT) /* 11: HSE oscillator clock divided by 32 used as RTC clock */ + +#define RCC_BDCR_LSESYSRDY (1 << 11) /* Bit 11: LSE system clock (LSESYS) ready */ + +#define RCC_BDCR_RTCEN (1 << 15) /* Bit 15: RTC clock enable */ +#define RCC_BDCR_BDRST (1 << 16) /* Bit 16: Backup domain software reset */ +#define RCC_BDCR_LSCOEN (1 << 24) /* Bit 24: Low speed clock output enable */ +#define RCC_BDCR_LSCOSEL (1 << 25) /* Bit 25: Low speed clock output selection */ +# define RCC_BCDR_LSCOSEL_LSI 0 /* LSI selected */ +# define RCC_BDCR_LSCOSEL_LSE RCC_BDCR_LSCOSEL /* LSE selected */ + +/* Control/status register */ + +#define RCC_CSR_LSION (1 << 0) /* Bit 0: Internal Low Speed oscillator enable */ +#define RCC_CSR_LSIRDY (1 << 1) /* Bit 1: Internal Low Speed oscillator Ready */ + +#define RCC_CSR_LSIPRE (1 << 4) /* Bit 4: Internal Low Speed oscillator prescaler (LSI/128) enable */ + +#define RCC_CSR_MSISRANGE_SHIFT 8 +# define RCC_CSR_MSISRANGE_MASK (0x0F << RCC_CSR_MSISRANGE_SHIFT) /* MSI range after Standby mode */ +# define RCC_CSR_MSISRANGE_1M (4 << RCC_CSR_MSISRANGE_SHIFT) /* 0100: around 1 MHz */ +# define RCC_CSR_MSISRANGE_2M (5 << RCC_CSR_MSISRANGE_SHIFT) /* 0101: around 2 MHz */ +# define RCC_CSR_MSISRANGE_4M (6 << RCC_CSR_MSISRANGE_SHIFT) /* 0110: around 4 MHz */ +# define RCC_CSR_MSISRANGE_8M (7 << RCC_CSR_MSISRANGE_SHIFT) /* 0111: around 8 MHz */ + +#define RCC_CSR_RFRSTF (1 << 14) /* Bit 14: Radio in reset status flag */ +#define RCC_CSR_RFRST (1 << 15) /* Bit 15: Radio reset */ +#define RCC_CSR_RMVF (1 << 23) /* Bit 23: Remove reset flag */ +#define RCC_CSR_RFILARSTF (1 << 24) /* Bit 24: Radio illegal command flag */ +#define RCC_CSR_OBLRSTF (1 << 25) /* Bit 25: Option byte loader reset flag */ +#define RCC_CSR_PINRSTF (1 << 26) /* Bit 26: PIN reset flag */ +#define RCC_CSR_BORRSTF (1 << 27) /* Bit 27: BOR reset flag */ +#define RCC_CSR_SFTRSTF (1 << 28) /* Bit 28: Software Reset flag */ +#define RCC_CSR_IWDGRSTF (1 << 29) /* Bit 29: Independent Watchdog reset flag */ +#define RCC_CSR_WWDGRSTF (1 << 30) /* Bit 30: Window watchdog reset flag */ +#define RCC_CSR_LPWRRSTF (1 << 31) /* Bit 31: Low-Power reset flag */ + +/* Extended Clock recovery RC register */ + +#define RCC_EXTCFGR_SHDHPRE_SHIFT (0) /* Bits 0-3: HCLK3 shared prescaler (ahb3, flash, sram1/2) */ +#define RCC_EXTCFGR_SHDHPRE_MASK (0x0f << RCC_EXTCFGR_SHDHPRE_SHIFT) +# define RCC_EXTCFGR_SHDHPRE_SYSCLK ( 0 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* not-listed: SYSCLK not divided */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_3 ( 1 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 0001: SYSCLK divided by 3 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_5 ( 2 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 0010: SYSCLK divided by 5 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_6 ( 5 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 0101: SYSCLK divided by 6 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_10 ( 6 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 0110: SYSCLK divided by 10 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_32 ( 7 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 0111: SYSCLK divided by 32 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_2 ( 8 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 1000: SYSCLK divided by 2 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_4 ( 9 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 1001: SYSCLK divided by 4 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_8 (10 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 1010: SYSCLK divided by 8 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_16 (11 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 1011: SYSCLK divided by 16 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_64 (12 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 1100: SYSCLK divided by 64 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_128 (13 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 1101: SYSCLK divided by 128 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_256 (14 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 1110: SYSCLK divided by 256 */ +# define RCC_EXTCFGR_SHDHPRE_SYSCLK_512 (15 << RCC_EXTCFGR_SHDHPRE_SHIFT) /* 1111: SYSCLK divided by 512 */ + +#define RCC_EXTCFGR_C2HPRE_SHIFT (4) /* Bits 4-7: HCLK2 prescaler (cpu2) */ +#define RCC_EXTCFGR_C2HPRE_MASK (0x0f << RCC_EXTCFGR_C2HPRE_SHIFT) +# define RCC_EXTCFGR_C2HPRE_SYSCLK ( 0 << RCC_EXTCFGR_C2HPRE_SHIFT) /* not-listed: SYSCLK not divided */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_3 ( 1 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 0001: SYSCLK divided by 3 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_5 ( 2 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 0010: SYSCLK divided by 5 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_6 ( 5 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 0101: SYSCLK divided by 6 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_10 ( 6 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 0110: SYSCLK divided by 10 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_32 ( 7 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 0111: SYSCLK divided by 32 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_2 ( 8 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 1000: SYSCLK divided by 2 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_4 ( 9 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 1001: SYSCLK divided by 4 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_8 (10 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 1010: SYSCLK divided by 8 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_16 (11 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 1011: SYSCLK divided by 16 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_64 (12 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 1100: SYSCLK divided by 64 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_128 (13 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 1101: SYSCLK divided by 128 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_256 (14 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 1110: SYSCLK divided by 256 */ +# define RCC_EXTCFGR_C2HPRE_SYSCLK_512 (15 << RCC_EXTCFGR_C2HPRE_SHIFT) /* 1111: SYSCLK divided by 512 */ + +#define RCC_EXTCFGR_SHDHPREF ( 1 << 16) /* Bit 16: Apply HCLK3 prescaller */ +#define RCC_EXTCFGR_C2HPREF ( 1 << 17) /* Bit 17: Apply HCLK2 prescaller (cpu2) */ + +#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL562XX_RCC_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_syscfg.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_syscfg.h new file mode 100644 index 0000000000..8f6a96ff0e --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_syscfg.h @@ -0,0 +1,244 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_syscfg.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_SYSCFG_H +#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_SYSCFG_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define STM32WL5_SYSCFG_MEMRMP_OFFSET 0x0000 /* SYSCFG memory remap register */ +#define STM32WL5_SYSCFG_CFGR1_OFFSET 0x0004 /* SYSCFG configuration register 1 */ + +#define STM32WL5_SYSCFG_EXTICR_OFFSET(p) (0x0008 + ((p) & 0x000c)) /* Registers are displaced by 4! */ + +#define STM32WL5_SYSCFG_EXTICR1_OFFSET 0x0008 /* SYSCFG external interrupt configuration register 1 */ +#define STM32WL5_SYSCFG_EXTICR2_OFFSET 0x000c /* SYSCFG external interrupt configuration register 2 */ +#define STM32WL5_SYSCFG_EXTICR3_OFFSET 0x0010 /* SYSCFG external interrupt configuration register 3 */ +#define STM32WL5_SYSCFG_EXTICR4_OFFSET 0x0014 /* SYSCFG external interrupt configuration register 4 */ +#define STM32WL5_SYSCFG_SCSR_OFFSET 0x0018 /* SYSCFG SRAM2 control and status register */ +#define STM32WL5_SYSCFG_CFGR2_OFFSET 0x001c /* SYSCFG configuration register 2 */ +#define STM32WL5_SYSCFG_SWPR_OFFSET 0x0020 /* SYSCFG SRAM2 write protection register */ +#define STM32WL5_SYSCFG_SKR_OFFSET 0x0024 /* SYSCFG SRAM2 key register */ +#define STM32WL5_SYSCFG_IMR1_OFFSET 0x0100 /* SYSCFG cpu1 interrupt mask register 1 */ +#define STM32WL5_SYSCFG_IMR2_OFFSET 0x0104 /* SYSCFG cpu1 interrupt mask register 2 */ +#define STM32WL5_SYSCFG_C2IMR1_OFFSET 0x0108 /* SYSCFG cpu2 interrupt mask register 1 */ +#define STM32WL5_SYSCFG_C2IMR2_OFFSET 0x010c /* SYSCFG cpu2 interrupt mask register 2 */ +#define STM32WL5_SYSCFG_RFDCR_OFFSET 0x0208 /* SYSCFG radio debug control register */ + +/* Register Addresses *******************************************************/ + +#define STM32WL5_SYSCFG_MEMRMP (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_MEMRMP_OFFSET) +#define STM32WL5_SYSCFG_CFGR1 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_CFGR1_OFFSET) +#define STM32WL5_SYSCFG_EXTICR(p) (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_EXTICR_OFFSET(p)) +#define STM32WL5_SYSCFG_EXTICR1 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_EXTICR1) +#define STM32WL5_SYSCFG_EXTICR2 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_EXTICR2) +#define STM32WL5_SYSCFG_EXTICR3 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_EXTICR3) +#define STM32WL5_SYSCFG_EXTICR4 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_EXTICR4) +#define STM32WL5_SYSCFG_SCSR (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_SCSR) +#define STM32WL5_SYSCFG_CFGR2 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_CFGR2) +#define STM32WL5_SYSCFG_SWPR (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_SWPR) +#define STM32WL5_SYSCFG_SKR (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_SKR) +#define STM32WL5_SYSCFG_IMR1 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_IMR1) +#define STM32WL5_SYSCFG_IMR2 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_IMR2) +#define STM32WL5_SYSCFG_C2IMR1 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_C2IMR1) +#define STM32WL5_SYSCFG_C2IMR2 (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_C2IMR2) +#define STM32WL5_SYSCFG_RFDCR (STM32WL5_SYSCFG_BASE+STM32WL5_SYSCFG_RFDCR) + +/* Register Bitfield Definitions ********************************************/ + +/* SYSCFG memory remap register */ + +#define SYSCFG_MEMRMP_SHIFT (0) /* Bits 2:0 MEM_MODE: Memory mapping selection */ +#define SYSCFG_MEMRMP_MASK (7 << SYSCFG_MEMRMP_SHIFT) +# define SYSCFG_MEMRMP_FLASH (0 << SYSCFG_MEMRMP_SHIFT) /* 000: Main Flash memory mapped at cpu1 0x0000 0000 */ +# define SYSCFG_MEMRMP_SYSTEM (1 << SYSCFG_MEMRMP_SHIFT) /* 001: System Flash memory mapped at cpu1 0x0000 0000 */ +# define SYSCFG_MEMRMP_SRAM (3 << SYSCFG_MEMRMP_SHIFT) /* 011: SRAM1 mapped at cpu1 0x0000 0000 */ + +/* SYSCFG configuration register 1 */ + +#define SYSCFG_CFGR1_BOOSTEN (1 << 8) /* Bit 8: I/O analog switch voltage booster enable (use when vdd is low) */ +#define SYSCFG_CFGR1_I2C_PB6_FMP (1 << 16) /* Bit 16: Fast-mode Plus (Fm+) driving capability activation on PB6 */ +#define SYSCFG_CFGR1_I2C_PB7_FMP (1 << 17) /* Bit 17: Fast-mode Plus (Fm+) driving capability activation on PB7 */ +#define SYSCFG_CFGR1_I2C_PB8_FMP (1 << 18) /* Bit 18: Fast-mode Plus (Fm+) driving capability activation on PB8 */ +#define SYSCFG_CFGR1_I2C_PB9_FMP (1 << 19) /* Bit 19: Fast-mode Plus (Fm+) driving capability activation on PB9 */ +#define SYSCFG_CFGR1_I2C1_FMP (1 << 20) /* Bit 20: I2C1 Fast-mode Plus (Fm+) driving capability activation */ +#define SYSCFG_CFGR1_I2C2_FMP (1 << 21) /* Bit 21: I2C2 Fast-mode Plus (Fm+) driving capability activation */ +#define SYSCFG_CFGR1_I2C3_FMP (1 << 22) /* Bit 22: I2C3 Fast-mode Plus (Fm+) driving capability activation */ + +/* SYSCFG external interrupt configuration register 1-4 */ + +#define SYSCFG_EXTICR_PORTA (0) /* 0000: PA[x] pin */ +#define SYSCFG_EXTICR_PORTB (1) /* 0001: PB[x] pin */ +#define SYSCFG_EXTICR_PORTC (2) /* 0010: PC[x] pin */ +#define SYSCFG_EXTICR_PORTH (7) /* 0111: PH[x] pin */ + +#define SYSCFG_EXTICR_PORT_MASK (7) +#define SYSCFG_EXTICR_EXTI_SHIFT(g) (((g) & 3) << 2) +#define SYSCFG_EXTICR_EXTI_MASK(g) (SYSCFG_EXTICR_PORT_MASK << (SYSCFG_EXTICR_EXTI_SHIFT(g))) + +#define SYSCFG_EXTICR1_EXTI0_SHIFT (0) /* Bits 0-2: EXTI 0 configuration */ +#define SYSCFG_EXTICR1_EXTI0_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI0_SHIFT) +#define SYSCFG_EXTICR1_EXTI1_SHIFT (4) /* Bits 4-6: EXTI 1 configuration */ +#define SYSCFG_EXTICR1_EXTI1_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI1_SHIFT) +#define SYSCFG_EXTICR1_EXTI2_SHIFT (8) /* Bits 8-10: EXTI 2 configuration */ +#define SYSCFG_EXTICR1_EXTI2_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI2_SHIFT) +#define SYSCFG_EXTICR1_EXTI3_SHIFT (12) /* Bits 12-14: EXTI 3 configuration */ +#define SYSCFG_EXTICR1_EXTI3_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR1_EXTI3_SHIFT) + +#define SYSCFG_EXTICR2_EXTI4_SHIFT (0) /* Bits 0-2: EXTI 4 configuration */ +#define SYSCFG_EXTICR2_EXTI4_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI4_SHIFT) +#define SYSCFG_EXTICR2_EXTI5_SHIFT (4) /* Bits 4-6: EXTI 5 configuration */ +#define SYSCFG_EXTICR2_EXTI5_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI5_SHIFT) +#define SYSCFG_EXTICR2_EXTI6_SHIFT (8) /* Bits 8-10: EXTI 6 configuration */ +#define SYSCFG_EXTICR2_EXTI6_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI6_SHIFT) +#define SYSCFG_EXTICR2_EXTI7_SHIFT (12) /* Bits 12-14: EXTI 7 configuration */ +#define SYSCFG_EXTICR2_EXTI7_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR2_EXTI7_SHIFT) + +#define SYSCFG_EXTICR3_EXTI8_SHIFT (0) /* Bits 0-2: EXTI 8 configuration */ +#define SYSCFG_EXTICR3_EXTI8_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI8_SHIFT) +#define SYSCFG_EXTICR3_EXTI9_SHIFT (4) /* Bits 4-6: EXTI 9 configuration */ +#define SYSCFG_EXTICR3_EXTI9_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI9_SHIFT) +#define SYSCFG_EXTICR3_EXTI10_SHIFT (8) /* Bits 8-10: EXTI 10 configuration */ +#define SYSCFG_EXTICR3_EXTI10_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI10_SHIFT) +#define SYSCFG_EXTICR3_EXTI11_SHIFT (12) /* Bits 12-14: EXTI 11 configuration */ +#define SYSCFG_EXTICR3_EXTI11_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR3_EXTI11_SHIFT) + +#define SYSCFG_EXTICR4_EXTI12_SHIFT (0) /* Bits 0-2: EXTI 12 configuration */ +#define SYSCFG_EXTICR4_EXTI12_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI12_SHIFT) +#define SYSCFG_EXTICR4_EXTI13_SHIFT (4) /* Bits 4-6: EXTI 13 configuration */ +#define SYSCFG_EXTICR4_EXTI13_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI13_SHIFT) +#define SYSCFG_EXTICR4_EXTI14_SHIFT (8) /* Bits 8-10: EXTI 14 configuration */ +#define SYSCFG_EXTICR4_EXTI14_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI14_SHIFT) +#define SYSCFG_EXTICR4_EXTI15_SHIFT (12) /* Bits 12-14: EXTI 15 configuration */ +#define SYSCFG_EXTICR4_EXTI15_MASK (SYSCFG_EXTICR_PORT_MASK << SYSCFG_EXTICR4_EXTI15_SHIFT) + +/* SYSCFG SRAM control and status register */ + +#define SYSCFG_SCSR_SRAM2ER (1 << 0) /* Bit 0: SRAM2 Erase */ +#define SYSCFG_SCSR_SRAMBSY (1 << 1) /* Bit 1: SRAM1/2 busy in erase operation */ +#define SYSCFG_SCSR_PKASRAMBSY (1 << 8) /* Bit 8: PKA SRAM busy in erase operation */ + +/* SYSCFG configuration register 2 */ + +#define SYSCFG_CFGR2_CLL (1 << 0) /* Bit 0: Cortex-M4 LOCKUP (Hardfault) output enable (TIMx break enable, see refman) */ +#define SYSCFG_CFGR2_SPL (1 << 1) /* Bit 1: SRAM2 parity lock enable (same) */ +#define SYSCFG_CFGR2_PVDL (1 << 2) /* Bit 2: PVD lock enable (same) */ +#define SYSCFG_CFGR2_ECCL (1 << 3) /* Bit 3: ECC lock enable (same) */ +#define SYSCFG_CFGR2_SPF (1 << 8) /* Bit 8: SRAM2 parity error flag */ + +/* SYSCFG SRAM2 write protection register */ + +/* There is one bit per SRAM2 page (0 to 31) */ + +/* SYSCFG SRAM2 key register */ + +#define SYSCFG_SKR_SHIFT 0 +#define SYSCFG_SKR_MASK (0xFF << SYSCFG_SKR_SHIFT) + +/* SYSCFG cpu1 interrupt mask register 1 (IMR1) */ + +#define SYSCFG_IMR1_RTCSTAMPTAMPLSECSSIM (1 << 0) /* Bit 0: RTCSTAMPTAMPLSECSS interrupt to cpu1 masked */ +#define SYSCFG_IMR1_RTCSSRUIM (1 << 2) /* Bit 2: RTC SSRU interrupt to cpu1 masked */ +#define SYSCFG_IMR1_EXTI5IM (1 << 21) /* Bit 21: Disable EXTI5IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI6IM (1 << 22) /* Bit 22: Disable EXTI6IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI7IM (1 << 23) /* Bit 23: Disable EXTI7IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI8IM (1 << 24) /* Bit 24: Disable EXTI8IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI9IM (1 << 25) /* Bit 25: Disable EXTI9IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI10IM (1 << 26) /* Bit 26: Disable EXTI10IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI11IM (1 << 27) /* Bit 27: Disable EXTI11IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI12IM (1 << 28) /* Bit 28: Disable EXTI12IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI13IM (1 << 29) /* Bit 29: Disable EXTI13IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI14IM (1 << 30) /* Bit 30: Disable EXTI14IM interrupt to cpu1 */ +#define SYSCFG_IMR1_EXTI15IM (1 << 31) /* Bit 31: Disable EXTI15IM interrupt to cpu1 */ + +/* SYSCFG cpu1 interrupt mask register 2 (IMR2) */ + +#define SYSCFG_IMR2_PCM3IM (1 << 18) /* Bit 18: Disable PVM3 interrupt to cpu1 */ +#define SYSCFG_IMR2_PVDIM (1 << 20) /* Bit 20: Disable PVD interrupt to cpu1 */ + +/* SYSCFG cpu2 interrupt mask register 1 (C2IMR1) */ + +#define SYSCFG_C2IMR1_RTCSTAMPTAMPLSECSSIM (1 << 0) /* Bit 0: RTCSTAMPTAMPLSECSS interrupt to CPU2 masked */ +#define SYSCFG_C2IMR1_RTCALARMIM (1 << 1) /* Bit 1: Disable rtc alarm interrupt to cpu2 */ +#define SYSCFG_C2IMR1_RTCSSRUIM (1 << 2) /* Bit 2: Disable rtc ssru interrupt to cpu2 */ +#define SYSCFG_C2IMR1_RTCWKUPIM (1 << 3) /* Bit 3: Disable rtc wkup interrupt to cpu2 */ +#define SYSCFG_C2IMR1_RCCIM (1 << 5) /* Bit 5: Disable rcc interrupt to cpu2 */ +#define SYSCFG_C2IMR1_FLASHIM (1 << 6) /* Bit 6: Disable flash interrupt to cpu2 */ +#define SYSCFG_C2IMR1_PKAIM (1 << 8) /* Bit 8: Disable pka interrupt to cpu2 */ +#define SYSCFG_C2IMR1_AESIM (1 << 10) /* Bit 10: Disable aes interrupt to cpu2 */ +#define SYSCFG_C2IMR1_COMPIM (1 << 11) /* Bit 11: Disable comp interrupt to cpu2 */ +#define SYSCFG_C2IMR1_ADCIM (1 << 12) /* Bit 12: Disable adc interrupt to cpu2 */ +#define SYSCFG_C2IMR1_DACIM (1 << 13) /* Bit 13: Disable dac interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI0IM (1 << 16) /* Bit 16: Disable EXTI0IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI1IM (1 << 17) /* Bit 17: Disable EXTI1IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI2IM (1 << 18) /* Bit 18: Disable EXTI2IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI3IM (1 << 19) /* Bit 19: Disable EXTI3IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI4IM (1 << 20) /* Bit 20: Disable EXTI4IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI5IM (1 << 21) /* Bit 21: Disable EXTI5IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI6IM (1 << 22) /* Bit 22: Disable EXTI6IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI7IM (1 << 23) /* Bit 23: Disable EXTI7IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI8IM (1 << 24) /* Bit 24: Disable EXTI8IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI9IM (1 << 25) /* Bit 25: Disable EXTI9IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI10IM (1 << 26) /* Bit 26: Disable EXTI10IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI11IM (1 << 27) /* Bit 27: Disable EXTI11IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI12IM (1 << 28) /* Bit 28: Disable EXTI12IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI13IM (1 << 29) /* Bit 29: Disable EXTI13IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI14IM (1 << 30) /* Bit 30: Disable EXTI14IM interrupt to cpu2 */ +#define SYSCFG_C2IMR1_EXTI15IM (1 << 31) /* Bit 31: Disable EXTI15IM interrupt to cpu2 */ + +/* SYSCFG cpu2 interrupt mask register 2 (C2IMR2) */ + +#define SYSCFG_C2IMR2_DMA1CH1IM (1 << 0) /* Bit 0: Disable DMA1CH1 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA1CH2IM (1 << 1) /* Bit 1: Disable DMA1CH2 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA1CH3IM (1 << 2) /* Bit 2: Disable DMA1CH3 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA1CH4IM (1 << 3) /* Bit 3: Disable DMA1CH4 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA1CH5IM (1 << 4) /* Bit 4: Disable DMA1CH5 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA1CH6IM (1 << 5) /* Bit 5: Disable DMA1CH6 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA1CH7IM (1 << 6) /* Bit 6: Disable DMA1CH7 interrupt to cpu2 */ + +#define SYSCFG_C2IMR2_DMA2CH1IM (1 << 8) /* Bit 8: Disable DMA2CH1 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA2CH2IM (1 << 9) /* Bit 9: Disable DMA2CH2 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA2CH3IM (1 << 10) /* Bit 10: Disable DMA2CH3 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA2CH4IM (1 << 11) /* Bit 11: Disable DMA2CH4 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA2CH5IM (1 << 12) /* Bit 12: Disable DMA2CH5 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA2CH6IM (1 << 13) /* Bit 13: Disable DMA2CH6 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_DMA2CH7IM (1 << 14) /* Bit 14: Disable DMA2CH7 interrupt to cpu2 */ + +#define SYSCFG_C2IMR2_DMAMUX1IM (1 << 15) /* Bit 15: Disable DMAMUX1 interrupt to cpu2 */ + +#define SYSCFG_C2IMR2_PCM3IM (1 << 18) /* Bit 18: Disable PVM3 interrupt to cpu2 */ +#define SYSCFG_C2IMR2_PVDIM (1 << 20) /* Bit 20: Disable PVD interrupt to cpu2 */ + +/* SYSCFG radio debug control register (RFDCR) */ + +#define SYSCFG_RFDCR_RFTBSEL (1 << 0) /* Bit 0: Analog test bus on RF[ADTB[3:0] */ + +#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_SYSCFG_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_tim.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_tim.h new file mode 100644 index 0000000000..fdc46a6493 --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_tim.h @@ -0,0 +1,1000 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_tim.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_TIM_H +#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_TIM_H + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +/* Basic Timers - TIM6 and TIM7 */ + +#define STM32WL5_BTIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */ +#define STM32WL5_BTIM_CR2_OFFSET 0x0004 /* Control register 2 (16-bit) */ +#define STM32WL5_BTIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */ +#define STM32WL5_BTIM_SR_OFFSET 0x0010 /* Status register (16-bit) */ +#define STM32WL5_BTIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */ +#define STM32WL5_BTIM_CCMR1_OFFSET 0x0018 /* Capture/compare mode */ +#define STM32WL5_BTIM_CCER_OFFSET 0x0020 /* Capture/compare enable register */ +#define STM32WL5_BTIM_CNT_OFFSET 0x0024 /* Counter (16-bit) */ +#define STM32WL5_BTIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */ +#define STM32WL5_BTIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */ + +/* 32-bit General Timers - TIM2 + * TIM2 and 5 are 32-bit. + * TIM15, 16 and 17 are 16-bit. + */ + +#define STM32WL5_GTIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */ +#define STM32WL5_GTIM_CR2_OFFSET 0x0004 /* Control register 2 (16-bit) */ +#define STM32WL5_GTIM_SMCR_OFFSET 0x0008 /* Slave mode control register (16-bit, TIM2-5,15 only) */ +#define STM32WL5_GTIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */ +#define STM32WL5_GTIM_SR_OFFSET 0x0010 /* Status register (16-bit) */ +#define STM32WL5_GTIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */ +#define STM32WL5_GTIM_CCMR1_OFFSET 0x0018 /* Capture/compare mode register 1 (32-bit) */ +#define STM32WL5_GTIM_CCMR2_OFFSET 0x001c /* Capture/compare mode register 2 (32-bit, TIM2-5 only) */ +#define STM32WL5_GTIM_CCER_OFFSET 0x0020 /* Capture/compare enable register (16-bit) */ +#define STM32WL5_GTIM_CNT_OFFSET 0x0024 /* Counter (16-bit or 32-bit TIM2/5) */ +#define STM32WL5_GTIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */ +#define STM32WL5_GTIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit or 32-bit TIM2/5) */ +#define STM32WL5_GTIM_CCR1_OFFSET 0x0034 /* Capture/compare register 1 (16-bit or 32-bit TIM2/5) */ +#define STM32WL5_GTIM_CCR2_OFFSET 0x0038 /* Capture/compare register 2 (16-bit TIM2-5,15 only or 32-bit TIM2/5) */ +#define STM32WL5_GTIM_CCR3_OFFSET 0x003c /* Capture/compare register 3 (16-bit TIM2-5 only or 32-bit TIM2/5) */ +#define STM32WL5_GTIM_CCR4_OFFSET 0x0040 /* Capture/compare register 4 (16-bit TIM2-5 only or 32-bit TIM2/5) */ +#define STM32WL5_GTIM_DCR_OFFSET 0x0048 /* DMA control register (16-bit) */ +#define STM32WL5_GTIM_DMAR_OFFSET 0x004c /* DMA address for burst mode (16-bit) */ +#define STM32WL5_GTIM_OR1_OFFSET 0x0050 /* Option register 1 */ +#define STM32WL5_GTIM_OR2_OFFSET 0x0060 /* Option register 2 */ + +/* TIM15, 16, and 17 only. + */ + +#define STM32WL5_GTIM_RCR_OFFSET 0x0030 /* Repetition counter register (TIM16/TIM17) */ +#define STM32WL5_GTIM_BDTR_OFFSET 0x0044 /* Break and dead-time register (TIM16/TIM17) */ + +/* Advanced Timers - TIM1 */ + +#define STM32WL5_ATIM_CR1_OFFSET 0x0000 /* Control register 1 (16-bit) */ +#define STM32WL5_ATIM_CR2_OFFSET 0x0004 /* Control register 2 (16-bit*) */ +#define STM32WL5_ATIM_SMCR_OFFSET 0x0008 /* Slave mode control register (16-bit) */ +#define STM32WL5_ATIM_DIER_OFFSET 0x000c /* DMA/Interrupt enable register (16-bit) */ +#define STM32WL5_ATIM_SR_OFFSET 0x0010 /* Status register (16-bit*) */ +#define STM32WL5_ATIM_EGR_OFFSET 0x0014 /* Event generation register (16-bit) */ +#define STM32WL5_ATIM_CCMR1_OFFSET 0x0018 /* Capture/compare mode register 1 (16-bit*) */ +#define STM32WL5_ATIM_CCMR2_OFFSET 0x001c /* Capture/compare mode register 2 (16-bit*) */ +#define STM32WL5_ATIM_CCER_OFFSET 0x0020 /* Capture/compare enable register (16-bit*) */ +#define STM32WL5_ATIM_CNT_OFFSET 0x0024 /* Counter (16-bit) */ +#define STM32WL5_ATIM_PSC_OFFSET 0x0028 /* Prescaler (16-bit) */ +#define STM32WL5_ATIM_ARR_OFFSET 0x002c /* Auto-reload register (16-bit) */ +#define STM32WL5_ATIM_RCR_OFFSET 0x0030 /* Repetition counter register (16-bit) */ +#define STM32WL5_ATIM_CCR1_OFFSET 0x0034 /* Capture/compare register 1 (16-bit) */ +#define STM32WL5_ATIM_CCR2_OFFSET 0x0038 /* Capture/compare register 2 (16-bit) */ +#define STM32WL5_ATIM_CCR3_OFFSET 0x003c /* Capture/compare register 3 (16-bit) */ +#define STM32WL5_ATIM_CCR4_OFFSET 0x0040 /* Capture/compare register 4 (16-bit) */ +#define STM32WL5_ATIM_BDTR_OFFSET 0x0044 /* Break and dead-time register (16-bit*) */ +#define STM32WL5_ATIM_DCR_OFFSET 0x0048 /* DMA control register (16-bit) */ +#define STM32WL5_ATIM_DMAR_OFFSET 0x004c /* DMA address for burst mode (16-bit) */ +#define STM32WL5_ATIM_OR1_OFFSET 0x0050 /* Timer option register 1 */ +#define STM32WL5_ATIM_CCMR3_OFFSET 0x0054 /* Capture/compare mode register 3 (32-bit) */ +#define STM32WL5_ATIM_CCR5_OFFSET 0x0058 /* Capture/compare register 4 (16-bit) */ +#define STM32WL5_ATIM_CCR6_OFFSET 0x005c /* Capture/compare register 4 (32-bit) */ +#define STM32WL5_ATIM_OR2_OFFSET 0x0050 /* Timer option register 2 */ +#define STM32WL5_ATIM_OR3_OFFSET 0x0050 /* Timer option register 3 */ + +/* Register Addresses *******************************************************/ + +/* Advanced Timers - TIM1 and TIM8 */ + +#define STM32WL5_TIM1_CR1 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CR1_OFFSET) +#define STM32WL5_TIM1_CR2 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CR2_OFFSET) +#define STM32WL5_TIM1_SMCR (STM32WL5_TIM1_BASE+STM32WL5_ATIM_SMCR_OFFSET) +#define STM32WL5_TIM1_DIER (STM32WL5_TIM1_BASE+STM32WL5_ATIM_DIER_OFFSET) +#define STM32WL5_TIM1_SR (STM32WL5_TIM1_BASE+STM32WL5_ATIM_SR_OFFSET) +#define STM32WL5_TIM1_EGR (STM32WL5_TIM1_BASE+STM32WL5_ATIM_EGR_OFFSET) +#define STM32WL5_TIM1_CCMR1 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCMR1_OFFSET) +#define STM32WL5_TIM1_CCMR2 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCMR2_OFFSET) +#define STM32WL5_TIM1_CCER (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCER_OFFSET) +#define STM32WL5_TIM1_CNT (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CNT_OFFSET) +#define STM32WL5_TIM1_PSC (STM32WL5_TIM1_BASE+STM32WL5_ATIM_PSC_OFFSET) +#define STM32WL5_TIM1_ARR (STM32WL5_TIM1_BASE+STM32WL5_ATIM_ARR_OFFSET) +#define STM32WL5_TIM1_RCR (STM32WL5_TIM1_BASE+STM32WL5_ATIM_RCR_OFFSET) +#define STM32WL5_TIM1_CCR1 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCR1_OFFSET) +#define STM32WL5_TIM1_CCR2 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCR2_OFFSET) +#define STM32WL5_TIM1_CCR3 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCR3_OFFSET) +#define STM32WL5_TIM1_CCR4 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCR4_OFFSET) +#define STM32WL5_TIM1_BDTR (STM32WL5_TIM1_BASE+STM32WL5_ATIM_BDTR_OFFSET) +#define STM32WL5_TIM1_DCR (STM32WL5_TIM1_BASE+STM32WL5_ATIM_DCR_OFFSET) +#define STM32WL5_TIM1_DMAR (STM32WL5_TIM1_BASE+STM32WL5_ATIM_DMAR_OFFSET) +#define STM32WL5_TIM1_OR1 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_OR1_OFFSET) +#define STM32WL5_TIM1_CCMR3 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCMR3_OFFSET) +#define STM32WL5_TIM1_CCR5 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCR5_OFFSET) +#define STM32WL5_TIM1_CCR6 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_CCR6_OFFSET) +#define STM32WL5_TIM1_OR2 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_OR2_OFFSET) +#define STM32WL5_TIM1_OR3 (STM32WL5_TIM1_BASE+STM32WL5_ATIM_OR3_OFFSET) + +/* 16-/32-bit General Timers - TIM2, TIM16-17. + * TIM2 is 32-bit. + * TIM16 and 17 are 16-bit. + */ + +#define STM32WL5_TIM2_CR1 (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CR1_OFFSET) +#define STM32WL5_TIM2_CR2 (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CR2_OFFSET) +#define STM32WL5_TIM2_SMCR (STM32WL5_TIM2_BASE+STM32WL5_GTIM_SMCR_OFFSET) +#define STM32WL5_TIM2_DIER (STM32WL5_TIM2_BASE+STM32WL5_GTIM_DIER_OFFSET) +#define STM32WL5_TIM2_SR (STM32WL5_TIM2_BASE+STM32WL5_GTIM_SR_OFFSET) +#define STM32WL5_TIM2_EGR (STM32WL5_TIM2_BASE+STM32WL5_GTIM_EGR_OFFSET) +#define STM32WL5_TIM2_CCMR1 (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CCMR1_OFFSET) +#define STM32WL5_TIM2_CCMR2 (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CCMR2_OFFSET) +#define STM32WL5_TIM2_CCER (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CCER_OFFSET) +#define STM32WL5_TIM2_CNT (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CNT_OFFSET) +#define STM32WL5_TIM2_PSC (STM32WL5_TIM2_BASE+STM32WL5_GTIM_PSC_OFFSET) +#define STM32WL5_TIM2_ARR (STM32WL5_TIM2_BASE+STM32WL5_GTIM_ARR_OFFSET) +#define STM32WL5_TIM2_CCR1 (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CCR1_OFFSET) +#define STM32WL5_TIM2_CCR2 (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CCR2_OFFSET) +#define STM32WL5_TIM2_CCR3 (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CCR3_OFFSET) +#define STM32WL5_TIM2_CCR4 (STM32WL5_TIM2_BASE+STM32WL5_GTIM_CCR4_OFFSET) +#define STM32WL5_TIM2_DCR (STM32WL5_TIM2_BASE+STM32WL5_GTIM_DCR_OFFSET) +#define STM32WL5_TIM2_DMAR (STM32WL5_TIM2_BASE+STM32WL5_GTIM_DMAR_OFFSET) +#define STM32WL5_TIM2_OR (STM32WL5_TIM2_BASE+STM32WL5_GTIM_OR_OFFSET) + +#define STM32WL5_TIM16_CR1 (STM32WL5_TIM16_BASE+STM32WL5_GTIM_CR1_OFFSET) +#define STM32WL5_TIM16_CR2 (STM32WL5_TIM16_BASE+STM32WL5_GTIM_CR2_OFFSET) +#define STM32WL5_TIM16_DIER (STM32WL5_TIM16_BASE+STM32WL5_GTIM_DIER_OFFSET) +#define STM32WL5_TIM16_SR (STM32WL5_TIM16_BASE+STM32WL5_GTIM_SR_OFFSET) +#define STM32WL5_TIM16_EGR (STM32WL5_TIM16_BASE+STM32WL5_GTIM_EGR_OFFSET) +#define STM32WL5_TIM16_CCMR1 (STM32WL5_TIM16_BASE+STM32WL5_GTIM_CCMR1_OFFSET) +#define STM32WL5_TIM16_CCER (STM32WL5_TIM16_BASE+STM32WL5_GTIM_CCER_OFFSET) +#define STM32WL5_TIM16_CNT (STM32WL5_TIM16_BASE+STM32WL5_GTIM_CNT_OFFSET) +#define STM32WL5_TIM16_PSC (STM32WL5_TIM16_BASE+STM32WL5_GTIM_PSC_OFFSET) +#define STM32WL5_TIM16_ARR (STM32WL5_TIM16_BASE+STM32WL5_GTIM_ARR_OFFSET) +#define STM32WL5_TIM16_RCR (STM32WL5_TIM16_BASE+STM32WL5_GTIM_RCR_OFFSET) +#define STM32WL5_TIM16_CCR1 (STM32WL5_TIM16_BASE+STM32WL5_GTIM_CCR1_OFFSET) +#define STM32WL5_TIM16_BDTR (STM32WL5_TIM16_BASE+STM32WL5_GTIM_BDTR_OFFSET) +#define STM32WL5_TIM16_DCR (STM32WL5_TIM16_BASE+STM32WL5_GTIM_DCR_OFFSET) +#define STM32WL5_TIM16_DMAR (STM32WL5_TIM16_BASE+STM32WL5_GTIM_DMAR_OFFSET) +#define STM32WL5_TIM16_OR (STM32WL5_TIM16_BASE+STM32WL5_GTIM_OR_OFFSET) + +#define STM32WL5_TIM17_CR1 (STM32WL5_TIM17_BASE+STM32WL5_GTIM_CR1_OFFSET) +#define STM32WL5_TIM17_CR2 (STM32WL5_TIM17_BASE+STM32WL5_GTIM_CR2_OFFSET) +#define STM32WL5_TIM17_DIER (STM32WL5_TIM17_BASE+STM32WL5_GTIM_DIER_OFFSET) +#define STM32WL5_TIM17_SR (STM32WL5_TIM17_BASE+STM32WL5_GTIM_SR_OFFSET) +#define STM32WL5_TIM17_EGR (STM32WL5_TIM17_BASE+STM32WL5_GTIM_EGR_OFFSET) +#define STM32WL5_TIM17_CCMR1 (STM32WL5_TIM17_BASE+STM32WL5_GTIM_CCMR1_OFFSET) +#define STM32WL5_TIM17_CCER (STM32WL5_TIM17_BASE+STM32WL5_GTIM_CCER_OFFSET) +#define STM32WL5_TIM17_CNT (STM32WL5_TIM17_BASE+STM32WL5_GTIM_CNT_OFFSET) +#define STM32WL5_TIM17_PSC (STM32WL5_TIM17_BASE+STM32WL5_GTIM_PSC_OFFSET) +#define STM32WL5_TIM17_ARR (STM32WL5_TIM17_BASE+STM32WL5_GTIM_ARR_OFFSET) +#define STM32WL5_TIM17_RCR (STM32WL5_TIM17_BASE+STM32WL5_GTIM_RCR_OFFSET) +#define STM32WL5_TIM17_CCR1 (STM32WL5_TIM17_BASE+STM32WL5_GTIM_CCR1_OFFSET) +#define STM32WL5_TIM17_BDTR (STM32WL5_TIM17_BASE+STM32WL5_GTIM_BDTR_OFFSET) +#define STM32WL5_TIM17_DCR (STM32WL5_TIM17_BASE+STM32WL5_GTIM_DCR_OFFSET) +#define STM32WL5_TIM17_DMAR (STM32WL5_TIM17_BASE+STM32WL5_GTIM_DMAR_OFFSET) + +/* Register Bitfield Definitions ********************************************/ + +/* Control register 1 */ + +#define ATIM_CR1_CEN (1 << 0) /* Bit 0: Counter enable */ +#define ATIM_CR1_UDIS (1 << 1) /* Bit 1: Update disable */ +#define ATIM_CR1_URS (1 << 2) /* Bit 2: Update request source */ +#define ATIM_CR1_OPM (1 << 3) /* Bit 3: One pulse mode */ +#define ATIM_CR1_DIR (1 << 4) /* Bit 4: Direction */ +#define ATIM_CR1_CMS_SHIFT (5) /* Bits 6-5: Center-aligned mode selection */ +#define ATIM_CR1_CMS_MASK (3 << ATIM_CR1_CMS_SHIFT) +# define ATIM_CR1_EDGE (0 << ATIM_CR1_CMS_SHIFT) /* 00: Edge-aligned mode */ +# define ATIM_CR1_CENTER1 (1 << ATIM_CR1_CMS_SHIFT) /* 01: Center-aligned mode 1 */ +# define ATIM_CR1_CENTER2 (2 << ATIM_CR1_CMS_SHIFT) /* 10: Center-aligned mode 2 */ +# define ATIM_CR1_CENTER3 (3 << ATIM_CR1_CMS_SHIFT) /* 11: Center-aligned mode 3 */ + +#define ATIM_CR1_ARPE (1 << 7) /* Bit 7: Auto-reload preload enable */ +#define ATIM_CR1_CKD_SHIFT (8) /* Bits 9-8: Clock division */ +#define ATIM_CR1_CKD_MASK (3 << ATIM_CR1_CKD_SHIFT) +# define ATIM_CR1_TCKINT (0 << ATIM_CR1_CKD_SHIFT) /* 00: tDTS=tCK_INT */ +# define ATIM_CR1_2TCKINT (1 << ATIM_CR1_CKD_SHIFT) /* 01: tDTS=2*tCK_INT */ +# define ATIM_CR1_4TCKINT (2 << ATIM_CR1_CKD_SHIFT) /* 10: tDTS=4*tCK_INT */ + +#define ATIM_CR1_UIFREMAP (1 << 11) /* Bit 11: UIF status bit remapping */ + +/* Control register 2 */ + +#define ATIM_CR2_CCPC (1 << 0) /* Bit 0: Capture/Compare Preloaded Control */ +#define ATIM_CR2_CCUS (1 << 2) /* Bit 2: Capture/Compare Control Update Selection */ +#define ATIM_CR2_CCDS (1 << 3) /* Bit 3: Capture/Compare DMA Selection */ +#define ATIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection */ +#define ATIM_CR2_MMS_MASK (7 << ATIM_CR2_MMS_SHIFT) +# define ATIM_CR2_MMS_RESET (0 << ATIM_CR2_MMS_SHIFT) /* 000: Reset - TIMx_EGR UG bit is TRGO */ +# define ATIM_CR2_MMS_ENABLE (1 << ATIM_CR2_MMS_SHIFT) /* 001: Enable - CNT_EN is TRGO */ +# define ATIM_CR2_MMS_UPDATE (2 << ATIM_CR2_MMS_SHIFT) /* 010: Update event is TRGO */ +# define ATIM_CR2_MMS_COMPP (3 << ATIM_CR2_MMS_SHIFT) /* 010: Compare Pulse - CC1IF flag */ +# define ATIM_CR2_MMS_OC1REF (4 << ATIM_CR2_MMS_SHIFT) /* 100: Compare OC1REF is TRGO */ +# define ATIM_CR2_MMS_OC2REF (5 << ATIM_CR2_MMS_SHIFT) /* 101: Compare OC2REF is TRGO */ +# define ATIM_CR2_MMS_OC3REF (6 << ATIM_CR2_MMS_SHIFT) /* 110: Compare OC3REF is TRGO */ +# define ATIM_CR2_MMS_OC4REF (7 << ATIM_CR2_MMS_SHIFT) /* 111: Compare OC4REF is TRGO */ + +#define ATIM_CR2_TI1S (1 << 7) /* Bit 7: TI1 Selection */ +#define ATIM_CR2_OIS1 (1 << 8) /* Bit 8: Output Idle state 1 (OC1 output) */ +#define ATIM_CR2_OIS1N (1 << 9) /* Bit 9: Output Idle state 1 (OC1N output) */ +#define ATIM_CR2_OIS2 (1 << 10) /* Bit 10: Output Idle state 2 (OC2 output) */ +#define ATIM_CR2_OIS2N (1 << 11) /* Bit 11: Output Idle state 2 (OC2N output) */ +#define ATIM_CR2_OIS3 (1 << 12) /* Bit 12: Output Idle state 3 (OC3 output) */ +#define ATIM_CR2_OIS3N (1 << 13) /* Bit 13: Output Idle state 3 (OC3N output) */ +#define ATIM_CR2_OIS4 (1 << 14) /* Bit 14: Output Idle state 4 (OC4 output) */ +#define ATIM_CR2_OIS5 (1 << 16) /* Bit 16: OOutput Idle state 5 (OC5 output) */ +#define ATIM_CR2_OIS6 (1 << 18) /* Bit 18: Output Idle state 6 (OC6 output) */ +#define ATIM_CR2_MMS2_SHIFT (20) /* Bits 20-23: Master Mode Selection 2 */ +#define ATIM_CR2_MMS2_MASK (15 << ATIM_CR2_MMS2_SHIFT) +# define ATIM_CR2_MMS2_RESET (0 << ATIM_CR2_MMS2_SHIFT) /* 0000: Reset - TIMx_EGR UG bit is TRG9 */ +# define ATIM_CR2_MMS2_ENABLE (1 << ATIM_CR2_MMS2_SHIFT) /* 0001: Enable - CNT_EN is TRGO2 */ +# define ATIM_CR2_MMS2_UPDATE (2 << ATIM_CR2_MMS2_SHIFT) /* 0010: Update event is TRGH0*/ +# define ATIM_CR2_MMS2_COMPP (3 << ATIM_CR2_MMS2_SHIFT) /* 0010: Compare Pulse - CC1IF flag */ +# define ATIM_CR2_MMS2_OC1REF (4 << ATIM_CR2_MMS2_SHIFT) /* 0100: Compare OC1REF is TRGO2 */ +# define ATIM_CR2_MMS2_OC2REF (5 << ATIM_CR2_MMS2_SHIFT) /* 0101: Compare OC2REF is TRGO2 */ +# define ATIM_CR2_MMS2_OC3REF (6 << ATIM_CR2_MMS2_SHIFT) /* 0110: Compare OC3REF is TRGO2 */ +# define ATIM_CR2_MMS2_OC4REF (7 << ATIM_CR2_MMS2_SHIFT) /* 0111: Compare OC4REF is TRGO2 */ +# define ATIM_CR2_MMS2_OC5REF (8 << ATIM_CR2_MMS2_SHIFT) /* 1000: Compare OC5REF is TRGO2 */ +# define ATIM_CR2_MMS2_OC6REF (9 << ATIM_CR2_MMS2_SHIFT) /* 1001: Compare OC6REF is TRGO2 */ +# define ATIM_CR2_MMS2_CMPOC4 (10 << ATIM_CR2_MMS2_SHIFT) /* 1010: Compare pulse - OC4REF edge is TRGO2 */ +# define ATIM_CR2_MMS2_CMPOC6 (11 << ATIM_CR2_MMS2_SHIFT) /* 1011: Compare pulse - OC6REF edge is TRGO2 */ +# define ATIM_CR2_MMS2_CMPOC4R6R (12 << ATIM_CR2_MMS2_SHIFT) /* 1100: Compare pulse - OC4REF/OC6REF rising */ +# define ATIM_CR2_MMS2_CMPOC4R6F (13 << ATIM_CR2_MMS2_SHIFT) /* 1101: Compare pulse - OC4REF rising/OC6REF falling */ +# define ATIM_CR2_MMS2_CMPOC5R6R (14 << ATIM_CR2_MMS2_SHIFT) /* 1110: Compare pulse - OC5REF/OC6REF rising */ +# define ATIM_CR2_MMS2_CMPOC5R6F (15 << ATIM_CR2_MMS2_SHIFT) /* 1111: Compare pulse - OC5REF rising/OC6REF falling */ + +/* Slave mode control register */ + +#define ATIM_SMCR_SMS_SHIFT (0) /* Bits 0-2: Slave mode selection */ +#define ATIM_SMCR_SMS_MASK (7 << ATIM_SMCR_SMS_SHIFT) +# define ATIM_SMCR_DISAB (0 << ATIM_SMCR_SMS_SHIFT) /* 000: Slave mode disabled */ +# define ATIM_SMCR_ENCMD1 (1 << ATIM_SMCR_SMS_SHIFT) /* 001: Encoder mode 1 */ +# define ATIM_SMCR_ENCMD2 (2 << ATIM_SMCR_SMS_SHIFT) /* 010: Encoder mode 2 */ +# define ATIM_SMCR_ENCMD3 (3 << ATIM_SMCR_SMS_SHIFT) /* 011: Encoder mode 3 */ +# define ATIM_SMCR_RESET (4 << ATIM_SMCR_SMS_SHIFT) /* 100: Reset Mode */ +# define ATIM_SMCR_GATED (5 << ATIM_SMCR_SMS_SHIFT) /* 101: Gated Mode */ +# define ATIM_SMCR_TRIGGER (6 << ATIM_SMCR_SMS_SHIFT) /* 110: Trigger Mode */ +# define ATIM_SMCR_EXTCLK1 (7 << ATIM_SMCR_SMS_SHIFT) /* 111: External Clock Mode 1 */ + +#define ATIM_SMCR_OCCS (1 << 3) /* Bit 3: OCREF clear selection */ +#define ATIM_SMCR_TS_SHIFT (4) /* Bits 4-6: Trigger selection */ +#define ATIM_SMCR_TS_MASK (7 << ATIM_SMCR_TS_SHIFT) +# define ATIM_SMCR_ITR0 (0 << ATIM_SMCR_TS_SHIFT) /* 000: Internal trigger 0 (ITR0) */ +# define ATIM_SMCR_ITR1 (1 << ATIM_SMCR_TS_SHIFT) /* 001: Internal trigger 1 (ITR1) */ +# define ATIM_SMCR_ITR2 (2 << ATIM_SMCR_TS_SHIFT) /* 010: Internal trigger 2 (ITR2) */ +# define ATIM_SMCR_ITR3 (3 << ATIM_SMCR_TS_SHIFT) /* 011: Internal trigger 3 (ITR3) */ +# define ATIM_SMCR_T1FED (4 << ATIM_SMCR_TS_SHIFT) /* 100: TI1 Edge Detector (TI1F_ED) */ +# define ATIM_SMCR_TI1FP1 (5 << ATIM_SMCR_TS_SHIFT) /* 101: Filtered Timer Input 1 (TI1FP1) */ +# define ATIM_SMCR_T12FP2 (6 << ATIM_SMCR_TS_SHIFT) /* 110: Filtered Timer Input 2 (TI2FP2) */ +# define ATIM_SMCR_ETRF (7 << ATIM_SMCR_TS_SHIFT) /* 111: External Trigger input (ETRF) */ + +#define ATIM_SMCR_MSM (1 << 7) /* Bit 7: Master/slave mode */ +#define ATIM_SMCR_ETF_SHIFT (8) /* Bits 8-11: External trigger filter */ +#define ATIM_SMCR_ETF_MASK (0x0f << ATIM_SMCR_ETF_SHIFT) +# define ATIM_SMCR_NOFILT (0 << ATIM_SMCR_ETF_SHIFT) /* 0000: No filter, sampling is done at fDTS */ +# define ATIM_SMCR_FCKINT2 (1 << ATIM_SMCR_ETF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */ +# define ATIM_SMCR_FCKINT4 (2 << ATIM_SMCR_ETF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */ +# define ATIM_SMCR_FCKINT8 (3 << ATIM_SMCR_ETF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */ +# define ATIM_SMCR_FDTSd26 (4 << ATIM_SMCR_ETF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */ +# define ATIM_SMCR_FDTSd28 (5 << ATIM_SMCR_ETF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */ +# define ATIM_SMCR_FDTSd46 (6 << ATIM_SMCR_ETF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */ +# define ATIM_SMCR_FDTSd48 (7 << ATIM_SMCR_ETF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */ +# define ATIM_SMCR_FDTSd86 (8 << ATIM_SMCR_ETF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */ +# define ATIM_SMCR_FDTSd88 (9 << ATIM_SMCR_ETF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */ +# define ATIM_SMCR_FDTSd165 (10 << ATIM_SMCR_ETF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */ +# define ATIM_SMCR_FDTSd166 (11 << ATIM_SMCR_ETF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */ +# define ATIM_SMCR_FDTSd168 (12 << ATIM_SMCR_ETF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */ +# define ATIM_SMCR_FDTSd325 (13 << ATIM_SMCR_ETF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */ +# define ATIM_SMCR_FDTSd326 (14 << ATIM_SMCR_ETF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */ +# define ATIM_SMCR_FDTSd328 (15 << ATIM_SMCR_ETF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */ + +#define ATIM_SMCR_ETPS_SHIFT (12) /* Bits 12-13: External trigger prescaler */ +#define ATIM_SMCR_ETPS_MASK (3 << ATIM_SMCR_ETPS_SHIFT) +# define ATIM_SMCR_PSCOFF (0 << ATIM_SMCR_ETPS_SHIFT) /* 00: Prescaler OFF */ +# define ATIM_SMCR_ETRPd2 (1 << ATIM_SMCR_ETPS_SHIFT) /* 01: ETRP frequency divided by 2 */ +# define ATIM_SMCR_ETRPd4 (2 << ATIM_SMCR_ETPS_SHIFT) /* 10: ETRP frequency divided by 4 */ +# define ATIM_SMCR_ETRPd8 (3 << ATIM_SMCR_ETPS_SHIFT) /* 11: ETRP frequency divided by 8 */ + +#define ATIM_SMCR_ECE (1 << 14) /* Bit 14: External clock enable */ +#define ATIM_SMCR_ETP (1 << 15) /* Bit 15: External trigger polarity */ +#define ATIM_SMCR_SMS (1 << 16) /* Bit 16: Slave mode selection - bit 3 */ + +/* DMA/Interrupt enable register */ + +#define ATIM_DIER_UIE (1 << 0) /* Bit 0: Update interrupt enable */ +#define ATIM_DIER_CC1IE (1 << 1) /* Bit 1: Capture/Compare 1 interrupt enable */ +#define ATIM_DIER_CC2IE (1 << 2) /* Bit 2: Capture/Compare 2 interrupt enable */ +#define ATIM_DIER_CC3IE (1 << 3) /* Bit 3: Capture/Compare 3 interrupt enable */ +#define ATIM_DIER_CC4IE (1 << 4) /* Bit 4: Capture/Compare 4 interrupt enable */ +#define ATIM_DIER_COMIE (1 << 5) /* Bit 5: COM interrupt enable */ +#define ATIM_DIER_TIE (1 << 6) /* Bit 6: Trigger interrupt enable */ +#define ATIM_DIER_BIE (1 << 7) /* Bit 7: Break interrupt enable */ +#define ATIM_DIER_UDE (1 << 8) /* Bit 8: Update DMA request enable */ +#define ATIM_DIER_CC1DE (1 << 9) /* Bit 9: Capture/Compare 1 DMA request enable */ +#define ATIM_DIER_CC2DE (1 << 10) /* Bit 10: Capture/Compare 2 DMA request enable */ +#define ATIM_DIER_CC3DE (1 << 11) /* Bit 11: Capture/Compare 3 DMA request enable */ +#define ATIM_DIER_CC4DE (1 << 12) /* Bit 12: Capture/Compare 4 DMA request enable */ +#define ATIM_DIER_COMDE (1 << 13) /* Bit 13: COM DMA request enable */ +#define ATIM_DIER_TDE (1 << 14) /* Bit 14: Trigger DMA request enable */ + +/* Status register */ + +#define ATIM_SR_UIF (1 << 0) /* Bit 0: Update interrupt Flag */ +#define ATIM_SR_CC1IF (1 << 1) /* Bit 1: Capture/Compare 1 interrupt Flag */ +#define ATIM_SR_CC2IF (1 << 2) /* Bit 2: Capture/Compare 2 interrupt Flag */ +#define ATIM_SR_CC3IF (1 << 3) /* Bit 3: Capture/Compare 3 interrupt Flag */ +#define ATIM_SR_CC4IF (1 << 4) /* Bit 4: Capture/Compare 4 interrupt Flag */ +#define ATIM_SR_COMIF (1 << 5) /* Bit 5: COM interrupt Flag */ +#define ATIM_SR_TIF (1 << 6) /* Bit 6: Trigger interrupt Flag */ +#define ATIM_SR_BIF (1 << 7) /* Bit 7: Break interrupt Flag */ +#define ATIM_SR_B2IF (1 << 8) /* Bit 8: Break 2 interrupt Flag */ +#define ATIM_SR_CC1OF (1 << 9) /* Bit 9: Capture/Compare 1 Overcapture Flag */ +#define ATIM_SR_CC2OF (1 << 10) /* Bit 10: Capture/Compare 2 Overcapture Flag */ +#define ATIM_SR_CC3OF (1 << 11) /* Bit 11: Capture/Compare 3 Overcapture Flag */ +#define ATIM_SR_CC4OF (1 << 12) /* Bit 12: Capture/Compare 4 Overcapture Flag */ +#define ATIM_SR_SBIF (1 << 13) /* Bit 13: System break interrupt Flag */ +#define ATIM_SR_CC5IF (1 << 16) /* Bit 16: Compare 5 interrupt flag */ +#define ATIM_SR_CC6IF (1 << 17) /* Bit 17: Compare 6 interrupt flag */ + +/* Event generation register */ + +#define ATIM_EGR_UG (1 << 0) /* Bit 0: Update Generation */ +#define ATIM_EGR_CC1G (1 << 1) /* Bit 1: Capture/Compare 1 Generation */ +#define ATIM_EGR_CC2G (1 << 2) /* Bit 2: Capture/Compare 2 Generation */ +#define ATIM_EGR_CC3G (1 << 3) /* Bit 3: Capture/Compare 3 Generation */ +#define ATIM_EGR_CC4G (1 << 4) /* Bit 4: Capture/Compare 4 Generation */ +#define ATIM_EGR_COMG (1 << 5) /* Bit 5: Capture/Compare Control Update Generation */ +#define ATIM_EGR_TG (1 << 6) /* Bit 6: Trigger Generation */ +#define ATIM_EGR_BG (1 << 7) /* Bit 7: Break Generation */ +#define ATIM_EGR_B2G (1 << 8) /* Bit 8: Break 2 Generation */ + +/* Capture/compare mode register 1 -- Output compare mode */ + +#define ATIM_CCMR1_CC1S_SHIFT (0) /* Bits 1-0: Capture/Compare 1 Selection */ +#define ATIM_CCMR1_CC1S_MASK (3 << ATIM_CCMR1_CC1S_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_OC1FE (1 << 2) /* Bit 2: Output Compare 1 Fast enable */ +#define ATIM_CCMR1_OC1PE (1 << 3) /* Bit 3: Output Compare 1 Preload enable */ +#define ATIM_CCMR1_OC1M_SHIFT (4) /* Bits 6-4: Output Compare 1 Mode */ +#define ATIM_CCMR1_OC1M_MASK (7 << ATIM_CCMR1_OC1M_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_OC1CE (1 << 7) /* Bit 7: Output Compare 1Clear Enable */ +#define ATIM_CCMR1_CC2S_SHIFT (8) /* Bits 8-9: Capture/Compare 2 Selection */ +#define ATIM_CCMR1_CC2S_MASK (3 << ATIM_CCMR1_CC2S_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_OC2FE (1 << 10) /* Bit 10: Output Compare 2 Fast enable */ +#define ATIM_CCMR1_OC2PE (1 << 11) /* Bit 11: Output Compare 2 Preload enable */ +#define ATIM_CCMR1_OC2M_SHIFT (12) /* Bits 14-12: Output Compare 2 Mode */ +#define ATIM_CCMR1_OC2M_MASK (7 << ATIM_CCMR1_OC2M_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_OC2CE (1 << 15) /* Bit 15: Output Compare 2 Clear Enable */ +#define ATIM_CCMR1_OC1M (1 << 16) /* Bit 16: Output Compare 1 mode - bit 3 */ +#define ATIM_CCMR1_OC2M (1 << 24) /* Bit 24: Output Compare 2 mode - bit 3 */ + +/* Common CCMR (unshifted) Capture/Compare Selection bit-field definitions */ + +#define ATIM_CCMR_CCS_CCOUT (0) /* 00: CCx channel output */ +#define ATIM_CCMR_CCS_CCIN1 (1) /* 01: CCx channel input, ICx is TIx */ +#define ATIM_CCMR_CCS_CCIN2 (2) /* 10: CCx channel input, ICx is TIy */ +#define ATIM_CCMR_CCS_CCINTRC (3) /* 11: CCx channel input, ICx is TRC */ + +/* Common CCMR (unshifted) Compare Mode bit field definitions */ + +#define ATIM_CCMR_MODE_FRZN (0) /* 000: Frozen */ +#define ATIM_CCMR_MODE_CHACT (1) /* 001: Channel x active on match */ +#define ATIM_CCMR_MODE_CHINACT (2) /* 010: Channel x inactive on match */ +#define ATIM_CCMR_MODE_OCREFTOG (3) /* 011: OCxREF toggle ATIM_CNT=ATIM_CCRx */ +#define ATIM_CCMR_MODE_OCREFLO (4) /* 100: OCxREF forced low */ +#define ATIM_CCMR_MODE_OCREFHI (5) /* 101: OCxREF forced high */ +#define ATIM_CCMR_MODE_PWM1 (6) /* 110: PWM mode 1 */ +#define ATIM_CCMR_MODE_PWM2 (7) /* 111: PWM mode 2 */ +#define ATIM_CCMR_MODE_COMBINED1 (12) /* 1100: Combined PWM mode 1 */ +#define ATIM_CCMR_MODE_COMBINED2 (13) /* 1101: Combined PWM mode 2 */ +#define ATIM_CCMR_MODE_ASYMMETRIC1 (14) /* 1110: Asymmetric PWM mode 1 */ +#define ATIM_CCMR_MODE_ASYMMETRIC2 (15) /* 1111: Asymmetric PWM mode 2 */ + +/* Capture/compare mode register 1 -- Input capture mode */ + +/* Bits 1-0: + * (same as output compare mode) + */ +#define ATIM_CCMR1_IC1PSC_SHIFT (2) /* Bits 3-2: Input Capture 1 Prescaler */ +#define ATIM_CCMR1_IC1PSC_MASK (3 << ATIM_CCMR1_IC1PSC_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_IC1F_SHIFT (4) /* Bits 7-4: Input Capture 1 Filter */ +#define ATIM_CCMR1_IC1F_MASK (0x0f << ATIM_CCMR1_IC1F_SHIFT) + /* (See common (unshifted) bit field definitions below) */ + /* Bits 9:8 (same as output compare mode) */ +#define ATIM_CCMR1_IC2PSC_SHIFT (10) /* Bits 11:10: Input Capture 2 Prescaler */ +#define ATIM_CCMR1_IC2PSC_MASK (3 << ATIM_CCMR1_IC2PSC_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR1_IC2F_SHIFT (12) /* Bits 15-12: Input Capture 2 Filter */ +#define ATIM_CCMR1_IC2F_MASK (0x0f << ATIM_CCMR1_IC2F_SHIFT) + /* (See common (unshifted) bit field definitions below) */ + +/* Common CCMR (unshifted) Input Capture Prescaler bit-field definitions */ + +#define ATIM_CCMR_ICPSC_NOPSC (0) /* 00: no prescaler, capture each edge */ +#define ATIM_CCMR_ICPSC_EVENTS2 (1) /* 01: capture once every 2 events */ +#define ATIM_CCMR_ICPSC_EVENTS4 (2) /* 10: capture once every 4 events */ +#define ATIM_CCMR_ICPSC_EVENTS8 (3) /* 11: capture once every 8 events */ + +/* Common CCMR (unshifted) Input Capture Filter bit-field definitions */ + +#define ATIM_CCMR_ICF_NOFILT (0) /* 0000: No filter, sampling at fDTS */ +#define ATIM_CCMR_ICF_FCKINT2 (1) /* 0001: fSAMPLING=fCK_INT, N=2 */ +#define ATIM_CCMR_ICF_FCKINT4 (2) /* 0010: fSAMPLING=fCK_INT, N=4 */ +#define ATIM_CCMR_ICF_FCKINT8 (3) /* 0011: fSAMPLING=fCK_INT, N=8 */ +#define ATIM_CCMR_ICF_FDTSd26 (4) /* 0100: fSAMPLING=fDTS/2, N=6 */ +#define ATIM_CCMR_ICF_FDTSd28 (5) /* 0101: fSAMPLING=fDTS/2, N=8 */ +#define ATIM_CCMR_ICF_FDTSd46 (6) /* 0110: fSAMPLING=fDTS/4, N=6 */ +#define ATIM_CCMR_ICF_FDTSd48 (7) /* 0111: fSAMPLING=fDTS/4, N=8 */ +#define ATIM_CCMR_ICF_FDTSd86 (8) /* 1000: fSAMPLING=fDTS/8, N=6 */ +#define ATIM_CCMR_ICF_FDTSd88 (9) /* 1001: fSAMPLING=fDTS/8, N=8 */ +#define ATIM_CCMR_ICF_FDTSd165 (10) /* 1010: fSAMPLING=fDTS/16, N=5 */ +#define ATIM_CCMR_ICF_FDTSd166 (11) /* 1011: fSAMPLING=fDTS/16, N=6 */ +#define ATIM_CCMR_ICF_FDTSd168 (12) /* 1100: fSAMPLING=fDTS/16, N=8 */ +#define ATIM_CCMR_ICF_FDTSd325 (13) /* 1101: fSAMPLING=fDTS/32, N=5 */ +#define ATIM_CCMR_ICF_FDTSd326 (14) /* 1110: fSAMPLING=fDTS/32, N=6 */ +#define ATIM_CCMR_ICF_FDTSd328 (15) /* 1111: fSAMPLING=fDTS/32, N=8 */ + +/* Capture/compare mode register 2 - Output Compare mode */ + +#define ATIM_CCMR2_CC3S_SHIFT (0) /* Bits 1-0: Capture/Compare 3 Selection */ +#define ATIM_CCMR2_CC3S_MASK (3 << ATIM_CCMR2_CC3S_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_OC3FE (1 << 2) /* Bit 2: Output Compare 3 Fast enable */ +#define ATIM_CCMR2_OC3PE (1 << 3) /* Bit 3: Output Compare 3 Preload enable */ +#define ATIM_CCMR2_OC3M_SHIFT (4) /* Bits 6-4: Output Compare 3 Mode */ +#define ATIM_CCMR2_OC3M_MASK (7 << ATIM_CCMR2_OC3M_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_OC3CE (1 << 7) /* Bit 7: Output Compare 3 Clear Enable */ +#define ATIM_CCMR2_CC4S_SHIFT (8) /* Bits 9-8: Capture/Compare 4 Selection */ +#define ATIM_CCMR2_CC4S_MASK (3 << ATIM_CCMR2_CC4S_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_OC4FE (1 << 10) /* Bit 10: Output Compare 4 Fast enable */ +#define ATIM_CCMR2_OC4PE (1 << 11) /* Bit 11: Output Compare 4 Preload enable */ +#define ATIM_CCMR2_OC4M_SHIFT (12) /* Bits 14-12: Output Compare 4 Mode */ +#define ATIM_CCMR2_OC4M_MASK (7 << ATIM_CCMR2_OC4M_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_OC4CE (1 << 15) /* Bit 15: Output Compare 4 Clear Enable */ +#define ATIM_CCMR2_OC3M (1 << 16) /* Bit 16: Output Compare 3 mode - bit 3 */ +#define ATIM_CCMR2_OC4M (1 << 24) /* Bit 24: Output Compare 4 mode - bit 3 */ + +/* Capture/compare mode register 2 - Input Capture Mode */ + +/* Bits 1-0: + * (same as output compare mode) + */ +#define ATIM_CCMR2_IC3PSC_SHIFT (2) /* Bits 3-2: Input Capture 3 Prescaler */ +#define ATIM_CCMR1_IC3PSC_MASK (3 << ATIM_CCMR2_IC3PSC_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_IC3F_SHIFT (4) /* Bits 7-4: Input Capture 3 Filter */ +#define ATIM_CCMR2_IC3F_MASK (0x0f << ATIM_CCMR2_IC3F_SHIFT) + /* (See common (unshifted) bit field definitions above) */ + /* Bits 9:8 (same as output compare mode) */ +#define ATIM_CCMR2_IC4PSC_SHIFT (10) /* Bits 11:10: Input Capture 4 Prescaler */ +#define ATIM_CCMR2_IC4PSC_MASK (3 << ATIM_CCMR2_IC4PSC_SHIFT) + /* (See common (unshifted) bit field definitions above) */ +#define ATIM_CCMR2_IC4F_SHIFT (12) /* Bits 15-12: Input Capture 4 Filter */ +#define ATIM_CCMR2_IC4F_MASK (0x0f << ATIM_CCMR2_IC4F_SHIFT) + /* (See common (unshifted) bit field definitions above) */ + +/* Capture/compare mode register 3 -- Output compare mode */ + +#define ATIM_CCMR3_OC5FE (1 << 2) /* Bit 2: Output Compare 5 Fast enable */ +#define ATIM_CCMR3_OC5PE (1 << 3) /* Bit 3: Output Compare 5 Preload enable */ +#define ATIM_CCMR3_OC5M_SHIFT (4) /* Bits 6-4: Output Compare 5 Mode */ +#define ATIM_CCMR3_OC5M_MASK (7 << ATIM_CCMR3_OC5M_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR3_OC5CE (1 << 7) /* Bit 7: Output Compare 5 Clear Enable */ +#define ATIM_CCMR3_OC6FE (1 << 10) /* Bit 10: Output Compare 6 Fast enable */ +#define ATIM_CCMR3_OC6PE (1 << 11) /* Bit 11: Output Compare 6 Preload enable */ +#define ATIM_CCMR3_OC6M_SHIFT (12) /* Bits 14-12: Output Compare 7 Mode */ +#define ATIM_CCMR3_OC6M_MASK (7 << ATIM_CCMR3_OC6M_SHIFT) + /* (See common (unshifted) bit field definitions below) */ +#define ATIM_CCMR3_OC6CE (1 << 15) /* Bit 15: Output Compare 7 Clear Enable */ +#define ATIM_CCMR3_OC5M (1 << 16) /* Bit 16: Output Compare 5 mode - bit 3 */ +#define ATIM_CCMR3_OC6M (1 << 24) /* Bit 24: Output Compare 6 mode - bit 3 */ + +/* Capture/compare enable register */ + +#define ATIM_CCER_CC1E (1 << 0) /* Bit 0: Capture/Compare 1 output enable */ +#define ATIM_CCER_CC1P (1 << 1) /* Bit 1: Capture/Compare 1 output Polarity */ +#define ATIM_CCER_CC1NE (1 << 2) /* Bit 2: Capture/Compare 1 Complementary output enable */ +#define ATIM_CCER_CC1NP (1 << 3) /* Bit 3: Capture/Compare 1 Complementary output polarity */ +#define ATIM_CCER_CC2E (1 << 4) /* Bit 4: Capture/Compare 2 output enable */ +#define ATIM_CCER_CC2P (1 << 5) /* Bit 5: Capture/Compare 2 output Polarity */ +#define ATIM_CCER_CC2NE (1 << 6) /* Bit 6: Capture/Compare 2 Complementary output enable */ +#define ATIM_CCER_CC2NP (1 << 7) /* Bit 7: Capture/Compare 2 Complementary output polarity */ +#define ATIM_CCER_CC3E (1 << 8) /* Bit 8: Capture/Compare 3 output enable */ +#define ATIM_CCER_CC3P (1 << 9) /* Bit 9: Capture/Compare 3 output Polarity */ +#define ATIM_CCER_CC3NE (1 << 10) /* Bit 10: Capture/Compare 3 Complementary output enable */ +#define ATIM_CCER_CC3NP (1 << 11) /* Bit 11: Capture/Compare 3 Complementary output polarity */ +#define ATIM_CCER_CC4E (1 << 12) /* Bit 12: Capture/Compare 4 output enable */ +#define ATIM_CCER_CC4P (1 << 13) /* Bit 13: Capture/Compare 4 output Polarity */ +#define ATIM_CCER_CC4NP (1 << 15) /* Bit 15: Capture/Compare 4 Complementary output polarity */ +#define ATIM_CCER_CC5E (1 << 16) /* Bit 16: Capture/Compare 5 output enable */ +#define ATIM_CCER_CC5P (1 << 17) /* Bit 17: Capture/Compare 5 output Polarity */ +#define ATIM_CCER_CC6E (1 << 20) /* Bit 20: Capture/Compare 6 output enable */ +#define ATIM_CCER_CC6P (1 << 21) /* Bit 21: Capture/Compare 6 output Polarity */ +#define ATIM_CCER_CCXBASE(ch) (ch << 2) /* Each channel uses 4-bits */ + +/* 16-bit counter register */ + +#define ATIM_CNT_SHIFT (0) /* Bits 0-15: Timer counter value */ +#define ATIM_CNT_MASK (0xffff << ATIM_CNT_SHIFT) +#define ATIM_CCER_UIFCPY (1 << 31) /* Bit 31: UIF copy */ + +/* Repetition counter register */ + +#define ATIM_RCR_REP_SHIFT (0) /* Bits 0-15: Repetition Counter Value */ +#define ATIM_RCR_REP_MASK (0xffff << ATIM_RCR_REP_SHIFT) +#define ATIM_RCR_REP_MAX 32768 /* REVISIT */ + +/* Capture/compare registers (CCR) */ + +#define ATIM_CCR5_GC5C1 (1 << 29) /* Bit 29: Group Channel 5 and Channel 1 */ +#define ATIM_CCR5_GC5C2 (1 << 30) /* Bit 30: Group Channel 5 and Channel 2 */ +#define ATIM_CCR5_GC5C3 (1 << 31) /* Bit 31: Group Channel 5 and Channel 3 */ + +#define ATIM_CCR_MASK (0xffff) + +/* Break and dead-time register */ + +#define ATIM_BDTR_DTG_SHIFT (0) /* Bits 7:0 [7:0]: Dead-Time Generator set-up */ +#define ATIM_BDTR_DTG_MASK (0xff << ATIM_BDTR_DTG_SHIFT) +#define ATIM_BDTR_LOCK_SHIFT (8) /* Bits 9:8 [1:0]: Lock Configuration */ +#define ATIM_BDTR_LOCK_MASK (3 << ATIM_BDTR_LOCK_SHIFT) +# define ATIM_BDTR_LOCKOFF (0 << ATIM_BDTR_LOCK_SHIFT) /* 00: LOCK OFF - No bit is write protected */ +# define ATIM_BDTR_LOCK1 (1 << ATIM_BDTR_LOCK_SHIFT) /* 01: LOCK Level 1 protection */ +# define ATIM_BDTR_LOCK2 (2 << ATIM_BDTR_LOCK_SHIFT) /* 10: LOCK Level 2 protection */ +# define ATIM_BDTR_LOCK3 (3 << ATIM_BDTR_LOCK_SHIFT) /* 11: LOCK Level 3 protection */ + +#define ATIM_BDTR_OSSI (1 << 10) /* Bit 10: Off-State Selection for Idle mode */ +#define ATIM_BDTR_OSSR (1 << 11) /* Bit 11: Off-State Selection for Run mode */ +#define ATIM_BDTR_BKE (1 << 12) /* Bit 12: Break enable */ +#define ATIM_BDTR_BKP (1 << 13) /* Bit 13: Break Polarity */ +#define ATIM_BDTR_AOE (1 << 14) /* Bit 14: Automatic Output enable */ +#define ATIM_BDTR_MOE (1 << 15) /* Bit 15: Main Output enable */ +#define ATIM_BDTR_BKF_SHIFT (16) /* Bits 16-19: Break filter */ +#define ATIM_BDTR_BKF_MASK (15 << ATIM_BDTR_BKF_SHIFT) +# define ATIM_BDTR_BKF_NOFILT (0 << ATIM_BDTR_BKF_SHIFT) /* 0000: No filter, BRK acts asynchronously */ +# define ATIM_BDTR_BKF_FCKINT2 (1 << ATIM_BDTR_BKF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */ +# define ATIM_BDTR_BKF_FCKINT4 (2 << ATIM_BDTR_BKF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */ +# define ATIM_BDTR_BKF_FCKINT8 (3 << ATIM_BDTR_BKF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */ +# define ATIM_BDTR_BKF_FDTSd26 (4 << ATIM_BDTR_BKF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */ +# define ATIM_BDTR_BKF_FDTSd28 (5 << ATIM_BDTR_BKF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */ +# define ATIM_BDTR_BKF_FDTSd36 (6 << ATIM_BDTR_BKF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */ +# define ATIM_BDTR_BKF_FDTSd38 (7 << ATIM_BDTR_BKF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */ +# define ATIM_BDTR_BKF_FDTSd86 (8 << ATIM_BDTR_BKF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */ +# define ATIM_BDTR_BKF_FDTSd88 (9 << ATIM_BDTR_BKF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */ +# define ATIM_BDTR_BKF_FDTSd165 (10 << ATIM_BDTR_BKF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */ +# define ATIM_BDTR_BKF_FDTSd166 (11 << ATIM_BDTR_BKF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */ +# define ATIM_BDTR_BKF_FDTSd168 (12 << ATIM_BDTR_BKF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */ +# define ATIM_BDTR_BKF_FDTSd325 (13 << ATIM_BDTR_BKF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */ +# define ATIM_BDTR_BKF_FDTSd326 (14 << ATIM_BDTR_BKF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */ +# define ATIM_BDTR_BKF_FDTSd328 (15 << ATIM_BDTR_BKF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */ + +#define ATIM_BDTR_BK2F_SHIFT (20) /* Bits 20-23: Break 2 filter */ +#define ATIM_BDTR_BK2F_MASK (15 << ATIM_BDTR_BK2F_SHIFT) +# define ATIM_BDTR_BK2F_NOFILT (0 << ATIM_BDTR_BK2F_SHIFT) /* 0000: No filter, BRK 2 acts asynchronously */ +# define ATIM_BDTR_BK2F_FCKINT2 (1 << ATIM_BDTR_BK2F_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */ +# define ATIM_BDTR_BK2F_FCKINT4 (2 << ATIM_BDTR_BK2F_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */ +# define ATIM_BDTR_BK2F_FCKINT8 (3 << ATIM_BDTR_BK2F_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */ +# define ATIM_BDTR_BK2F_FDTSd26 (4 << ATIM_BDTR_BK2F_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */ +# define ATIM_BDTR_BK2F_FDTSd28 (5 << ATIM_BDTR_BK2F_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */ +# define ATIM_BDTR_BK2F_FDTSd36 (6 << ATIM_BDTR_BK2F_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */ +# define ATIM_BDTR_BK2F_FDTSd38 (7 << ATIM_BDTR_BK2F_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */ +# define ATIM_BDTR_BK2F_FDTSd86 (8 << ATIM_BDTR_BK2F_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */ +# define ATIM_BDTR_BK2F_FDTSd88 (9 << ATIM_BDTR_BK2F_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */ +# define ATIM_BDTR_BK2F_FDTSd165 (10 << ATIM_BDTR_BK2F_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */ +# define ATIM_BDTR_BK2F_FDTSd166 (11 << ATIM_BDTR_BK2F_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */ +# define ATIM_BDTR_BK2F_FDTSd168 (12 << ATIM_BDTR_BK2F_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */ +# define ATIM_BDTR_BK2F_FDTSd325 (13 << ATIM_BDTR_BK2F_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */ +# define ATIM_BDTR_BK2F_FDTSd326 (14 << ATIM_BDTR_BK2F_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */ +# define ATIM_BDTR_BK2F_FDTSd328 (15 << ATIM_BDTR_BK2F_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */ + +#define ATIM_BDTR_BK2E (1 << 24) /* Bit 24: Break 2 enable */ +#define ATIM_BDTR_BK2P (1 << 1525 /* Bit 25:Break 2 polarity */ + +/* DMA control register */ + +#define ATIM_DCR_DBA_SHIFT (0) /* Bits 4-0: DMA Base Address */ +#define ATIM_DCR_DBA_MASK (0x1f << ATIM_DCR_DBA_SHIFT) +#define ATIM_DCR_DBL_SHIFT (8) /* Bits 12-8: DMA Burst Length */ +#define ATIM_DCR_DBL_MASK (0x1f << ATIM_DCR_DBL_SHIFT) +# define ATIM_DCR_DBL(n) (((n)-1) << ATIM_DCR_DBL_SHIFT) /* n transfers, n = 1..18 */ + +/* Control register 1 (TIM2-5) */ + +#define GTIM_CR1_CEN (1 << 0) /* Bit 0: Counter enable */ +#define GTIM_CR1_UDIS (1 << 1) /* Bit 1: Update Disable */ +#define GTIM_CR1_URS (1 << 2) /* Bit 2: Update Request Source */ +#define GTIM_CR1_OPM (1 << 3) /* Bit 3: One Pulse Mode (TIM2-5, 9, and 12 only) */ +#define GTIM_CR1_DIR (1 << 4) /* Bit 4: Direction (TIM2-5 only) */ +#define GTIM_CR1_CMS_SHIFT (5) /* Bits 6-5: Center-aligned Mode Selection (TIM2-5 only) */ +#define GTIM_CR1_CMS_MASK (3 << GTIM_CR1_CMS_SHIFT) +# define GTIM_CR1_EDGE (0 << GTIM_CR1_CMS_SHIFT) /* 00: Edge-aligned mode. */ +# define GTIM_CR1_CENTER1 (1 << GTIM_CR1_CMS_SHIFT) /* 01: Center-aligned mode 1 */ +# define GTIM_CR1_CENTER2 (2 << GTIM_CR1_CMS_SHIFT) /* 10: Center-aligned mode 2 */ +# define GTIM_CR1_CENTER3 (3 << GTIM_CR1_CMS_SHIFT) /* 11: Center-aligned mode 3 */ + +#define GTIM_CR1_ARPE (1 << 7) /* Bit 7: Auto-Reload Preload enable */ +#define GTIM_CR1_CKD_SHIFT (8) /* Bits 9-8: Clock Division */ +#define GTIM_CR1_CKD_MASK (3 << GTIM_CR1_CKD_SHIFT) +# define GTIM_CR1_TCKINT (0 << GTIM_CR1_CKD_SHIFT) /* 00: tDTS = tCK_INT */ +# define GTIM_CR1_2TCKINT (1 << GTIM_CR1_CKD_SHIFT) /* 01: tDTS = 2 x tCK_INT */ +# define GTIM_CR1_4TCKINT (2 << GTIM_CR1_CKD_SHIFT) /* 10: tDTS = 4 x tCK_INT */ + +#define GTIM_CR1_UIFREMAP (1 << 11) /* Bit 11: UIF status bit remapping */ + +/* Control register 2 (TIM2-5, and TIM15-17 only) */ + +#define GTIM_CR2_CCPC (1 << 0) /* Bit 0: Capture/compare preloaded control (TIM15-17 only) */ +#define GTIM_CR2_CCUS (1 << 2) /* Bit 2: Capture/compare control update selection (TIM15-17 only) */ +#define GTIM_CR2_CCDS (1 << 3) /* Bit 3: Capture/Compare DMA Selection (TIM2-5,1,&16 only) */ +#define GTIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection (not TIM16) */ +#define GTIM_CR2_MMS_MASK (7 << GTIM_CR2_MMS_SHIFT) +# define GTIM_CR2_MMS_RESET (0 << GTIM_CR2_MMS_SHIFT) /* 000: Reset */ +# define GTIM_CR2_MMS_ENABLE (1 << GTIM_CR2_MMS_SHIFT) /* 001: Enable */ +# define GTIM_CR2_MMS_UPDATE (2 << GTIM_CR2_MMS_SHIFT) /* 010: Update */ +# define GTIM_CR2_MMS_COMPP (3 << GTIM_CR2_MMS_SHIFT) /* 011: Compare Pulse */ +# define GTIM_CR2_MMS_OC1REF (4 << GTIM_CR2_MMS_SHIFT) /* 100: Compare - OC1REF signal is used as trigger output (TRGO) */ +# define GTIM_CR2_MMS_OC2REF (5 << GTIM_CR2_MMS_SHIFT) /* 101: Compare - OC2REF signal is used as trigger output (TRGO) */ +# define GTIM_CR2_MMS_OC3REF (6 << GTIM_CR2_MMS_SHIFT) /* 110: Compare - OC3REF signal is used as trigger output (TRGO, TIM2-5 and TIM15 only) */ +# define GTIM_CR2_MMS_OC4REF (7 << GTIM_CR2_MMS_SHIFT) /* 111: Compare - OC4REF signal is used as trigger output (TRGO, TIM2-5 and TIM15 only) */ + +#define GTIM_CR2_TI1S (1 << 7) /* Bit 7: TI1 Selection (not TIM16) */ +#define GTIM_CR2_OIS1 (1 << 8) /* Bit 8: COutput Idle state 1 (OC1 output) (TIM15-17 only) */ +#define GTIM_CR2_OIS1N (1 << 9) /* Bit 9: Output Idle state 1 (OC1N output) (TIM15-17 only) */ +#define GTIM_CR2_OIS2 (1 << 10) /* Bit 10: Output idle state 2 (OC2 output) (TIM15 only) */ + +/* Slave mode control register (TIM2-5 and TIM15 only) */ + +#define GTIM_SMCR_SMS_SHIFT (0) /* Bits 2-0: Slave Mode Selection */ +#define GTIM_SMCR_SMS_MASK (7 << GTIM_SMCR_SMS_SHIFT) +# define GTIM_SMCR_DISAB (0 << GTIM_SMCR_SMS_SHIFT) /* 000: Slave mode disabled */ +# define GTIM_SMCR_ENCMD1 (1 << GTIM_SMCR_SMS_SHIFT) /* 001: Encoder mode 1 */ +# define GTIM_SMCR_ENCMD2 (2 << GTIM_SMCR_SMS_SHIFT) /* 010: Encoder mode 2 */ +# define GTIM_SMCR_ENCMD3 (3 << GTIM_SMCR_SMS_SHIFT) /* 011: Encoder mode 3 */ +# define GTIM_SMCR_RESET (4 << GTIM_SMCR_SMS_SHIFT) /* 100: Reset Mode */ +# define GTIM_SMCR_GATED (5 << GTIM_SMCR_SMS_SHIFT) /* 101: Gated Mode */ +# define GTIM_SMCR_TRIGGER (6 << GTIM_SMCR_SMS_SHIFT) /* 110: Trigger Mode */ +# define GTIM_SMCR_EXTCLK1 (7 << GTIM_SMCR_SMS_SHIFT) /* 111: External Clock Mode 1 */ + +#define GTIM_SMCR_TS_SHIFT (4) /* Bits 6-4: Trigger Selection */ +#define GTIM_SMCR_TS_MASK (7 << GTIM_SMCR_TS_SHIFT) +# define GTIM_SMCR_ITR0 (0 << GTIM_SMCR_TS_SHIFT) /* 000: Internal Trigger 0 (ITR0). TIM1 */ +# define GTIM_SMCR_ITR1 (1 << GTIM_SMCR_TS_SHIFT) /* 001: Internal Trigger 1 (ITR1). TIM2 */ +# define GTIM_SMCR_ITR2 (2 << GTIM_SMCR_TS_SHIFT) /* 010: Internal Trigger 2 (ITR2). TIM3 */ +# define GTIM_SMCR_ITR3 (3 << GTIM_SMCR_TS_SHIFT) /* 011: Internal Trigger 3 (ITR3). TIM4 */ +# define GTIM_SMCR_TI1FED (4 << GTIM_SMCR_TS_SHIFT) /* 100: TI1 Edge Detector (TI1F_ED) */ +# define GTIM_SMCR_TI1FP1 (5 << GTIM_SMCR_TS_SHIFT) /* 101: Filtered Timer Input 1 (TI1FP1) */ +# define GTIM_SMCR_TI2FP2 (6 << GTIM_SMCR_TS_SHIFT) /* 110: Filtered Timer Input 2 (TI2FP2) */ +# define GTIM_SMCR_ETRF (7 << GTIM_SMCR_TS_SHIFT) /* 111: External Trigger input (ETRF) */ + +#define GTIM_SMCR_MSM (1 << 7) /* Bit 7: Master/Slave mode */ +#define GTIM_SMCR_ETF_SHIFT (8) /* Bits 11-8: External Trigger Filter (not TIM15) */ +#define GTIM_SMCR_ETF_MASK (0x0f << GTIM_SMCR_ETF_SHIFT) +# define GTIM_SMCR_NOFILT (0 << GTIM_SMCR_ETF_SHIFT) /* 0000: No filter, sampling is done at fDTS */ +# define GTIM_SMCR_FCKINT2 (1 << GTIM_SMCR_ETF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */ +# define GTIM_SMCR_FCKINT4 (2 << GTIM_SMCR_ETF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */ +# define GTIM_SMCR_FCKINT8 (3 << GTIM_SMCR_ETF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */ +# define GTIM_SMCR_FDTSd26 (4 << GTIM_SMCR_ETF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */ +# define GTIM_SMCR_FDTSd28 (5 << GTIM_SMCR_ETF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */ +# define GTIM_SMCR_FDTSd36 (6 << GTIM_SMCR_ETF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */ +# define GTIM_SMCR_FDTSd38 (7 << GTIM_SMCR_ETF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */ +# define GTIM_SMCR_FDTSd86 (8 << GTIM_SMCR_ETF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */ +# define GTIM_SMCR_FDTSd88 (9 << GTIM_SMCR_ETF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */ +# define GTIM_SMCR_FDTSd165 (10 << GTIM_SMCR_ETF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */ +# define GTIM_SMCR_FDTSd166 (11 << GTIM_SMCR_ETF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */ +# define GTIM_SMCR_FDTSd168 (12 << GTIM_SMCR_ETF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */ +# define GTIM_SMCR_FDTSd325 (13 << GTIM_SMCR_ETF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */ +# define GTIM_SMCR_FDTSd326 (14 << GTIM_SMCR_ETF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */ +# define GTIM_SMCR_FDTSd328 (15 << GTIM_SMCR_ETF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */ + +#define GTIM_SMCR_ETPS_SHIFT (12) /* Bits 13-12: External Trigger Prescaler (not TIM15) */ +#define GTIM_SMCR_ETPS_MASK (3 << GTIM_SMCR_ETPS_SHIFT) +# define GTIM_SMCR_PSCOFF (0 << GTIM_SMCR_ETPS_SHIFT) /* 00: Prescaler OFF */ +# define GTIM_SMCR_ETRPd2 (1 << GTIM_SMCR_ETPS_SHIFT) /* 01: ETRP frequency divided by 2 */ +# define GTIM_SMCR_ETRPd4 (2 << GTIM_SMCR_ETPS_SHIFT) /* 10: ETRP frequency divided by 4 */ +# define GTIM_SMCR_ETRPd8 (3 << GTIM_SMCR_ETPS_SHIFT) /* 11: ETRP frequency divided by 8 */ + +#define GTIM_SMCR_ECE (1 << 14) /* Bit 14: External Clock enable */ +#define GTIM_SMCR_ETP (1 << 15) /* Bit 15: External Trigger Polarity */ +#define GTIM_SMCR_SMS (1 << 16) /* Bit 16: Slave mode selection - bit 3 */ + +/* DMA/Interrupt enable register (TIM2-5) */ + +#define GTIM_DIER_UIE (1 << 0) /* Bit 0: Update interrupt enable */ +#define GTIM_DIER_CC1IE (1 << 1) /* Bit 1: Capture/Compare 1 interrupt enable */ +#define GTIM_DIER_CC2IE (1 << 2) /* Bit 2: Capture/Compare 2 interrupt enable (TIM2-5,9,12,&15 only) */ +#define GTIM_DIER_CC3IE (1 << 3) /* Bit 3: Capture/Compare 3 interrupt enable (TIM2-5 only) */ +#define GTIM_DIER_CC4IE (1 << 4) /* Bit 4: Capture/Compare 4 interrupt enable (TIM2-5 only) */ +#define GTIM_DIER_COMIE (1 << 5) /* Bit 5: COM interrupt enable (TIM15-17 only) */ +#define GTIM_DIER_TIE (1 << 6) /* Bit 6: Trigger interrupt enable (TIM2-5,9,&12 only) */ +#define GTIM_DIER_BIE (1 << 7) /* Bit 7: Break interrupt enable (TIM15-17 only) */ +#define GTIM_DIER_UDE (1 << 8) /* Bit 8: Update DMA request enable (TIM2-5&15-17 only) */ +#define GTIM_DIER_CC1DE (1 << 9) /* Bit 9: Capture/Compare 1 DMA request enable (TIM2-5&15-17 only) */ +#define GTIM_DIER_CC2DE (1 << 10) /* Bit 10: Capture/Compare 2 DMA request enable (TIM2-5&15 only) */ +#define GTIM_DIER_CC3DE (1 << 11) /* Bit 11: Capture/Compare 3 DMA request enable (TIM2-5 only) */ +#define GTIM_DIER_CC4DE (1 << 12) /* Bit 12: Capture/Compare 4 DMA request enable (TIM2-5 only) */ +#define GTIM_DIER_COMDE (1 << 13) /* Bit 13: COM DMA request enable (TIM15-17 only) */ +#define GTIM_DIER_TDE (1 << 14) /* Bit 14: Trigger DMA request enable (TIM2-5&15-17 only) */ + +/* Status register */ + +#define GTIM_SR_UIF (1 << 0) /* Bit 0: Update interrupt flag */ +#define GTIM_SR_CC1IF (1 << 1) /* Bit 1: Capture/compare 1 interrupt flag */ +#define GTIM_SR_CC2IF (1 << 2) /* Bit 2: Capture/Compare 2 interrupt flag (TIM2-5,9,12,&15 only) */ +#define GTIM_SR_CC3IF (1 << 3) /* Bit 3: Capture/Compare 3 interrupt flag (TIM2-5 only) */ +#define GTIM_SR_CC4IF (1 << 4) /* Bit 4: Capture/Compare 4 interrupt flag (TIM2-5 only) */ +#define GTIM_SR_COMIF (1 << 5) /* Bit 5: COM interrupt flag (TIM15-17 only) */ +#define GTIM_SR_TIF (1 << 6) /* Bit 6: Trigger interrupt Flag (TIM2-5,9,12&15-17 only) */ +#define GTIM_SR_BIF (1 << 7) /* Bit 7: Break interrupt flag (TIM15-17 only) */ +#define GTIM_SR_CC1OF (1 << 9) /* Bit 9: Capture/Compare 1 Overcapture flag */ +#define GTIM_SR_CC2OF (1 << 10) /* Bit 10: Capture/Compare 2 Overcapture flag (TIM2-5,9,12&15 only) */ +#define GTIM_SR_CC3OF (1 << 11) /* Bit 11: Capture/Compare 3 Overcapture flag (TIM2-5 only) */ +#define GTIM_SR_CC4OF (1 << 12) /* Bit 12: Capture/Compare 4 Overcapture flag (TIM2-5 only) */ + +/* Event generation register (TIM2-5, TIM15-17) */ + +#define GTIM_EGR_UG (1 << 0) /* Bit 0: Update generation */ +#define GTIM_EGR_CC1G (1 << 1) /* Bit 1: Capture/compare 1 generation */ +#define GTIM_EGR_CC2G (1 << 2) /* Bit 2: Capture/compare 2 generation (TIM2-5,15 only) */ +#define GTIM_EGR_CC3G (1 << 3) /* Bit 3: Capture/compare 3 generation (TIM2-5 only) */ +#define GTIM_EGR_CC4G (1 << 4) /* Bit 4: Capture/compare 4 generation (TIM2-5 only) */ +#define GTIM_EGR_COMIG (1 << 5) /* Bit 5: Capture/Compare control update generation (TIM15-17 only) */ +#define GTIM_EGR_TG (1 << 6) /* Bit 6: Trigger generation (TIM2-5,16-17 only) */ +#define GTIM_EGR_BG (1 << 7) /* Bit 7: Break generation (TIM15-17 only) */ + +/* Capture/compare mode register 1 - Output compare mode (TIM2-5) */ + +#define GTIM_CCMR1_CC1S_SHIFT (0) /* Bits 1-0: Capture/Compare 1 Selection */ +#define GTIM_CCMR1_CC1S_MASK (3 << GTIM_CCMR1_CC1S_SHIFT) + /* (See common CCMR Capture/Compare Selection definitions below) */ +#define GTIM_CCMR1_OC1FE (1 << 2) /* Bit 2: Output Compare 1 Fast enable */ +#define GTIM_CCMR1_OC1PE (1 << 3) /* Bit 3: Output Compare 1 Preload enable */ +#define GTIM_CCMR1_OC1M_SHIFT (4) /* Bits 6-4: Output Compare 1 Mode */ +#define GTIM_CCMR1_OC1M_MASK (7 << GTIM_CCMR1_OC1M_SHIFT) + /* (See common CCMR Output Compare Mode definitions below) */ +#define GTIM_CCMR1_OC1CE (1 << 7) /* Bit 7: Output Compare 1Clear Enable */ +#define GTIM_CCMR1_CC2S_SHIFT (8) /* Bits 9-8: Capture/Compare 2 Selection */ +#define GTIM_CCMR1_CC2S_MASK (3 << GTIM_CCMR1_CC2S_SHIFT) + /* (See common CCMR Capture/Compare Selection definitions below) */ +#define GTIM_CCMR1_OC2FE (1 << 10) /* Bit 10: Output Compare 2 Fast enable */ +#define GTIM_CCMR1_OC2PE (1 << 11) /* Bit 11: Output Compare 2 Preload enable */ +#define GTIM_CCMR1_OC2M_SHIFT (12) /* Bits 14-12: Output Compare 2 Mode */ +#define GTIM_CCMR1_OC2M_MASK (7 << GTIM_CCMR1_OC2M_SHIFT) + /* (See common CCMR Output Compare Mode definitions below) */ +#define GTIM_CCMR1_OC2CE (1 << 15) /* Bit 15: Output Compare 2 Clear Enable */ +#define GTIM_CCMR1_OC1M (1 << 16) /* Bit 16: Output Compare 1 mode - bit 3 */ +#define GTIM_CCMR1_OC2M (1 << 24) /* Bit 24: Output Compare 2 mode - bit 3 */ + +/* Common CCMR (unshifted) Capture/Compare Selection bit-field definitions */ + +#define GTIM_CCMR_CCS_CCOUT (0) /* 00: CCx channel output */ +#define GTIM_CCMR_CCS_CCIN1 (1) /* 01: CCx channel input, ICx is TIx */ +#define GTIM_CCMR_CCS_CCIN2 (2) /* 10: CCx channel input, ICx is TIy */ +#define GTIM_CCMR_CCS_CCINTRC (3) /* 11: CCx channel input, ICx is TRC */ + +/* Common CCMR (unshifted) Compare Mode bit field definitions */ + +#define GTIM_CCMR_MODE_FRZN (0) /* 000: Frozen */ +#define GTIM_CCMR_MODE_CHACT (1) /* 001: Channel x active on match */ +#define GTIM_CCMR_MODE_CHINACT (2) /* 010: Channel x inactive on match */ +#define GTIM_CCMR_MODE_OCREFTOG (3) /* 011: OCxREF toggle ATIM_CNT=ATIM_CCRx */ +#define GTIM_CCMR_MODE_OCREFLO (4) /* 100: OCxREF forced low */ +#define GTIM_CCMR_MODE_OCREFHI (5) /* 101: OCxREF forced high */ +#define GTIM_CCMR_MODE_PWM1 (6) /* 110: PWM mode 1 */ +#define GTIM_CCMR_MODE_PWM2 (7) /* 111: PWM mode 2 */ + +/* Capture/compare mode register 1 - Input capture mode + * (TIM2-5 and TIM9-14) + */ + +/* Bits 1-0 + * (Same as Output Compare Mode) + */ +#define GTIM_CCMR1_IC1PSC_SHIFT (2) /* Bits 3-2: Input Capture 1 Prescaler */ +#define GTIM_CCMR1_IC1PSC_MASK (3 << GTIM_CCMR1_IC1PSC_SHIFT) + /* (See common CCMR Input Capture Prescaler definitions below) */ +#define GTIM_CCMR1_IC1F_SHIFT (4) /* Bits 7-4: Input Capture 1 Filter */ +#define GTIM_CCMR1_IC1F_MASK (0x0f << GTIM_CCMR1_IC1F_SHIFT) + /* (See common CCMR Input Capture Filter definitions below) */ + /* Bits 9-8: (Same as Output Compare Mode) */ +#define GTIM_CCMR1_IC2PSC_SHIFT (10) /* Bits 11-10: Input Capture 2 Prescaler */ +#define GTIM_CCMR1_IC2PSC_MASK (3 << GTIM_CCMR1_IC2PSC_SHIFT) + /* (See common CCMR Input Capture Prescaler definitions below) */ +#define GTIM_CCMR1_IC2F_SHIFT (12) /* Bits 15-12: Input Capture 2 Filter */ +#define GTIM_CCMR1_IC2F_MASK (0x0f << GTIM_CCMR1_IC2F_SHIFT) + /* (See common CCMR Input Capture Filter definitions below) */ + +/* Common CCMR (unshifted) Input Capture Prescaler bit-field definitions */ + +#define GTIM_CCMR_ICPSC_NOPSC (0) /* 00: no prescaler, capture each edge */ +#define GTIM_CCMR_ICPSC_EVENTS2 (1) /* 01: capture once every 2 events */ +#define GTIM_CCMR_ICPSC_EVENTS4 (2) /* 10: capture once every 4 events */ +#define GTIM_CCMR_ICPSC_EVENTS8 (3) /* 11: capture once every 8 events */ + +/* Common CCMR (unshifted) Input Capture Filter bit-field definitions */ + +#define GTIM_CCMR_ICF_NOFILT (0) /* 0000: No filter, sampling at fDTS */ +#define GTIM_CCMR_ICF_FCKINT2 (1) /* 0001: fSAMPLING=fCK_INT, N=2 */ +#define GTIM_CCMR_ICF_FCKINT4 (2) /* 0010: fSAMPLING=fCK_INT, N=4 */ +#define GTIM_CCMR_ICF_FCKINT8 (3) /* 0011: fSAMPLING=fCK_INT, N=8 */ +#define GTIM_CCMR_ICF_FDTSd26 (4) /* 0100: fSAMPLING=fDTS/2, N=6 */ +#define GTIM_CCMR_ICF_FDTSd28 (5) /* 0101: fSAMPLING=fDTS/2, N=8 */ +#define GTIM_CCMR_ICF_FDTSd46 (6) /* 0110: fSAMPLING=fDTS/4, N=6 */ +#define GTIM_CCMR_ICF_FDTSd48 (7) /* 0111: fSAMPLING=fDTS/4, N=8 */ +#define GTIM_CCMR_ICF_FDTSd86 (8) /* 1000: fSAMPLING=fDTS/8, N=6 */ +#define GTIM_CCMR_ICF_FDTSd88 (9) /* 1001: fSAMPLING=fDTS/8, N=8 */ +#define GTIM_CCMR_ICF_FDTSd165 (10) /* 1010: fSAMPLING=fDTS/16, N=5 */ +#define GTIM_CCMR_ICF_FDTSd166 (11) /* 1011: fSAMPLING=fDTS/16, N=6 */ +#define GTIM_CCMR_ICF_FDTSd168 (12) /* 1100: fSAMPLING=fDTS/16, N=8 */ +#define GTIM_CCMR_ICF_FDTSd325 (13) /* 1101: fSAMPLING=fDTS/32, N=5 */ +#define GTIM_CCMR_ICF_FDTSd326 (14) /* 1110: fSAMPLING=fDTS/32, N=6 */ +#define GTIM_CCMR_ICF_FDTSd328 (15) /* 1111: fSAMPLING=fDTS/32, N=8 */ + +/* Capture/compare mode register 2 - Output Compare mode (TIM2-5 only) */ + +#define GTIM_CCMR2_CC3S_SHIFT (0) /* Bits 1-0: Capture/Compare 3 Selection */ +#define GTIM_CCMR2_CC3S_MASK (3 << GTIM_CCMR2_CC3S_SHIFT) + /* (See common CCMR Capture/Compare Selection definitions above) */ +#define GTIM_CCMR2_OC3FE (1 << 2) /* Bit 2: Output Compare 3 Fast enable */ +#define GTIM_CCMR2_OC3PE (1 << 3) /* Bit 3: Output Compare 3 Preload enable */ +#define GTIM_CCMR2_OC3M_SHIFT (4) /* Bits 6-4: Output Compare 3 Mode */ +#define GTIM_CCMR2_OC3M_MASK (7 << GTIM_CCMR2_OC3M_SHIFT) + /* (See common CCMR Output Compare Mode definitions above) */ +#define GTIM_CCMR2_OC3CE (1 << 7) /* Bit 7: Output Compare 3 Clear Enable */ +#define GTIM_CCMR2_CC4S_SHIFT (8) /* Bits 9-8: Capture/Compare 4 Selection */ +#define GTIM_CCMR2_CC4S_MASK (3 << GTIM_CCMR2_CC4S_SHIFT) + /* (See common CCMR Capture/Compare Selection definitions above) */ +#define GTIM_CCMR2_OC4FE (1 << 10) /* Bit 10: Output Compare 4 Fast enable */ +#define GTIM_CCMR2_OC4PE (1 << 11) /* Bit 11: Output Compare 4 Preload enable */ +#define GTIM_CCMR2_OC4M_SHIFT (12) /* Bits 14-12: Output Compare 4 Mode */ +#define GTIM_CCMR2_OC4M_MASK (7 << GTIM_CCMR2_OC4M_SHIFT) + /* (See common CCMR Output Compare Mode definitions above) */ +#define GTIM_CCMR2_OC4CE (1 << 15) /* Bit 15: Output Compare 4 Clear Enable */ + +/* Capture/compare mode register 2 - Input capture mode (TIM2-5 only) */ + +/* Bits 1-0 + * (Same as Output Compare Mode) + */ +#define GTIM_CCMR2_IC3PSC_SHIFT (2) /* Bits 3-2: Input Capture 3 Prescaler */ +#define GTIM_CCMR2_IC3PSC_MASK (3 << GTIM_CCMR2_IC3PSC_SHIFT) + /* (See common CCMR Input Capture Prescaler definitions below) */ +#define GTIM_CCMR2_IC3F_SHIFT (4) /* Bits 7-4: Input Capture 3 Filter */ +#define GTIM_CCMR2_IC3F_MASK (0x0f << GTIM_CCMR2_IC3F_SHIFT) + /* (See common CCMR Input Capture Filter definitions below) */ + /* Bits 9-8: (Same as Output Compare Mode) */ +#define GTIM_CCMR2_IC4PSC_SHIFT (10) /* Bits 11-10: Input Capture 4 Prescaler */ +#define GTIM_CCMR2_IC4PSC_MASK (3 << GTIM_CCMR2_IC4PSC_SHIFT) + /* (See common CCMR Input Capture Prescaler definitions below) */ +#define GTIM_CCMR2_IC4F_SHIFT (12) /* Bits 15-12: Input Capture 4 Filter */ +#define GTIM_CCMR2_IC4F_MASK (0x0f << GTIM_CCMR2_IC4F_SHIFT) + /* (See common CCMR Input Capture Filter definitions below) */ + +/* Capture/compare enable register (TIM1 and TIM8, TIM2-5) */ + +#define GTIM_CCER_CC1E (1 << 0) /* Bit 0: Capture/Compare 1 output enable */ +#define GTIM_CCER_CC1P (1 << 1) /* Bit 1: Capture/Compare 1 output polarity */ +#define GTIM_CCER_CC1NE (1 << 2) /* Bit 2: Capture/Compare 1 complementary output enable (TIM1 and TIM8 only) */ +#define GTIM_CCER_CC1NP (1 << 3) /* Bit 3: Capture/Compare 1 output Polarity (F2,F3,F4 and TIM15-17) */ +#define GTIM_CCER_CC2E (1 << 4) /* Bit 4: Capture/Compare 2 output enable (TIM2-5,9&12 only) */ +#define GTIM_CCER_CC2P (1 << 5) /* Bit 5: Capture/Compare 2 output polarity (TIM2-5,9&12 only) */ +#define GTIM_CCER_CC2NE (1 << 6) /* Bit 6: Capture/Compare 2 complementary output enable (TIM1 and TIM8 only) */ +#define GTIM_CCER_CC2NP (1 << 7) /* Bit 7: Capture/Compare 2 output Polarity (F2,F3,F4 and TIM2-5,9,12&15 only) */ +#define GTIM_CCER_CC3E (1 << 8) /* Bit 8: Capture/Compare 3 output enable (TIM2-5 only) */ +#define GTIM_CCER_CC3P (1 << 9) /* Bit 9: Capture/Compare 3 output Polarity (TIM2-5 only) */ +#define GTIM_CCER_CC3NE (1 << 10) /* Bit 10: Capture/Compare 3 complementary output enable (TIM1 and TIM8 only) */ +#define GTIM_CCER_CC3NP (1 << 11) /* Bit 11: Capture/Compare 3 output Polarity (F2,F4 and TIM2-5 only) */ +#define GTIM_CCER_CC4E (1 << 12) /* Bit 12: Capture/Compare 4 output enable (TIM2-5 only) */ +#define GTIM_CCER_CC4P (1 << 13) /* Bit 13: Capture/Compare 4 output Polarity (TIM2-5 only) */ +#define GTIM_CCER_CC4NP (1 << 15) /* Bit 15: Capture/Compare 4 output Polarity */ +#define GTIM_CCER_CCXBASE(ch) (ch << 2) /* Each channel uses 4-bits */ + +/* 16-bit counter register */ + +#define GTIM_CNT_SHIFT (0) /* Bits 0-15: Timer counter value */ +#define GTIM_CNT_MASK (0xffff << ATIM_CNT_SHIFT) + +/* Repetition counter (TIM15-17 only) */ + +#define GTIM_RCR_REP_SHIFT (0) /* Bits 0-7: Repetition Counter Value */ +#define GTIM_RCR_REP_MASK (0xff << GTIM_RCR_REP_SHIFT) + +#define GTIM_RCR_REP_MAX 128 + +/* Break and dead-time register (TIM15-17 only */ + +#define GTIM_BDTR_DTG_SHIFT (0) /* Bits 7:0 [7:0]: Dead-Time Generator set-up */ +#define GTIM_BDTR_DTG_MASK (0xff << GTIM_BDTR_DTG_SHIFT) +#define GTIM_BDTR_LOCK_SHIFT (8) /* Bits 9:8 [1:0]: Lock Configuration */ +#define GTIM_BDTR_LOCK_MASK (3 << GTIM_BDTR_LOCK_SHIFT) +# define GTIM_BDTR_LOCKOFF (0 << GTIM_BDTR_LOCK_SHIFT) /* 00: LOCK OFF - No bit is write protected */ +# define GTIM_BDTR_LOCK1 (1 << GTIM_BDTR_LOCK_SHIFT) /* 01: LOCK Level 1 protection */ +# define GTIM_BDTR_LOCK2 (2 << GTIM_BDTR_LOCK_SHIFT) /* 10: LOCK Level 2 protection */ +# define GTIM_BDTR_LOCK3 (3 << GTIM_BDTR_LOCK_SHIFT) /* 11: LOCK Level 3 protection */ + +#define GTIM_BDTR_OSSI (1 << 10) /* Bit 10: Off-State Selection for Idle mode */ +#define GTIM_BDTR_OSSR (1 << 11) /* Bit 11: Off-State Selection for Run mode */ +#define GTIM_BDTR_BKE (1 << 12) /* Bit 12: Break enable */ +#define GTIM_BDTR_BKP (1 << 13) /* Bit 13: Break Polarity */ +#define GTIM_BDTR_AOE (1 << 14) /* Bit 14: Automatic Output enable */ +#define GTIM_BDTR_MOE (1 << 15) /* Bit 15: Main Output enable */ +#define GTIM_BDTR_BKF_SHIFT (16) /* Bits 16-19: Break filter */ +#define GTIM_BDTR_BKF_MASK (15 << GTIM_BDTR_BKF_SHIFT) +# define GTIM_BDTR_BKF_NOFILT (0 << GTIM_BDTR_BKF_SHIFT) /* 0000: No filter, BRK acts asynchronously */ +# define GTIM_BDTR_BKF_FCKINT2 (1 << GTIM_BDTR_BKF_SHIFT) /* 0001: fSAMPLING=fCK_INT, N=2 */ +# define GTIM_BDTR_BKF_FCKINT4 (2 << GTIM_BDTR_BKF_SHIFT) /* 0010: fSAMPLING=fCK_INT, N=4 */ +# define GTIM_BDTR_BKF_FCKINT8 (3 << GTIM_BDTR_BKF_SHIFT) /* 0011: fSAMPLING=fCK_INT, N=8 */ +# define GTIM_BDTR_BKF_FDTSd26 (4 << GTIM_BDTR_BKF_SHIFT) /* 0100: fSAMPLING=fDTS/2, N=6 */ +# define GTIM_BDTR_BKF_FDTSd28 (5 << GTIM_BDTR_BKF_SHIFT) /* 0101: fSAMPLING=fDTS/2, N=8 */ +# define GTIM_BDTR_BKF_FDTSd36 (6 << GTIM_BDTR_BKF_SHIFT) /* 0110: fSAMPLING=fDTS/4, N=6 */ +# define GTIM_BDTR_BKF_FDTSd38 (7 << GTIM_BDTR_BKF_SHIFT) /* 0111: fSAMPLING=fDTS/4, N=8 */ +# define GTIM_BDTR_BKF_FDTSd86 (8 << GTIM_BDTR_BKF_SHIFT) /* 1000: fSAMPLING=fDTS/8, N=6 */ +# define GTIM_BDTR_BKF_FDTSd88 (9 << GTIM_BDTR_BKF_SHIFT) /* 1001: fSAMPLING=fDTS/8, N=8 */ +# define GTIM_BDTR_BKF_FDTSd165 (10 << GTIM_BDTR_BKF_SHIFT) /* 1010: fSAMPLING=fDTS/16, N=5 */ +# define GTIM_BDTR_BKF_FDTSd166 (11 << GTIM_BDTR_BKF_SHIFT) /* 1011: fSAMPLING=fDTS/16, N=6 */ +# define GTIM_BDTR_BKF_FDTSd168 (12 << GTIM_BDTR_BKF_SHIFT) /* 1100: fSAMPLING=fDTS/16, N=8 */ +# define GTIM_BDTR_BKF_FDTSd325 (13 << GTIM_BDTR_BKF_SHIFT) /* 1101: fSAMPLING=fDTS/32, N=5 */ +# define GTIM_BDTR_BKF_FDTSd326 (14 << GTIM_BDTR_BKF_SHIFT) /* 1110: fSAMPLING=fDTS/32, N=6 */ +# define GTIM_BDTR_BKF_FDTSd328 (15 << GTIM_BDTR_BKF_SHIFT) /* 1111: fSAMPLING=fDTS/32, N=8 */ + +/* DMA control register */ + +#define GTIM_DCR_DBA_SHIFT (0) /* Bits 4-0: DMA Base Address */ +#define GTIM_DCR_DBA_MASK (0x1f << GTIM_DCR_DBA_SHIFT) +#define GTIM_DCR_DBL_SHIFT (8) /* Bits 12-8: DMA Burst Length */ +#define GTIM_DCR_DBL_MASK (0x1f << GTIM_DCR_DBL_SHIFT) + +/* Control register 1 */ + +#define BTIM_CR1_CEN (1 << 0) /* Bit 0: Counter enable */ +#define BTIM_CR1_UDIS (1 << 1) /* Bit 1: Update Disable */ +#define BTIM_CR1_URS (1 << 2) /* Bit 2: Update Request Source */ +#define BTIM_CR1_OPM (1 << 3) /* Bit 3: One Pulse Mode */ +#define BTIM_CR1_ARPE (1 << 7) /* Bit 7: Auto-Reload Preload enable */ + +/* Control register 2 */ + +#define BTIM_CR2_MMS_SHIFT (4) /* Bits 6-4: Master Mode Selection */ +#define BTIM_CR2_MMS_MASK (7 << BTIM_CR2_MMS_SHIFT) +# define BTIM_CR2_RESET (0 << BTIM_CR2_MMS_SHIFT) /* 000: Reset */ +# define BTIM_CR2_ENAB (1 << BTIM_CR2_MMS_SHIFT) /* 001: Enable */ +# define BTIM_CR2_UPDT (2 << BTIM_CR2_MMS_SHIFT) /* 010: Update */ + +/* DMA/Interrupt enable register */ + +#define BTIM_DIER_UIE (1 << 0) /* Bit 0: Update interrupt enable */ +#define BTIM_DIER_UDE (1 << 8) /* Bit 8: Update DMA request enable */ + +/* Status register */ + +#define BTIM_SR_UIF (1 << 0) /* Bit 0: Update interrupt flag */ + +/* Event generation register */ + +#define BTIM_EGR_UG (1 << 0) /* Bit 0: Update generation */ + +#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_TIM_H */ diff --git a/arch/arm/src/stm32wl5/hardware/stm32wl5_uart.h b/arch/arm/src/stm32wl5/hardware/stm32wl5_uart.h new file mode 100644 index 0000000000..f0d5d20074 --- /dev/null +++ b/arch/arm/src/stm32wl5/hardware/stm32wl5_uart.h @@ -0,0 +1,331 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/hardware/stm32wl5_uart.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_UART_H +#define __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Register Offsets *********************************************************/ + +#define STM32WL5_USART_CR1_OFFSET 0x0000 /* Control register 1 */ +#define STM32WL5_USART_CR2_OFFSET 0x0004 /* Control register 2 */ +#define STM32WL5_USART_CR3_OFFSET 0x0008 /* Control register 3 */ +#define STM32WL5_USART_BRR_OFFSET 0x000c /* Baud Rate register */ +#define STM32WL5_USART_GTPR_OFFSET 0x0010 /* Guard time and prescaler register */ +#define STM32WL5_USART_RTOR_OFFSET 0x0014 /* Receiver timeout register */ +#define STM32WL5_USART_RQR_OFFSET 0x0018 /* Request register */ +#define STM32WL5_USART_ISR_OFFSET 0x001c /* Interrupt and status register */ +#define STM32WL5_USART_ICR_OFFSET 0x0020 /* Interrupt flag clear register */ +#define STM32WL5_USART_RDR_OFFSET 0x0024 /* Receive Data register */ +#define STM32WL5_USART_TDR_OFFSET 0x0028 /* Transmit Data register */ +#define STM32WL5_USART_PRESC_OFFSET 0x002c /* Prescaler */ + +/* Register Addresses *******************************************************/ + +#define STM32WL5_USART1_CR1 (STM32WL5_USART1_BASE+STM32WL5_USART_CR1_OFFSET) +#define STM32WL5_USART1_CR2 (STM32WL5_USART1_BASE+STM32WL5_USART_CR2_OFFSET) +#define STM32WL5_USART1_CR3 (STM32WL5_USART1_BASE+STM32WL5_USART_CR3_OFFSET) +#define STM32WL5_USART1_BRR (STM32WL5_USART1_BASE+STM32WL5_USART_BRR_OFFSET) +#define STM32WL5_USART1_GTPR (STM32WL5_USART1_BASE+STM32WL5_USART_GTPR_OFFSET) +#define STM32WL5_USART1_RTOR (STM32WL5_USART1_BASE+STM32WL5_USART_RTOR_OFFSET) +#define STM32WL5_USART1_RQR (STM32WL5_USART1_BASE+STM32WL5_USART_RQR_OFFSET) +#define STM32WL5_USART1_ISR (STM32WL5_USART1_BASE+STM32WL5_USART_ISR_OFFSET) +#define STM32WL5_USART1_ICR (STM32WL5_USART1_BASE+STM32WL5_USART_ICR_OFFSET) +#define STM32WL5_USART1_RDR (STM32WL5_USART1_BASE+STM32WL5_USART_RDR_OFFSET) +#define STM32WL5_USART1_TDR (STM32WL5_USART1_BASE+STM32WL5_USART_TDR_OFFSET) +#define STM32WL5_USART1_PRESC (STM32WL5_USART1_BASE+STM32WL5_USART_PRESC_OFFSET) + +#define STM32WL5_USART2_CR1 (STM32WL5_USART2_BASE+STM32WL5_USART_CR1_OFFSET) +#define STM32WL5_USART2_CR2 (STM32WL5_USART2_BASE+STM32WL5_USART_CR2_OFFSET) +#define STM32WL5_USART2_CR3 (STM32WL5_USART2_BASE+STM32WL5_USART_CR3_OFFSET) +#define STM32WL5_USART2_BRR (STM32WL5_USART2_BASE+STM32WL5_USART_BRR_OFFSET) +#define STM32WL5_USART2_GTPR (STM32WL5_USART2_BASE+STM32WL5_USART_GTPR_OFFSET) +#define STM32WL5_USART2_RTOR (STM32WL5_USART2_BASE+STM32WL5_USART_RTOR_OFFSET) +#define STM32WL5_USART2_RQR (STM32WL5_USART2_BASE+STM32WL5_USART_RQR_OFFSET) +#define STM32WL5_USART2_ISR (STM32WL5_USART2_BASE+STM32WL5_USART_ISR_OFFSET) +#define STM32WL5_USART2_ICR (STM32WL5_USART2_BASE+STM32WL5_USART_ICR_OFFSET) +#define STM32WL5_USART2_RDR (STM32WL5_USART2_BASE+STM32WL5_USART_RDR_OFFSET) +#define STM32WL5_USART2_TDR (STM32WL5_USART2_BASE+STM32WL5_USART_TDR_OFFSET) +#define STM32WL5_USART2_PRESC (STM32WL5_USART2_BASE+STM32WL5_USART_PRESC_OFFSET) + +#define STM32WL5_LPUART1_CR1 (STM32WL5_LPUART1_BASE+STM32WL5_USART_CR1_OFFSET) +#define STM32WL5_LPUART1_CR2 (STM32WL5_LPUART1_BASE+STM32WL5_USART_CR2_OFFSET) +#define STM32WL5_LPUART1_CR3 (STM32WL5_LPUART1_BASE+STM32WL5_USART_CR3_OFFSET) +#define STM32WL5_LPUART1_BRR (STM32WL5_LPUART1_BASE+STM32WL5_USART_BRR_OFFSET) +#define STM32WL5_LPUART1_RQR (STM32WL5_LPUART1_BASE+STM32WL5_USART_RQR_OFFSET) +#define STM32WL5_LPUART1_ISR (STM32WL5_LPUART1_BASE+STM32WL5_USART_ISR_OFFSET) +#define STM32WL5_LPUART1_ICR (STM32WL5_LPUART1_BASE+STM32WL5_USART_ICR_OFFSET) +#define STM32WL5_LPUART1_RDR (STM32WL5_LPUART1_BASE+STM32WL5_USART_RDR_OFFSET) +#define STM32WL5_LPUART1_TDR (STM32WL5_LPUART1_BASE+STM32WL5_USART_TDR_OFFSET) +#define STM32WL5_LPUART1_PRESC (STM32WL5_LPUART1_BASE+STM32WL5_USART_PRESC_OFFSET) + +/* Register Bitfield Definitions ********************************************/ + +/* Control register 1 */ + +#define USART_CR1_UE (1 << 0) /* Bit 0: USART Enable */ +#define USART_CR1_UESM (1 << 1) /* Bit 1: USART Enable in Stop mode */ +#define USART_CR1_RE (1 << 2) /* Bit 2: Receiver Enable */ +#define USART_CR1_TE (1 << 3) /* Bit 3: Transmitter Enable */ +#define USART_CR1_IDLEIE (1 << 4) /* Bit 4: IDLE Interrupt Enable */ +#define USART_CR1_RXNEIE (1 << 5) /* Bit 5: RXNE Interrupt Enable */ +#define USART_CR1_TCIE (1 << 6) /* Bit 6: Transmission Complete Interrupt Enable */ +#define USART_CR1_TXEIE (1 << 7) /* Bit 7: TXE Interrupt Enable */ +#define USART_CR1_PEIE (1 << 8) /* Bit 8: PE Interrupt Enable */ +#define USART_CR1_PS (1 << 9) /* Bit 9: Parity Selection */ +#define USART_CR1_PCE (1 << 10) /* Bit 10: Parity Control Enable */ +#define USART_CR1_WAKE (1 << 11) /* Bit 11: Wakeup method */ +#define USART_CR1_M0 (1 << 12) /* Bit 12: Word length */ +#define USART_CR1_MME (1 << 13) /* Bit 13: Mute mode enable */ +#define USART_CR1_CMIE (1 << 14) /* Bit 14: Character match interrupt enable */ +#define USART_CR1_OVER8 (1 << 15) /* Bit 15: Oversampling mode */ + +#define USART_CR1_DEDT_SHIFT (16) /* Bits 16..20 DE deactivation delay */ +#define USART_CR1_DEDT_MASK (0x1f << USART_CR1_DEDT_SHIFT) + +#define USART_CR1_DEAT_SHIFT (21) /* Bits 21..25 DE activation delay */ +#define USART_CR1_DEAT_MASK (0x1f << USART_CR1_DEAT_SHIFT) + +#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_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) + +/* Control register 2 */ + +#define USART_CR2_SLVEN (1 << 0) /* Bit 0: Enable slave mode */ +#define USART_CR2_NSS (1 << 3) /* Bit 3: SPI slave is always selected */ +#define USART_CR2_ADDM7 (1 << 4) /* Bit 4: 7-bit/4-bit Address Detection */ +#define USART_CR2_LBDL (1 << 5) /* Bit 5: LIN Break Detection Length */ +#define USART_CR2_LBDIE (1 << 6) /* Bit 6: LIN Break Detection Interrupt Enable */ +#define USART_CR2_LBCL (1 << 8) /* Bit 8: Last Bit Clock pulse */ +#define USART_CR2_CPHA (1 << 9) /* Bit 9: Clock Phase */ +#define USART_CR2_CPOL (1 << 10) /* Bit 10: Clock Polarity */ +#define USART_CR2_CLKEN (1 << 11) /* Bit 11: Clock Enable */ + +#define USART_CR2_STOP_SHIFT (12) /* Bits 13-12: STOP bits */ +#define USART_CR2_STOP_MASK (3 << USART_CR2_STOP_SHIFT) +# define USART_CR2_STOP1 (0 << USART_CR2_STOP_SHIFT) /* 00: 1 Stop bit */ +# define USART_CR2_STOP0p5 (1 << USART_CR2_STOP_SHIFT) /* 01: 0.5 Stop bit */ +# define USART_CR2_STOP2 (2 << USART_CR2_STOP_SHIFT) /* 10: 2 Stop bits */ +# define USART_CR2_STOP1p5 (3 << USART_CR2_STOP_SHIFT) /* 11: 1.5 Stop bit */ + +#define USART_CR2_LINEN (1 << 14) /* Bit 14: LIN mode enable */ +#define USART_CR2_SWAP (1 << 15) /* Bit 15: Swap TX/RX pins */ +#define USART_CR2_RXINV (1 << 16) /* Bit 16: RX pin active level inversion */ +#define USART_CR2_TXINV (1 << 17) /* Bit 17: TX pin active level inversion */ +#define USART_CR2_DATAINV (1 << 18) /* Bit 18: Binary data inversion */ +#define USART_CR2_MSBFIRST (1 << 19) /* Bit 19: Most significant bit first */ +#define USART_CR2_ABREN (1 << 20) /* Bit 20: Auto Baud rate enable */ + +#define USART_CR2_ABRMOD_SHIFT (21) /* Bits 21-22: Autobaud rate mode*/ +#define USART_CR2_ABRMOD_MASK (3 << USART_CR2_ABRMOD_SHIFT) +#define USART_CR2_ABRMOD_START (0 << USART_CR2_ABRMOD_SHIFT) /* 00: Start bit */ +#define USART_CR2_ABRMOD_EDGES (1 << USART_CR2_ABRMOD_SHIFT) /* 01: Falling-to-falling edge -> frame must start with 10xxxxxx */ +#define USART_CR2_ABRMOD_7F (2 << USART_CR2_ABRMOD_SHIFT) /* 10: 0x7F */ +#define USART_CR2_ABRMOD_55 (3 << USART_CR2_ABRMOD_SHIFT) /* 11: 0x55 */ + +#define USART_CR2_RTOEN (1 << 23) /* Bit 23: Receiver timeout enable */ + +#define USART_CR2_ADD_SHIFT (24) /* Bits 24-31: Address of the USART node */ +#define USART_CR2_ADD_MASK (0xff << USART_CR2_ADD_SHIFT) + +/* Control register 3 */ + +#define USART_CR3_EIE (1 << 0) /* Bit 0: Error Interrupt Enable */ +#define USART_CR3_IREN (1 << 1) /* Bit 1: IrDA mode Enable */ +#define USART_CR3_IRLP (1 << 2) /* Bit 2: IrDA Low-Power */ +#define USART_CR3_HDSEL (1 << 3) /* Bit 3: Half-Duplex Selection */ +#define USART_CR3_NACK (1 << 4) /* Bit 4: Smartcard NACK enable */ +#define USART_CR3_SCEN (1 << 5) /* Bit 5: Smartcard mode enable */ +#define USART_CR3_DMAR (1 << 6) /* Bit 6: DMA Enable Receiver */ +#define USART_CR3_DMAT (1 << 7) /* Bit 7: DMA Enable Transmitter */ +#define USART_CR3_RTSE (1 << 8) /* Bit 8: RTS Enable */ +#define USART_CR3_CTSE (1 << 9) /* Bit 9: CTS Enable */ +#define USART_CR3_CTSIE (1 << 10) /* Bit 10: CTS Interrupt Enable */ +#define USART_CR3_ONEBIT (1 << 11) /* Bit 11: One sample bit method Enable */ +#define USART_CR3_OVRDIS (1 << 12) /* Bit 12: Overrun Disable */ +#define USART_CR3_DDRE (1 << 13) /* Bit 13: DMA disable on Reception error */ +#define USART_CR3_DEM (1 << 14) /* Bit 14: Driver Enable mode */ +#define USART_CR3_DEP (1 << 15) /* Bit 15: Driver Enable polarity selection */ +#define USART_CR3_SCARCNT2_SHIFT (17) /* Bits 17-19: Smart card auto retry count */ +#define USART_CR3_SCARCNT2_MASK (7 << USART_CR3_SCARCNT2_SHIFT) +#define USART_CR3_WUS_SHIFT (20) /* Bits 20-21: Wakeup from Stop mode interrupt flag selection */ +#define USART_CR3_WUS_MASK (3 << USART_CR3_WUS_SHIFT) +#define USART_CR3_WUS_ADDRESS (0 << USART_CR3_WUS_SHIFT) /* 00: WUF active on address match */ +#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: Generate IRQ when TXFIFO reaches threshold */ +#define USART_CR3_TCBGTIE (1 << 24) /* Bit 24: Generate IRQ when TCBGT=1 */ + +#define USART_CR3_RXFTCFG_SHIFT (25) /* Bit 25-27: Receive FIFO threshold configuration */ +#define USART_CR3_RXFTCFG_MASK (7 << USART_CR3_RXFTCFG_SHIFT) +#define USART_CR3_RXFTCFG_1_8 (0 << USART_CR3_RXFTCFG_SHIFT) /* 000: RXFIFO reaches 1/8 of its depth */ +#define USART_CR3_RXFTCFG_1_8 (0 << USART_CR3_RXFTCFG_SHIFT) /* 000: RXFIFO reaches 1/8 of its depth */ +#define USART_CR3_RXFTCFG_2_8 (1 << USART_CR3_RXFTCFG_SHIFT) /* 001: RXFIFO reaches 2/8 of its depth */ +#define USART_CR3_RXFTCFG_4_8 (2 << USART_CR3_RXFTCFG_SHIFT) /* 010: RXFIFO reaches 4/8 of its depth */ +#define USART_CR3_RXFTCFG_6_8 (3 << USART_CR3_RXFTCFG_SHIFT) /* 011: RXFIFO reaches 6/8 of its depth */ +#define USART_CR3_RXFTCFG_7_8 (4 << USART_CR3_RXFTCFG_SHIFT) /* 100: RXFIFO reaches 7/8 of its depth */ +#define USART_CR3_RXFTCFG_8_8 (5 << USART_CR3_RXFTCFG_SHIFT) /* 101: RXFIFO reaches 8/8 of its depth */ + +#define USART_CR3_RXFTIE (1 << 28) /* Bit 28: Generate IRQ when RXFIFO reaches threshold */ + +#define USART_CR3_TXFTCFG_SHIFT (29) /* Bit 29-31: Receive FIFO threshold configuration */ +#define USART_CR3_TXFTCFG_MASK (7 << USART_CR3_TXFTCFG_SHIFT) +#define USART_CR3_TXFTCFG_1_8 (0 << USART_CR3_TXFTCFG_SHIFT) /* 000: TXFIFO reaches 1/8 of its depth */ +#define USART_CR3_TXFTCFG_1_8 (0 << USART_CR3_TXFTCFG_SHIFT) /* 000: TXFIFO reaches 1/8 of its depth */ +#define USART_CR3_TXFTCFG_2_8 (1 << USART_CR3_TXFTCFG_SHIFT) /* 001: TXFIFO reaches 2/8 of its depth */ +#define USART_CR3_TXFTCFG_4_8 (2 << USART_CR3_TXFTCFG_SHIFT) /* 010: TXFIFO reaches 4/8 of its depth */ +#define USART_CR3_TXFTCFG_6_8 (3 << USART_CR3_TXFTCFG_SHIFT) /* 011: TXFIFO reaches 6/8 of its depth */ +#define USART_CR3_TXFTCFG_7_8 (4 << USART_CR3_TXFTCFG_SHIFT) /* 100: TXFIFO reaches 7/8 of its depth */ +#define USART_CR3_TXFTCFG_8_8 (5 << USART_CR3_TXFTCFG_SHIFT) /* 101: TXFIFO reaches 8/8 of its depth */ + +/* Baud Rate Register (USART) */ + +#define USART_BRR_FRAC_SHIFT (0) /* Bits 3-0: fraction of USARTDIV */ +#define USART_BRR_FRAC_MASK (0x0f << USART_BRR_FRAC_SHIFT) +#define USART_BRR_MANT_SHIFT (4) /* Bits 15-4: mantissa of USARTDIV */ +#define USART_BRR_MANT_MASK (0x0fff << USART_BRR_MANT_SHIFT) + +/* Baud Rate Register (LPUART) */ + +#define LPUART_BRR_SHIFT (0) /* Bits 19-0: LPUART baud rate */ +#define LPUART_BRR_MASK (0xfffff << LPUART_BRR_SHIFT) +#define LPUART_BRR_MIN (0x300) /* Minimum value permitted for BRR register */ + +/* Guard time and prescaler register */ + +#define USART_GTPR_PSC_SHIFT (0) /* Bits 0-7: Prescaler value */ +#define USART_GTPR_PSC_MASK (0xff << USART_GTPR_PSC_SHIFT) +#define USART_GTPR_GT_SHIFT (8) /* Bits 8-15: Guard time value */ +#define USART_GTPR_GT_MASK (0xff << USART_GTPR_GT_SHIFT) + +/* Receiver timeout register */ + +/* Request Register */ + +#define USART_RQR_ABRRQ (1 << 0) /* Bit 0: Send auto baud rate */ +#define USART_RQR_SBRKQ (1 << 1) /* Bit 1: Send Break */ +#define USART_RQR_MMRQ (1 << 2) /* Bit 2: Put USART in mute mode */ +#define USART_RQR_RXFRQ (1 << 3) /* Bit 3: Flush RX fifo */ +#define USART_RQR_TXFRQ (1 << 4) /* Bit 4: Flush (transmit) TX fifo */ + +/* Interrupt and Status register */ + +#define USART_ISR_PE (1 << 0) /* Bit 0: Parity Error */ +#define USART_ISR_FE (1 << 1) /* Bit 1: Framing Error */ +#define USART_ISR_NF (1 << 2) /* Bit 2: Noise Error Flag */ +#define USART_ISR_ORE (1 << 3) /* Bit 3: OverRun Error */ +#define USART_ISR_IDLE (1 << 4) /* Bit 4: IDLE line detected */ +#define USART_ISR_RXNE (1 << 5) /* Bit 5: Read Data Register Not Empty */ +#define USART_ISR_TC (1 << 6) /* Bit 6: Transmission Complete */ +#define USART_ISR_TXE (1 << 7) /* Bit 7: Transmit Data Register Empty */ +#define USART_ISR_LBDF (1 << 8) /* Bit 8: LIN Break Detection Flag */ +#define USART_ISR_CTSIF (1 << 9) /* Bit 9: CTS interrupt Flag */ +#define USART_ISR_CTS (1 << 10) /* Bit 10: CTS Flag */ +#define USART_ISR_RTOF (1 << 11) /* Bit 11: Receiver timeout Flag */ +#define USART_ISR_EOBF (1 << 12) /* Bit 12: End of block Flag */ +#define USART_ISR_UDR (1 << 13) /* Bit 13: SPI slave underrun error */ +#define USART_ISR_ABRE (1 << 14) /* Bit 14: Auto baud rate Error */ +#define USART_ISR_ABRF (1 << 15) /* Bit 15: Auto baud rate Flag */ +#define USART_ISR_BUSY (1 << 16) /* Bit 16: Busy Flag */ +#define USART_ISR_CMF (1 << 17) /* Bit 17: Character match Flag */ +#define USART_ISR_SBKF (1 << 18) /* Bit 18: Send break Flag */ +#define USART_ISR_RWU (1 << 19) /* Bit 19: Receiver wakeup from Mute mode */ +#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_TCBGT (1 << 25) /* Bit 25: Transmission complete before guard time Flag */ + +/* ICR */ + +#define USART_ICR_PECF (1 << 0) /* Bit 0: Parity error clear flag */ +#define USART_ICR_FECF (1 << 1) /* Bit 1: Framing error clear flag */ +#define USART_ICR_NCF (1 << 2) /* Bit 2: Noise detected clear flag */ +#define USART_ICR_ORECF (1 << 3) /* Bit 3: Overrun error clear flag */ +#define USART_ICR_IDLECF (1 << 4) /* Bit 4: Idle line detected clear flag */ +#define USART_ICR_TXFECF (1 << 5) /* Bit 5: TXFIFO empty clear flag */ +#define USART_ICR_TCCF (1 << 6) /* Bit 6: Transmission complete clear flag */ +#define USART_ICR_TCBGTCF (1 << 7) /* Bit 7: Transmission complete before guard time clear flag */ +#define USART_ICR_LBDCF (1 << 8) /* Bit 8: LIN break detection clear flag */ +#define USART_ICR_CTSCF (1 << 9) /* Bit 9: CTS clear flag */ +#define USART_ICR_RTOCF (1 << 11) /* Bit 11: Receiver timeout clear flag */ +#define USART_ICR_EOBCF (1 << 12) /* Bit 12: End of block clear flag */ +#define USART_ICR_UDRCF (1 << 13) /* Bit 13: SPI slave underrun clear flag */ +#define USART_ICR_CMCF (1 << 17) /* Bit 17: Character match clear flag */ +#define USART_ICR_WUCF (1 << 20) /* Bit 20: Wakeup from Stop mode clear flag */ + +/* Receive Data register */ + +#define USART_RDR_SHIFT (0) /* Bits 8:0: Data value */ +#define USART_RDR_MASK (0x1ff << USART_RDR_SHIFT) + +/* Transmit Data register */ + +#define USART_TDR_SHIFT (0) /* Bits 8:0: Data value */ +#define USART_TDR_MASK (0x1ff << USART_TDR_SHIFT) + +/* Prescaler register */ + +#define USART_PRESC_SHIFT (0) /* Bits 3:0: Prescaler */ +#define USART_PRESC_MASK (0x0f) +#define USART_PRESC_DIV_1 ( 0 << USART_PRESC_SHIFT) /* 0000: input clock divided by 1 */ +#define USART_PRESC_DIV_2 ( 1 << USART_PRESC_SHIFT) /* 0001: input clock divided by 2 */ +#define USART_PRESC_DIV_4 ( 2 << USART_PRESC_SHIFT) /* 0010: input clock divided by 4 */ +#define USART_PRESC_DIV_6 ( 3 << USART_PRESC_SHIFT) /* 0011: input clock divided by 6 */ +#define USART_PRESC_DIV_8 ( 4 << USART_PRESC_SHIFT) /* 0100: input clock divided by 8 */ +#define USART_PRESC_DIV_10 ( 5 << USART_PRESC_SHIFT) /* 0101: input clock divided by 10 */ +#define USART_PRESC_DIV_12 ( 6 << USART_PRESC_SHIFT) /* 0110: input clock divided by 12 */ +#define USART_PRESC_DIV_16 ( 7 << USART_PRESC_SHIFT) /* 0111: input clock divided by 16 */ +#define USART_PRESC_DIV_32 ( 8 << USART_PRESC_SHIFT) /* 1000: input clock divided by 32 */ +#define USART_PRESC_DIV_64 ( 9 << USART_PRESC_SHIFT) /* 1001: input clock divided by 64 */ +#define USART_PRESC_DIV_128 (10 << USART_PRESC_SHIFT) /* 1010: input clock divided by 128 */ +#define USART_PRESC_DIV_256 (11 << USART_PRESC_SHIFT) /* 1011: input clock divided by 256 */ + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32WL5_HARDWARE_STM32WL5_UART_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5.h b/arch/arm/src/stm32wl5/stm32wl5.h new file mode 100644 index 0000000000..b819b71ffb --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include +#include + +#include "arm_internal.h" + +/* Peripherals **************************************************************/ + +#include "chip.h" +#include "stm32wl5_flash.h" +#include "stm32wl5_gpio.h" +#include "stm32wl5_lowputc.h" +#include "stm32wl5_pwr.h" +#include "stm32wl5_rcc.h" +#include "stm32wl5_tim.h" +#include "stm32wl5_uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_allocateheap.c b/arch/arm/src/stm32wl5/stm32wl5_allocateheap.c new file mode 100644 index 0000000000..06d01bf888 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_allocateheap.c @@ -0,0 +1,280 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_allocateheap.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "chip.h" +#include "mpu.h" +#include "arm_internal.h" +#include "arm_internal.h" +#include "stm32wl5_mpuinit.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Internal SRAM is available in all members of the STM32WL5 family. The + * following definitions must be provided to specify the size and + * location of internal (system) SRAM1 and SRAM2: + * + * SRAM1_START 0x20000000 + * SRAM1_END + * SRAM2_START 0x20008000 + * SRAM2_END + */ + +/* STM32WL5xxx have 64KiB in two banks, both accessible to DMA + * + * 1) 32 KiB of System SRAM beginning at address 0x2000:0000 - 0x2000:7fff + * 2) 32 KiB of System SRAM beginning at address 0x2000:8000 - 0x2000:ffff + */ + +/* Set the range of system SRAM */ + +#define SRAM1_START STM32WL5_SRAM_BASE +#define SRAM1_END (SRAM1_START + STM32WL5_SRAM1_SIZE) + +/* Set the range of SRAM2 as well, requires a second memory region */ + +#define SRAM2_START STM32WL5_SRAM2_BASE +#define SRAM2_END (SRAM2_START + STM32WL5_SRAM2_SIZE) + +/* Some sanity checking. If multiple memory regions are defined, verify + * that CONFIG_MM_REGIONS is set to match the number of memory regions + * that we have been asked to add to the heap. + */ + +#if CONFIG_MM_REGIONS < defined(CONFIG_STM32WL5_SRAM2_HEAP) + 1 +# error "You need more memory manager regions to support selected heap components" +#endif + +#if CONFIG_MM_REGIONS > defined(CONFIG_STM32WL5_SRAM2_HEAP) + 1 +# warning "CONFIG_MM_REGIONS large enough but I do not know what some of the region(s) are" +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_heap_color + * + * Description: + * Set heap memory to a known, non-zero state to checking heap usage. + * + ****************************************************************************/ + +#ifdef CONFIG_HEAP_COLORATION +static inline void up_heap_color(FAR void *start, size_t size) +{ + memset(start, HEAP_COLOR, size); +} +#else +# define up_heap_color(start,size) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_allocate_heap + * + * Description: + * This function will be called to dynamically set aside the heap region. + * + * For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and + * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function provides the + * size of the unprotected, user-space heap. + * + * If a protected kernel-space heap is provided, the kernel heap must be + * allocated (and protected) by an analogous up_allocate_kheap(). + * + * The following memory map is assumed for the flat build: + * + * .data region. Size determined at link time. + * .bss region Size determined at link time. + * IDLE thread stack. Size determined by CONFIG_IDLETHREAD_STACKSIZE. + * Heap. Extends to the end of SRAM. + * + * The following memory map is assumed for the kernel build: + * + * Kernel .data region. Size determined at link time. + * Kernel .bss region Size determined at link time. + * Kernel IDLE thread stack. Size determined by + * CONFIG_IDLETHREAD_STACKSIZE. + * Padding for alignment + * User .data region. Size determined at link time. + * User .bss region Size determined at link time. + * Kernel heap. Size determined by CONFIG_MM_KERNEL_HEAPSIZE. + * User heap. Extends to the end of SRAM. + * + ****************************************************************************/ + +void up_allocate_heap(FAR void **heap_start, size_t *heap_size) +{ +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) + /* Get the unaligned size and position of the user-space heap. + * This heap begins after the user-space .bss section at an offset + * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment). + */ + + uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend + + CONFIG_MM_KERNEL_HEAPSIZE; + size_t usize = SRAM1_END - ubase; + int log2; + + DEBUGASSERT(ubase < (uintptr_t)SRAM1_END); + + /* Adjust that size to account for MPU alignment requirements. + * NOTE that there is an implicit assumption that the SRAM1_END + * is aligned to the MPU requirement. + */ + + log2 = (int)mpu_log2regionfloor(usize); + DEBUGASSERT((SRAM1_END & ((1 << log2) - 1)) == 0); + + usize = (1 << log2); + ubase = SRAM1_END - usize; + + /* Return the user-space heap settings */ + + board_autoled_on(LED_HEAPALLOCATE); + *heap_start = (FAR void *)ubase; + *heap_size = usize; + + /* Colorize the heap for debug */ + + up_heap_color((FAR void *)ubase, usize); + + /* Allow user-mode access to the user heap memory */ + + stm32wl5_mpu_uheap((uintptr_t)ubase, usize); +#else + + /* Return the heap settings */ + + board_autoled_on(LED_HEAPALLOCATE); + *heap_start = (FAR void *)g_idle_topstack; + *heap_size = SRAM1_END - g_idle_topstack; + + /* Colorize the heap for debug */ + + up_heap_color(*heap_start, *heap_size); +#endif +} + +/**************************************************************************** + * Name: up_allocate_kheap + * + * Description: + * For the kernel build (CONFIG_BUILD_PROTECTED=y) with both kernel- and + * user-space heaps (CONFIG_MM_KERNEL_HEAP=y), this function allocates + * (and protects) the kernel-space heap. + * + ****************************************************************************/ + +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) +void up_allocate_kheap(FAR void **heap_start, size_t *heap_size) +{ + /* Get the unaligned size and position of the user-space heap. + * This heap begins after the user-space .bss section at an offset + * of CONFIG_MM_KERNEL_HEAPSIZE (subject to alignment). + */ + + uintptr_t ubase = (uintptr_t)USERSPACE->us_bssend + + CONFIG_MM_KERNEL_HEAPSIZE; + size_t usize = SRAM1_END - ubase; + int log2; + + DEBUGASSERT(ubase < (uintptr_t)SRAM1_END); + + /* Adjust that size to account for MPU alignment requirements. + * NOTE that there is an implicit assumption that the SRAM1_END + * is aligned to the MPU requirement. + */ + + log2 = (int)mpu_log2regionfloor(usize); + DEBUGASSERT((SRAM1_END & ((1 << log2) - 1)) == 0); + + usize = (1 << log2); + ubase = SRAM1_END - usize; + + /* Return the kernel heap settings (i.e., the part of the heap region + * that was not dedicated to the user heap). + */ + + *heap_start = (FAR void *)USERSPACE->us_bssend; + *heap_size = ubase - (uintptr_t)USERSPACE->us_bssend; +} +#endif + +/**************************************************************************** + * Name: arm_addregion + * + * Description: + * Memory may be added in non-contiguous chunks. Additional chunks are + * added by calling this function. + * + ****************************************************************************/ + +#if CONFIG_MM_REGIONS > 1 +void arm_addregion(void) +{ +#ifdef CONFIG_STM32WL5_SRAM2_HEAP + +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_MM_KERNEL_HEAP) + + /* Allow user-mode access to the SRAM2 heap */ + + stm32wl5_mpu_uheap((uintptr_t)SRAM2_START, SRAM2_END - SRAM2_START); +#endif + + /* Colorize the heap for debug */ + + up_heap_color((FAR void *)SRAM2_START, SRAM2_END - SRAM2_START); + + /* Add the SRAM2 user heap region. */ + + kumm_addregion((FAR void *)SRAM2_START, SRAM2_END - SRAM2_START); + +#endif /* SRAM2 */ +} +#endif diff --git a/arch/arm/src/stm32wl5/stm32wl5_exti.h b/arch/arm/src/stm32wl5/stm32wl5_exti.h new file mode 100644 index 0000000000..91f2bb1384 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_exti.h @@ -0,0 +1,153 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_exti.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_EXTI_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_EXTI_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" +#include "hardware/stm32wl5_exti.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_gpiosetevent + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Input Parameters: + * pinset - GPIO pin configuration + * risingedge - Enables interrupt on rising edges + * fallingedge - Enables interrupt on falling edges + * event - Generate event when set + * func - When non-NULL, generate interrupt + * arg - Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) is returned on success, otherwise a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stm32wl5_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, + bool event, xcpt_t func, void *arg); + +/**************************************************************************** + * Name: stm32wl5_exti_alarm + * + * Description: + * Sets/clears EXTI alarm interrupt. + * + * Input Parameters: + * - rising/falling edge: enables interrupt on rising/falling edges + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * - arg: Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure indicating the + * nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_ALARM +int stm32wl5_exti_alarm(bool risingedge, bool fallingedge, bool event, + xcpt_t func, void *arg); +#endif + +/**************************************************************************** + * Name: stm32wl5_exti_wakeup + * + * Description: + * Sets/clears EXTI wakeup interrupt. + * + * Input Parameters: + * - rising/falling edge: enables interrupt on rising/falling edges + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * - arg: Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure indicating the + * nature of the failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RTC_PERIODIC +int stm32wl5_exti_wakeup(bool risingedge, bool fallingedge, bool event, + xcpt_t func, void *arg); +#endif + +/**************************************************************************** + * Name: stm32wl5_exti_comp + * + * Description: + * Sets/clears comparator based events and interrupt triggers. + * + * Input Parameters: + * - cmp: comparator + * - rising/falling edge: enables interrupt on rising/falling edges + * - event: generate event when set + * - func: when non-NULL, generate interrupt + * - arg: Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) returned on success; a negated errno value is returned on + * failure. + * + ****************************************************************************/ + +#ifdef CONFIG_STM32WL5_COMP +int stm32wl5_exti_comp(int cmp, bool risingedge, bool fallingedge, + bool event, xcpt_t func, void *arg); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_EXTI_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_exti_gpio.c b/arch/arm/src/stm32wl5/stm32wl5_exti_gpio.c new file mode 100644 index 0000000000..2da29516a5 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_exti_gpio.c @@ -0,0 +1,173 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_exti_gpio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "arm_internal.h" +#include "chip.h" +#include "stm32wl5_gpio.h" +#include "stm32wl5_exti.h" + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct gpio_callback_s +{ + xcpt_t callback; /* Callback entry point */ + void *arg; /* The argument that accompanies the callback */ +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* Interrupt handlers attached to each EXTI */ + +static struct gpio_callback_s g_gpio_handlers[16]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Interrupt Service Routine - Dispatcher + ****************************************************************************/ + +static int stm32wl5_exti0_15_isr(int irq, void *context, FAR void *arg) +{ + int ret = OK; + int exti; + (void)arg; + + exti = irq - STM32WL5_IRQ_EXTI0; + DEBUGASSERT((exti >= 0) && (exti <= 15)); + + /* Clear the pending interrupt for both rising and falling edges. */ + + putreg32(0x0001 << exti, STM32WL5_EXTI_PR1); + + /* And dispatch the interrupt to the handler */ + + if (g_gpio_handlers[exti].callback != NULL) + { + xcpt_t callback = g_gpio_handlers[exti].callback; + void *cbarg = g_gpio_handlers[exti].arg; + + ret = callback(irq, context, cbarg); + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_gpiosetevent + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Input Parameters: + * pinset - GPIO pin configuration + * risingedge - Enables interrupt on rising edges + * fallingedge - Enables interrupt on falling edges + * event - Generate event when set + * func - When non-NULL, generate interrupt + * arg - Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) is returned on success, otherwise a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stm32wl5_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, + bool event, xcpt_t func, void *arg) +{ + uint32_t pin = pinset & GPIO_PIN_MASK; + uint32_t exti = 1 << pin; + int irq = STM32WL5_IRQ_EXTI0 + pin; + + g_gpio_handlers[pin].callback = func; + g_gpio_handlers[pin].arg = arg; + + /* Install external interrupt handlers */ + + if (func) + { + irq_attach(irq, stm32wl5_exti0_15_isr, NULL); + up_enable_irq(irq); + } + else + { + up_disable_irq(irq); + } + + /* Configure GPIO, enable EXTI line enabled if event or interrupt is + * enabled. + */ + + if (event || func) + { + pinset |= GPIO_EXTI; + } + + stm32wl5_configgpio(pinset); + + /* Configure rising/falling edges */ + + modifyreg32(STM32WL5_EXTI_RTSR1, + risingedge ? 0 : exti, + risingedge ? exti : 0); + modifyreg32(STM32WL5_EXTI_FTSR1, + fallingedge ? 0 : exti, + fallingedge ? exti : 0); + + /* Enable Events and Interrupts */ + + modifyreg32(STM32WL5_EXTI_C1EMR1, + event ? 0 : exti, + event ? exti : 0); + modifyreg32(STM32WL5_EXTI_C1IMR1, + func ? 0 : exti, + func ? exti : 0); + + return OK; +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_flash.c b/arch/arm/src/stm32wl5/stm32wl5_flash.c new file mode 100644 index 0000000000..d79a8e3adf --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_flash.c @@ -0,0 +1,505 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_flash.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/* Provides standard flash access functions, to be used by the flash mtd + * driver. The interface is defined in the include/nuttx/progmem.h + * + * Notes about this implementation: + * - HSI16 is automatically turned ON by MCU, if not enabled beforehand + * - Only Standard Programming is supported, no Fast Programming. + * - Low Power Modes are not permitted during write/erase + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "stm32wl5_rcc.h" +#include "stm32wl5_waste.h" +#include "stm32wl5_flash.h" + +#include "arm_internal.h" + +#if !defined(CONFIG_STM32WL5_FLASH_OVERRIDE_DEFAULT) +# warning "Flash Configuration has been overridden - make sure it is correct" +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define FLASH_KEY1 0x45670123 +#define FLASH_KEY2 0xCDEF89AB + +#define OPTBYTES_KEY1 0x08192A3B +#define OPTBYTES_KEY2 0x4C5D6E7F + +#define FLASH_PAGE_SIZE STM32WL5_FLASH_PAGESIZE +#define FLASH_PAGE_WORDS (FLASH_PAGE_SIZE / 4) +#define FLASH_PAGE_MASK (FLASH_PAGE_SIZE - 1) +#if FLASH_PAGE_SIZE == 2048 +# define FLASH_PAGE_SHIFT (11) /* 2**11 = 2048B */ +#elif FLASH_PAGE_SIZE == 4096 +# define FLASH_PAGE_SHIFT (12) /* 2**12 = 4096B */ +#elif FLASH_PAGE_SIZE == 8192 +# define FLASH_PAGE_SHIFT (13) /* 2**13 = 8192B */ +#else +# error Unsupported STM32WL5_FLASH_PAGESIZE +#endif +#define FLASH_BYTE2PAGE(o) ((o) >> FLASH_PAGE_SHIFT) + +#define FLASH_CR_PAGE_ERASE FLASH_CR_PER +#define FLASH_SR_WRITE_PROTECTION_ERROR FLASH_SR_WRPERR + +/* All errors for Standard Programming, not for other operations. */ + +#define FLASH_SR_ALLERRS (FLASH_SR_PGSERR | FLASH_SR_SIZERR | \ + FLASH_SR_PGAERR | FLASH_SR_WRPERR | \ + FLASH_SR_PROGERR) + +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static sem_t g_sem = SEM_INITIALIZER(1); +static uint32_t g_page_buffer[FLASH_PAGE_WORDS]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline void sem_lock(void) +{ + int ret; + + do + { + /* Take the semaphore (perhaps waiting) */ + + ret = nxsem_wait(&g_sem); + + /* The only case that an error should occur here is if the wait was + * awakened by a signal. + */ + + DEBUGASSERT(ret == OK || ret == -EINTR); + } + while (ret == -EINTR); +} + +static inline void sem_unlock(void) +{ + nxsem_post(&g_sem); +} + +static void flash_unlock(void) +{ + while (getreg32(STM32WL5_FLASH_SR) & FLASH_SR_BSY) + { + stm32wl5_waste(); + } + + if (getreg32(STM32WL5_FLASH_CR) & FLASH_CR_LOCK) + { + /* Unlock sequence */ + + putreg32(FLASH_KEY1, STM32WL5_FLASH_KEYR); + putreg32(FLASH_KEY2, STM32WL5_FLASH_KEYR); + } +} + +static void flash_lock(void) +{ + modifyreg32(STM32WL5_FLASH_CR, 0, FLASH_CR_LOCK); +} + +static void flash_optbytes_unlock(void) +{ + flash_unlock(); + + if (getreg32(STM32WL5_FLASH_CR) & FLASH_CR_OPTLOCK) + { + /* Unlock Option Bytes sequence */ + + putreg32(OPTBYTES_KEY1, STM32WL5_FLASH_OPTKEYR); + putreg32(OPTBYTES_KEY2, STM32WL5_FLASH_OPTKEYR); + } +} + +static inline void flash_optbytes_lock(void) +{ + /* We don't need to set OPTLOCK here as it is automatically + * set by MCU when flash_lock() sets LOCK. + */ + + flash_lock(); +} + +static inline void flash_erase(size_t page) +{ + finfo("erase page %u\n", page); + + modifyreg32(STM32WL5_FLASH_CR, 0, FLASH_CR_PAGE_ERASE); + modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PNB_MASK, FLASH_CR_PNB(page)); + modifyreg32(STM32WL5_FLASH_CR, 0, FLASH_CR_START); + + while (getreg32(STM32WL5_FLASH_SR) & FLASH_SR_BSY) + { + stm32wl5_waste(); + } + + modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PAGE_ERASE, 0); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void stm32wl5_flash_unlock(void) +{ + sem_lock(); + flash_unlock(); + sem_unlock(); +} + +void stm32wl5_flash_lock(void) +{ + sem_lock(); + flash_lock(); + sem_unlock(); +} + +/**************************************************************************** + * Name: stm32wl5_flash_user_optbytes + * + * Description: + * Modify the contents of the user option bytes (USR OPT) on the flash. + * This does not set OBL_LAUNCH so new options take effect only after + * next power reset. + * + * Input Parameters: + * clrbits - Bits in the option bytes to be cleared + * setbits - Bits in the option bytes to be set + * + * Returned Value: + * Option bytes after operation is completed + * + ****************************************************************************/ + +uint32_t stm32wl5_flash_user_optbytes(uint32_t clrbits, uint32_t setbits) +{ + uint32_t regval; + + /* To avoid accidents, do not allow setting RDP via this function. + * Remove these asserts if want to enable changing the protection level. + * WARNING: level 2 protection is permanent! + */ + + DEBUGASSERT((clrbits & FLASH_OPTR_RDP_MASK) == 0); + DEBUGASSERT((setbits & FLASH_OPTR_RDP_MASK) == 0); + + sem_lock(); + flash_optbytes_unlock(); + + /* Modify Option Bytes in register. */ + + regval = getreg32(STM32WL5_FLASH_OPTR); + + finfo("Flash option bytes before: 0x%x\n", (unsigned)regval); + + regval = (regval & ~clrbits) | setbits; + putreg32(regval, STM32WL5_FLASH_OPTR); + + finfo("Flash option bytes after: 0x%x\n", (unsigned)regval); + + /* Start Option Bytes programming and wait for completion. */ + + modifyreg32(STM32WL5_FLASH_CR, 0, FLASH_CR_OPTSTRT); + + while (getreg32(STM32WL5_FLASH_SR) & FLASH_SR_BSY) + { + stm32wl5_waste(); + } + + flash_optbytes_lock(); + sem_unlock(); + + return regval; +} + +size_t up_progmem_pagesize(size_t page) +{ + (void)page; + return STM32WL5_FLASH_PAGESIZE; +} + +size_t up_progmem_erasesize(size_t block) +{ + (void)block; + return STM32WL5_FLASH_PAGESIZE; +} + +ssize_t up_progmem_getpage(size_t addr) +{ + if (addr >= STM32WL5_FLASH_BASE) + { + addr -= STM32WL5_FLASH_BASE; + } + + if (addr >= STM32WL5_FLASH_SIZE) + { + return -EFAULT; + } + + return addr / STM32WL5_FLASH_PAGESIZE; +} + +size_t up_progmem_getaddress(size_t page) +{ + if (page >= STM32WL5_FLASH_NPAGES) + { + return SIZE_MAX; + } + + return page * STM32WL5_FLASH_PAGESIZE + STM32WL5_FLASH_BASE; +} + +size_t up_progmem_neraseblocks(void) +{ + return STM32WL5_FLASH_NPAGES; +} + +bool up_progmem_isuniform(void) +{ + return true; +} + +ssize_t up_progmem_ispageerased(size_t page) +{ + size_t addr; + size_t count; + size_t bwritten = 0; + + if (page >= STM32WL5_FLASH_NPAGES) + { + return -EFAULT; + } + + /* Verify */ + + for (addr = up_progmem_getaddress(page), count = up_progmem_pagesize(page); + count; count--, addr++) + { + if (getreg8(addr) != 0xff) + { + bwritten++; + } + } + + return bwritten; +} + +ssize_t up_progmem_eraseblock(size_t block) +{ + if (block >= STM32WL5_FLASH_NPAGES) + { + return -EFAULT; + } + + /* Erase single block */ + + sem_lock(); + flash_unlock(); + + flash_erase(block); + + flash_lock(); + sem_unlock(); + + /* Verify */ + + if (up_progmem_ispageerased(block) == 0) + { + return up_progmem_erasesize(block); + } + else + { + return -EIO; + } +} + +ssize_t up_progmem_write(size_t addr, const void *buf, size_t buflen) +{ + uint32_t *dest; + const uint32_t *src; + size_t written; + size_t xfrsize; + size_t offset; + size_t page; + int i; + int ret = OK; + + /* Check for valid address range. */ + + offset = addr; + if (addr >= STM32WL5_FLASH_BASE) + { + offset -= STM32WL5_FLASH_BASE; + } + + if (offset + buflen > STM32WL5_FLASH_SIZE) + { + return -EFAULT; + } + + /* Get the page number corresponding to the flash offset and the byte + * offset into the page. Align write destination to page boundary. + */ + + page = FLASH_BYTE2PAGE((uint32_t)offset); + offset &= FLASH_PAGE_MASK; + + dest = (uint32_t *)((uint8_t *)addr - offset); + written = 0; + + sem_lock(); + + /* Get flash ready and begin flashing. */ + + flash_unlock(); + + /* Loop until all of the data has been written */ + + while (buflen > 0) + { + /* How much can we write into this page? */ + + xfrsize = MIN((size_t)FLASH_PAGE_SIZE - offset, buflen); + + /* Do we need to use the intermediate buffer? */ + + if (offset == 0 && xfrsize == FLASH_PAGE_SIZE) + { + /* No, we can take the data directly from the user buffer */ + + src = (const uint32_t *)buf; + } + else + { + /* Yes, copy data into global page buffer */ + + if (offset > 0) + { + memcpy(g_page_buffer, dest, offset); + } + + memcpy((uint8_t *)g_page_buffer + offset, buf, xfrsize); + + if (offset + xfrsize < FLASH_PAGE_SIZE) + { + memcpy((uint8_t *)g_page_buffer + offset + xfrsize, + (const uint8_t *)dest + offset + xfrsize, + FLASH_PAGE_SIZE - offset - xfrsize); + } + + src = g_page_buffer; + } + + /* Erase the page. Unlike most flash chips, STM32WL5 is unable to + * write back existing data read from page without erase. + */ + + flash_erase(page); + + /* Write the page. Must be with double-words. */ + + modifyreg32(STM32WL5_FLASH_CR, 0, FLASH_CR_PG); + + for (i = 0; i < FLASH_PAGE_WORDS; i += 2) + { + *dest++ = *src++; + *dest++ = *src++; + + while (getreg32(STM32WL5_FLASH_SR) & FLASH_SR_BSY) + { + stm32wl5_waste(); + } + + /* Verify */ + + if (getreg32(STM32WL5_FLASH_SR) & FLASH_SR_WRITE_PROTECTION_ERROR) + { + modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PG, 0); + ret = -EROFS; + goto out; + } + + if (getreg32(dest - 1) != *(src - 1) || + getreg32(dest - 2) != *(src - 2)) + { + modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PG, 0); + ret = -EIO; + goto out; + } + } + + modifyreg32(STM32WL5_FLASH_CR, FLASH_CR_PG, 0); + + /* Adjust pointers and counts for the next time through the loop */ + + written += xfrsize; + addr += xfrsize; + dest = (uint32_t *)addr; + buf = (void *)((uintptr_t)buf + xfrsize); + buflen -= xfrsize; + page++; + } + +out: + /* If there was an error, clear all error flags in status + * register (rc_w1 register so do this by writing the + * error bits). + */ + + if (ret != OK) + { + ferr("flash write error: %d, status: 0x%x\n", ret, + (unsigned)getreg32(STM32WL5_FLASH_SR)); + modifyreg32(STM32WL5_FLASH_SR, 0, FLASH_SR_ALLERRS); + } + + flash_lock(); + sem_unlock(); + return (ret == OK) ? written : ret; +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_flash.h b/arch/arm/src/stm32wl5/stm32wl5_flash.h new file mode 100644 index 0000000000..9978309d59 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_flash.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_flash.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_FLASH_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_FLASH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "hardware/stm32wl5_flash.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void stm32wl5_flash_lock(void); +void stm32wl5_flash_unlock(void); + +/**************************************************************************** + * Name: stm32wl5_flash_user_optbytes + * + * Description: + * Modify the contents of the user option bytes (USR OPT) on the flash. + * This does not set OBL_LAUNCH so new options take effect only after + * next power reset. + * + * Input Parameters: + * clrbits - Bits in the option bytes to be cleared + * setbits - Bits in the option bytes to be set + * + * Returned Value: + * Option bytes after operation is completed + * + ****************************************************************************/ + +uint32_t stm32wl5_flash_user_optbytes(uint32_t clrbits, uint32_t setbits); + +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_FLASH_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_gpio.c b/arch/arm/src/stm32wl5/stm32wl5_gpio.c new file mode 100644 index 0000000000..1a570cdf64 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_gpio.c @@ -0,0 +1,388 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_gpio.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "arm_internal.h" + +#include "chip.h" +#include "stm32wl5_gpio.h" + +#include "hardware/stm32wl5_syscfg.h" + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* Base addresses for each GPIO block */ + +const uint32_t g_gpiobase[STM32WL5_NPORTS] = +{ +#if STM32WL5_NPORTS > 0 + STM32WL5_GPIOA_BASE, +#endif +#if STM32WL5_NPORTS > 1 + STM32WL5_GPIOB_BASE, +#endif +#if STM32WL5_NPORTS > 2 + STM32WL5_GPIOC_BASE, +#endif +#if STM32WL5_NPORTS > 3 + STM32WL5_GPIOH_BASE, +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: stm32wl5_gpioinit + * + * Description: + * Based on configuration within the .config file, it does: + * - Remaps positions of alternative functions. + * + * Typically called from stm32wl5_start(). + * + * Assumptions: + * This function is called early in the initialization sequence so that + * no mutual exclusion is necessary. + * + ****************************************************************************/ + +void stm32wl5_gpioinit(void) +{ +} + +/**************************************************************************** + * Name: stm32wl5_configgpio + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * Once it is configured as Alternative (GPIO_ALT|GPIO_CNF_AFPP|...) + * function, it must be unconfigured with stm32wl5_unconfiggpio() with + * the same cfgset first before it can be set to non-alternative function. + * + * Returned Value: + * OK on success + * A negated errno value on invalid port, or when pin is locked as ALT + * function. + * + * To-Do: Auto Power Enable + ****************************************************************************/ + +int stm32wl5_configgpio(uint32_t cfgset) +{ + uintptr_t base; + uint32_t regval; + uint32_t setting; + unsigned int regoffset; + unsigned int port; + unsigned int pin; + unsigned int pos; + unsigned int pinmode; + irqstate_t flags; + + /* Verify that this hardware supports the select GPIO port */ + + port = (cfgset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + if (port >= STM32WL5_NPORTS) + { + return -EINVAL; + } + + /* Get the port base address */ + + base = g_gpiobase[port]; + + /* Get the pin number and select the port configuration register for that + * pin + */ + + pin = (cfgset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + /* Set up the mode register (and remember whether the pin mode) */ + + switch (cfgset & GPIO_MODE_MASK) + { + default: + case GPIO_INPUT: /* Input mode */ + pinmode = GPIO_MODER_INPUT; + break; + + case GPIO_OUTPUT: /* General purpose output mode */ + + /* Set the initial output value */ + + stm32wl5_gpiowrite(cfgset, (cfgset & GPIO_OUTPUT_SET) != 0); + pinmode = GPIO_MODER_OUTPUT; + break; + + case GPIO_ALT: /* Alternate function mode */ + pinmode = GPIO_MODER_ALT; + break; + + case GPIO_ANALOG: /* Analog mode */ + pinmode = GPIO_MODER_ANALOG; + break; + } + + /* Interrupts must be disabled from here on out so that we have mutually + * exclusive access to all of the GPIO configuration registers. + */ + + flags = enter_critical_section(); + + /* Now apply the configuration to the mode register */ + + regval = getreg32(base + STM32WL5_GPIO_MODER_OFFSET); + regval &= ~GPIO_MODER_MASK(pin); + regval |= ((uint32_t)pinmode << GPIO_MODER_SHIFT(pin)); + putreg32(regval, base + STM32WL5_GPIO_MODER_OFFSET); + + /* Set up the pull-up/pull-down configuration (all but analog pins) */ + + setting = GPIO_PUPDR_NONE; + if (pinmode != GPIO_MODER_ANALOG) + { + switch (cfgset & GPIO_PUPD_MASK) + { + default: + case GPIO_FLOAT: /* No pull-up, pull-down */ + break; + + case GPIO_PULLUP: /* Pull-up */ + setting = GPIO_PUPDR_PULLUP; + break; + + case GPIO_PULLDOWN: /* Pull-down */ + setting = GPIO_PUPDR_PULLDOWN; + break; + } + } + + regval = getreg32(base + STM32WL5_GPIO_PUPDR_OFFSET); + regval &= ~GPIO_PUPDR_MASK(pin); + regval |= (setting << GPIO_PUPDR_SHIFT(pin)); + putreg32(regval, base + STM32WL5_GPIO_PUPDR_OFFSET); + + /* Set the alternate function (Only alternate function pins) */ + + if (pinmode == GPIO_MODER_ALT) + { + setting = (cfgset & GPIO_AF_MASK) >> GPIO_AF_SHIFT; + } + else + { + setting = 0; + } + + if (pin < 8) + { + regoffset = STM32WL5_GPIO_AFRL_OFFSET; + pos = pin; + } + else + { + regoffset = STM32WL5_GPIO_AFRH_OFFSET; + pos = pin - 8; + } + + regval = getreg32(base + regoffset); + regval &= ~GPIO_AFR_MASK(pos); + regval |= (setting << GPIO_AFR_SHIFT(pos)); + putreg32(regval, base + regoffset); + + /* Set speed (Only outputs and alternate function pins) */ + + if (pinmode == GPIO_MODER_OUTPUT || pinmode == GPIO_MODER_ALT) + { + switch (cfgset & GPIO_SPEED_MASK) + { + default: + case GPIO_SPEED_2MHz: /* 2 MHz Low speed output */ + setting = GPIO_OSPEED_2MHz; + break; + + case GPIO_SPEED_25MHz: /* 25 MHz Medium speed output */ + setting = GPIO_OSPEED_25MHz; + break; + + case GPIO_SPEED_50MHz: /* 50 MHz High speed output */ + setting = GPIO_OSPEED_50MHz; + break; + + case GPIO_SPEED_100MHz: /* 100 MHz Very High speed output */ + setting = GPIO_OSPEED_100MHz; + break; + } + } + else + { + setting = 0; + } + + regval = getreg32(base + STM32WL5_GPIO_OSPEED_OFFSET); + regval &= ~GPIO_OSPEED_MASK(pin); + regval |= (setting << GPIO_OSPEED_SHIFT(pin)); + putreg32(regval, base + STM32WL5_GPIO_OSPEED_OFFSET); + + /* Set push-pull/open-drain (Only outputs and alternate function pins) */ + + regval = getreg32(base + STM32WL5_GPIO_OTYPER_OFFSET); + setting = GPIO_OTYPER_OD(pin); + + if ((pinmode == GPIO_MODER_OUTPUT || pinmode == GPIO_MODER_ALT) && + (cfgset & GPIO_OPENDRAIN) != 0) + { + regval |= setting; + } + else + { + regval &= ~setting; + } + + putreg32(regval, base + STM32WL5_GPIO_OTYPER_OFFSET); + + leave_critical_section(flags); + return OK; +} + +/**************************************************************************** + * Name: stm32wl5_unconfiggpio + * + * Description: + * Unconfigure a GPIO pin based on bit-encoded description of the pin, set + * it into default HiZ state (and possibly mark it's unused) and unlock it + * whether it was previously selected as alternative function + * (GPIO_ALT|GPIO_CNF_AFPP|...). + * + * This is a safety function and prevents hardware from shocks, as + * unexpected write to the Timer Channel Output GPIO to fixed '1' or '0' + * while it should operate in PWM mode could produce excessive on-board + * currents and trigger over-current/alarm function. + * + * Returned Value: + * OK on success + * A negated errno value on invalid port + * + * To-Do: Auto Power Disable + ****************************************************************************/ + +int stm32wl5_unconfiggpio(uint32_t cfgset) +{ + /* Reuse port and pin number and set it to default HiZ INPUT */ + + cfgset &= GPIO_PORT_MASK | GPIO_PIN_MASK; + cfgset |= GPIO_INPUT | GPIO_FLOAT; + + /* To-Do: Mark its unuse for automatic power saving options */ + + return stm32wl5_configgpio(cfgset); +} + +/**************************************************************************** + * Name: stm32wl5_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void stm32wl5_gpiowrite(uint32_t pinset, bool value) +{ + uint32_t base; + uint32_t bit; + unsigned int port; + unsigned int pin; + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + if (port < STM32WL5_NPORTS) + { + /* Get the port base address */ + + base = g_gpiobase[port]; + + /* Get the pin number */ + + pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + + /* Set or clear the output on the pin */ + + if (value) + { + bit = GPIO_BSRR_SET(pin); + } + else + { + bit = GPIO_BSRR_RESET(pin); + } + + putreg32(bit, base + STM32WL5_GPIO_BSRR_OFFSET); + } +} + +/**************************************************************************** + * Name: stm32wl5_gpioread + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool stm32wl5_gpioread(uint32_t pinset) +{ + uint32_t base; + unsigned int port; + unsigned int pin; + + port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT; + if (port < STM32WL5_NPORTS) + { + /* Get the port base address */ + + base = g_gpiobase[port]; + + /* Get the pin number and return the input state of that pin */ + + pin = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT; + return ((getreg32(base + STM32WL5_GPIO_IDR_OFFSET) & (1 << pin)) != 0); + } + + return 0; +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_gpio.h b/arch/arm/src/stm32wl5/stm32wl5_gpio.h new file mode 100644 index 0000000000..a666686198 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_gpio.h @@ -0,0 +1,359 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_gpio.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_GPIO_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_GPIO_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#ifndef __ASSEMBLY__ +# include +# include +#endif + +#include +#include + +#include "chip.h" + +#if defined(CONFIG_STM32WL5_STM32WL5XXX) +# include "hardware/stm32wl5_gpio.h" +#else +# error "Unsupported STM32WL5 chip" +#endif + +/**************************************************************************** + * Pre-Processor Declarations + ****************************************************************************/ + +/* Bit-encoded input to stm32wl5_configgpio() */ + +/* Each port bit of the general-purpose I/O (GPIO) ports can be individually + * configured by software in several modes: + * + * - Input floating + * - Input pull-up + * - Input-pull-down + * - Output open-drain with pull-up or pull-down capability + * - Output push-pull with pull-up or pull-down capability + * - Alternate function push-pull with pull-up or pull-down capability + * - Alternate function open-drain with pull-up or pull-down capability + * - Analog + * + * 20-bit Encoding: 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * Inputs: MMUU .... ...X PPPP BBBB + * Outputs: MMUU .... FFOV PPPP BBBB + * Alternate Functions: MMUU AAAA FFO. PPPP BBBB + * Analog: MM.. .... .... PPPP BBBB + */ + +/* Mode: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * MM.. .... .... .... .... + */ + +#define GPIO_MODE_SHIFT (18) /* Bits 18-19: GPIO port mode */ +#define GPIO_MODE_MASK (3 << GPIO_MODE_SHIFT) +# define GPIO_INPUT (0 << GPIO_MODE_SHIFT) /* Input mode */ +# define GPIO_OUTPUT (1 << GPIO_MODE_SHIFT) /* General purpose output mode */ +# define GPIO_ALT (2 << GPIO_MODE_SHIFT) /* Alternate function mode */ +# define GPIO_ANALOG (3 << GPIO_MODE_SHIFT) /* Analog mode */ + +/* Input/output pull-ups/downs (not used with analog): + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * ..UU .... .... .... .... + */ + +#define GPIO_PUPD_SHIFT (16) /* Bits 16-17: Pull-up/pull down */ +#define GPIO_PUPD_MASK (3 << GPIO_PUPD_SHIFT) +# define GPIO_FLOAT (0 << GPIO_PUPD_SHIFT) /* No pull-up, pull-down */ +# define GPIO_PULLUP (1 << GPIO_PUPD_SHIFT) /* Pull-up */ +# define GPIO_PULLDOWN (2 << GPIO_PUPD_SHIFT) /* Pull-down */ + +/* Alternate Functions: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... AAAA .... .... .... + */ + +#define GPIO_AF_SHIFT (12) /* Bits 12-15: Alternate function */ +#define GPIO_AF_MASK (15 << GPIO_AF_SHIFT) +# define GPIO_AF(n) ((n) << GPIO_AF_SHIFT) +# define GPIO_AF0 (0 << GPIO_AF_SHIFT) +# define GPIO_AF1 (1 << GPIO_AF_SHIFT) +# define GPIO_AF2 (2 << GPIO_AF_SHIFT) +# define GPIO_AF3 (3 << GPIO_AF_SHIFT) +# define GPIO_AF4 (4 << GPIO_AF_SHIFT) +# define GPIO_AF5 (5 << GPIO_AF_SHIFT) +# define GPIO_AF6 (6 << GPIO_AF_SHIFT) +# define GPIO_AF7 (7 << GPIO_AF_SHIFT) +# define GPIO_AF8 (8 << GPIO_AF_SHIFT) +# define GPIO_AF9 (9 << GPIO_AF_SHIFT) +# define GPIO_AF10 (10 << GPIO_AF_SHIFT) +# define GPIO_AF11 (11 << GPIO_AF_SHIFT) +# define GPIO_AF12 (12 << GPIO_AF_SHIFT) +# define GPIO_AF13 (13 << GPIO_AF_SHIFT) +# define GPIO_AF14 (14 << GPIO_AF_SHIFT) +# define GPIO_AF15 (15 << GPIO_AF_SHIFT) + +/* Output/Alt function frequency selection: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... FF.. .... .... + */ + +#define GPIO_SPEED_SHIFT (10) /* Bits 10-11: GPIO frequency selection */ +#define GPIO_SPEED_MASK (3 << GPIO_SPEED_SHIFT) +# define GPIO_SPEED_2MHz (0 << GPIO_SPEED_SHIFT) /* 2 MHz Low speed output */ +# define GPIO_SPEED_25MHz (1 << GPIO_SPEED_SHIFT) /* 25 MHz Medium speed output */ +# define GPIO_SPEED_50MHz (2 << GPIO_SPEED_SHIFT) /* 50 MHz High speed output */ +# define GPIO_SPEED_100MHz (3 << GPIO_SPEED_SHIFT) /* 100 MHz Very High speed output */ + +/* Output/Alt function type selection: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... ..O. .... .... + */ + +#define GPIO_OPENDRAIN (1 << 9) /* Bit9: 1=Open-drain output */ +#define GPIO_PUSHPULL (0) /* Bit9: 0=Push-pull output */ + +/* If the pin is a GPIO digital output, then this identifies the initial + * output value. If the pin is an input, this bit is overloaded to provide + * the qualifier to distinguish input pull-up and -down: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... ...V .... .... + */ + +#define GPIO_OUTPUT_SET (1 << 8) /* Bit 8: If output, initial value of output */ +#define GPIO_OUTPUT_CLEAR (0) + +/* External interrupt selection (GPIO inputs only): + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... ...X .... .... + */ + +#define GPIO_EXTI (1 << 8) /* Bit 8: Configure as EXTI interrupt */ + +/* This identifies the GPIO port: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... .... PPPP .... + */ + +#define GPIO_PORT_SHIFT (4) /* Bit 4-7: Port number */ +#define GPIO_PORT_MASK (15 << GPIO_PORT_SHIFT) +# define GPIO_PORTA (0 << GPIO_PORT_SHIFT) /* GPIOA */ +# define GPIO_PORTB (1 << GPIO_PORT_SHIFT) /* GPIOB */ +# define GPIO_PORTC (2 << GPIO_PORT_SHIFT) /* GPIOC */ +# define GPIO_PORTH (3 << GPIO_PORT_SHIFT) /* GPIOH */ + +/* This identifies the bit in the port: + * + * 1111 1111 1100 0000 0000 + * 9876 5432 1098 7654 3210 + * ---- ---- ---- ---- ---- + * .... .... .... .... BBBB + */ + +#define GPIO_PIN_SHIFT (0) /* Bits 0-3: GPIO number: 0-15 */ +#define GPIO_PIN_MASK (15 << GPIO_PIN_SHIFT) +# define GPIO_PIN0 (0 << GPIO_PIN_SHIFT) +# define GPIO_PIN1 (1 << GPIO_PIN_SHIFT) +# define GPIO_PIN2 (2 << GPIO_PIN_SHIFT) +# define GPIO_PIN3 (3 << GPIO_PIN_SHIFT) +# define GPIO_PIN4 (4 << GPIO_PIN_SHIFT) +# define GPIO_PIN5 (5 << GPIO_PIN_SHIFT) +# define GPIO_PIN6 (6 << GPIO_PIN_SHIFT) +# define GPIO_PIN7 (7 << GPIO_PIN_SHIFT) +# define GPIO_PIN8 (8 << GPIO_PIN_SHIFT) +# define GPIO_PIN9 (9 << GPIO_PIN_SHIFT) +# define GPIO_PIN10 (10 << GPIO_PIN_SHIFT) +# define GPIO_PIN11 (11 << GPIO_PIN_SHIFT) +# define GPIO_PIN12 (12 << GPIO_PIN_SHIFT) +# define GPIO_PIN13 (13 << GPIO_PIN_SHIFT) +# define GPIO_PIN14 (14 << GPIO_PIN_SHIFT) +# define GPIO_PIN15 (15 << GPIO_PIN_SHIFT) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* Base addresses for each GPIO block */ + +EXTERN const uint32_t g_gpiobase[STM32WL5_NPORTS]; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_configgpio + * + * Description: + * Configure a GPIO pin based on bit-encoded description of the pin. + * Once it is configured as Alternative (GPIO_ALT|GPIO_CNF_AFPP|...) + * function, it must be unconfigured with stm32wl5_unconfiggpio() with + * the same cfgset first before it can be set to non-alternative function. + * + * Returned Value: + * OK on success + * ERROR on invalid port, or when pin is locked as ALT function. + * + ****************************************************************************/ + +int stm32wl5_configgpio(uint32_t cfgset); + +/**************************************************************************** + * Name: stm32wl5_unconfiggpio + * + * Description: + * Unconfigure a GPIO pin based on bit-encoded description of the pin, set + * it into default HiZ state (and possibly mark it's unused) and unlock it + * whether it was previously selected as alternative function + * (GPIO_ALT|GPIO_CNF_AFPP|...). + * + * This is a safety function and prevents hardware from shocks, as + * unexpected write to the Timer Channel Output GPIO to fixed '1' or '0' + * while it should operate in PWM mode could produce excessive on-board + * currents and trigger over-current/alarm function. + * + * Returned Value: + * OK on success + * ERROR on invalid port + * + ****************************************************************************/ + +int stm32wl5_unconfiggpio(uint32_t cfgset); + +/**************************************************************************** + * Name: stm32wl5_gpiowrite + * + * Description: + * Write one or zero to the selected GPIO pin + * + ****************************************************************************/ + +void stm32wl5_gpiowrite(uint32_t pinset, bool value); + +/**************************************************************************** + * Name: stm32wl5_gpioread + * + * Description: + * Read one or zero from the selected GPIO pin + * + ****************************************************************************/ + +bool stm32wl5_gpioread(uint32_t pinset); + +/**************************************************************************** + * Name: stm32wl5_gpiosetevent + * + * Description: + * Sets/clears GPIO based event and interrupt triggers. + * + * Input Parameters: + * pinset - GPIO pin configuration + * risingedge - Enables interrupt on rising edges + * fallingedge - Enables interrupt on falling edges + * event - Generate event when set + * func - When non-NULL, generate interrupt + * arg - Argument passed to the interrupt callback + * + * Returned Value: + * Zero (OK) is returned on success, otherwise a negated errno value is + * returned to indicate the nature of the failure. + * + ****************************************************************************/ + +int stm32wl5_gpiosetevent(uint32_t pinset, bool risingedge, bool fallingedge, + bool event, xcpt_t func, void *arg); + +/**************************************************************************** + * Function: stm32wl5_dumpgpio + * + * Description: + * Dump all GPIO registers associated with the provided base address + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +int stm32wl5_dumpgpio(uint32_t pinset, const char *msg); +#else +# define stm32wl5_dumpgpio(p,m) +#endif + +/**************************************************************************** + * Function: stm32wl5_gpioinit + * + * Description: + * Based on configuration within the .config file, it does: + * - Remaps positions of alternative functions. + * + * Typically called from stm32wl5_start(). + * + ****************************************************************************/ + +void stm32wl5_gpioinit(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_GPIO_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_idle.c b/arch/arm/src/stm32wl5/stm32wl5_idle.c new file mode 100644 index 0000000000..cebad64ad7 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_idle.c @@ -0,0 +1,96 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_idle.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include + +#include "chip.h" +#include "stm32wl5_rcc.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Does the board support an IDLE LED to indicate that the board is in the + * IDLE state? + */ + +#if defined(CONFIG_ARCH_LEDS) && defined(LED_IDLE) +# define BEGIN_IDLE() board_autoled_on(LED_IDLE) +# define END_IDLE() board_autoled_off(LED_IDLE) +#else +# define BEGIN_IDLE() +# define END_IDLE() +#endif + +#define PM_IDLE_DOMAIN 0 /* Revisit */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_idle + * + * Description: + * up_idle() is the logic that will be executed when there is no other + * ready-to-run task. This is processor idle time and will continue until + * some interrupt occurs to cause a context switch from the idle task. + * + * Processing in this state may be processor-specific. e.g., this is where + * power management operations might be performed. + * + ****************************************************************************/ + +void up_idle(void) +{ +#if defined(CONFIG_SUPPRESS_INTERRUPTS) || defined(CONFIG_SUPPRESS_TIMER_INTS) + /* If the system is idle and there are no timer interrupts, then process + * "fake" timer interrupts. Hopefully, something will wake up. + */ + + nxsched_process_timer(); +#else + + /* Sleep until an interrupt occurs to save power. */ + +#if !(defined(CONFIG_DEBUG_SYMBOLS) && defined(CONFIG_STM32WL5_DISABLE_IDLE_SLEEP_DURING_DEBUG)) + BEGIN_IDLE(); + asm("WFI"); + END_IDLE(); +#endif + +#endif +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_irq.c b/arch/arm/src/stm32wl5/stm32wl5_irq.c new file mode 100644 index 0000000000..aba4945a78 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_irq.c @@ -0,0 +1,537 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_irq.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include "nvic.h" +#include "ram_vectors.h" +#include "arm_internal.h" +#include "arm_internal.h" +#include "stm32wl5.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Get a 32-bit version of the default priority */ + +#define DEFPRIORITY32 \ + (NVIC_SYSH_PRIORITY_DEFAULT << 24 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 16 | \ + NVIC_SYSH_PRIORITY_DEFAULT << 8 | \ + NVIC_SYSH_PRIORITY_DEFAULT) + +/* Given the address of a NVIC ENABLE register, this is the offset to + * the corresponding CLEAR ENABLE register. + */ + +#define NVIC_ENA_OFFSET (0) +#define NVIC_CLRENA_OFFSET (NVIC_IRQ0_31_CLEAR - NVIC_IRQ0_31_ENABLE) + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* g_current_regs[] holds a references to the current interrupt level + * register storage structure. If is non-NULL only during interrupt + * processing. Access to g_current_regs[] must be through the macro + * CURRENT_REGS for portability. + */ + +volatile uint32_t *g_current_regs[1]; + +/* This is the address of the exception vector table (determined by the + * linker script). + */ + +extern uint32_t _vectors[]; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_dumpnvic + * + * Description: + * Dump some interesting NVIC registers + * + ****************************************************************************/ + +#if defined(CONFIG_DEBUG_IRQ_INFO) +static void stm32wl5_dumpnvic(const char *msg, int irq) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + irqinfo("NVIC (%s, irq=%d):\n", msg, irq); + irqinfo(" INTCTRL: %08x VECTAB: %08x\n", + getreg32(NVIC_INTCTRL), getreg32(NVIC_VECTAB)); +#if 0 + irqinfo(" SYSH ENABLE MEMFAULT: %08x BUSFAULT: %08x USGFAULT: %08x " + "SYSTICK: %08x\n", + getreg32(NVIC_SYSHCON_MEMFAULTENA), + getreg32(NVIC_SYSHCON_BUSFAULTENA), + getreg32(NVIC_SYSHCON_USGFAULTENA), + getreg32(NVIC_SYSTICK_CTRL_ENABLE)); +#endif + irqinfo(" IRQ ENABLE: %08x %08x %08x\n", + getreg32(NVIC_IRQ0_31_ENABLE), + getreg32(NVIC_IRQ32_63_ENABLE), + getreg32(NVIC_IRQ64_95_ENABLE)); + irqinfo(" SYSH_PRIO: %08x %08x %08x\n", + getreg32(NVIC_SYSH4_7_PRIORITY), + getreg32(NVIC_SYSH8_11_PRIORITY), + getreg32(NVIC_SYSH12_15_PRIORITY)); + irqinfo(" IRQ PRIO: %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ0_3_PRIORITY), + getreg32(NVIC_IRQ4_7_PRIORITY), + getreg32(NVIC_IRQ8_11_PRIORITY), + getreg32(NVIC_IRQ12_15_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ16_19_PRIORITY), + getreg32(NVIC_IRQ20_23_PRIORITY), + getreg32(NVIC_IRQ24_27_PRIORITY), + getreg32(NVIC_IRQ28_31_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ32_35_PRIORITY), + getreg32(NVIC_IRQ36_39_PRIORITY), + getreg32(NVIC_IRQ40_43_PRIORITY), + getreg32(NVIC_IRQ44_47_PRIORITY)); + irqinfo(" %08x %08x %08x %08x\n", + getreg32(NVIC_IRQ48_51_PRIORITY), + getreg32(NVIC_IRQ52_55_PRIORITY), + getreg32(NVIC_IRQ56_59_PRIORITY), + getreg32(NVIC_IRQ60_63_PRIORITY)); + irqinfo(" %08x\n", + getreg32(NVIC_IRQ64_67_PRIORITY)); + + leave_critical_section(flags); +} +#else +# define stm32wl5_dumpnvic(msg, irq) +#endif + +/**************************************************************************** + * Name: stm32wl5_nmi, stm32wl5_busfault, stm32wl5_usagefault, + * stm32wl5_pendsv, stm32wl5_dbgmonitor, stm32wl5_pendsv, + * stm32wl5_reserved + * + * Description: + * Handlers for various exceptions. None are handled and all are fatal + * error conditions. The only advantage these provided over the default + * unexpected interrupt handler is that they provide a diagnostic output. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +static int stm32wl5_nmi(int irq, FAR void *context, FAR void *arg) +{ + up_irq_save(); + _err("PANIC!!! NMI received\n"); + PANIC(); + return 0; +} + +static int stm32wl5_busfault(int irq, FAR void *context, FAR void *arg) +{ + up_irq_save(); + _err("PANIC!!! Bus fault received: %08x\n", + (unsigned int)getreg32(NVIC_CFAULTS)); + PANIC(); + return 0; +} + +static int stm32wl5_usagefault(int irq, FAR void *context, FAR void *arg) +{ + up_irq_save(); + _err("PANIC!!! Usage fault received: %08x\n", + (unsigned int)getreg32(NVIC_CFAULTS)); + PANIC(); + return 0; +} + +static int stm32wl5_pendsv(int irq, FAR void *context, FAR void *arg) +{ + up_irq_save(); + _err("PANIC!!! PendSV received\n"); + PANIC(); + return 0; +} + +static int stm32wl5_dbgmonitor(int irq, FAR void *context, FAR void *arg) +{ + up_irq_save(); + _err("PANIC!!! Debug Monitor received\n"); + PANIC(); + return 0; +} + +static int stm32wl5_reserved(int irq, FAR void *context, FAR void *arg) +{ + up_irq_save(); + _err("PANIC!!! Reserved interrupt\n"); + PANIC(); + return 0; +} +#endif + +/**************************************************************************** + * Name: stm32wl5_prioritize_syscall + * + * Description: + * Set the priority of an exception. This function may be needed + * internally even if support for prioritized interrupts is not enabled. + * + ****************************************************************************/ + +#ifdef CONFIG_ARMV7M_USEBASEPRI +static inline void stm32wl5_prioritize_syscall(int priority) +{ + uint32_t regval; + + /* SVCALL is system handler 11 */ + + regval = getreg32(NVIC_SYSH8_11_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR11_MASK; + regval |= (priority << NVIC_SYSH_PRIORITY_PR11_SHIFT); + putreg32(regval, NVIC_SYSH8_11_PRIORITY); +} +#endif + +/**************************************************************************** + * Name: stm32wl5_irqinfo + * + * Description: + * Given an IRQ number, provide the register and bit setting to enable or + * disable the irq. + * + ****************************************************************************/ + +static int stm32wl5_irqinfo(int irq, uintptr_t *regaddr, uint32_t *bit, + uintptr_t offset) +{ + int n; + + DEBUGASSERT(irq >= STM32WL5_IRQ_NMI && irq < NR_IRQS); + + /* Check for external interrupt */ + + if (irq >= STM32WL5_IRQ_FIRST) + { + n = irq - STM32WL5_IRQ_FIRST; + *regaddr = NVIC_IRQ_ENABLE(n) + offset; + *bit = (uint32_t)1 << (n & 0x1f); + } + + /* Handle processor exceptions. Only a few can be disabled */ + + else + { + *regaddr = NVIC_SYSHCON; + if (irq == STM32WL5_IRQ_MEMFAULT) + { + *bit = NVIC_SYSHCON_MEMFAULTENA; + } + else if (irq == STM32WL5_IRQ_BUSFAULT) + { + *bit = NVIC_SYSHCON_BUSFAULTENA; + } + else if (irq == STM32WL5_IRQ_USAGEFAULT) + { + *bit = NVIC_SYSHCON_USGFAULTENA; + } + else if (irq == STM32WL5_IRQ_SYSTICK) + { + *regaddr = NVIC_SYSTICK_CTRL; + *bit = NVIC_SYSTICK_CTRL_ENABLE; + } + else + { + return ERROR; /* Invalid or unsupported exception */ + } + } + + return OK; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: up_irqinitialize + ****************************************************************************/ + +void up_irqinitialize(void) +{ + uint32_t regaddr; + int num_priority_registers; + int i; + + /* Disable all interrupts */ + + for (i = 0; i < NR_IRQS - STM32WL5_IRQ_FIRST; i += 32) + { + putreg32(0xffffffff, NVIC_IRQ_CLEAR(i)); + } + + /* The standard location for the vector table is at the beginning of FLASH + * at address 0x0800:0000. If we are using the STMicro DFU bootloader, + * then the vector table will be offset to a different location in FLASH + * and we will need to set the NVIC vector location to this alternative + * location. + */ + + putreg32((uint32_t)_vectors, NVIC_VECTAB); + +#ifdef CONFIG_ARCH_RAMVECTORS + /* If CONFIG_ARCH_RAMVECTORS is defined, then we are using a RAM-based + * vector table that requires special initialization. + */ + + arm_ramvec_initialize(); +#endif + + /* Set all interrupts (and exceptions) to the default priority */ + + putreg32(DEFPRIORITY32, NVIC_SYSH4_7_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH8_11_PRIORITY); + putreg32(DEFPRIORITY32, NVIC_SYSH12_15_PRIORITY); + + /* The NVIC ICTR register (bits 0-4) holds the number of interrupt + * lines that the NVIC supports: + * + * 0 -> 32 interrupt lines, 8 priority registers + * 1 -> 64 " " " ", 16 priority registers + * 2 -> 96 " " " ", 32 priority registers + * ... + */ + + num_priority_registers = (getreg32(NVIC_ICTR) + 1) * 8; + + /* Now set all of the interrupt lines to the default priority */ + + regaddr = NVIC_IRQ0_3_PRIORITY; + while (num_priority_registers--) + { + putreg32(DEFPRIORITY32, regaddr); + regaddr += 4; + } + + /* currents_regs is non-NULL only while processing an interrupt */ + + CURRENT_REGS = NULL; + + /* Attach the SVCall and Hard Fault exception handlers. The SVCall + * exception is used for performing context switches; The Hard Fault + * must also be caught because a SVCall may show up as a Hard Fault + * under certain conditions. + */ + + irq_attach(STM32WL5_IRQ_SVCALL, arm_svcall, NULL); + irq_attach(STM32WL5_IRQ_HARDFAULT, arm_hardfault, NULL); + + /* Set the priority of the SVCall interrupt */ + +#ifdef CONFIG_ARCH_IRQPRIO + /* up_prioritize_irq(STM32WL5_IRQ_PENDSV, NVIC_SYSH_PRIORITY_MIN); */ +#endif +#ifdef CONFIG_ARMV7M_USEBASEPRI + stm32wl5_prioritize_syscall(NVIC_SYSH_SVCALL_PRIORITY); +#endif + + /* If the MPU is enabled, then attach and enable the Memory Management + * Fault handler. + */ + +#ifdef CONFIG_ARM_MPU + irq_attach(STM32WL5_IRQ_MEMFAULT, arm_memfault, NULL); + up_enable_irq(STM32WL5_IRQ_MEMFAULT); +#endif + + /* Attach all other processor exceptions (except reset and sys tick) */ + +#ifdef CONFIG_DEBUG_FEATURES + irq_attach(STM32WL5_IRQ_NMI, stm32wl5_nmi, NULL); +#ifndef CONFIG_ARM_MPU + irq_attach(STM32WL5_IRQ_MEMFAULT, arm_memfault, NULL); +#endif + irq_attach(STM32WL5_IRQ_BUSFAULT, stm32wl5_busfault, NULL); + irq_attach(STM32WL5_IRQ_USAGEFAULT, stm32wl5_usagefault, NULL); + irq_attach(STM32WL5_IRQ_PENDSV, stm32wl5_pendsv, NULL); + irq_attach(STM32WL5_IRQ_DBGMONITOR, stm32wl5_dbgmonitor, NULL); + irq_attach(STM32WL5_IRQ_RESERVED, stm32wl5_reserved, NULL); +#endif + + stm32wl5_dumpnvic("initial", NR_IRQS); + +#ifndef CONFIG_SUPPRESS_INTERRUPTS + + /* And finally, enable interrupts */ + + up_irq_enable(); +#endif +} + +/**************************************************************************** + * Name: up_disable_irq + * + * Description: + * Disable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_disable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (stm32wl5_irqinfo(irq, ®addr, &bit, NVIC_CLRENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to disable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Clear Enable register. For other exceptions, we need to + * clear the bit in the System Handler Control and State Register. + */ + + if (irq >= STM32WL5_IRQ_FIRST) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval &= ~bit; + putreg32(regval, regaddr); + } + } +} + +/**************************************************************************** + * Name: up_enable_irq + * + * Description: + * Enable the IRQ specified by 'irq' + * + ****************************************************************************/ + +void up_enable_irq(int irq) +{ + uintptr_t regaddr; + uint32_t regval; + uint32_t bit; + + if (stm32wl5_irqinfo(irq, ®addr, &bit, NVIC_ENA_OFFSET) == 0) + { + /* Modify the appropriate bit in the register to enable the interrupt. + * For normal interrupts, we need to set the bit in the associated + * Interrupt Set Enable register. For other exceptions, we need to + * set the bit in the System Handler Control and State Register. + */ + + if (irq >= STM32WL5_IRQ_FIRST) + { + putreg32(bit, regaddr); + } + else + { + regval = getreg32(regaddr); + regval |= bit; + putreg32(regval, regaddr); + } + } +} + +/**************************************************************************** + * Name: arm_ack_irq + * + * Description: + * Acknowledge the IRQ + * + ****************************************************************************/ + +void arm_ack_irq(int irq) +{ +} + +/**************************************************************************** + * Name: up_prioritize_irq + * + * Description: + * Set the priority of an IRQ. + * + * Since this API is not supported on all architectures, it should be + * avoided in common implementations where possible. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_IRQPRIO +int up_prioritize_irq(int irq, int priority) +{ + uint32_t regaddr; + uint32_t regval; + int shift; + + DEBUGASSERT(irq >= STM32WL5_IRQ_MEMFAULT && irq < NR_IRQS && + (unsigned)priority <= NVIC_SYSH_PRIORITY_MIN); + + if (irq < STM32WL5_IRQ_FIRST) + { + /* NVIC_SYSH_PRIORITY() maps {0..15} to one of three priority + * registers (0-3 are invalid) + */ + + regaddr = NVIC_SYSH_PRIORITY(irq); + irq -= 4; + } + else + { + /* NVIC_IRQ_PRIORITY() maps {0..} to one of many priority registers */ + + irq -= STM32WL5_IRQ_FIRST; + regaddr = NVIC_IRQ_PRIORITY(irq); + } + + regval = getreg32(regaddr); + shift = ((irq & 3) << 3); + regval &= ~(0xff << shift); + regval |= (priority << shift); + putreg32(regval, regaddr); + + stm32wl5_dumpnvic("prioritize", irq); + return OK; +} +#endif diff --git a/arch/arm/src/stm32wl5/stm32wl5_lowputc.c b/arch/arm/src/stm32wl5/stm32wl5_lowputc.c new file mode 100644 index 0000000000..b7c8717d1f --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_lowputc.c @@ -0,0 +1,347 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_lowputc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "arm_internal.h" +#include "arm_internal.h" + +#include "chip.h" + +#include "stm32wl5.h" +#include "stm32wl5_rcc.h" +#include "stm32wl5_gpio.h" +#include "stm32wl5_uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Select USART parameters for the selected console */ + +#ifdef HAVE_CONSOLE +# if defined(CONFIG_LPUART1_SERIAL_CONSOLE) +# define STM32WL5_CONSOLE_BASE STM32WL5_LPUART1_BASE +# define STM32WL5_APBCLOCK STM32WL5_PCLK1_FREQUENCY +# define STM32WL5_CONSOLE_APBREG STM32WL5_RCC_APB1ENR2 +# define STM32WL5_CONSOLE_APBEN RCC_APB1ENR2_LPUART1EN +# define STM32WL5_CONSOLE_BAUD CONFIG_LPUART1_BAUD +# define STM32WL5_CONSOLE_BITS CONFIG_LPUART1_BITS +# define STM32WL5_CONSOLE_PARITY CONFIG_LPUART1_PARITY +# define STM32WL5_CONSOLE_2STOP CONFIG_LPUART1_2STOP +# define STM32WL5_CONSOLE_TX GPIO_LPUART1_TX +# define STM32WL5_CONSOLE_RX GPIO_LPUART1_RX +# ifdef CONFIG_LPUART1_RS485 +# define STM32WL5_CONSOLE_RS485_DIR GPIO_LPUART1_RS485_DIR +# if (CONFIG_LPUART1_RS485_DIR_POLARITY == 0) +# define STM32WL5_CONSOLE_RS485_DIR_POLARITY false +# else +# define STM32WL5_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# elif defined(CONFIG_USART1_SERIAL_CONSOLE) +# define STM32WL5_CONSOLE_BASE STM32WL5_USART1_BASE +# define STM32WL5_APBCLOCK STM32WL5_PCLK2_FREQUENCY +# define STM32WL5_CONSOLE_APBREG STM32WL5_RCC_APB2ENR +# define STM32WL5_CONSOLE_APBEN RCC_APB2ENR_USART1EN +# define STM32WL5_CONSOLE_BAUD CONFIG_USART1_BAUD +# define STM32WL5_CONSOLE_BITS CONFIG_USART1_BITS +# define STM32WL5_CONSOLE_PARITY CONFIG_USART1_PARITY +# define STM32WL5_CONSOLE_2STOP CONFIG_USART1_2STOP +# define STM32WL5_CONSOLE_TX GPIO_USART1_TX +# define STM32WL5_CONSOLE_RX GPIO_USART1_RX +# ifdef CONFIG_USART1_RS485 +# define STM32WL5_CONSOLE_RS485_DIR GPIO_USART1_RS485_DIR +# if (CONFIG_USART1_RS485_DIR_POLARITY == 0) +# define STM32WL5_CONSOLE_RS485_DIR_POLARITY false +# else +# define STM32WL5_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# elif defined(CONFIG_USART2_SERIAL_CONSOLE) +# define STM32WL5_CONSOLE_BASE STM32WL5_USART2_BASE +# define STM32WL5_APBCLOCK STM32WL5_PCLK1_FREQUENCY +# define STM32WL5_CONSOLE_APBREG STM32WL5_RCC_APB1ENR1 +# define STM32WL5_CONSOLE_APBEN RCC_APB1ENR1_USART2EN +# define STM32WL5_CONSOLE_BAUD CONFIG_USART2_BAUD +# define STM32WL5_CONSOLE_BITS CONFIG_USART2_BITS +# define STM32WL5_CONSOLE_PARITY CONFIG_USART2_PARITY +# define STM32WL5_CONSOLE_2STOP CONFIG_USART2_2STOP +# define STM32WL5_CONSOLE_TX GPIO_USART2_TX +# define STM32WL5_CONSOLE_RX GPIO_USART2_RX +# ifdef CONFIG_USART2_RS485 +# define STM32WL5_CONSOLE_RS485_DIR GPIO_USART2_RS485_DIR +# if (CONFIG_USART2_RS485_DIR_POLARITY == 0) +# define STM32WL5_CONSOLE_RS485_DIR_POLARITY false +# else +# define STM32WL5_CONSOLE_RS485_DIR_POLARITY true +# endif +# endif +# endif + + /* CR1 settings */ + +# if STM32WL5_CONSOLE_BITS == 9 +# define USART_CR1_M0_VALUE USART_CR1_M0 +# define USART_CR1_M1_VALUE 0 +# elif STM32WL5_CONSOLE_BITS == 7 +# define USART_CR1_M0_VALUE 0 +# define USART_CR1_M1_VALUE USART_CR1_M1 +# else /* 8 bits */ +# define USART_CR1_M0_VALUE 0 +# define USART_CR1_M1_VALUE 0 +# endif + +# if STM32WL5_CONSOLE_PARITY == 1 /* odd parity */ +# define USART_CR1_PARITY_VALUE (USART_CR1_PCE|USART_CR1_PS) +# elif STM32WL5_CONSOLE_PARITY == 2 /* even parity */ +# define USART_CR1_PARITY_VALUE USART_CR1_PCE +# else /* no parity */ +# define USART_CR1_PARITY_VALUE 0 +# endif + +# define USART_CR1_CLRBITS \ + (USART_CR1_UE | USART_CR1_UESM | USART_CR1_RE | USART_CR1_TE | USART_CR1_PS | \ + USART_CR1_PCE | USART_CR1_WAKE | USART_CR1_M0 | USART_CR1_M1 | \ + USART_CR1_MME | USART_CR1_OVER8 | USART_CR1_DEDT_MASK | \ + USART_CR1_DEAT_MASK | USART_CR1_ALLINTS) + +# define USART_CR1_SETBITS (USART_CR1_M0_VALUE|USART_CR1_M1_VALUE|USART_CR1_PARITY_VALUE) + + /* CR2 settings */ + +# if STM32WL5_CONSOLE_2STOP != 0 +# define USART_CR2_STOP2_VALUE USART_CR2_STOP2 +# else +# define USART_CR2_STOP2_VALUE 0 +# endif + +# define USART_CR2_CLRBITS \ + (USART_CR2_ADDM7 | USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL | \ + USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_STOP_MASK | \ + USART_CR2_LINEN | USART_CR2_SWAP | USART_CR2_RXINV | USART_CR2_TXINV | \ + USART_CR2_DATAINV | USART_CR2_MSBFIRST | USART_CR2_ABREN | \ + USART_CR2_ABRMOD_MASK | USART_CR2_RTOEN | USART_CR2_ADD_MASK) + +# define USART_CR2_SETBITS USART_CR2_STOP2_VALUE + + /* CR3 settings */ + +# define USART_CR3_CLRBITS \ + (USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | USART_CR3_HDSEL | \ + USART_CR3_NACK | USART_CR3_SCEN | USART_CR3_DMAR | USART_CR3_DMAT | \ + USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT | \ + USART_CR3_OVRDIS | USART_CR3_DDRE | USART_CR3_DEM | USART_CR3_DEP | \ + USART_CR3_SCARCNT2_MASK | USART_CR3_WUS_MASK | USART_CR3_WUFIE) + +# define USART_CR3_SETBITS 0 + +# undef USE_OVER8 + + /* Calculate USART BAUD rate divider */ + + /* Baud rate for standard USART (SPI mode included): + * + * In case of oversampling by 16, the equation is: + * baud = fCK / UARTDIV + * UARTDIV = fCK / baud + * + * In case of oversampling by 8, the equation is: + * + * baud = 2 * fCK / UARTDIV + * UARTDIV = 2 * fCK / baud + */ + +# define STM32WL5_USARTDIV8 \ + (((STM32WL5_APBCLOCK << 1) + (STM32WL5_CONSOLE_BAUD >> 1)) / STM32WL5_CONSOLE_BAUD) +# define STM32WL5_USARTDIV16 \ + ((STM32WL5_APBCLOCK + (STM32WL5_CONSOLE_BAUD >> 1)) / STM32WL5_CONSOLE_BAUD) + + /* Use oversamply by 8 only if the divisor is small. But what is small? */ + +# if defined(CONFIG_LPUART1_SERIAL_CONSOLE) + /* lpuart has different formula for baud rate than normal uart */ +# define STM32WL5_BRR_VALUE \ + (((256ull * STM32WL5_APBCLOCK) / STM32WL5_CONSOLE_BAUD) & LPUART_BRR_MASK) +# else /* CONFIG_LPUART1_SERIAL_CONSOLE */ +# if STM32WL5_USARTDIV8 > 2000 +# define STM32WL5_BRR_VALUE STM32WL5_USARTDIV16 +# else +# define USE_OVER8 1 +# define STM32WL5_BRR_VALUE \ + ((STM32WL5_USARTDIV8 & 0xfff0) | ((STM32WL5_USARTDIV8 & 0x000f) >> 1)) +# endif +# endif /* CONFIG_LPUART1_SERIAL_CONSOLE */ + +#endif /* HAVE_CONSOLE */ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/**************************************************************************** + * Private Variables + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: arm_lowputc + * + * Description: + * Output one byte on the serial console + * + ****************************************************************************/ + +void arm_lowputc(char ch) +{ +#ifdef HAVE_CONSOLE + /* Wait until the TX data register is empty */ + + while ((getreg32(STM32WL5_CONSOLE_BASE + STM32WL5_USART_ISR_OFFSET) & + USART_ISR_TXE) == 0); +#ifdef STM32WL5_CONSOLE_RS485_DIR + stm32wl5_gpiowrite(STM32WL5_CONSOLE_RS485_DIR, + STM32WL5_CONSOLE_RS485_DIR_POLARITY); +#endif + + /* Then send the character */ + + putreg32((uint32_t)ch, STM32WL5_CONSOLE_BASE + STM32WL5_USART_TDR_OFFSET); + +#ifdef STM32WL5_CONSOLE_RS485_DIR + while ((getreg32(STM32WL5_CONSOLE_BASE + STM32WL5_USART_ISR_OFFSET) & + USART_ISR_TC) == 0); + stm32wl5_gpiowrite(STM32WL5_CONSOLE_RS485_DIR, + !STM32WL5_CONSOLE_RS485_DIR_POLARITY); +#endif + +#endif /* HAVE_CONSOLE */ +} + +/**************************************************************************** + * Name: stm32wl5_lowsetup + * + * Description: + * This performs basic initialization of the USART used for the serial + * console. Its purpose is to get the console output available as soon + * as possible. + * + ****************************************************************************/ + +void stm32wl5_lowsetup(void) +{ +#if defined(HAVE_UART) +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) + uint32_t cr; +#endif + +#if defined(HAVE_CONSOLE) + /* Enable USART APB1/2 clock */ + + modifyreg32(STM32WL5_CONSOLE_APBREG, 0, STM32WL5_CONSOLE_APBEN); +#endif + + /* Enable the console USART and configure GPIO pins needed for rx/tx. + * + * NOTE: Clocking for selected U[S]ARTs was already provided in + * stm32wl5_rcc.c + */ + +#ifdef STM32WL5_CONSOLE_TX + stm32wl5_configgpio(STM32WL5_CONSOLE_TX); +#endif +#ifdef STM32WL5_CONSOLE_RX + stm32wl5_configgpio(STM32WL5_CONSOLE_RX); +#endif + +#ifdef STM32WL5_CONSOLE_RS485_DIR + stm32wl5_configgpio(STM32WL5_CONSOLE_RS485_DIR); + stm32wl5_gpiowrite(STM32WL5_CONSOLE_RS485_DIR, + !STM32WL5_CONSOLE_RS485_DIR_POLARITY); +#endif + + /* Enable and configure the selected console device */ + +#if defined(HAVE_CONSOLE) && !defined(CONFIG_SUPPRESS_UART_CONFIG) + /* Configure CR2 */ + + cr = getreg32(STM32WL5_CONSOLE_BASE + STM32WL5_USART_CR2_OFFSET); + cr &= ~USART_CR2_CLRBITS; + cr |= USART_CR2_SETBITS; + putreg32(cr, STM32WL5_CONSOLE_BASE + STM32WL5_USART_CR2_OFFSET); + + /* Configure CR1 */ + + cr = getreg32(STM32WL5_CONSOLE_BASE + STM32WL5_USART_CR1_OFFSET); + cr &= ~USART_CR1_CLRBITS; + cr |= USART_CR1_SETBITS; + putreg32(cr, STM32WL5_CONSOLE_BASE + STM32WL5_USART_CR1_OFFSET); + + /* Configure CR3 */ + + cr = getreg32(STM32WL5_CONSOLE_BASE + STM32WL5_USART_CR3_OFFSET); + cr &= ~USART_CR3_CLRBITS; + cr |= USART_CR3_SETBITS; + putreg32(cr, STM32WL5_CONSOLE_BASE + STM32WL5_USART_CR3_OFFSET); + + /* Configure the USART Baud Rate */ + + putreg32(STM32WL5_BRR_VALUE, + STM32WL5_CONSOLE_BASE + STM32WL5_USART_BRR_OFFSET); + + /* Select oversampling by 8 */ + + cr = getreg32(STM32WL5_CONSOLE_BASE + STM32WL5_USART_CR1_OFFSET); +#ifdef USE_OVER8 + cr |= USART_CR1_OVER8; + putreg32(cr, STM32WL5_CONSOLE_BASE + STM32WL5_USART_CR1_OFFSET); +#endif + + /* Enable Rx, Tx, and the USART */ + + cr |= (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE); + putreg32(cr, STM32WL5_CONSOLE_BASE + STM32WL5_USART_CR1_OFFSET); + +#endif /* HAVE_CONSOLE && !CONFIG_SUPPRESS_UART_CONFIG */ +#endif /* HAVE_UART */ +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_lowputc.h b/arch/arm/src/stm32wl5/stm32wl5_lowputc.h new file mode 100644 index 0000000000..28a9e972b3 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_lowputc.h @@ -0,0 +1,64 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_lowputc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_LOWPUTC_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_LOWPUTC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: stm32wl5_lowsetup + * + * Description: + * Called at the very beginning of _start. Performs low level + * initialization of serial console. + * + ****************************************************************************/ + +void stm32wl5_lowsetup(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_LOWPUTC_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_lse.c b/arch/arm/src/stm32wl5/stm32wl5_lse.c new file mode 100644 index 0000000000..509290cff9 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_lse.c @@ -0,0 +1,187 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_lse.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "arm_internal.h" + +#include "stm32wl5_pwr.h" +#include "stm32wl5_rcc.h" +#include "stm32wl5_waste.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define LSERDY_TIMEOUT (500 * CONFIG_BOARD_LOOPSPERMSEC) + +#ifdef CONFIG_STM32WL5_RTC_LSECLOCK_START_DRV_CAPABILITY +# if CONFIG_STM32WL5_RTC_LSECLOCK_START_DRV_CAPABILITY < 0 || \ + CONFIG_STM32WL5_RTC_LSECLOCK_START_DRV_CAPABILITY > 3 +# error "Invalid LSE drive capability setting" +#endif +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifdef CONFIG_STM32WL5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY +static const uint32_t drives[4] = +{ + RCC_BDCR_LSEDRV_LOW, + RCC_BDCR_LSEDRV_MEDLO, + RCC_BDCR_LSEDRV_MEDHI, + RCC_BDCR_LSEDRV_HIGH +}; +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_rcc_enablelse + * + * Description: + * Enable the External Low-Speed (LSE) oscillator and the LSE system clock. + * + ****************************************************************************/ + +void stm32wl5_rcc_enablelse(void) +{ + int writable; + uint32_t regval; + volatile int32_t timeout; +#ifdef CONFIG_STM32WL5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY + volatile int32_t drive = 0; +#endif + + /* Check if both the External Low-Speed (LSE) oscillator and the LSE system + * clock are already running. + */ + + regval = getreg32(STM32WL5_RCC_BDCR); + + if ((regval & (RCC_BDCR_LSEON | RCC_BDCR_LSERDY | + RCC_BDCR_LSESYSEN | RCC_BDCR_LSESYSEN)) != + (RCC_BDCR_LSEON | RCC_BDCR_LSERDY | + RCC_BDCR_LSESYSEN | RCC_BDCR_LSESYSEN)) + { + /* The LSE is in the RTC domain and write access is denied to this + * domain after reset, you have to enable write access using DBP bit in + * the PWR CR register before to configuring the LSE. + */ + + writable = stm32wl5_pwr_enablebkp(true); + + /* Enable the External Low-Speed (LSE) oscillator by setting the LSEON + * bit the RCC BDCR register. + */ + + regval |= RCC_BDCR_LSEON; + +#ifdef CONFIG_STM32WL5_RTC_LSECLOCK_START_DRV_CAPABILITY + /* Set start-up drive capability for LSE oscillator. LSE must be OFF + * to change drive strength. + */ + + regval &= ~(RCC_BDCR_LSEDRV_MASK | RCC_BDCR_LSEON); + regval |= CONFIG_STM32WL5_RTC_LSECLOCK_START_DRV_CAPABILITY << + RCC_BDCR_LSEDRV_SHIFT; + putreg32(regval, STM32WL5_RCC_BDCR); + regval |= RCC_BDCR_LSEON; +#endif + +#ifdef CONFIG_STM32WL5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY + do + { + regval &= ~(RCC_BDCR_LSEDRV_MASK | RCC_BDCR_LSEON); + regval |= drives[drive++]; + putreg32(regval, STM32WL5_RCC_BDCR); + regval |= RCC_BDCR_LSEON; +#endif + + putreg32(regval, STM32WL5_RCC_BDCR); + + /* Wait for the LSE clock to be ready (or until a timeout elapsed) + */ + + for (timeout = LSERDY_TIMEOUT; timeout > 0; timeout--) + { + /* Check if the LSERDY flag is the set in the BDCR */ + + regval = getreg32(STM32WL5_RCC_BDCR); + + if (regval & RCC_BDCR_LSERDY) + { + /* If so, then break-out with timeout > 0 */ + + break; + } + } + +#ifdef CONFIG_STM32WL5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY + if (timeout != 0) + { + break; + } + } + while (drive < sizeof(drives) / sizeof(drives[0])); +#endif + + if (timeout != 0) + { + /* Enable LSE system clock. The LSE system clock seems to provide + * a means to gate the LSE clock distribution to peripherals. It + * must be enabled for MSI PLL mode (syncing the MSI to the LSE). + */ + + regval |= RCC_BDCR_LSESYSEN; + + putreg32(regval, STM32WL5_RCC_BDCR); + + /* Wait for the LSE system clock to be ready */ + + while (!((regval = getreg32(STM32WL5_RCC_BDCR)) & + RCC_BDCR_LSESYSRDY)) + { + stm32wl5_waste(); + } + } + +#ifdef CONFIG_STM32WL5_RTC_LSECLOCK_LOWER_RUN_DRV_CAPABILITY + + /* Set running drive capability for LSE oscillator. */ + + regval &= ~RCC_BDCR_LSEDRV_MASK; + regval |= RCC_BDCR_LSEDRV_LOW << RCC_BDCR_LSEDRV_SHIFT; + putreg32(regval, STM32WL5_RCC_BDCR); +#endif + + /* Disable backup domain access if it was disabled on entry */ + + (void)stm32wl5_pwr_enablebkp(writable); + } +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_lsi.c b/arch/arm/src/stm32wl5/stm32wl5_lsi.c new file mode 100644 index 0000000000..03aab52bbd --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_lsi.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_lsi.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include "arm_internal.h" +#include "stm32wl5_rcc.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_rcc_enablelsi + * + * Description: + * Enable the Internal Low-Speed (LSI) RC Oscillator. + * + ****************************************************************************/ + +void stm32wl5_rcc_enablelsi(void) +{ + /* Enable the Internal Low-Speed (LSI) RC Oscillator by setting the LSION + * bit the RCC CSR register. + */ + + modifyreg32(STM32WL5_RCC_CSR, 0, RCC_CSR_LSION); + + /* Wait for the internal LSI oscillator to be stable. */ + + while ((getreg32(STM32WL5_RCC_CSR) & RCC_CSR_LSIRDY) == 0); +} + +/**************************************************************************** + * Name: stm32wl5_rcc_disablelsi + * + * Description: + * Disable the Internal Low-Speed (LSI) RC Oscillator. + * + ****************************************************************************/ + +void stm32wl5_rcc_disablelsi(void) +{ + /* Enable the Internal Low-Speed (LSI) RC Oscillator by setting the LSION + * bit the RCC CSR register. + */ + + modifyreg32(STM32WL5_RCC_CSR, RCC_CSR_LSION, 0); + + /* LSIRDY should go low after 3 LSI clock cycles */ +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_mpuinit.c b/arch/arm/src/stm32wl5/stm32wl5_mpuinit.c new file mode 100644 index 0000000000..a6bd84f6a6 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_mpuinit.c @@ -0,0 +1,100 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_mpuinit.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include + +#include "mpu.h" +#include "stm32wl5_mpuinit.h" + +#if defined(CONFIG_BUILD_PROTECTED) && defined(CONFIG_ARM_MPU) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef MAX +# define MAX(a,b) a > b ? a : b +#endif + +#ifndef MIN +# define MIN(a,b) a < b ? a : b +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_mpuinitialize + * + * Description: + * Configure the MPU to permit user-space access to only restricted SAM3U + * resources. + * + ****************************************************************************/ + +void stm32wl5_mpuinitialize(void) +{ + uintptr_t datastart = MIN(USERSPACE->us_datastart, USERSPACE->us_bssstart); + uintptr_t dataend = MAX(USERSPACE->us_dataend, USERSPACE->us_bssend); + + DEBUGASSERT(USERSPACE->us_textend >= USERSPACE->us_textstart && + dataend >= datastart); + + /* Show MPU information */ + + mpu_showtype(); + + /* Configure user flash and SRAM space */ + + mpu_user_flash(USERSPACE->us_textstart, + USERSPACE->us_textend - USERSPACE->us_textstart); + + mpu_user_intsram(datastart, dataend - datastart); + + /* Then enable the MPU */ + + mpu_control(true, false, true); +} + +/**************************************************************************** + * Name: stm32wl5_mpu_uheap + * + * Description: + * Map the user-heap region. + * + * This logic may need an extension to handle external SDRAM). + * + ****************************************************************************/ + +void stm32wl5_mpu_uheap(uintptr_t start, size_t size) +{ + mpu_user_intsram(start, size); +} + +#endif /* CONFIG_BUILD_PROTECTED && CONFIG_ARM_MPU */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_mpuinit.h b/arch/arm/src/stm32wl5/stm32wl5_mpuinit.h new file mode 100644 index 0000000000..0d04603796 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_mpuinit.h @@ -0,0 +1,63 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_mpuinit.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_MPUINIT_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_MPUINIT_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Functions Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_mpuinitialize + * + * Description: + * Configure the MPU to permit user-space access to only unrestricted MCU + * resources. + * + ****************************************************************************/ + +#ifdef CONFIG_BUILD_PROTECTED +void stm32wl5_mpuinitialize(void); +#else +# define stm32wl5_mpuinitialize() +#endif + +/**************************************************************************** + * Name: stm32wl5_mpu_uheap + * + * Description: + * Map the user heap region. + * + ****************************************************************************/ + +#ifdef CONFIG_BUILD_PROTECTED +void stm32wl5_mpu_uheap(uintptr_t start, size_t size); +#else +# define stm32wl5_mpu_uheap(start,size) +#endif + +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_MPUINIT_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_pwr.c b/arch/arm/src/stm32wl5/stm32wl5_pwr.c new file mode 100644 index 0000000000..059a9ca24f --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_pwr.c @@ -0,0 +1,108 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_pwr.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include +#include +#include + +#include "arm_internal.h" +#include "stm32wl5_pwr.h" +#include "stm32wl5_rcc.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline uint16_t stm32wl5_pwr_getreg(uint8_t offset) +{ + return (uint16_t)getreg32(STM32WL5_PWR_BASE + (uint32_t)offset); +} + +static inline void stm32wl5_pwr_putreg(uint8_t offset, uint16_t value) +{ + putreg32((uint32_t)value, STM32WL5_PWR_BASE + (uint32_t)offset); +} + +static inline void stm32wl5_pwr_modifyreg(uint8_t offset, uint16_t clearbits, + uint16_t setbits) +{ + modifyreg32(STM32WL5_PWR_BASE + (uint32_t)offset, (uint32_t)clearbits, + (uint32_t)setbits); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_pwr_enablebkp + * + * Description: + * Enables access to the backup domain (RTC registers, RTC backup data + * registers and backup SRAM). + * + * Input Parameters: + * writable - True: enable ability to write to backup domain registers + * + * Returned Value: + * True: The backup domain was previously writable. + * + ****************************************************************************/ + +bool stm32wl5_pwr_enablebkp(bool writable) +{ + uint16_t regval; + bool waswritable; + + /* Get the current state of the STM32WL5 PWR control register 1 */ + + regval = stm32wl5_pwr_getreg(STM32WL5_PWR_CR1_OFFSET); + waswritable = ((regval & PWR_CR1_DBP) != 0); + + /* Enable or disable the ability to write */ + + if (waswritable && !writable) + { + /* Disable backup domain access */ + + regval &= ~PWR_CR1_DBP; + stm32wl5_pwr_putreg(STM32WL5_PWR_CR1_OFFSET, regval); + } + else if (!waswritable && writable) + { + /* Enable backup domain access */ + + regval |= PWR_CR1_DBP; + stm32wl5_pwr_putreg(STM32WL5_PWR_CR1_OFFSET, regval); + + /* Enable does not happen right away */ + + up_udelay(4); + } + + return waswritable; +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_pwr.h b/arch/arm/src/stm32wl5/stm32wl5_pwr.h new file mode 100644 index 0000000000..55ec2b3403 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_pwr.h @@ -0,0 +1,77 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_pwr.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_PWR_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_PWR_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include "chip.h" +#include "hardware/stm32wl5_pwr.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_pwr_enablebkp + * + * Description: + * Enables access to the backup domain (RTC registers, RTC backup data + * registers and backup SRAM). + * + * Input Parameters: + * writable - True: enable ability to write to backup domain registers + * + * Returned Value: + * True: The backup domain was previously writable. + * + ****************************************************************************/ + +bool stm32wl5_pwr_enablebkp(bool writable); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_PWR_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_rcc.c b/arch/arm/src/stm32wl5/stm32wl5_rcc.c new file mode 100644 index 0000000000..51b03ca2d8 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_rcc.c @@ -0,0 +1,851 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_rcc.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include "arm_internal.h" +#include "arm_internal.h" + +#include "chip.h" +#include "stm32wl5_rcc.h" +#include "stm32wl5_flash.h" +#include "stm32wl5.h" +#include "stm32wl5_waste.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name + * + * Description + * The RTC needs to reset the Backup Domain to change RTCSEL and resetting + * the Backup Domain renders to disabling the LSE as consequence. In + * order to avoid resetting the Backup Domain when we already configured + * LSE we will reset the Backup Domain early (here). + * + * Input Parameters + * None + * + * Returned Value + * None + * + ****************************************************************************/ + +#if defined(CONFIG_STM32WL5_PWR) && defined(CONFIG_STM32WL5_RTC) +static inline void stm32wl5_rcc_resetbkp(void) +{ + bool init_stat; + + /* Check if the RTC is already configured */ + + init_stat = stm32wl5_rtc_is_initialized(); + if (!init_stat) + { + uint32_t bkregs[STM32WL5_RTC_BKCOUNT]; + int i; + + /* Backup backup-registers before RTC reset. */ + + for (i = 0; i < STM32WL5_RTC_BKCOUNT; i++) + { + bkregs[i] = getreg32(STM32WL5_RTC_BKR(i)); + } + + /* Enable write access to the backup domain (RTC registers, RTC + * backup data registers and backup SRAM). + */ + + (void)stm32wl5_pwr_enablebkp(true); + + /* We might be changing RTCSEL - to ensure such changes work, we must + * reset the backup domain (having backed up the RTC_MAGIC token) + */ + + modifyreg32(STM32WL5_RCC_BDCR, 0, RCC_BDCR_BDRST); + modifyreg32(STM32WL5_RCC_BDCR, RCC_BDCR_BDRST, 0); + + /* Restore backup-registers, except RTC related. */ + + for (i = 0; i < STM32WL5_RTC_BKCOUNT; i++) + { + if (RTC_MAGIC_REG == STM32WL5_RTC_BKR(i)) + { + continue; + } + + putreg32(bkregs[i], STM32WL5_RTC_BKR(i)); + } + + (void)stm32wl5_pwr_enablebkp(false); + } +} +#else +# define rcc_resetbkp() +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name + * + * Description + * Called to establish the clock settings based on the values in board.h. + * This function (by default) will reset most everything, enable the PLL, + * and enable peripheral clocking for all peripherals enabled in the NuttX + * configuration file. + * + * If CONFIG_ARCH_BOARD_STM32WL5_CUSTOM_CLOCKCONFIG is defined, then + * clocking will be enabled by an externally provided, board-specific + * function called stm32wl5_board_clockconfig(). + * + * Input Parameters + * None + * + * Returned Value + * None + * + ****************************************************************************/ + +void stm32wl5_clockconfig(void) +{ +#if 0 + /* Make sure that we are starting in the reset state */ + + rcc_reset(); + + /* Reset backup domain if appropriate */ + + rcc_resetbkp(); +#endif +#if defined(CONFIG_ARCH_BOARD_STM32WL5_CUSTOM_CLOCKCONFIG) + + /* Invoke Board Custom Clock Configuration */ + + stm32wl5_board_clockconfig(); + +#else + + /* Invoke standard, fixed clock configuration based on definitions in + * board.h + */ + + stm32wl5_stdclockconfig(); + +#endif + + /* Enable peripheral clocking */ + + stm32wl5_rcc_enableperipherals(); +} + +/**************************************************************************** + * Name: rcc_enableahb1 + * + * Description: + * Enable selected AHB1 peripherals + * + ****************************************************************************/ + +static void stm32wl5_rcc_enableahb1(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the AHB1ENR register to enabled the + * selected AHB1 peripherals. + */ + + regval = getreg32(STM32WL5_RCC_AHB1ENR); + +#ifdef CONFIG_STM32WL5_DMA1 + /* DMA 1 clock enable */ + + regval |= RCC_AHB1ENR_DMA1EN; +#endif + +#ifdef CONFIG_STM32WL5_DMA2 + /* DMA 2 clock enable */ + + regval |= RCC_AHB1ENR_DMA2EN; +#endif + +#ifdef CONFIG_STM32WL5_CRC + /* CRC clock enable */ + + regval |= RCC_AHB1ENR_CRCEN; +#endif + + putreg32(regval, STM32WL5_RCC_AHB1ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableahb2 + * + * Description: + * Enable selected AHB2 peripherals + * + ****************************************************************************/ + +static inline void stm32wl5_rcc_enableahb2(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the AHB2ENR register to enable the + * selected AHB2 peripherals. + */ + + regval = getreg32(STM32WL5_RCC_AHB2ENR); + + /* Enable GPIOA, GPIOB, .... GPIOH */ + +#if STM32WL5_NPORTS > 0 + regval |= (RCC_AHB2ENR_GPIOAEN +#if STM32WL5_NPORTS > 1 + | RCC_AHB2ENR_GPIOBEN +#endif +#if STM32WL5_NPORTS > 2 + | RCC_AHB2ENR_GPIOCEN +#endif +#if STM32WL5_NPORTS > 3 + | RCC_AHB2ENR_GPIOHEN +#endif + ); +#endif /* STM32WL5_NPORTS */ + + putreg32(regval, STM32WL5_RCC_AHB2ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableahb3 + * + * Description: + * Enable selected AHB3 peripherals + * + ****************************************************************************/ + +static inline void stm32wl5_rcc_enableahb3(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the AHB3ENR register to enabled the + * selected AHB3 peripherals. + */ + + regval = getreg32(STM32WL5_RCC_AHB3ENR); + +#ifdef CONFIG_STM32WL5_AES + /* Cryptographic modules clock enable */ + + regval |= RCC_AHB2ENR_AESEN; +#endif + +#ifdef CONFIG_STM32WL5_RNG + /* Random number generator clock enable */ + + regval |= RCC_AHB2ENR_RNGEN; +#endif + +#ifdef CONFIG_STM32WL5_FLASHEN + /* Flash memory interface clock enable */ + + regval |= RCC_AHB3ENR_FLASHEN; +#endif + + putreg32(regval, STM32WL5_RCC_AHB3ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableapb1 + * + * Description: + * Enable selected APB1 peripherals + * + ****************************************************************************/ + +static inline void stm32wl5_rcc_enableapb1(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the APB1ENR register to enabled the + * selected APB1 peripherals. + */ + + regval = getreg32(STM32WL5_RCC_APB1ENR1); + +#ifdef CONFIG_STM32WL5_TIM2 + /* TIM2 clock enable */ + + regval |= RCC_APB1ENR1_TIM2EN; +#endif + +#ifdef CONFIG_STM32WL5_SPI2 + /* SPI2 clock enable */ + + regval |= RCC_APB1ENR1_SPI2EN; +#endif + +#ifdef CONFIG_STM32WL5_USART2 + /* USART 2 clock enable */ + + regval |= RCC_APB1ENR1_USART2EN; +#endif + +#ifdef CONFIG_STM32WL5_I2C1 + /* I2C1 clock enable */ + + regval |= RCC_APB1ENR1_I2C1EN; +#endif + +#ifdef CONFIG_STM32WL5_I2C2 + /* I2C2 clock enable */ + + regval |= RCC_APB1ENR1_I2C2EN; +#endif + +#ifdef CONFIG_STM32WL5_I2C3 + /* I2C3 clock enable */ + + regval |= RCC_APB1ENR1_I2C3EN; +#endif + +#if defined (CONFIG_STM32WL5_DAC1) + /* DAC interface clock enable */ + + regval |= RCC_APB1ENR1_DAC1EN; +#endif + +#ifdef CONFIG_STM32WL5_LPTIM1 + /* Low power timer 1 clock enable */ + + regval |= RCC_APB1ENR1_LPTIM1EN; +#endif + + putreg32(regval, STM32WL5_RCC_APB1ENR1); /* Enable peripherals */ + + /* Second APB1 register */ + + regval = getreg32(STM32WL5_RCC_APB1ENR2); + +#ifdef CONFIG_STM32WL5_LPUART1 + /* Low power uart clock enable */ + + regval |= RCC_APB1ENR2_LPUART1EN; +#endif + +#ifdef CONFIG_STM32WL5_LPTIM2 + /* Low power timer 2 clock enable */ + + regval |= RCC_APB1ENR2_LPTIM2EN; +#endif + +#ifdef CONFIG_STM32WL5_LPTIM3 + /* Low power timer 3 clock enable */ + + regval |= RCC_APB1ENR2_LPTIM3EN; +#endif + + putreg32(regval, STM32WL5_RCC_APB1ENR2); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableapb2 + * + * Description: + * Enable selected APB2 peripherals + * + ****************************************************************************/ + +static inline void stm32wl5_rcc_enableapb2(void) +{ + uint32_t regval; + + /* Set the appropriate bits in the APB2ENR register to enabled the + * selected APB2 peripherals. + */ + + regval = getreg32(STM32WL5_RCC_APB2ENR); + +#if defined(CONFIG_STM32WL5_ADC1) + /* ADC clock enable */ + + regval |= RCC_AHB2ENR_ADC1EN; +#endif + +#ifdef CONFIG_STM32WL5_TIM1 + /* TIM1 clock enable */ + + regval |= RCC_APB2ENR_TIM1EN; +#endif + +#ifdef CONFIG_STM32WL5_SPI1 + /* SPI1 clock enable */ + + regval |= RCC_APB2ENR_SPI1EN; +#endif + +#ifdef CONFIG_STM32WL5_USART1 + /* USART1 clock enable */ + + regval |= RCC_APB2ENR_USART1EN; +#endif + +#ifdef CONFIG_STM32WL5_TIM16 + /* TIM16 clock enable */ + + regval |= RCC_APB2ENR_TIM16EN; +#endif + +#ifdef CONFIG_STM32WL5_TIM17 + /* TIM16 clock enable */ + + regval |= RCC_APB2ENR_TIM17EN; +#endif + + putreg32(regval, STM32WL5_RCC_APB2ENR); /* Enable peripherals */ +} + +/**************************************************************************** + * Name: rcc_enableccip + * + * Description: + * Set peripherals independent clock configuration. + * + ****************************************************************************/ + +static inline void stm32wl5_rcc_enableccip(void) +{ + uint32_t regval; + + /* Certain peripherals have no clock selected even when their enable bit is + * set. Set some defaults in the CCIPR register so those peripherals + * will at least have a clock. + */ + + regval = getreg32(STM32WL5_RCC_CCIPR); + +#if defined(STM32WL5_I2C_USE_HSI16) +#ifdef CONFIG_STM32WL5_I2C1 + /* Select HSI16 as I2C1 clock source. */ + + regval |= RCC_CCIPR_I2C1SEL_HSI; +#endif +#ifdef CONFIG_STM32WL5_I2C2 + /* Select HSI16 as I2C2 clock source. */ + + regval |= RCC_CCIPR_I2C2SEL_HSI; +#endif +#ifdef CONFIG_STM32WL5_I2C3 + /* Select HSI16 as I2C3 clock source. */ + + regval |= RCC_CCIPR_I2C3SEL_HSI; +#endif +#endif /* STM32WL5_I2C_USE_HSI16 */ + +#if defined(STM32WL5_USE_CLK48) + /* XXX sanity if sdmmc1 or usb or rng, then we need to set the clk48 source + * and then we can also do away with STM32WL5_USE_CLK48, and give better + * warning messages. + */ + + regval |= STM32WL5_CLK48_SEL; +#endif + +#if defined(CONFIG_STM32WL5_ADC1) + /* Select SYSCLK as ADC clock source */ + + regval |= RCC_CCIPR_ADCSEL_SYSCLK; +#endif + +#ifdef CONFIG_STM32WL5_DFSDM1 + /* Select SYSCLK as DFSDM clock source */ + + /* RM0394 Rev 3, p. 525 is confused about DFSDM clock source. + * ST has confirmed that at least in STM32WL551, the bit DFSDMSEL + * in RCC_CCIPR is present and bit description was omitted from + * RM0394 by accident. + */ + + regval |= RCC_CCIPR_DFSDMSEL_SYSCLK; +#endif + + putreg32(regval, STM32WL5_RCC_CCIPR); + + /* I2C4 alone has their clock selection in CCIPR2 register. */ + +#if defined(STM32WL5_I2C_USE_HSI16) +#ifdef CONFIG_STM32WL5_I2C4 + regval = getreg32(STM32WL5_RCC_CCIPR2); + + /* Select HSI16 as I2C4 clock source. */ + + regval |= RCC_CCIPR_I2C4SEL_HSI; + + putreg32(regval, STM32WL5_RCC_CCIPR2); +#endif +#endif +} + +/**************************************************************************** + * Name + * + * Description + * Re-enable the clock and restore the clock settings based on settings in + * board.h. This function is only available to support low-power modes of + * operation + * re-enable/re-start the PLL + * + * This function performs a subset of the operations performed by + * stm32wl5_clockconfig() + * reset the currently enabled peripheral clocks. + * + * If CONFIG_ARCH_BOARD_STM32WL5_CUSTOM_CLOCKCONFIG is defined, then + * clocking will be enabled by an externally provided, board-specific + * function called stm32wl5_board_clockconfig(). + * + * Input Parameters + * None + * + * Returned Value + * None + * + ****************************************************************************/ + +#ifdef CONFIG_PM +void stm32wl5_clockenable(void) +{ +#if defined(CONFIG_ARCH_BOARD_STM32WL5_CUSTOM_CLOCKCONFIG) + + /* Invoke Board Custom Clock Configuration */ + + stm32wl5_board_clockconfig(); + +#else + + /* Invoke standard, fixed clock configuration based on definitions in + * board.h + */ + + stm32wl5_stdclockconfig(); + +#endif +} +#endif + +/**************************************************************************** + * Name: stm32wl5_rcc_enableperipherals + ****************************************************************************/ + +void stm32wl5_rcc_enableperipherals(void) +{ + stm32wl5_rcc_enableccip(); + stm32wl5_rcc_enableahb1(); + stm32wl5_rcc_enableahb2(); + stm32wl5_rcc_enableahb3(); + stm32wl5_rcc_enableapb1(); + stm32wl5_rcc_enableapb2(); +} + +/**************************************************************************** + * Name: stm32wl5_stdclockconfig + * + * Description: + * Called to change to new clock based on settings in board.h + * + * NOTE: This logic would need to be extended if you need to select low- + * power clocking modes! + ****************************************************************************/ + +#ifndef CONFIG_ARCH_BOARD_STM32WL5_CUSTOM_CLOCKCONFIG +void stm32wl5_stdclockconfig(void) +{ + uint32_t regval; + +#if defined(STM32WL5_BOARD_USEHSI) || defined(STM32WL5_I2C_USE_HSI16) + /* Enable Internal High-Speed Clock (HSI) */ + + regval = getreg32(STM32WL5_RCC_CR); + regval |= RCC_CR_HSION; /* Enable HSI */ + putreg32(regval, STM32WL5_RCC_CR); + + /* Wait until the HSI is ready */ + + for (; ; ) + { + /* Check if the HSIRDY flag is the set in the CR */ + + if ((getreg32(STM32WL5_RCC_CR) & RCC_CR_HSIRDY) != 0) + { + /* If so, then break-out */ + + break; + } + } +#endif + +#if defined(STM32WL5_BOARD_USEHSI) + /* Already set above */ + +#elif defined(STM32WL5_BOARD_USEMSI) + /* Enable Internal Multi-Speed Clock (MSI) */ + + /* Wait until the MSI is either off or ready */ + + for (; ; ) + { + if ((regval = getreg32(STM32WL5_RCC_CR)), + (regval & RCC_CR_MSIRDY) || ~(regval & RCC_CR_MSION)) + { + /* If so, then break-out */ + + break; + } + } + + /* setting MSIRANGE */ + + regval = getreg32(STM32WL5_RCC_CR); + regval |= (STM32WL5_BOARD_MSIRANGE | RCC_CR_MSION); /* Enable MSI and frequency */ + putreg32(regval, STM32WL5_RCC_CR); + + /* Wait until the MSI is ready */ + + for (; ; ) + { + /* Check if the MSIRDY flag is the set in the CR */ + + if ((getreg32(STM32WL5_RCC_CR) & RCC_CR_MSIRDY) != 0) + { + /* If so, then break-out */ + + break; + } + } + +#elif defined(STM32WL5_BOARD_USEHSE) + /* Enable External High-Speed Clock (HSE) */ + +#if defined(STM32WL5_BOARD_USETCXO) + /* nucleo-wl55jc uses TCXO crystal, which needs to be first + * powered up with PB0 pin - or more convinently by setting + * HSEBYPPWR register. This has to be done before HSE is enabled + */ + + regval = getreg32(STM32WL5_RCC_CR); + regval |= RCC_CR_HSEBYPPWR; + putreg32(regval, STM32WL5_RCC_CR); +#endif + + regval = getreg32(STM32WL5_RCC_CR); + regval |= RCC_CR_HSEON; /* Enable HSE */ + putreg32(regval, STM32WL5_RCC_CR); + + /* Wait until the HSE is ready */ + + for (; ; ) + { + /* Check if the HSERDY flag is the set in the CR */ + + if ((getreg32(STM32WL5_RCC_CR) & RCC_CR_HSERDY) != 0) + { + /* If so, then break-out */ + + break; + } + } +#else + +# error stm32wl5_stdclockconfig(), must have one of STM32WL5_BOARD_USEHSI, STM32WL5_BOARD_USEMSI, STM32WL5_BOARD_USEHSE defined + +#endif + + /* Select main regulator voltage range according to system clock + * frequency. + */ + + /* Select correct main regulator range */ + + regval = getreg32(STM32WL5_PWR_CR1); + regval &= ~PWR_CR1_VOS_MASK; + + if (STM32WL5_SYSCLK_FREQUENCY <= 16000000) + { + /* set low power range for frequencies <= 16MHz */ + + regval |= PWR_CR1_VOS_RANGE2; + } + else + { + /* set performance range for frequencies > 16MHz */ + + regval |= PWR_CR1_VOS_RANGE1; + } + + putreg32(regval, STM32WL5_PWR_CR1); + + /* Wait for voltage regulator to stabilize */ + + while (getreg32(STM32WL5_PWR_SR2) & PWR_SR2_VOSF) + { + } + + /* Set the HCLK source/divider */ + + regval = getreg32(STM32WL5_RCC_CFGR); + regval &= ~RCC_CFGR_HPRE_MASK; + regval |= STM32WL5_RCC_CFGR_HPRE; + putreg32(regval, STM32WL5_RCC_CFGR); + + /* Set the PCLK2 divider */ + + regval = getreg32(STM32WL5_RCC_CFGR); + regval &= ~RCC_CFGR_PPRE2_MASK; + regval |= STM32WL5_RCC_CFGR_PPRE2; + putreg32(regval, STM32WL5_RCC_CFGR); + + /* Set the PCLK1 divider */ + + regval = getreg32(STM32WL5_RCC_CFGR); + regval &= ~RCC_CFGR_PPRE1_MASK; + regval |= STM32WL5_RCC_CFGR_PPRE1; + putreg32(regval, STM32WL5_RCC_CFGR); + +#ifdef CONFIG_STM32WL5_RTC_HSECLOCK + /* Set the RTC clock divisor */ + + regval = getreg32(STM32WL5_RCC_CFGR); + regval &= ~RCC_CFGR_RTCPRE_MASK; + regval |= RCC_CFGR_RTCPRE(HSE_DIVISOR); + putreg32(regval, STM32WL5_RCC_CFGR); +#endif + + /* Set the PLL source and main divider */ + + regval = getreg32(STM32WL5_RCC_PLLCFG); + + /* Configure Main PLL */ + + /* Set the PLL dividers and multipliers to configure the main PLL */ + + regval = (STM32WL5_PLLCFG_PLLM | STM32WL5_PLLCFG_PLLN | + STM32WL5_PLLCFG_PLLP | STM32WL5_PLLCFG_PLLQ | + STM32WL5_PLLCFG_PLLR); + +#ifdef STM32WL5_PLLCFG_PLLP_ENABLED + regval |= RCC_PLLCFG_PLLPEN; +#endif +#ifdef STM32WL5_PLLCFG_PLLQ_ENABLED + regval |= RCC_PLLCFG_PLLQEN; +#endif +#ifdef STM32WL5_PLLCFG_PLLR_ENABLED + regval |= RCC_PLLCFG_PLLREN; +#endif + + /* XXX The choice of clock source to PLL (all three) is independent + * of the sys clock source choice, review the STM32WL5_BOARD_USEHSI + * name; probably split it into two, one for PLL source and one + * for sys clock source. + */ + +#ifdef STM32WL5_BOARD_USEHSI + regval |= RCC_PLLCFG_PLLSRC_HSI16; +#elif defined(STM32WL5_BOARD_USEMSI) + regval |= RCC_PLLCFG_PLLSRC_MSI; +#else /* if STM32WL5_BOARD_USEHSE */ + regval |= RCC_PLLCFG_PLLSRC_HSE; +#endif + + putreg32(regval, STM32WL5_RCC_PLLCFG); + + /* Enable the main PLL */ + + regval = getreg32(STM32WL5_RCC_CR); + regval |= RCC_CR_PLLON; + putreg32(regval, STM32WL5_RCC_CR); + + /* Wait until the PLL is ready */ + + while ((getreg32(STM32WL5_RCC_CR) & RCC_CR_PLLRDY) == 0) + { + } + + /* Configure flash wait states according to manual */ + + if (STM32WL5_HCLK3_FREQUENCY <= 18000000 /* 18MHz */) + { + regval = FLASH_ACR_LATENCY_0; + } + else if (STM32WL5_HCLK3_FREQUENCY <= 36000000 /* 36MHz */) + { + regval = FLASH_ACR_LATENCY_1; + } + else /* STM32WL5_HCLK3_FREQUENCY <= 48MHz */ + { + regval = FLASH_ACR_LATENCY_2; + } + + putreg32(regval, STM32WL5_FLASH_ACR); + + /* Select the main PLL as system clock source */ + + regval = getreg32(STM32WL5_RCC_CFGR); + regval &= ~RCC_CFGR_SW_MASK; + regval |= RCC_CFGR_SW_PLL; + putreg32(regval, STM32WL5_RCC_CFGR); + + /* Wait until the PLL source is used as the system clock source */ + + while ((getreg32(STM32WL5_RCC_CFGR) & RCC_CFGR_SWS_MASK) != + RCC_CFGR_SWS_PLL) + { + } + +#if defined(CONFIG_STM32WL5_IWDG) || defined(CONFIG_STM32WL5_RTC_LSICLOCK) + /* Low speed internal clock source LSI */ + + stm32wl5_rcc_enablelsi(); +#endif +} +#endif diff --git a/arch/arm/src/stm32wl5/stm32wl5_rcc.h b/arch/arm/src/stm32wl5/stm32wl5_rcc.h new file mode 100644 index 0000000000..062a5035b9 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_rcc.h @@ -0,0 +1,235 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_rcc.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_RCC_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_RCC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "arm_internal.h" +#include "chip.h" + +#include "hardware/stm32wl5_rcc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#elseO +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +/* This symbol references the Cortex-M33 vector table (as positioned by the + * linker script, ld.script or ld.script.dfu. The standard location for the + * vector table is at the beginning of FLASH at address 0x0800:0000. If we + * are using the STMicro DFU bootloader, then the vector table will be offset + * to a different location in FLASH and we will need to set the NVIC vector + * location to this alternative location. + */ + +extern uint32_t _vectors[]; /* See stm32wl5_vectors.S */ + +/**************************************************************************** + * Inline Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_mcoconfig + * + * Description: + * Selects the clock source to output on MC pin (PA8) for stm32wl562xx + * PA8 should be configured in alternate function mode. + * + * Input Parameters: + * source - One of the definitions for the RCC_CFGR_MCO definitions from + * chip/stm32wl562xx_rcc.h {RCC_CFGR_SYSCLK, RCC_CFGR_INTCLK, + * RCC_CFGR_EXTCLK, RCC_CFGR_PLLCLKd2, RCC_CFGR_PLL2CLK, + * RCC_CFGR_PLL3CLKd2, RCC_CFGR_XT1, RCC_CFGR_PLL3CLK} + * + * Returned Value: + * None + * + ****************************************************************************/ + +static inline void stm32wl5_mcoconfig(uint32_t source) +{ + uint32_t regval; + + /* Set MCO source */ + + regval = getreg32(STM32WL5_RCC_CFGR); + regval &= ~(RCC_CFGR_MCOSEL_MASK); + regval |= (source & RCC_CFGR_MCOSEL_MASK); + putreg32(regval, STM32WL5_RCC_CFGR); +} + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_clockconfig + * + * Description: + * Called to establish the clock settings based on the values in board.h. + * This function (by default) will reset most everything, enable the PLL, + * and enable peripheral clocking for all periperipherals enabled in the + * NuttX configuration file. + * + * If CONFIG_ARCH_BOARD_STM32WL5_CUSTOM_CLOCKCONFIG is defined, then + * clocking will be enabled by an externally provided, board-specific + * function called stm32wl5_board_clockconfig(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stm32wl5_clockconfig(void); + +/**************************************************************************** + * Name: stm32wl5_board_clockconfig + * + * Description: + * Any STM32WL5 board may replace the "standard" board clock configuration + * logic with its own, custom clock configuration logic. + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_BOARD_STM32WL5_CUSTOM_CLOCKCONFIG +void stm32wl5_board_clockconfig(void); +#endif + +/**************************************************************************** + * Name: stm32wl5_stdclockconfig + * + * Description: + * The standard logic to configure the clocks based on settings in board.h. + * Applicable if no custom clock config is provided. This function is + * chip type specific and implemented in corresponding modules such as e.g. + * stm32wl562xx_rcc.c + * + ****************************************************************************/ + +#ifndef CONFIG_ARCH_BOARD_STM32WL5_CUSTOM_CLOCKCONFIG +void stm32wl5_stdclockconfig(void); +#endif + +/**************************************************************************** + * Name: stm32wl5_clockenable + * + * Description: + * Re-enable the clock and restore the clock settings based on settings in + * board.h. This function is only available to support low-power modes of + * operation: When re-awakening from deep-sleep modes, it is necessary to + * re-enable/re-start the PLL + * + * This function performs a subset of the operations performed by + * stm32wl5_clockconfig(): It does not reset any devices, and it does not + * reset the currently enabled peripheral clocks. + * + * If CONFIG_ARCH_BOARD_STM32WL5_CUSTOM_CLOCKCONFIG is defined, then + * clocking will be enabled by an externally provided, board-specific + * function called stm32wl5_board_clockconfig(). + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_PM +void stm32wl5_clockenable(void); +#endif + +/**************************************************************************** + * Name: stm32wl5_rcc_enablelse + * + * Description: + * Enable the External Low-Speed (LSE) Oscillator. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stm32wl5_rcc_enablelse(void); + +/**************************************************************************** + * Name: stm32wl5_rcc_enablelsi + * + * Description: + * Enable the Internal Low-Speed (LSI) RC Oscillator. + * + ****************************************************************************/ + +void stm32wl5_rcc_enablelsi(void); + +/**************************************************************************** + * Name: stm32wl5_rcc_disablelsi + * + * Description: + * Disable the Internal Low-Speed (LSI) RC Oscillator. + * + ****************************************************************************/ + +void stm32wl5_rcc_disablelsi(void); + +/**************************************************************************** + * Name: stm32wl5_rcc_enableperipherals + * + * Description: + * Enable all the chip peripherals according to configuration. This is + * chip type specific and thus implemented in corresponding modules such as + * e.g. stm32wl562xx_rcc.c + * + ****************************************************************************/ + +void stm32wl5_rcc_enableperipherals(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_RCC_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_serial.c b/arch/arm/src/stm32wl5/stm32wl5_serial.c new file mode 100644 index 0000000000..fb41305006 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_serial.c @@ -0,0 +1,2983 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_serial.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + +#include + +#include "chip.h" +#include "stm32wl5_gpio.h" +#include "stm32wl5_uart.h" +#ifdef SERIAL_HAVE_DMA +# include "stm32wl5_dma.h" +#endif +#include "stm32wl5_rcc.h" +#include "arm_internal.h" +#include "arm_internal.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Some sanity checks *******************************************************/ + +/* DMA configuration */ + +/* If DMA is enabled on any USART, then very that other pre-requisites + * have also been selected. + * UART DMA1 DMA2 + * 1 X X + * 2 X + * 3 X + * 4 X + * 5 X + */ + +#ifdef SERIAL_HAVE_DMA + +/* Verify that DMA has been enabled and the DMA channel has been defined. + */ + +# if defined(CONFIG_USART2_RXDMA) +# if !defined(CONFIG_STM32WL5_DMA1) && !defined(CONFIG_STM32WL5_DMAMUX) +# error STM32WL5 USART2/3 receive DMA requires CONFIG_STM32WL5_DMA1 +# endif +# endif + +/* Currently RS-485 support cannot be enabled when RXDMA is in use due to + * lack of testing - RS-485 support was developed on STM32F1x + */ + +# if (defined(CONFIG_USART1_RXDMA) && defined(CONFIG_USART1_RS485)) || \ + (defined(CONFIG_USART2_RXDMA) && defined(CONFIG_USART2_RS485)) +# error "RXDMA and RS-485 cannot be enabled at the same time for the same U[S]ART" +# endif + +/* UART2-5 have no alternate channels without DMAMUX */ + +# ifndef CONFIG_STM32WL5_HAVE_DMAMUX +# define DMAMAP_USART2_RX DMACHAN_USART2_RX +# endif + +# if defined(CONFIG_USART2_RXDMA) && !defined(DMAMAP_USART2_RX) +# error "USART2 DMA channel not defined (DMAMAP_USART2_RX)" +# endif + +/* The DMA buffer size when using RX DMA to emulate a FIFO. + * + * When streaming data, the generic serial layer will be called + * every time the FIFO receives half this number of bytes. + * + * If there ever is a STM32WL5 with D-cache, the buffer size + * should be an even multiple of ARMV7M_DCACHE_LINESIZE, so that it + * can be individually invalidated. + */ + +# if !defined(CONFIG_STM32WL5_SERIAL_RXDMA_BUFFER_SIZE) || \ + CONFIG_STM32WL5_SERIAL_RXDMA_BUFFER_SIZE == 0 +# define RXDMA_BUFFER_SIZE 32 +# else +# define RXDMA_BUFFER_SIZE ((CONFIG_STM32WL5_SERIAL_RXDMA_BUFFER_SIZE + 31) & ~31) +# endif + +/* DMA priority */ + +# ifndef CONFIG_USART_DMAPRIO +# define CONFIG_USART_DMAPRIO DMA_CCR_PRIMED +# endif +# if (CONFIG_USART_DMAPRIO & ~DMA_CCR_PL_MASK) != 0 +# error "Illegal value for CONFIG_USART_DMAPRIO" +# endif + +/* DMA control words */ + +# define SERIAL_DMA_CONTROL_WORD \ + (DMA_CCR_CIRC | \ + DMA_CCR_MINC | \ + DMA_CCR_PSIZE_8BITS | \ + DMA_CCR_MSIZE_8BITS | \ + CONFIG_USART_DMAPRIO) +# ifdef CONFIG_SERIAL_IFLOWCONTROL +# define SERIAL_DMA_IFLOW_CONTROL_WORD \ + (DMA_CCR_MINC | \ + DMA_CCR_PSIZE_8BITS | \ + DMA_CCR_MSIZE_8BITS | \ + CONFIG_USART_DMAPRIO) +# endif + +#endif + +/* Power management definitions */ + +#if defined(CONFIG_PM) && !defined(CONFIG_STM32WL5_PM_SERIAL_ACTIVITY) +# define CONFIG_STM32WL5_PM_SERIAL_ACTIVITY 10 +#endif +#if defined(CONFIG_PM) +# define PM_IDLE_DOMAIN 0 /* Revisit */ +#endif + +/* Keep track if a Break was set + * + * Note: + * + * 1) This value is set in the priv->ie but never written to the control + * register. It must not collide with USART_CR1_USED_INTS or USART_CR3_EIE + * 2) USART_CR3_EIE is also carried in the up_dev_s ie member. + * + * See stm32wl5serial_restoreusartint where the masking is done. + */ + +#ifdef CONFIG_STM32WL5_SERIALBRK_BSDCOMPAT +# define USART_CR1_IE_BREAK_INPROGRESS_SHFTS 15 +# define USART_CR1_IE_BREAK_INPROGRESS (1 << USART_CR1_IE_BREAK_INPROGRESS_SHFTS) +#endif + +#ifdef USE_SERIALDRIVER +#ifdef HAVE_UART + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct stm32wl5_serial_s +{ + struct uart_dev_s dev; /* Generic UART device */ + uint16_t ie; /* Saved interrupt mask bits value */ + uint16_t sr; /* Saved status bits */ + + /* Has been initialized and HW is setup. */ + + bool initialized; + +#ifdef CONFIG_PM + bool suspended; /* UART device has been suspended. */ + + /* Interrupt mask value stored before suspending for stop mode. */ + + uint16_t suspended_ie; +#endif + + /* If termios are supported, then the following fields may vary at + * runtime. + */ + +#ifdef CONFIG_SERIAL_TERMIOS + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (7 or 8) */ + bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */ +#ifdef CONFIG_SERIAL_IFLOWCONTROL + bool iflow; /* input flow control (RTS) enabled */ +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + bool oflow; /* output flow control (CTS) enabled */ +#endif + uint32_t baud; /* Configured baud */ +#else + const uint8_t parity; /* 0=none, 1=odd, 2=even */ + const uint8_t bits; /* Number of bits (7 or 8) */ + const bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */ +#ifdef CONFIG_SERIAL_IFLOWCONTROL + const bool iflow; /* input flow control (RTS) enabled */ +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + const bool oflow; /* output flow control (CTS) enabled */ +#endif + 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 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 */ +#ifdef CONFIG_SERIAL_IFLOWCONTROL + const uint32_t rts_gpio; /* U[S]ART RTS GPIO pin configuration */ +#endif +#ifdef CONFIG_SERIAL_OFLOWCONTROL + const uint32_t cts_gpio; /* U[S]ART CTS GPIO pin configuration */ +#endif + +#ifdef SERIAL_HAVE_DMA + const unsigned int rxdma_channel; /* DMA channel assigned */ +#endif + + /* RX DMA state */ + +#ifdef SERIAL_HAVE_DMA + DMA_HANDLE rxdma; /* currently-open receive DMA stream */ + bool rxenable; /* DMA-based reception en/disable */ +#ifdef CONFIG_PM + bool rxdmasusp; /* Rx DMA suspended */ +#endif + uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */ + char *const rxfifo; /* Receive DMA buffer */ +#endif + +#ifdef HAVE_RS485 + const uint32_t rs485_dir_gpio; /* U[S]ART RS-485 DIR GPIO pin configuration */ + const bool rs485_dir_polarity; /* U[S]ART RS-485 DIR pin state for TX enabled */ +#endif +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_UART_CONFIG +static void stm32wl5serial_setformat(FAR struct uart_dev_s *dev); +#endif +static int stm32wl5serial_setup(FAR struct uart_dev_s *dev); +static void stm32wl5serial_shutdown(FAR struct uart_dev_s *dev); +static int stm32wl5serial_attach(FAR struct uart_dev_s *dev); +static void stm32wl5serial_detach(FAR struct uart_dev_s *dev); +static int stm32wl5serial_interrupt(int irq, FAR void *context, + FAR void *arg); +static int stm32wl5serial_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); +#ifndef SERIAL_HAVE_ONLY_DMA +static int stm32wl5serial_receive(FAR struct uart_dev_s *dev, + FAR unsigned int *status); +static void stm32wl5serial_rxint(FAR struct uart_dev_s *dev, bool enable); +static bool stm32wl5serial_rxavailable(FAR struct uart_dev_s *dev); +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool stm32wl5serial_rxflowcontrol(FAR struct uart_dev_s *dev, + unsigned int nbuffered, bool upper); +#endif +static void stm32wl5serial_send(FAR struct uart_dev_s *dev, int ch); +static void stm32wl5serial_txint(FAR struct uart_dev_s *dev, bool enable); +static bool stm32wl5serial_txready(FAR struct uart_dev_s *dev); + +#ifdef SERIAL_HAVE_DMA +static int stm32wl5serial_dmasetup(FAR struct uart_dev_s *dev); +static void stm32wl5serial_dmashutdown(FAR struct uart_dev_s *dev); +static int stm32wl5serial_dmareceive(FAR struct uart_dev_s *dev, + FAR unsigned int *status); +static void stm32wl5serial_dmareenable(struct stm32wl5_serial_s *priv); +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool stm32wl5serial_dmaiflowrestart(struct stm32wl5_serial_s *priv); +#endif +static void stm32wl5serial_dmarxint(FAR struct uart_dev_s *dev, bool enable); +static bool stm32wl5serial_dmarxavailable(struct uart_dev_s *dev); + +static void stm32wl5serial_dmarxcallback(DMA_HANDLE handle, uint8_t status, + FAR void *arg); +#endif + +#ifdef CONFIG_PM +static void stm32wl5serial_setsuspend(struct uart_dev_s *dev, bool suspend); +static void stm32wl5serial_pm_setsuspend(bool suspend); +static void stm32wl5serial_pmnotify(FAR struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate); +static int stm32wl5serial_pmprepare(FAR struct pm_callback_s *cb, + int domain, + enum pm_state_e pmstate); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#ifndef SERIAL_HAVE_ONLY_DMA +static const struct uart_ops_s g_uart_ops = +{ + .setup = stm32wl5serial_setup, + .shutdown = stm32wl5serial_shutdown, + .attach = stm32wl5serial_attach, + .detach = stm32wl5serial_detach, + .ioctl = stm32wl5serial_ioctl, + .receive = stm32wl5serial_receive, + .rxint = stm32wl5serial_rxint, + .rxavailable = stm32wl5serial_rxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = stm32wl5serial_rxflowcontrol, +#endif + .send = stm32wl5serial_send, + .txint = stm32wl5serial_txint, + .txready = stm32wl5serial_txready, + .txempty = stm32wl5serial_txready, +}; +#endif + +#ifdef SERIAL_HAVE_DMA +static const struct uart_ops_s g_uart_dma_ops = +{ + .setup = stm32wl5serial_dmasetup, + .shutdown = stm32wl5serial_dmashutdown, + .attach = stm32wl5serial_attach, + .detach = stm32wl5serial_detach, + .ioctl = stm32wl5serial_ioctl, + .receive = stm32wl5serial_dmareceive, + .rxint = stm32wl5serial_dmarxint, + .rxavailable = stm32wl5serial_dmarxavailable, +#ifdef CONFIG_SERIAL_IFLOWCONTROL + .rxflowcontrol = stm32wl5serial_rxflowcontrol, +#endif + .send = stm32wl5serial_send, + .txint = stm32wl5serial_txint, + .txready = stm32wl5serial_txready, + .txempty = stm32wl5serial_txready, +}; +#endif + +/* I/O buffers */ + +#ifdef CONFIG_STM32WL5_LPUART1_SERIALDRIVER +static char g_lpuart1rxbuffer[CONFIG_LPUART1_RXBUFSIZE]; +static char g_lpuart1txbuffer[CONFIG_LPUART1_TXBUFSIZE]; +# ifdef CONFIG_LPUART1_RXDMA +static char g_lpuart1rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_STM32WL5_USART1_SERIALDRIVER +static char g_usart1rxbuffer[CONFIG_USART1_RXBUFSIZE]; +static char g_usart1txbuffer[CONFIG_USART1_TXBUFSIZE]; +# ifdef CONFIG_USART1_RXDMA +static char g_usart1rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +#ifdef CONFIG_STM32WL5_USART2_SERIALDRIVER +static char g_usart2rxbuffer[CONFIG_USART2_RXBUFSIZE]; +static char g_usart2txbuffer[CONFIG_USART2_TXBUFSIZE]; +# ifdef CONFIG_USART2_RXDMA +static char g_usart2rxfifo[RXDMA_BUFFER_SIZE]; +# endif +#endif + +/* This describes the state of the STM32 USART1 ports. */ + +#ifdef CONFIG_STM32WL5_LPUART1_SERIALDRIVER +static struct stm32wl5_serial_s g_lpuart1priv = +{ + .dev = + { +#if CONSOLE_UART == 1 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_LPUART1_RXBUFSIZE, + .buffer = g_lpuart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_LPUART1_TXBUFSIZE, + .buffer = g_lpuart1txbuffer, + }, +#ifdef CONFIG_LPUART1_RXDMA + .ops = &g_uart_dma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_lpuart1priv, + }, + + .irq = STM32WL5_IRQ_LPUART1, + .parity = CONFIG_LPUART1_PARITY, + .bits = CONFIG_LPUART1_BITS, + .stopbits2 = CONFIG_LPUART1_2STOP, + .baud = CONFIG_LPUART1_BAUD, + .apbclock = STM32WL5_PCLK2_FREQUENCY, + .usartbase = STM32WL5_LPUART1_BASE, + .tx_gpio = GPIO_LPUART1_TX, + .rx_gpio = GPIO_LPUART1_RX, +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_LPUART1_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_LPUART1_CTS, +#endif +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_LPUART1_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_LPUART1_RTS, +#endif +#ifdef CONFIG_LPUART1_RXDMA + .rxdma_channel = DMAMAP_LPUSART_RX, + .rxfifo = g_lpuart1rxfifo, +#endif + +#ifdef CONFIG_USART1_RS485 + .rs485_dir_gpio = GPIO_LPUART1_RS485_DIR, +# if (CONFIG_USART1_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; +#endif + +#ifdef CONFIG_STM32WL5_USART1_SERIALDRIVER +static struct stm32wl5_serial_s g_usart1priv = +{ + .dev = + { +#if CONSOLE_UART == 2 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART1_RXBUFSIZE, + .buffer = g_usart1rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART1_TXBUFSIZE, + .buffer = g_usart1txbuffer, + }, +#ifdef CONFIG_USART1_RXDMA + .ops = &g_uart_dma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_usart1priv, + }, + + .irq = STM32WL5_IRQ_USART1, + .parity = CONFIG_USART1_PARITY, + .bits = CONFIG_USART1_BITS, + .stopbits2 = CONFIG_USART1_2STOP, + .baud = CONFIG_USART1_BAUD, + .apbclock = STM32WL5_PCLK2_FREQUENCY, + .usartbase = STM32WL5_USART1_BASE, + .tx_gpio = GPIO_USART1_TX, + .rx_gpio = GPIO_USART1_RX, +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_USART1_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_USART1_CTS, +#endif +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART1_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_USART1_RTS, +#endif +#ifdef CONFIG_USART1_RXDMA + .rxdma_channel = DMAMAP_USART1_RX, + .rxfifo = g_usart1rxfifo, +#endif + +#ifdef CONFIG_USART1_RS485 + .rs485_dir_gpio = GPIO_USART1_RS485_DIR, +# if (CONFIG_USART1_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; +#endif + +/* This describes the state of the STM32 USART2 port. */ + +#ifdef CONFIG_STM32WL5_USART2_SERIALDRIVER +static struct stm32wl5_serial_s g_usart2priv = +{ + .dev = + { +#if CONSOLE_UART == 3 + .isconsole = true, +#endif + .recv = + { + .size = CONFIG_USART2_RXBUFSIZE, + .buffer = g_usart2rxbuffer, + }, + .xmit = + { + .size = CONFIG_USART2_TXBUFSIZE, + .buffer = g_usart2txbuffer, + }, +#ifdef CONFIG_USART2_RXDMA + .ops = &g_uart_dma_ops, +#else + .ops = &g_uart_ops, +#endif + .priv = &g_usart2priv, + }, + + .irq = STM32WL5_IRQ_USART2, + .parity = CONFIG_USART2_PARITY, + .bits = CONFIG_USART2_BITS, + .stopbits2 = CONFIG_USART2_2STOP, + .baud = CONFIG_USART2_BAUD, + .apbclock = STM32WL5_PCLK1_FREQUENCY, + .usartbase = STM32WL5_USART2_BASE, + .tx_gpio = GPIO_USART2_TX, + .rx_gpio = GPIO_USART2_RX, +#if defined(CONFIG_SERIAL_OFLOWCONTROL) && defined(CONFIG_USART2_OFLOWCONTROL) + .oflow = true, + .cts_gpio = GPIO_USART2_CTS, +#endif +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && defined(CONFIG_USART2_IFLOWCONTROL) + .iflow = true, + .rts_gpio = GPIO_USART2_RTS, +#endif +#ifdef CONFIG_USART2_RXDMA + .rxdma_channel = DMAMAP_USART2_RX, + .rxfifo = g_usart2rxfifo, +#endif + +#ifdef CONFIG_USART2_RS485 + .rs485_dir_gpio = GPIO_USART2_RS485_DIR, +# if (CONFIG_USART2_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif +}; +#endif + +/* This table lets us iterate over the configured USARTs */ + +FAR static struct stm32wl5_serial_s * const + g_uart_devs[STM32WL5_NLPUART + STM32WL5_NUSART] = +{ +#ifdef CONFIG_STM32WL5_LPUART1_SERIALDRIVER + [0] = &g_lpuart1priv, +#endif +#ifdef CONFIG_STM32WL5_USART1_SERIALDRIVER + [1] = &g_usart1priv, +#endif +#ifdef CONFIG_STM32WL5_USART2_SERIALDRIVER + [2] = &g_usart2priv, +#endif +}; + +#ifdef CONFIG_PM +struct serialpm_s +{ + struct pm_callback_s pm_cb; + bool serial_suspended; +}; + +static struct serialpm_s g_serialpm = +{ + .pm_cb.notify = stm32wl5serial_pmnotify, + .pm_cb.prepare = stm32wl5serial_pmprepare, + .serial_suspended = false +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5serial_getreg + ****************************************************************************/ + +static inline +uint32_t stm32wl5serial_getreg(FAR struct stm32wl5_serial_s *priv, + int offset) +{ + return getreg32(priv->usartbase + offset); +} + +/**************************************************************************** + * Name: stm32wl5serial_putreg + ****************************************************************************/ + +static inline +void stm32wl5serial_putreg(FAR struct stm32wl5_serial_s *priv, + int offset, uint32_t value) +{ + putreg32(value, priv->usartbase + offset); +} + +/**************************************************************************** + * Name: stm32wl5serial_setusartint + ****************************************************************************/ + +static inline +void stm32wl5serial_setusartint(FAR struct stm32wl5_serial_s *priv, + uint16_t ie) +{ + uint32_t cr; + + /* Save the interrupt mask */ + + priv->ie = ie; + + /* And restore the interrupt state (see the interrupt enable/usage table + * above) + */ + + cr = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + cr &= ~(USART_CR1_USED_INTS); + cr |= (ie & (USART_CR1_USED_INTS)); + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, cr); + + cr = stm32wl5serial_getreg(priv, STM32WL5_USART_CR3_OFFSET); + cr &= ~USART_CR3_EIE; + cr |= (ie & USART_CR3_EIE); + stm32wl5serial_putreg(priv, STM32WL5_USART_CR3_OFFSET, cr); +} + +/**************************************************************************** + * Name: up_restoreusartint + ****************************************************************************/ + +static void stm32wl5serial_restoreusartint( + FAR struct stm32wl5_serial_s *priv, + uint16_t ie) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + stm32wl5serial_setusartint(priv, ie); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: stm32wl5serial_disableusartint + ****************************************************************************/ + +static void stm32wl5serial_disableusartint( + FAR struct stm32wl5_serial_s *priv, + FAR uint16_t *ie) +{ + irqstate_t flags; + + flags = enter_critical_section(); + + if (ie) + { + uint32_t cr1; + uint32_t cr3; + + /* USART interrupts: + * + * Enable Status Meaning Usage + * ---------------- -------------- ---------------------- ------------- + * USART_CR1_IDLEIE USART_ISR_IDLE Idle Line Detected (not used) + * USART_CR1_RXNEIE USART_ISR_RXNE Received Data Ready to + * be Read + * " " USART_ISR_ORE Overrun Error Detected + * USART_CR1_TCIE USART_ISR_TC Transmission Complete (only RS-485) + * USART_CR1_TXEIE USART_ISR_TXE Transmit Data Register + * Empty + * USART_CR1_PEIE USART_ISR_PE Parity Error + * + * USART_CR2_LBDIE USART_ISR_LBD Break Flag (not used) + * USART_CR3_EIE USART_ISR_FE Framing Error + * " " USART_ISR_NF Noise Flag + * " " USART_ISR_ORE Overrun Error Detected + * USART_CR3_CTSIE USART_ISR_CTS CTS flag (not used) + */ + + cr1 = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + cr3 = stm32wl5serial_getreg(priv, STM32WL5_USART_CR3_OFFSET); + + /* Return the current interrupt mask value for the used interrupts. + * Notice that this depends on the fact that none of the used interrupt + * enable bits overlap. This logic would fail if we needed the break + * interrupt! + */ + + *ie = (cr1 & (USART_CR1_USED_INTS)) | (cr3 & USART_CR3_EIE); + } + + /* Disable all interrupts */ + + stm32wl5serial_setusartint(priv, 0); + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: stm32wl5serial_dmanextrx + * + * Description: + * Returns the index into the RX FIFO where the DMA will place the next + * byte that it receives. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static int stm32wl5serial_dmanextrx(FAR struct stm32wl5_serial_s *priv) +{ + size_t dmaresidual; + + dmaresidual = stm32wl5_dmaresidual(priv->rxdma); + + return (RXDMA_BUFFER_SIZE - (int)dmaresidual); +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_setformat + * + * Description: + * Set the serial line format and speed. + * + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_UART_CONFIG +static void stm32wl5serial_setformat(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + uint32_t regval; + + /* This first implementation is for U[S]ARTs that support oversampling + * by 8 in additional to the standard oversampling by 16. + */ + + uint32_t usartdiv8; + uint32_t cr1; + uint32_t brr; + + if (priv->usartbase == STM32WL5_LPUART1_BASE) + { + /* lpuart has different calculations baudrate, and there is not + * oversampling: + * + * lpuartdiv = 256 * fCK / baud + */ + + brr = (256ull * priv->apbclock) / priv->baud; + } + else + { + /* In case of oversampling by 8, the equation is: + * + * baud = 2 * fCK / usartdiv8 + * usartdiv8 = 2 * fCK / baud + */ + + usartdiv8 = ((priv->apbclock << 1) + (priv->baud >> 1)) / priv->baud; + + /* Baud rate for standard USART (SPI mode included): + * + * In case of oversampling by 16, the equation is: + * baud = fCK / usartdiv16 + * usartdiv16 = fCK / baud + * = 2 * usartdiv8 + */ + + /* Use oversamply by 8 only if the divisor is small. + * But what is small? + */ + + cr1 = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + if (usartdiv8 > 2000) + { + /* Use usartdiv16 */ + + brr = (usartdiv8 + 1) >> 1; + + /* Clear oversampling by 8 to enable oversampling by 16 */ + + cr1 &= ~USART_CR1_OVER8; + } + else + { + DEBUGASSERT(usartdiv8 >= 8); + + /* Perform mysterious operations on bits 0-3 */ + + brr = ((usartdiv8 & 0xfff0) | ((usartdiv8 & 0x000f) >> 1)); + + /* Set oversampling by 8 */ + + cr1 |= USART_CR1_OVER8; + } + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, cr1); + } + + stm32wl5serial_putreg(priv, STM32WL5_USART_BRR_OFFSET, brr); + + /* Configure parity mode */ + + regval = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + regval &= ~(USART_CR1_PCE | USART_CR1_PS | USART_CR1_M0 | USART_CR1_M1); + + if (priv->parity == 1) /* Odd parity */ + { + regval |= (USART_CR1_PCE | USART_CR1_PS); + } + else if (priv->parity == 2) /* Even parity */ + { + regval |= USART_CR1_PCE; + } + + /* Configure word length (parity uses one of configured bits) + * + * Default: 1 start, 8 data (no parity), n stop, OR + * 1 start, 7 data + parity, n stop + */ + + if (priv->bits == 9 || (priv->bits == 8 && priv->parity != 0)) + { + /* Select: 1 start, 8 data + parity, n stop, OR + * 1 start, 9 data (no parity), n stop. + */ + + regval |= USART_CR1_M0; + } + else if (priv->bits == 7 && priv->parity == 0) + { + /* Select: 1 start, 7 data (no parity), n stop, OR + */ + + regval |= USART_CR1_M1; + } + + /* Else Select: 1 start, 7 data + parity, n stop, OR + * 1 start, 8 data (no parity), n stop. + */ + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, regval); + + /* Configure STOP bits */ + + regval = stm32wl5serial_getreg(priv, STM32WL5_USART_CR2_OFFSET); + regval &= ~(USART_CR2_STOP_MASK); + + if (priv->stopbits2) + { + regval |= USART_CR2_STOP2; + } + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR2_OFFSET, regval); + + /* Configure hardware flow control */ + + regval = stm32wl5serial_getreg(priv, STM32WL5_USART_CR3_OFFSET); + regval &= ~(USART_CR3_CTSE | USART_CR3_RTSE); + +#if defined(CONFIG_SERIAL_IFLOWCONTROL) && !defined(CONFIG_STM32WL5_FLOWCONTROL_BROKEN) + if (priv->iflow && (priv->rts_gpio != 0)) + { + regval |= USART_CR3_RTSE; + } +#endif + +#ifdef CONFIG_SERIAL_OFLOWCONTROL + if (priv->oflow && (priv->cts_gpio != 0)) + { + regval |= USART_CR3_CTSE; + } +#endif + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR3_OFFSET, regval); +} +#endif /* CONFIG_SUPPRESS_UART_CONFIG */ + +/**************************************************************************** + * Name: stm32wl5serial_setsuspend + * + * Description: + * Suspend or resume serial peripheral. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void stm32wl5serial_setsuspend(struct uart_dev_s *dev, bool suspend) +{ + FAR struct stm32wl5_serial_s *priv = (struct stm32wl5_serial_s *)dev->priv; +#ifdef SERIAL_HAVE_DMA + bool dmarestored = false; +#endif + + if (priv->suspended == suspend) + { + return; + } + + priv->suspended = suspend; + + if (suspend) + { +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + /* Force RTS high to prevent further Rx. */ + + stm32wl5_configgpio((priv->rts_gpio & ~GPIO_MODE_MASK) + | (GPIO_OUTPUT | GPIO_OUTPUT_SET)); + } +#endif + + /* Disable interrupts to prevent Tx. */ + + stm32wl5serial_disableusartint(priv, &priv->suspended_ie); + + /* Wait last Tx to complete. */ + + while ((stm32wl5serial_getreg(priv, STM32WL5_USART_ISR_OFFSET) & + USART_ISR_TC) == 0); + +#ifdef SERIAL_HAVE_DMA + if (priv->dev.ops == &g_uart_dma_ops && !priv->rxdmasusp) + { +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow && priv->rxdmanext == RXDMA_BUFFER_SIZE) + { + /* Rx DMA in non-circular iflow mode and already stopped + * at end of DMA buffer. No need to suspend. + */ + } + else +#endif + { + /* Suspend Rx DMA. */ + + stm32wl5_dmastop(priv->rxdma); + priv->rxdmasusp = true; + } + } +#endif + } + else + { +#ifdef SERIAL_HAVE_DMA + if (priv->dev.ops == &g_uart_dma_ops && priv->rxdmasusp) + { +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + (void)stm32wl5serial_dmaiflowrestart(priv); + } + else +#endif + { + /* This USART does not have HW flow-control. Unconditionally + * re-enable DMA (might loss unprocessed bytes received + * to DMA buffer before suspending). + */ + + stm32wl5serial_dmareenable(priv); + priv->rxdmasusp = false; + } + + dmarestored = true; + } +#endif + + /* Re-enable interrupts to resume Tx. */ + + stm32wl5serial_restoreusartint(priv, priv->suspended_ie); + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + /* Restore peripheral RTS control. */ + + stm32wl5_configgpio(priv->rts_gpio); + } +#endif + } + +#ifdef SERIAL_HAVE_DMA + if (dmarestored) + { + irqstate_t flags; + + flags = enter_critical_section(); + + /* Perform initial Rx DMA buffer fetch to wake-up serial device + * activity. + */ + + if (priv->rxdma != NULL) + { + stm32wl5serial_dmarxcallback(priv->rxdma, 0, priv); + } + + leave_critical_section(flags); + } +#endif +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_pm_setsuspend + * + * Description: + * Suspend or resume serial peripherals for/from deep-sleep/stop modes. + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void stm32wl5serial_pm_setsuspend(bool suspend) +{ + int n; + + /* Already in desired state? */ + + if (suspend == g_serialpm.serial_suspended) + return; + + g_serialpm.serial_suspended = suspend; + + for (n = 0; n < STM32WL5_NLPUART + STM32WL5_NUSART; n++) + { + struct stm32wl5_serial_s *priv = g_uart_devs[n]; + + if (!priv || !priv->initialized) + { + continue; + } + + stm32wl5serial_setsuspend(&priv->dev, suspend); + } +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_setapbclock + * + * Description: + * Enable or disable APB clock for the USART peripheral + * + * Input Parameters: + * dev - A reference to the UART driver state structure + * on - Enable clock if 'on' is 'true' and disable if 'false' + * + ****************************************************************************/ + +static void stm32wl5serial_setapbclock(FAR struct uart_dev_s *dev, bool on) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + uint32_t rcc_en; + uint32_t regaddr; + + /* Determine which USART to configure */ + + switch (priv->usartbase) + { + default: + return; +#ifdef CONFIG_STM32WL5_LPUART1_SERIALDRIVER + case STM32WL5_LPUART1_BASE: + rcc_en = RCC_APB1ENR2_LPUART1EN; + regaddr = STM32WL5_RCC_APB1ENR2; + break; +#endif +#ifdef CONFIG_STM32WL5_USART1_SERIALDRIVER + case STM32WL5_USART1_BASE: + rcc_en = RCC_APB2ENR_USART1EN; + regaddr = STM32WL5_RCC_APB2ENR; + break; +#endif +#ifdef CONFIG_STM32WL5_USART2_SERIALDRIVER + case STM32WL5_USART2_BASE: + rcc_en = RCC_APB1ENR1_USART2EN; + regaddr = STM32WL5_RCC_APB1ENR1; + break; +#endif + } + + /* Enable/disable APB 1/2 clock for USART */ + + if (on) + { + modifyreg32(regaddr, 0, rcc_en); + } + else + { + modifyreg32(regaddr, rcc_en, 0); + } +} + +/**************************************************************************** + * Name: stm32wl5serial_setup + * + * Description: + * Configure the USART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +static int stm32wl5serial_setup(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + +#ifndef CONFIG_SUPPRESS_UART_CONFIG + uint32_t regval; + + /* Note: The logic here depends on the fact that that the USART module + * was enabled in stm32wl5_lowsetup(). + */ + + /* Enable USART APB1/2 clock */ + + stm32wl5serial_setapbclock(dev, true); + + /* Configure pins for USART use */ + + stm32wl5_configgpio(priv->tx_gpio); + stm32wl5_configgpio(priv->rx_gpio); + +#ifdef CONFIG_SERIAL_OFLOWCONTROL + if (priv->cts_gpio != 0) + { + stm32wl5_configgpio(priv->cts_gpio); + } +#endif + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->rts_gpio != 0) + { + uint32_t config = priv->rts_gpio; + +#ifdef CONFIG_STM32WL5_FLOWCONTROL_BROKEN + /* Instead of letting hw manage this pin, we will bitbang */ + + config = (config & ~GPIO_MODE_MASK) | GPIO_OUTPUT; +#endif + stm32wl5_configgpio(config); + } +#endif + +#ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + stm32wl5_configgpio(priv->rs485_dir_gpio); + stm32wl5_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity); + } +#endif + + /* Configure CR2 */ + + /* Clear STOP, CLKEN, CPOL, CPHA, LBCL, and interrupt enable bits */ + + regval = stm32wl5serial_getreg(priv, STM32WL5_USART_CR2_OFFSET); + regval &= ~(USART_CR2_STOP_MASK | USART_CR2_CLKEN | USART_CR2_CPOL | + USART_CR2_CPHA | USART_CR2_LBCL | USART_CR2_LBDIE); + + /* Configure STOP bits */ + + if (priv->stopbits2) + { + regval |= USART_CR2_STOP2; + } + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR2_OFFSET, regval); + + /* Configure CR1 */ + + /* Clear TE, REm and all interrupt enable bits */ + + regval = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + regval &= ~(USART_CR1_TE | USART_CR1_RE | USART_CR1_ALLINTS); + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, regval); + + /* Configure CR3 */ + + /* Clear CTSE, RTSE, and all interrupt enable bits */ + + regval = stm32wl5serial_getreg(priv, STM32WL5_USART_CR3_OFFSET); + regval &= ~(USART_CR3_CTSIE | USART_CR3_CTSE | USART_CR3_RTSE | + USART_CR3_EIE); + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR3_OFFSET, regval); + + /* Configure the USART line format and speed. */ + + stm32wl5serial_setformat(dev); + + /* Enable Rx, Tx, and the USART */ + + regval = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + regval |= (USART_CR1_UE | USART_CR1_TE | USART_CR1_RE); + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, regval); + +#endif /* CONFIG_SUPPRESS_UART_CONFIG */ + + /* Set up the cached interrupt enables value */ + + priv->ie = 0; + + /* Mark device as initialized. */ + + priv->initialized = true; + + return OK; +} + +/**************************************************************************** + * Name: stm32wl5serial_dmasetup + * + * Description: + * Configure the USART baud, bits, parity, etc. This method is called the + * first time that the serial port is opened. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static int stm32wl5serial_dmasetup(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + int result; + uint32_t regval; + + /* Do the basic UART setup first, unless we are the console */ + + if (!dev->isconsole) + { + result = stm32wl5serial_setup(dev); + if (result != OK) + { + return result; + } + } + + /* Acquire the DMA channel. This should always succeed. */ + + priv->rxdma = stm32wl5_dmachannel(priv->rxdma_channel); + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + /* Configure for non-circular DMA reception into the RX FIFO */ + + stm32wl5_dmasetup(priv->rxdma, + priv->usartbase + STM32WL5_USART_RDR_OFFSET, + (uint32_t)priv->rxfifo, + RXDMA_BUFFER_SIZE, + SERIAL_DMA_IFLOW_CONTROL_WORD); + } + else +#endif + { + /* Configure for circular DMA reception into the RX FIFO */ + + stm32wl5_dmasetup(priv->rxdma, + priv->usartbase + STM32WL5_USART_RDR_OFFSET, + (uint32_t)priv->rxfifo, + RXDMA_BUFFER_SIZE, + SERIAL_DMA_CONTROL_WORD); + } + + /* Reset our DMA shadow pointer to match the address just + * programmed above. + */ + + priv->rxdmanext = 0; + + /* Enable receive DMA for the UART */ + + regval = stm32wl5serial_getreg(priv, STM32WL5_USART_CR3_OFFSET); + regval |= USART_CR3_DMAR; + stm32wl5serial_putreg(priv, STM32WL5_USART_CR3_OFFSET, regval); + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + /* Start the DMA channel, and arrange for callbacks at the full point + * in the FIFO. After buffer gets full, hardware flow-control kicks + * in and DMA transfer is stopped. + */ + + stm32wl5_dmastart(priv->rxdma, stm32wl5serial_dmarxcallback, + (void *)priv, false); + } + else +#endif + { + /* Start the DMA channel, and arrange for callbacks at the half and + * full points in the FIFO. This ensures that we have half a FIFO + * worth of time to claim bytes before they are overwritten. + */ + + stm32wl5_dmastart(priv->rxdma, stm32wl5serial_dmarxcallback, + (void *)priv, true); + } + + return OK; +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_shutdown + * + * Description: + * Disable the USART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +static void stm32wl5serial_shutdown(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + uint32_t regval; + + /* Mark device as uninitialized. */ + + priv->initialized = false; + + /* Disable all interrupts */ + + stm32wl5serial_disableusartint(priv, NULL); + + /* Disable USART APB1/2 clock */ + + stm32wl5serial_setapbclock(dev, false); + + /* Disable Rx, Tx, and the UART */ + + regval = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + regval &= ~(USART_CR1_UE | USART_CR1_TE | USART_CR1_RE); + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, regval); + + /* Release pins. "If the serial-attached device is powered down, the TX + * pin causes back-powering, potentially confusing the device to the point + * of complete lock-up." + * + * REVISIT: Is unconfiguring the pins appropriate for all device? If not, + * then this may need to be a configuration option. + */ + + stm32wl5_unconfiggpio(priv->tx_gpio); + stm32wl5_unconfiggpio(priv->rx_gpio); + +#ifdef CONFIG_SERIAL_OFLOWCONTROL + if (priv->cts_gpio != 0) + { + stm32wl5_unconfiggpio(priv->cts_gpio); + } +#endif + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->rts_gpio != 0) + { + stm32wl5_unconfiggpio(priv->rts_gpio); + } +#endif + +#ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + stm32wl5_unconfiggpio(priv->rs485_dir_gpio); + } +#endif +} + +/**************************************************************************** + * Name: stm32wl5serial_dmashutdown + * + * Description: + * Disable the USART. This method is called when the serial + * port is closed + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static void stm32wl5serial_dmashutdown(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + + /* Perform the normal UART shutdown */ + + stm32wl5serial_shutdown(dev); + + /* Stop the DMA channel */ + + stm32wl5_dmastop(priv->rxdma); + + /* Release the DMA channel */ + + stm32wl5_dmafree(priv->rxdma); + priv->rxdma = NULL; +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_attach + * + * Description: + * Configure the USART to operation in interrupt driven mode. This method + * is called when the serial port is opened. Normally, this is just after + * the setup() method is called, however, the serial console may operate in + * a non-interrupt driven mode during the boot phase. + * + * RX and TX interrupts are not enabled when by the attach method (unless + * the hardware supports multiple levels of interrupt enabling). The RX + * and TX interrupts are not enabled until the txint() and rxint() methods + * are called. + * + ****************************************************************************/ + +static int stm32wl5serial_attach(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + int ret; + + /* Attach and enable the IRQ */ + + ret = irq_attach(priv->irq, stm32wl5serial_interrupt, priv); + + if (ret == OK) + { + /* Enable the interrupt (RX and TX interrupts are still disabled + * in the USART + */ + + up_enable_irq(priv->irq); + } + + return ret; +} + +/**************************************************************************** + * Name: stm32wl5serial_detach + * + * Description: + * Detach USART interrupts. This method is called when the serial port is + * closed normally just before the shutdown method is called. The + * exception is the serial console which is never shutdown. + * + ****************************************************************************/ + +static void stm32wl5serial_detach(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + up_disable_irq(priv->irq); + irq_detach(priv->irq); +} + +/**************************************************************************** + * Name: stm32wl5serial_interrupt + * + * Description: + * This is the USART interrupt handler. It will be invoked when an + * interrupt received on the 'irq' It should call uart_transmitchars or + * uart_receivechar to perform the appropriate data transfers. The + * interrupt handling logic must be able to map the 'irq' number into the + * appropriate uart_dev_s structure in order to call these functions. + * + ****************************************************************************/ + +static int stm32wl5serial_interrupt(int irq, FAR void *context, + FAR void *arg) +{ + FAR struct stm32wl5_serial_s *priv = (FAR struct stm32wl5_serial_s *)arg; + int passes; + bool handled; + + DEBUGASSERT(priv != NULL); + + /* Report serial activity to the power management logic */ + +#if defined(CONFIG_PM) && CONFIG_STM32WL5_PM_SERIAL_ACTIVITY > 0 + pm_activity(PM_IDLE_DOMAIN, CONFIG_STM32WL5_PM_SERIAL_ACTIVITY); +#endif + + /* Loop until there are no characters to be transferred or, + * until we have been looping for a long time. + */ + + handled = true; + for (passes = 0; passes < 256 && handled; passes++) + { + handled = false; + + /* Get the masked USART status word. */ + + priv->sr = stm32wl5serial_getreg(priv, STM32WL5_USART_ISR_OFFSET); + + /* USART interrupts: + * + * Enable Status Meaning Usage + * ---------------- -------------- ---------------------- ------------- + * USART_CR1_IDLEIE USART_ISR_IDLE Idle Line Detected (not used) + * USART_CR1_RXNEIE USART_ISR_RXNE Received Data Ready to + * be Read + * " " USART_ISR_ORE Overrun Error Detected + * USART_CR1_TCIE USART_ISR_TC Transmission Complete (only RS-485) + * USART_CR1_TXEIE USART_ISR_TXE Transmit Data Register + * Empty + * USART_CR1_PEIE USART_ISR_PE Parity Error + * + * USART_CR2_LBDIE USART_ISR_LBD Break Flag (not used) + * USART_CR3_EIE USART_ISR_FE Framing Error + * " " USART_ISR_NE Noise Error + * " " USART_ISR_ORE Overrun Error Detected + * USART_CR3_CTSIE USART_ISR_CTS CTS flag (not used) + * + * NOTE: Some of these status bits must be cleared by explicitly + * writing one to the ICR register: USART_ICR_CTSCF, USART_ICR_LBDCF. + * None of those are currently being used. + */ + +#ifdef HAVE_RS485 + /* Transmission of whole buffer is over - TC is set, TXEIE is cleared. + * Note - this should be first, to have the most recent TC bit value + * from SR register - sending data affects TC, but without refresh we + * will not know that... + */ + + if ((priv->sr & USART_ISR_TC) != 0 && + (priv->ie & USART_CR1_TCIE) != 0 && + (priv->ie & USART_CR1_TXEIE) == 0) + { + stm32wl5_gpiowrite(priv->rs485_dir_gpio, + !priv->rs485_dir_polarity); + stm32wl5serial_restoreusartint(priv, priv->ie & ~USART_CR1_TCIE); + } +#endif + + /* Handle incoming, receive bytes. */ + + if ((priv->sr & USART_ISR_RXNE) != 0 && + (priv->ie & USART_CR1_RXNEIE) != 0) + { + /* Received data ready... process incoming bytes. NOTE the check + * for RXNEIE: We cannot call uart_recvchards of RX interrupts are + * disabled. + */ + + uart_recvchars(&priv->dev); + handled = true; + } + + /* We may still have to read from the DR register to clear any pending + * error conditions. + */ + + else if ((priv->sr & (USART_ISR_ORE | USART_ISR_NF | USART_ISR_FE)) + != 0) + { + /* These errors are cleared by writing the corresponding bit to the + * interrupt clear register (ICR). + */ + + stm32wl5serial_putreg(priv, STM32WL5_USART_ICR_OFFSET, + (USART_ICR_NCF | USART_ICR_ORECF | + USART_ICR_FECF)); + } + + /* Handle outgoing, transmit bytes */ + + if ((priv->sr & USART_ISR_TXE) != 0 && + (priv->ie & USART_CR1_TXEIE) != 0) + { + /* Transmit data register empty ... process outgoing bytes */ + + uart_xmitchars(&priv->dev); + handled = true; + } + } + + return OK; +} + +/**************************************************************************** + * Name: stm32wl5serial_ioctl + * + * Description: + * All ioctl calls will be routed through this method + * + ****************************************************************************/ + +static int stm32wl5serial_ioctl(FAR struct file *filep, int cmd, + unsigned long arg) +{ +#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) + FAR struct inode *inode = filep->f_inode; + FAR struct uart_dev_s *dev = inode->i_private; +#endif +#if defined(CONFIG_SERIAL_TERMIOS) + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; +#endif + int ret = OK; + + switch (cmd) + { +#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT + case TIOCSERGSTRUCT: + { + FAR struct stm32wl5_serial_s *user; + + user = (FAR struct stm32wl5_serial_s *)arg; + + if (!user) + { + ret = -EINVAL; + } + else + { + memcpy(user, dev, sizeof(struct stm32wl5_serial_s)); + } + } + break; +#endif + +#ifdef CONFIG_STM32WL5_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 = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + cr1_ue = cr1 & USART_CR1_UE; + cr1 &= ~USART_CR1_UE; + + /* Disable UE, HDSEL can only be written when UE=0 */ + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, cr1); + + /* Change the TX port to be open-drain/push-pull and enable/disable + * half-duplex mode. + */ + + uint32_t cr = stm32wl5serial_getreg(priv, STM32WL5_USART_CR3_OFFSET); + + 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; + } + + stm32wl5_configgpio((priv->tx_gpio & + ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) | + gpio_val); + + cr |= USART_CR3_HDSEL; + } + else + { + stm32wl5_configgpio((priv->tx_gpio & + ~(GPIO_PUPD_MASK | GPIO_OPENDRAIN)) | + GPIO_PUSHPULL); + cr &= ~USART_CR3_HDSEL; + } + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR3_OFFSET, cr); + + /* Re-enable UE if appropriate */ + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, cr1 | cr1_ue); + leave_critical_section(flags); + } + break; +#endif + +#ifdef CONFIG_STM32WL5_USART_INVERT + case TIOCSINVERT: + { + uint32_t cr1; + uint32_t cr1_ue; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Get the original state of UE */ + + cr1 = stm32wl5serial_getreg(priv, STM32WL5_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 */ + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, cr1); + + /* Enable/disable signal inversion. */ + + uint32_t cr = stm32wl5serial_getreg(priv, STM32WL5_USART_CR2_OFFSET); + + 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; + } + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR2_OFFSET, cr); + + /* Re-enable UE if appropriate */ + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, cr1 | cr1_ue); + leave_critical_section(flags); + } + break; +#endif + +#ifdef CONFIG_STM32WL5_USART_SWAP + case TIOCSSWAP: + { + uint32_t cr1; + uint32_t cr1_ue; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Get the original state of UE */ + + cr1 = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + cr1_ue = cr1 & USART_CR1_UE; + cr1 &= ~USART_CR1_UE; + + /* Disable UE, SWAP can only be written when UE=0 */ + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, cr1); + + /* Enable/disable Swap mode. */ + + uint32_t cr = stm32wl5serial_getreg(priv, STM32WL5_USART_CR2_OFFSET); + + if (arg == SER_SWAP_ENABLED) + { + cr |= USART_CR2_SWAP; + } + else + { + cr &= ~USART_CR2_SWAP; + } + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR2_OFFSET, cr); + + /* Re-enable UE if appropriate */ + + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, cr1 | cr1_ue); + leave_critical_section(flags); + } + break; +#endif + +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + { + FAR struct termios *termiosp = (FAR struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + 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. + */ + + 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) | +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + ((priv->iflow) ? CRTS_IFLOW : 0) | +#endif + CS8; + + /* TODO: CCTS_IFLOW, CCTS_OFLOW */ + } + break; + + case TCSETS: + { + FAR struct termios *termiosp = (FAR struct termios *)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Perform some sanity checks before accepting any changes */ + + if (((termiosp->c_cflag & CSIZE) != CS8) +#ifdef CONFIG_SERIAL_OFLOWCONTROL + || ((termiosp->c_cflag & CCTS_OFLOW) && (priv->cts_gpio == 0)) +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + || ((termiosp->c_cflag & CRTS_IFLOW) && (priv->rts_gpio == 0)) +#endif + ) + { + ret = -EINVAL; + break; + } + + if (termiosp->c_cflag & PARENB) + { + priv->parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + } + else + { + priv->parity = 0; + } + + priv->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0; +#ifdef CONFIG_SERIAL_OFLOWCONTROL + priv->oflow = (termiosp->c_cflag & CCTS_OFLOW) != 0; +#endif +#ifdef CONFIG_SERIAL_IFLOWCONTROL + 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 only cfgetispeed is used because we have knowledge + * that only one speed is supported. + */ + + priv->baud = cfgetispeed(termiosp); + + /* Effect the changes immediately - note that we do not implement + * TCSADRAIN / TCSAFLUSH + */ + + stm32wl5serial_setformat(dev); + } + break; +#endif /* CONFIG_SERIAL_TERMIOS */ + +#ifdef CONFIG_STM32WL5_USART_BREAKS +# ifdef CONFIG_STM32WL5_SERIALBRK_BSDCOMPAT + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ + { + irqstate_t flags; + uint32_t tx_break; + + flags = enter_critical_section(); + + /* Disable any further tx activity */ + + priv->ie |= USART_CR1_IE_BREAK_INPROGRESS; + + stm32wl5serial_txint(dev, false); + + /* Configure TX as a GPIO output pin and Send a break signal */ + + tx_break = GPIO_OUTPUT | + (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio); + stm32wl5_configgpio(tx_break); + + leave_critical_section(flags); + } + break; + + case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ + { + irqstate_t flags; + + flags = enter_critical_section(); + + /* Configure TX back to U(S)ART */ + + stm32wl5_configgpio(priv->tx_gpio); + + priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS; + + /* Enable further tx activity */ + + stm32wl5serial_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 = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + stm32wl5serial_putreg(priv, STM32WL5_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 = stm32wl5serial_getreg(priv, STM32WL5_USART_CR1_OFFSET); + stm32wl5serial_putreg(priv, STM32WL5_USART_CR1_OFFSET, + cr1 & ~USART_CR1_SBK); + leave_critical_section(flags); + } + break; +# endif +#endif + + default: + ret = -ENOTTY; + break; + } + + return ret; +} + +/**************************************************************************** + * Name: stm32wl5serial_receive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the USART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +#ifndef SERIAL_HAVE_ONLY_DMA +static int stm32wl5serial_receive(FAR struct uart_dev_s *dev, + FAR unsigned int *status) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + uint32_t rdr; + + /* Get the Rx byte */ + + rdr = stm32wl5serial_getreg(priv, STM32WL5_USART_RDR_OFFSET); + + /* Get the Rx byte plux error information. Return those in status */ + + *status = priv->sr << 16 | rdr; + priv->sr = 0; + + /* Then return the actual received byte */ + + return rdr & 0xff; +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_rxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +#ifndef SERIAL_HAVE_ONLY_DMA +static void stm32wl5serial_rxint(FAR struct uart_dev_s *dev, bool enable) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + irqstate_t flags; + uint16_t ie; + + /* USART receive interrupts: + * + * Enable Status Meaning Usage + * ---------------- -------------- ---------------------- ---------- + * USART_CR1_IDLEIE USART_ISR_IDLE Idle Line Detected (not used) + * USART_CR1_RXNEIE USART_ISR_RXNE Received Data Ready + * to be Read + * " " USART_ISR_ORE Overrun Error Detected + * USART_CR1_PEIE USART_ISR_PE Parity Error + * + * USART_CR2_LBDIE USART_ISR_LBD Break Flag (not used) + * USART_CR3_EIE USART_ISR_FE Framing Error + * " " USART_ISR_NF Noise Flag + * " " USART_ISR_ORE Overrun Error Detected + */ + + flags = enter_critical_section(); + ie = priv->ie; + if (enable) + { + /* Receive an interrupt when their is anything in the Rx data + * register (or an Rx timeout occurs). + */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS +#ifdef CONFIG_USART_ERRINTS + ie |= (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR3_EIE); +#else + ie |= USART_CR1_RXNEIE; +#endif +#endif + } + else + { + ie &= ~(USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR3_EIE); + } + + /* Then set the new interrupt state */ + + stm32wl5serial_restoreusartint(priv, ie); + leave_critical_section(flags); +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_rxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +#ifndef SERIAL_HAVE_ONLY_DMA +static bool stm32wl5serial_rxavailable(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + + return ((stm32wl5serial_getreg(priv, STM32WL5_USART_ISR_OFFSET) & + USART_ISR_RXNE) != 0); +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_rxflowcontrol + * + * Description: + * Called when Rx buffer is full (or exceeds configured watermark levels + * if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is defined). + * Return true if UART activated RX flow control to block more incoming + * data + * + * Input Parameters: + * dev - UART device instance + * nbuffered - the number of characters currently buffered + * (if CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS is + * not defined the value will be 0 for an empty buffer or the + * defined buffer size for a full buffer) + * upper - true indicates the upper watermark was crossed where + * false indicates the lower watermark has been crossed + * + * Returned Value: + * true if RX flow control activated. + * + ****************************************************************************/ + +#ifdef CONFIG_SERIAL_IFLOWCONTROL +static bool stm32wl5serial_rxflowcontrol(FAR struct uart_dev_s *dev, + unsigned int nbuffered, bool upper) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + +#if defined(CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS) && \ + defined(CONFIG_STM32WL5_FLOWCONTROL_BROKEN) + if (priv->iflow && (priv->rts_gpio != 0)) + { + /* Assert/de-assert nRTS set it high resume/stop sending */ + + stm32wl5_gpiowrite(priv->rts_gpio, upper); + + if (upper) + { + /* With heavy Rx traffic, RXNE might be set and data pending. + * Returning 'true' in such case would cause RXNE left unhandled + * and causing interrupt storm. Sending end might be also be slow + * to react on nRTS, and returning 'true' here would prevent + * processing that data. + * + * Therefore, return 'false' so input data is still being processed + * until sending end reacts on nRTS signal and stops sending more. + */ + + return false; + } + + return upper; + } + +#else + if (priv->iflow) + { + /* Is the RX buffer full? */ + + if (upper) + { + /* Disable Rx interrupt to prevent more data being from + * peripheral. When hardware RTS is enabled, this will + * prevent more data from coming in. + * + * This function is only called when UART recv buffer is full, + * that is: "dev->recv.head + 1 == dev->recv.tail". + * + * Logic in "uart_read" will automatically toggle Rx interrupts + * when buffer is read empty and thus we do not have to re- + * enable Rx interrupts. + */ + + uart_disablerxint(dev); + return true; + } + + /* No.. The RX buffer is empty */ + + else + { + /* We might leave Rx interrupt disabled if full recv buffer was + * read empty. Enable Rx interrupt to make sure that more input is + * received. + */ + + uart_enablerxint(dev); + } + } +#endif + + return false; +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_dmareceive + * + * Description: + * Called (usually) from the interrupt level to receive one + * character from the USART. Error bits associated with the + * receipt are provided in the return 'status'. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static int stm32wl5serial_dmareceive(FAR struct uart_dev_s *dev, + FAR unsigned int *status) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + int c = 0; + + if (stm32wl5serial_dmanextrx(priv) != priv->rxdmanext) + { + c = priv->rxfifo[priv->rxdmanext]; + + priv->rxdmanext++; + if (priv->rxdmanext == RXDMA_BUFFER_SIZE) + { +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + /* RX DMA buffer full. RX paused, RTS line pulled up to prevent + * more input data from other end. + */ + } + else +#endif + { + priv->rxdmanext = 0; + } + } + } + + return c; +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_dmareenable + * + * Description: + * Call to re-enable RX DMA. + * + ****************************************************************************/ + +#if defined(SERIAL_HAVE_DMA) +static void stm32wl5serial_dmareenable(FAR struct stm32wl5_serial_s *priv) +{ +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + /* Configure for non-circular DMA reception into the RX FIFO */ + + stm32wl5_dmasetup(priv->rxdma, + priv->usartbase + STM32WL5_USART_RDR_OFFSET, + (uint32_t)priv->rxfifo, + RXDMA_BUFFER_SIZE, + SERIAL_DMA_IFLOW_CONTROL_WORD); + } + else +#endif + { + /* Configure for circular DMA reception into the RX FIFO */ + + stm32wl5_dmasetup(priv->rxdma, + priv->usartbase + STM32WL5_USART_RDR_OFFSET, + (uint32_t)priv->rxfifo, + RXDMA_BUFFER_SIZE, + SERIAL_DMA_CONTROL_WORD); + } + + /* Reset our DMA shadow pointer to match the address just + * programmed above. + */ + + priv->rxdmanext = 0; + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + /* Start the DMA channel, and arrange for callbacks at the full point + * in the FIFO. After buffer gets full, hardware flow-control kicks + * in and DMA transfer is stopped. + */ + + stm32wl5_dmastart(priv->rxdma, stm32wl5serial_dmarxcallback, + (void *)priv, false); + } + else +#endif + { + /* Start the DMA channel, and arrange for callbacks at the half and + * full points in the FIFO. This ensures that we have half a FIFO + * worth of time to claim bytes before they are overwritten. + */ + + stm32wl5_dmastart(priv->rxdma, stm32wl5serial_dmarxcallback, + (void *)priv, true); + } + +#ifdef CONFIG_PM + /* Clear DMA suspended flag. */ + + priv->rxdmasusp = false; +#endif +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_dmaiflowrestart + * + * Description: + * Call to restart RX DMA for input flow-controlled USART + * + ****************************************************************************/ + +#if defined(SERIAL_HAVE_DMA) && defined(CONFIG_SERIAL_IFLOWCONTROL) +static bool stm32wl5serial_dmaiflowrestart(struct stm32wl5_serial_s *priv) +{ + if (!priv->rxenable) + { + /* Rx not enabled by upper layer. */ + + return false; + } + + if (priv->rxdmanext != RXDMA_BUFFER_SIZE) + { +#ifdef CONFIG_PM + if (priv->rxdmasusp) + { + /* Rx DMA in suspended state. */ + + if (stm32wl5serial_dmarxavailable(&priv->dev)) + { + /* DMA buffer has unprocessed data, do not re-enable yet. */ + + return false; + } + } + else +#endif + { + return false; + } + } + + /* DMA is stopped or suspended and DMA buffer does not have pending data, + * re-enabling without data loss is now safe. + */ + + stm32wl5serial_dmareenable(priv); + + return true; +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_dmarxint + * + * Description: + * Call to enable or disable RX interrupts + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static void stm32wl5serial_dmarxint(FAR struct uart_dev_s *dev, bool enable) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + + /* En/disable DMA reception. + * + * Note that it is not safe to check for available bytes and immediately + * pass them to uart_recvchars as that could potentially recurse back + * to us again. Instead, bytes must wait until the next up_dma_poll or + * DMA event. + */ + + priv->rxenable = enable; + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + /* Re-enable RX DMA. */ + + (void)stm32wl5serial_dmaiflowrestart(priv); + } +#endif +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_dmarxavailable + * + * Description: + * Return true if the receive register is not empty + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static bool stm32wl5serial_dmarxavailable(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + + /* Compare our receive pointer to the current DMA pointer, if they + * do not match, then there are bytes to be received. + */ + + return (stm32wl5serial_dmanextrx(priv) != priv->rxdmanext); +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_send + * + * Description: + * This method will send one byte on the USART + * + ****************************************************************************/ + +static void stm32wl5serial_send(FAR struct uart_dev_s *dev, int ch) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + +#ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + stm32wl5_gpiowrite(priv->rs485_dir_gpio, priv->rs485_dir_polarity); + } +#endif + + stm32wl5serial_putreg(priv, STM32WL5_USART_TDR_OFFSET, (uint32_t)ch); +} + +/**************************************************************************** + * Name: stm32wl5serial_txint + * + * Description: + * Call to enable or disable TX interrupts + * + ****************************************************************************/ + +static void stm32wl5serial_txint(FAR struct uart_dev_s *dev, bool enable) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + irqstate_t flags; + + /* USART transmit interrupts: + * + * Enable Status Meaning Usage + * --------------- ------------- ---------------------------- ------------- + * USART_CR1_TCIE USART_ISR_TC Transmission Complete (only RS-485) + * USART_CR1_TXEIE USART_ISR_TXE Transmit Data Register Empty + * USART_CR3_CTSIE USART_ISR_CTS CTS flag (not used) + */ + + flags = enter_critical_section(); + if (enable) + { + /* Set to receive an interrupt when the TX data register is empty */ + +#ifndef CONFIG_SUPPRESS_SERIAL_INTS + uint16_t ie = priv->ie | USART_CR1_TXEIE; + + /* If RS-485 is supported on this U[S]ART, then also enable the + * transmission complete interrupt. + */ + +# ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + ie |= USART_CR1_TCIE; + } +# endif + +# ifdef CONFIG_STM32WL5_SERIALBRK_BSDCOMPAT + if (priv->ie & USART_CR1_IE_BREAK_INPROGRESS) + { + return; + } +# endif + + stm32wl5serial_restoreusartint(priv, ie); + + /* Fake a TX interrupt here by just calling uart_xmitchars() with + * interrupts disabled (note this may recurse). + */ + + uart_xmitchars(dev); +#endif + } + else + { + /* Disable the TX interrupt */ + + stm32wl5serial_restoreusartint(priv, priv->ie & ~USART_CR1_TXEIE); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Name: stm32wl5serial_txready + * + * Description: + * Return true if the transmit data register is empty + * + ****************************************************************************/ + +static bool stm32wl5serial_txready(FAR struct uart_dev_s *dev) +{ + FAR struct stm32wl5_serial_s *priv = + (FAR struct stm32wl5_serial_s *)dev->priv; + + return ((stm32wl5serial_getreg(priv, STM32WL5_USART_ISR_OFFSET) & + USART_ISR_TXE) != 0); +} + +/**************************************************************************** + * Name: stm32wl5serial_dmarxcallback + * + * Description: + * This function checks the current DMA state and calls the generic + * serial stack when bytes appear to be available. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +static void stm32wl5serial_dmarxcallback(DMA_HANDLE handle, uint8_t status, + FAR void *arg) +{ + FAR struct stm32wl5_serial_s *priv = (FAR struct stm32wl5_serial_s *)arg; + + if (priv->rxenable && stm32wl5serial_dmarxavailable(&priv->dev)) + { + uart_recvchars(&priv->dev); + +#ifdef CONFIG_SERIAL_IFLOWCONTROL + if (priv->iflow) + { + /* Re-enable RX DMA. */ + + (void)stm32wl5serial_dmaiflowrestart(priv); + } +#endif + } + + /* Get the masked USART status word to check and clear error flags. + * + * When wake-up from low power mode was not fast enough, UART is resumed + * too late and sometimes exactly when character was coming over UART, + * resulting to frame error. + * If error flag is not cleared, Rx DMA will be stuck. Clearing errors + * will release Rx DMA. + */ + + priv->sr = stm32wl5serial_getreg(priv, STM32WL5_USART_ISR_OFFSET); + + if ((priv->sr & (USART_ISR_ORE | USART_ISR_NF | USART_ISR_FE)) != 0) + { + stm32wl5serial_putreg(priv, STM32WL5_USART_ICR_OFFSET, + (USART_ICR_NCF | USART_ICR_ORECF | + USART_ICR_FECF)); + } +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_pmnotify + * + * Description: + * Notify the driver of new power state. This callback is called after + * all drivers have had the opportunity to prepare for the new power state. + * + * Input Parameters: + * + * cb - Returned to the driver. The driver version of the callback + * structure may include additional, driver-specific state data at + * the end of the structure. + * + * pmstate - Identifies the new PM state + * + * Returned Value: + * None - The driver already agreed to transition to the low power + * consumption state when when it returned OK to the prepare() call. + * + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static void stm32wl5serial_pmnotify(FAR struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + switch (pmstate) + { + case PM_NORMAL: + { + stm32wl5serial_pm_setsuspend(false); + } + break; + + case PM_IDLE: + { + stm32wl5serial_pm_setsuspend(false); + } + break; + + case PM_STANDBY: + { + /* TODO: Alternative configuration and logic for enabling serial in + * Stop 1 mode with HSI16 missing. Current logic allows + * suspending serial peripherals for Stop 0/1/2 when serial + * Rx/Tx buffers are empty (checked in pmprepare). + */ + + stm32wl5serial_pm_setsuspend(true); + } + break; + + case PM_SLEEP: + { + stm32wl5serial_pm_setsuspend(true); + } + break; + + default: + + /* Should not get here */ + + break; + } +} +#endif + +/**************************************************************************** + * Name: stm32wl5serial_pmprepare + * + * Description: + * Request the driver to prepare for a new power state. This is a warning + * that the system is about to enter into a new power state. The driver + * should begin whatever operations that may be required to enter power + * state. The driver may abort the state change mode by returning a + * non-zero value from the callback function. + * + * Input Parameters: + * + * cb - Returned to the driver. The driver version of the callback + * structure may include additional, driver-specific state data at + * the end of the structure. + * + * pmstate - Identifies the new PM state + * + * Returned Value: + * Zero - (OK) means the event was successfully processed and that the + * driver is prepared for the PM state change. + * + * Non-zero - means that the driver is not prepared to perform the tasks + * needed achieve this power setting and will cause the state + * change to be aborted. NOTE: The prepare() method will also + * be called when reverting from lower back to higher power + * consumption modes (say because another driver refused a + * lower power state change). Drivers are not permitted to + * return non-zero values when reverting back to higher power + * consumption modes! + * + ****************************************************************************/ + +#ifdef CONFIG_PM +static int stm32wl5serial_pmprepare(FAR struct pm_callback_s *cb, int domain, + enum pm_state_e pmstate) +{ + int n; + + /* Logic to prepare for a reduced power state goes here. */ + + switch (pmstate) + { + case PM_NORMAL: + case PM_IDLE: + break; + + case PM_STANDBY: + case PM_SLEEP: + +#ifdef SERIAL_HAVE_DMA + /* Flush Rx DMA buffers before checking state of serial device + * buffers. + */ + + stm32wl5_serial_dma_poll(); +#endif + + /* Check if any of the active ports have data pending on Tx/Rx + * buffers. + */ + + for (n = 0; n < STM32WL5_NLPUART + STM32WL5_NUSART; n++) + { + struct stm32wl5_serial_s *priv = g_uart_devs[n]; + + if (!priv || !priv->initialized) + { + /* Not active, skip. */ + + continue; + } + + if (priv->suspended) + { + /* Port already suspended, skip. */ + + continue; + } + + /* Check if port has data pending (Rx & Tx). */ + + if (priv->dev.xmit.head != priv->dev.xmit.tail) + { + return ERROR; + } + + if (priv->dev.recv.head != priv->dev.recv.tail) + { + return ERROR; + } + } + break; + + default: + + /* Should not get here */ + + break; + } + + return OK; +} +#endif + +#endif /* HAVE_UART */ +#endif /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef USE_SERIALDRIVER + +/**************************************************************************** + * Name: arm_earlyserialinit + * + * Description: + * Performs the low level USART initialization early in debug so that the + * serial console will be available during bootup. This must be called + * before arm_serialinit. + * + ****************************************************************************/ + +#ifdef USE_EARLYSERIALINIT +void arm_earlyserialinit(void) +{ +#ifdef HAVE_UART + unsigned i; + + /* Disable all USART interrupts */ + + for (i = 0; i < STM32WL5_NLPUART + STM32WL5_NUSART; i++) + { + if (g_uart_devs[i]) + { + stm32wl5serial_disableusartint(g_uart_devs[i], NULL); + } + } + + /* Configure whichever one is the console */ + +#if CONSOLE_UART > 0 + stm32wl5serial_setup(&g_uart_devs[CONSOLE_UART - 1]->dev); +#endif +#endif /* HAVE UART */ +} +#endif /* USE_EARLYSERIALINIT */ + +/**************************************************************************** + * Name: arm_serialinit + * + * Description: + * Register serial console and serial ports. This assumes + * that arm_earlyserialinit was called previously. + * + ****************************************************************************/ + +void arm_serialinit(void) +{ +#ifdef HAVE_UART + char devname[16]; + unsigned i; + unsigned minor = 0; +#ifdef CONFIG_PM + int ret; +#endif + + /* Register to receive power management callbacks */ + +#ifdef CONFIG_PM + ret = pm_register(&g_serialpm.pm_cb); + DEBUGASSERT(ret == OK); + UNUSED(ret); +#endif + + /* Register the console */ + +#if CONSOLE_UART > 0 + (void)uart_register("/dev/console", &g_uart_devs[CONSOLE_UART - 1]->dev); + +#ifndef CONFIG_STM32WL5_SERIAL_DISABLE_REORDERING + /* If not disabled, register the console UART to ttyS0 and exclude + * it from initializing it further down + */ + + (void)uart_register("/dev/ttyS0", &g_uart_devs[CONSOLE_UART - 1]->dev); + minor = 1; +#endif + +#ifdef SERIAL_HAVE_CONSOLE_DMA + /* If we need to re-initialise the console to enable DMA do that here. */ + + stm32wl5serial_dmasetup(&g_uart_devs[CONSOLE_UART - 1]->dev); +#endif +#endif /* CONSOLE_UART > 0 */ + + /* Register all remaining USARTs */ + + strcpy(devname, "/dev/ttySx"); + + for (i = 0; i < STM32WL5_NLPUART + STM32WL5_NUSART; i++) + { + /* Don't create a device for non-configured ports. */ + + if (g_uart_devs[i] == 0) + { + continue; + } + +#ifndef CONFIG_STM32WL5_SERIAL_DISABLE_REORDERING + /* Don't create a device for the console - we did that above */ + + if (g_uart_devs[i]->dev.isconsole) + { + continue; + } +#endif + + /* Register USARTs as devices in increasing order */ + + devname[9] = '0' + minor++; + (void)uart_register(devname, &g_uart_devs[i]->dev); + } +#endif /* HAVE UART */ +} + +/**************************************************************************** + * Name: stm32wl5_serial_dma_poll + * + * Description: + * Checks receive DMA buffers for received bytes that have not accumulated + * to the point where the DMA half/full interrupt has triggered. + * + * This function should be called from a timer or other periodic context. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +void stm32wl5_serial_dma_poll(void) +{ + irqstate_t flags; + + flags = enter_critical_section(); + +#ifdef CONFIG_LPUART1_RXDMA + if (g_lpuart1priv.rxdma != NULL) + { + stm32wl5serial_dmarxcallback(g_lpuart1priv.rxdma, 0, &g_lpuart1priv); + } +#endif + +#ifdef CONFIG_USART1_RXDMA + if (g_usart1priv.rxdma != NULL) + { + stm32wl5serial_dmarxcallback(g_usart1priv.rxdma, 0, &g_usart1priv); + } +#endif + +#ifdef CONFIG_USART2_RXDMA + if (g_usart2priv.rxdma != NULL) + { + stm32wl5serial_dmarxcallback(g_usart2priv.rxdma, 0, &g_usart2priv); + } +#endif + + leave_critical_section(flags); +} +#endif + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#if CONSOLE_UART > 0 + struct stm32wl5_serial_s *priv = g_uart_devs[CONSOLE_UART - 1]; + uint16_t ie; + + stm32wl5serial_disableusartint(priv, &ie); + + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + arm_lowputc('\r'); + } + + arm_lowputc(ch); + stm32wl5serial_restoreusartint(priv, ie); +#endif + return ch; +} + +#else /* USE_SERIALDRIVER */ + +/**************************************************************************** + * Name: up_putc + * + * Description: + * Provide priority, low-level access to support OS debug writes + * + ****************************************************************************/ + +int up_putc(int ch) +{ +#if CONSOLE_UART > 0 + /* Check for LF */ + + if (ch == '\n') + { + /* Add CR */ + + arm_lowputc('\r'); + } + + arm_lowputc(ch); +#endif + return ch; +} + +#endif /* USE_SERIALDRIVER */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_start.c b/arch/arm/src/stm32wl5/stm32wl5_start.c new file mode 100644 index 0000000000..9b73df69a7 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_start.c @@ -0,0 +1,217 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_start.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include + +#include "arm_internal.h" +#include "arm_internal.h" +#include "nvic.h" + +#include "stm32wl5.h" +#include "stm32wl5_gpio.h" +#include "stm32wl5_userspace.h" +#include "stm32wl5_start.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Memory Map ***************************************************************/ + +/* 0x0800:0000 - Beginning of the internal FLASH. Address of vectors. + * Mapped as boot memory address 0x0000:0000 at reset. + * 0x080f:ffff - End of flash region (assuming the max of 2MiB of FLASH). + * 0x2000:0000 - Start of internal SRAM and start of .data (_sdata) + * - End of .data (_edata) and start of .bss (_sbss) + * - End of .bss (_ebss) and bottom of idle stack + * - _ebss + CONFIG_IDLETHREAD_STACKSIZE = end of idle stack, + * start of heap. NOTE that the ARM uses a decrement before + * store stack so that the correct initial value is the end of + * the stack + 4; + * 0x2000:8000 - Start of internal SRAM2 + */ + +#define SRAM2_START STM32WL5_SRAM2_BASE +#define SRAM2_END (SRAM2_START + STM32WL5_SRAM2_SIZE) + +#define HEAP_BASE ((uintptr_t)&_ebss+CONFIG_IDLETHREAD_STACKSIZE) + +/* g_idle_topstack: _sbss is the start of the BSS region as defined by the + * linker script. _ebss lies at the end of the BSS region. The idle task + * stack starts at the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE. + * The IDLE thread is the thread that the system boots on and, eventually, + * becomes the IDLE, do nothing task that runs only when there is nothing + * else to run. The heap continues from there until the end of memory. + * g_idle_topstack is a read-only variable the provides this computed + * address. + */ + +const uintptr_t g_idle_topstack = HEAP_BASE; + +/**************************************************************************** + * Private Function prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: showprogress + * + * Description: + * Print a character on the UART to show boot status. + * + ****************************************************************************/ + +#ifdef CONFIG_DEBUG_FEATURES +# define showprogress(c) arm_lowputc(c) +#else +# define showprogress(c) +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +#ifdef CONFIG_ARMV7M_STACKCHECK +/* we need to get r10 set before we can allow instrumentation calls */ + +void __start(void) noinstrument_function; +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: _start + * + * Description: + * This is the reset entry point. + * + ****************************************************************************/ + +void __start(void) +{ + const uint32_t *src; + uint32_t *dest; + +#ifdef CONFIG_ARMV7M_STACKCHECK + /* Set the stack limit before we attempt to call any functions */ + + __asm__ volatile("sub r10, sp, %0" : : + "r"(CONFIG_IDLETHREAD_STACKSIZE - 64) :); +#endif + +#ifdef CONFIG_STM32WL5_SRAM2_INIT + /* The SRAM2 region is parity checked, but upon power up, it will be in + * a random state and probably invalid with respect to parity, potentially + * generating faults if accessed. If elected, we will write zeros to the + * memory, forcing the parity to be set to a valid state. + * NOTE: this is optional because this may be inappropriate, especially + * if the memory is being used for it's battery backed purpose. In that + * case, the first-time initialization needs to be performed by the board + * under application-specific circumstances. On the other hand, if we're + * using this memory for, say, additional heap space, then this is handy. + */ + + for (dest = (uint32_t *)SRAM2_START; dest < (uint32_t *)SRAM2_END; ) + { + *dest++ = 0; + } +#endif + + /* Configure the UART so that we can get debug output as soon as possible */ + + stm32wl5_clockconfig(); + stm32wl5_lowsetup(); + stm32wl5_gpioinit(); + showprogress('A'); + + /* Clear .bss. We'll do this inline (vs. calling memset) just to be + * certain that there are no issues with the state of global variables. + */ + + for (dest = &_sbss; dest < &_ebss; ) + { + *dest++ = 0; + } + + showprogress('B'); + + /* Move the initialized data section from his temporary holding spot in + * FLASH into the correct place in SRAM. The correct place in SRAM is + * give by _sdata and _edata. The temporary location is in FLASH at the + * end of all of the other read-only data (.text, .rodata) at _eronly. + */ + + for (src = &_eronly, dest = &_sdata; dest < &_edata; ) + { + *dest++ = *src++; + } + + showprogress('C'); + + /* Perform early serial initialization */ + +#ifdef USE_EARLYSERIALINIT + arm_earlyserialinit(); +#endif + showprogress('D'); + + /* For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + */ + +#ifdef CONFIG_BUILD_PROTECTED + stm32wl5_userspace(); + showprogress('E'); +#endif + + /* Initialize onboard resources */ + + stm32wl5_board_initialize(); + showprogress('F'); + + /* Then start NuttX */ + + showprogress('\r'); + showprogress('\n'); + + nx_start(); + + /* Shouldn't get here */ + + for (; ; ); +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_start.h b/arch/arm/src/stm32wl5/stm32wl5_start.h new file mode 100644 index 0000000000..714805a84e --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_start.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_start.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_START_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_START_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_board_initialize + * + * Description: + * All STM32WL5 architectures must provide the following entry point. This + * entry point is called early in the initialization -- after all memory + * has been configured and mapped but before any devices have been + * initialized. + * + ****************************************************************************/ + +void stm32wl5_board_initialize(void); + +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_START_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_tim.c b/arch/arm/src/stm32wl5/stm32wl5_tim.c new file mode 100644 index 0000000000..45ba68e12f --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_tim.c @@ -0,0 +1,1695 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_tim.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "chip.h" +#include "arm_internal.h" +#include "arm_internal.h" + +#include "stm32wl5.h" +#include "stm32wl5_gpio.h" +#include "stm32wl5_tim.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Configuration ************************************************************/ + +/* Timer devices may be used for different purposes. Such special purposes + * include: + * + * - To generate modulated outputs for such things as motor control. If + * CONFIG_STM32WL5_TIMn is defined then the CONFIG_STM32WL5_TIMn_PWM may + * also be defined to indicate that the timer is intended to be used for + * pulsed output modulation. + * + * - To control periodic ADC input sampling. If CONFIG_STM32WL5_TIMn is + * defined then CONFIG_STM32WL5_TIMn_ADC may also be defined to indicate + * that timer "n" is intended to be used for that purpose. + * + * - To control periodic DAC outputs. If CONFIG_STM32WL5_TIMn is defined + * then CONFIG_STM32WL5_TIMn_DAC may also be defined to indicate that + * timer "n" is intended to be used for that purpose. + * + * - To use a Quadrature Encoder. If CONFIG_STM32WL5_TIMn is defined then + * CONFIG_STM32WL5_TIMn_QE may also be defined to indicate that timer "n" + * is intended to be used for that purpose. + * + * In any of these cases, the timer will not be used by this timer module. + */ + +#if defined(CONFIG_STM32WL5_TIM1_PWM) || defined (CONFIG_STM32WL5_TIM1_ADC) || \ + defined(CONFIG_STM32WL5_TIM1_DAC) || defined(CONFIG_STM32WL5_TIM1_QE) +# undef CONFIG_STM32WL5_TIM1 +#endif + +#if defined(CONFIG_STM32WL5_TIM2_PWM) || defined (CONFIG_STM32WL5_TIM2_ADC) || \ + defined(CONFIG_STM32WL5_TIM2_DAC) || defined(CONFIG_STM32WL5_TIM2_QE) +# undef CONFIG_STM32WL5_TIM2 +#endif + +#if defined(CONFIG_STM32WL5_TIM3_PWM) || defined (CONFIG_STM32WL5_TIM3_ADC) || \ + defined(CONFIG_STM32WL5_TIM3_DAC) || defined(CONFIG_STM32WL5_TIM3_QE) +# undef CONFIG_STM32WL5_TIM3 +#endif + +#if defined(CONFIG_STM32WL5_TIM4_PWM) || defined (CONFIG_STM32WL5_TIM4_ADC) || \ + defined(CONFIG_STM32WL5_TIM4_DAC) || defined(CONFIG_STM32WL5_TIM4_QE) +# undef CONFIG_STM32WL5_TIM4 +#endif + +#if defined(CONFIG_STM32WL5_TIM5_PWM) || defined (CONFIG_STM32WL5_TIM5_ADC) || \ + defined(CONFIG_STM32WL5_TIM5_DAC) || defined(CONFIG_STM32WL5_TIM5_QE) +# undef CONFIG_STM32WL5_TIM5 +#endif + +#if defined(CONFIG_STM32WL5_TIM6_PWM) || defined (CONFIG_STM32WL5_TIM6_ADC) || \ + defined(CONFIG_STM32WL5_TIM6_DAC) || defined(CONFIG_STM32WL5_TIM6_QE) +# undef CONFIG_STM32WL5_TIM6 +#endif + +#if defined(CONFIG_STM32WL5_TIM7_PWM) || defined (CONFIG_STM32WL5_TIM7_ADC) || \ + defined(CONFIG_STM32WL5_TIM7_DAC) || defined(CONFIG_STM32WL5_TIM7_QE) +# undef CONFIG_STM32WL5_TIM7 +#endif + +#if defined(CONFIG_STM32WL5_TIM8_PWM) || defined (CONFIG_STM32WL5_TIM8_ADC) || \ + defined(CONFIG_STM32WL5_TIM8_DAC) || defined(CONFIG_STM32WL5_TIM8_QE) +# undef CONFIG_STM32WL5_TIM8 +#endif + +#if defined(CONFIG_STM32WL5_TIM15_PWM) || defined (CONFIG_STM32WL5_TIM15_ADC) || \ + defined(CONFIG_STM32WL5_TIM15_DAC) || defined(CONFIG_STM32WL5_TIM15_QE) +# undef CONFIG_STM32WL5_TIM15 +#endif + +#if defined(CONFIG_STM32WL5_TIM16_PWM) || defined (CONFIG_STM32WL5_TIM16_ADC) || \ + defined(CONFIG_STM32WL5_TIM16_DAC) || defined(CONFIG_STM32WL5_TIM16_QE) +# undef CONFIG_STM32WL5_TIM16 +#endif + +#if defined(CONFIG_STM32WL5_TIM17_PWM) || defined (CONFIG_STM32WL5_TIM17_ADC) || \ + defined(CONFIG_STM32WL5_TIM17_DAC) || defined(CONFIG_STM32WL5_TIM17_QE) +# undef CONFIG_STM32WL5_TIM17 +#endif + +#if defined(CONFIG_STM32WL5_TIM1) +# if defined(GPIO_TIM1_CH1OUT) ||defined(GPIO_TIM1_CH2OUT)||\ + defined(GPIO_TIM1_CH3OUT) ||defined(GPIO_TIM1_CH4OUT) +# define HAVE_TIM1_GPIOCONFIG 1 +#endif +#endif + +#if defined(CONFIG_STM32WL5_TIM2) +# if defined(GPIO_TIM2_CH1OUT) ||defined(GPIO_TIM2_CH2OUT)||\ + defined(GPIO_TIM2_CH3OUT) ||defined(GPIO_TIM2_CH4OUT) +# define HAVE_TIM2_GPIOCONFIG 1 +#endif +#endif + +#if defined(CONFIG_STM32WL5_TIM3) +# if defined(GPIO_TIM3_CH1OUT) ||defined(GPIO_TIM3_CH2OUT)||\ + defined(GPIO_TIM3_CH3OUT) ||defined(GPIO_TIM3_CH4OUT) +# define HAVE_TIM3_GPIOCONFIG 1 +#endif +#endif + +#if defined(CONFIG_STM32WL5_TIM4) +# if defined(GPIO_TIM4_CH1OUT) ||defined(GPIO_TIM4_CH2OUT)||\ + defined(GPIO_TIM4_CH3OUT) ||defined(GPIO_TIM4_CH4OUT) +# define HAVE_TIM4_GPIOCONFIG 1 +#endif +#endif + +#if defined(CONFIG_STM32WL5_TIM5) +# if defined(GPIO_TIM5_CH1OUT) ||defined(GPIO_TIM5_CH2OUT)||\ + defined(GPIO_TIM5_CH3OUT) ||defined(GPIO_TIM5_CH4OUT) +# define HAVE_TIM5_GPIOCONFIG 1 +#endif +#endif + +#if defined(CONFIG_STM32WL5_TIM8) +# if defined(GPIO_TIM8_CH1OUT) ||defined(GPIO_TIM8_CH2OUT)||\ + defined(GPIO_TIM8_CH3OUT) ||defined(GPIO_TIM8_CH4OUT) +# define HAVE_TIM8_GPIOCONFIG 1 +#endif +#endif + +#if defined(CONFIG_STM32WL5_TIM15) +# if defined(GPIO_TIM15_CH1OUT) ||defined(GPIO_TIM15_CH2OUT)||\ + defined(GPIO_TIM15_CH3OUT) ||defined(GPIO_TIM15_CH4OUT) +# define HAVE_TIM15_GPIOCONFIG 1 +#endif +#endif + +#if defined(CONFIG_STM32WL5_TIM16) +# if defined(GPIO_TIM16_CH1OUT) ||defined(GPIO_TIM16_CH2OUT)||\ + defined(GPIO_TIM16_CH3OUT) ||defined(GPIO_TIM16_CH4OUT) +# define HAVE_TIM16_GPIOCONFIG 1 +#endif +#endif + +#if defined(CONFIG_STM32WL5_TIM17) +# if defined(GPIO_TIM17_CH1OUT) ||defined(GPIO_TIM17_CH2OUT)||\ + defined(GPIO_TIM17_CH3OUT) ||defined(GPIO_TIM17_CH4OUT) +# define HAVE_TIM17_GPIOCONFIG 1 +#endif +#endif + +/* This module then only compiles if there are enabled timers that are not + * intended for some other purpose. + */ + +#if defined(CONFIG_STM32WL5_TIM1) || defined(CONFIG_STM32WL5_TIM2) || \ + defined(CONFIG_STM32WL5_TIM3) || defined(CONFIG_STM32WL5_TIM4) || \ + defined(CONFIG_STM32WL5_TIM5) || defined(CONFIG_STM32WL5_TIM6) || \ + defined(CONFIG_STM32WL5_TIM7) || defined(CONFIG_STM32WL5_TIM8) || \ + defined(CONFIG_STM32WL5_TIM15) || defined(CONFIG_STM32WL5_TIM16) || \ + defined(CONFIG_STM32WL5_TIM17) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* TIM Device Structure */ + +struct stm32wl5_tim_priv_s +{ + FAR const struct stm32wl5_tim_ops_s *ops; + enum stm32wl5_tim_mode_e mode; + uint32_t base; /* TIMn base address */ +}; + +/**************************************************************************** + * Private Function prototypes + ****************************************************************************/ + +/* Register helpers */ + +static inline uint16_t stm32wl5_getreg16(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset); +static inline void stm32wl5_putreg16(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset, uint16_t value); +static inline void stm32wl5_modifyreg16(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset, uint16_t clearbits, + uint16_t setbits); +static inline uint32_t stm32wl5_getreg32(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset); +static inline void stm32wl5_putreg32(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset, uint32_t value); + +/* Timer helpers */ + +static void stm32wl5_tim_reload_counter(FAR struct stm32wl5_tim_dev_s *dev); +static void stm32wl5_tim_enable(FAR struct stm32wl5_tim_dev_s *dev); +static void stm32wl5_tim_disable(FAR struct stm32wl5_tim_dev_s *dev); +static void stm32wl5_tim_reset(FAR struct stm32wl5_tim_dev_s *dev); +#if defined(HAVE_TIM1_GPIOCONFIG) || defined(HAVE_TIM2_GPIOCONFIG) || \ + defined(HAVE_TIM3_GPIOCONFIG) || defined(HAVE_TIM4_GPIOCONFIG) || \ + defined(HAVE_TIM5_GPIOCONFIG) || defined(HAVE_TIM8_GPIOCONFIG) || \ + defined(HAVE_TIM15_GPIOCONFIG) || defined(HAVE_TIM16_GPIOCONFIG) || \ + defined(HAVE_TIM17_GPIOCONFIG) +static void stm32wl5_tim_gpioconfig(uint32_t cfg, + enum stm32wl5_tim_channel_e mode); +#endif + +/* Timer methods */ + +static int stm32wl5_tim_setmode(FAR struct stm32wl5_tim_dev_s *dev, + enum stm32wl5_tim_mode_e mode); +static int stm32wl5_tim_setclock(FAR struct stm32wl5_tim_dev_s *dev, + uint32_t freq); +static uint32_t stm32wl5_tim_getclock(FAR struct stm32wl5_tim_dev_s *dev); +static void stm32wl5_tim_setperiod(FAR struct stm32wl5_tim_dev_s *dev, + uint32_t period); +static uint32_t stm32wl5_tim_getperiod(FAR struct stm32wl5_tim_dev_s *dev); +static uint32_t stm32wl5_tim_getcounter(FAR struct stm32wl5_tim_dev_s *dev); +static int stm32wl5_tim_setchannel(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t channel, + enum stm32wl5_tim_channel_e mode); +static int stm32wl5_tim_setcompare(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t channel, uint32_t compare); +static int stm32wl5_tim_getcapture(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t channel); +static int stm32wl5_tim_setisr(FAR struct stm32wl5_tim_dev_s *dev, + xcpt_t handler, void *arg, int source); +static void stm32wl5_tim_enableint(FAR struct stm32wl5_tim_dev_s *dev, + int source); +static void stm32wl5_tim_disableint(FAR struct stm32wl5_tim_dev_s *dev, + int source); +static void stm32wl5_tim_ackint(FAR struct stm32wl5_tim_dev_s *dev, + int source); +static int stm32wl5_tim_checkint(FAR struct stm32wl5_tim_dev_s *dev, + int source); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct stm32wl5_tim_ops_s stm32wl5_tim_ops = +{ + .setmode = stm32wl5_tim_setmode, + .setclock = stm32wl5_tim_setclock, + .getclock = stm32wl5_tim_getclock, + .setperiod = stm32wl5_tim_setperiod, + .getperiod = stm32wl5_tim_getperiod, + .getcounter = stm32wl5_tim_getcounter, + .setchannel = stm32wl5_tim_setchannel, + .setcompare = stm32wl5_tim_setcompare, + .getcapture = stm32wl5_tim_getcapture, + .setisr = stm32wl5_tim_setisr, + .enableint = stm32wl5_tim_enableint, + .disableint = stm32wl5_tim_disableint, + .ackint = stm32wl5_tim_ackint, + .checkint = stm32wl5_tim_checkint, +}; + +#ifdef CONFIG_STM32WL5_TIM1 +struct stm32wl5_tim_priv_s stm32wl5_tim1_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM1_BASE, +}; +#endif +#ifdef CONFIG_STM32WL5_TIM2 +struct stm32wl5_tim_priv_s stm32wl5_tim2_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM2_BASE, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM3 +struct stm32wl5_tim_priv_s stm32wl5_tim3_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM3_BASE, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM4 +struct stm32wl5_tim_priv_s stm32wl5_tim4_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM4_BASE, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM5 +struct stm32wl5_tim_priv_s stm32wl5_tim5_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM5_BASE, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM6 +struct stm32wl5_tim_priv_s stm32wl5_tim6_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM6_BASE, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM7 +struct stm32wl5_tim_priv_s stm32wl5_tim7_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM7_BASE, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM8 +struct stm32wl5_tim_priv_s stm32wl5_tim8_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM8_BASE, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM15 +struct stm32wl5_tim_priv_s stm32wl5_tim15_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM15_BASE, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM16 +struct stm32wl5_tim_priv_s stm32wl5_tim16_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM16_BASE, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM17 +struct stm32wl5_tim_priv_s stm32wl5_tim17_priv = +{ + .ops = &stm32wl5_tim_ops, + .mode = STM32WL5_TIM_MODE_UNUSED, + .base = STM32WL5_TIM17_BASE, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_getreg16 + * + * Description: + * Get a 16-bit register value by offset + * + ****************************************************************************/ + +static inline uint16_t stm32wl5_getreg16(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset) +{ + return getreg16(((struct stm32wl5_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: stm32wl5_putreg16 + * + * Description: + * Put a 16-bit register value by offset + * + ****************************************************************************/ + +static inline void stm32wl5_putreg16(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset, uint16_t value) +{ + putreg16(value, ((struct stm32wl5_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: stm32wl5_modifyreg16 + * + * Description: + * Modify a 16-bit register value by offset + * + ****************************************************************************/ + +static inline void stm32wl5_modifyreg16(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset, uint16_t clearbits, + uint16_t setbits) +{ + modifyreg16(((struct stm32wl5_tim_priv_s *)dev)->base + offset, clearbits, + setbits); +} + +/**************************************************************************** + * Name: stm32wl5_getreg32 + * + * Description: + * Get a 32-bit register value by offset. This applies only for the + * STM32WL5 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5 + * + ****************************************************************************/ + +static inline uint32_t stm32wl5_getreg32(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset) +{ + return getreg32(((struct stm32wl5_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: stm32wl5_putreg32 + * + * Description: + * Put a 32-bit register value by offset. This applies only for the + * STM32WL5 32-bit registers (CNT, ARR, CRR1-4) in the 32-bit timers TIM2-5 + * + ****************************************************************************/ + +static inline void stm32wl5_putreg32(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t offset, uint32_t value) +{ + putreg32(value, ((struct stm32wl5_tim_priv_s *)dev)->base + offset); +} + +/**************************************************************************** + * Name: stm32wl5_tim_reload_counter + ****************************************************************************/ + +static void stm32wl5_tim_reload_counter(FAR struct stm32wl5_tim_dev_s *dev) +{ + uint16_t val = stm32wl5_getreg16(dev, STM32WL5_GTIM_EGR_OFFSET); + val |= GTIM_EGR_UG; + stm32wl5_putreg16(dev, STM32WL5_GTIM_EGR_OFFSET, val); +} + +/**************************************************************************** + * Name: stm32wl5_tim_enable + ****************************************************************************/ + +static void stm32wl5_tim_enable(FAR struct stm32wl5_tim_dev_s *dev) +{ + uint16_t val = stm32wl5_getreg16(dev, STM32WL5_GTIM_CR1_OFFSET); + val |= GTIM_CR1_CEN; + stm32wl5_tim_reload_counter(dev); + stm32wl5_putreg16(dev, STM32WL5_GTIM_CR1_OFFSET, val); +} + +/**************************************************************************** + * Name: stm32wl5_tim_disable + ****************************************************************************/ + +static void stm32wl5_tim_disable(FAR struct stm32wl5_tim_dev_s *dev) +{ + uint16_t val = stm32wl5_getreg16(dev, STM32WL5_GTIM_CR1_OFFSET); + val &= ~GTIM_CR1_CEN; + stm32wl5_putreg16(dev, STM32WL5_GTIM_CR1_OFFSET, val); +} + +/**************************************************************************** + * Name: stm32wl5_tim_reset + * + * Description: + * Reset timer into system default state, but do not affect output/input + * pins + * + ****************************************************************************/ + +static void stm32wl5_tim_reset(FAR struct stm32wl5_tim_dev_s *dev) +{ + ((struct stm32wl5_tim_priv_s *)dev)->mode = STM32WL5_TIM_MODE_DISABLED; + stm32wl5_tim_disable(dev); +} + +/**************************************************************************** + * Name: stm32wl5_tim_gpioconfig + ****************************************************************************/ + +#if defined(HAVE_TIM1_GPIOCONFIG) || defined(HAVE_TIM2_GPIOCONFIG) || \ + defined(HAVE_TIM3_GPIOCONFIG) || defined(HAVE_TIM4_GPIOCONFIG) || \ + defined(HAVE_TIM5_GPIOCONFIG) || defined(HAVE_TIM8_GPIOCONFIG) || \ + defined(HAVE_TIM15_GPIOCONFIG) || defined(HAVE_TIM16_GPIOCONFIG) || \ + defined(HAVE_TIM17_GPIOCONFIG) +static void stm32wl5_tim_gpioconfig(uint32_t cfg, + enum stm32wl5_tim_channel_e mode) +{ + /* TODO: Add support for input capture and bipolar dual outputs for TIM8 */ + + if (mode & STM32WL5_TIM_CH_MODE_MASK) + { + stm32wl5_configgpio(cfg); + } + else + { + stm32wl5_unconfiggpio(cfg); + } +} +#endif + +/**************************************************************************** + * Name: stm32wl5_tim_setmode + ****************************************************************************/ + +static int stm32wl5_tim_setmode(FAR struct stm32wl5_tim_dev_s *dev, + enum stm32wl5_tim_mode_e mode) +{ + uint16_t val = GTIM_CR1_CEN | GTIM_CR1_ARPE; + + DEBUGASSERT(dev != NULL); + + /* This function is not supported on basic timers. To enable or + * disable it, simply set its clock to valid frequency or zero. + */ + +#if STM32WL5_NBTIM > 0 + if (((struct stm32wl5_tim_priv_s *)dev)->base == STM32WL5_TIM6_BASE +#endif +#if STM32WL5_NBTIM > 1 + || ((struct stm32wl5_tim_priv_s *)dev)->base == STM32WL5_TIM7_BASE +#endif +#if STM32WL5_NBTIM > 0 + ) + { + return -EINVAL; + } +#endif + + /* Decode operational modes */ + + switch (mode & STM32WL5_TIM_MODE_MASK) + { + case STM32WL5_TIM_MODE_DISABLED: + val = 0; + break; + + case STM32WL5_TIM_MODE_DOWN: + val |= GTIM_CR1_DIR; + + case STM32WL5_TIM_MODE_UP: + break; + + case STM32WL5_TIM_MODE_UPDOWN: + val |= GTIM_CR1_CENTER1; + + /* Our default: Interrupts are generated on compare, when counting + * down + */ + + break; + + case STM32WL5_TIM_MODE_PULSE: + val |= GTIM_CR1_OPM; + break; + + default: + return -EINVAL; + } + + stm32wl5_tim_reload_counter(dev); + stm32wl5_putreg16(dev, STM32WL5_GTIM_CR1_OFFSET, val); + +#if STM32WL5_NATIM > 0 + /* Advanced registers require Main Output Enable */ + + if (((struct stm32wl5_tim_priv_s *)dev)->base == STM32WL5_TIM1_BASE || + ((struct stm32wl5_tim_priv_s *)dev)->base == STM32WL5_TIM8_BASE) + { + stm32wl5_modifyreg16(dev, STM32WL5_ATIM_BDTR_OFFSET, + 0, ATIM_BDTR_MOE); + } +#endif + + return OK; +} + +/**************************************************************************** + * Name: stm32wl5_tim_setclock + ****************************************************************************/ + +static int stm32wl5_tim_setclock(FAR struct stm32wl5_tim_dev_s *dev, + uint32_t freq) +{ + uint32_t freqin; + int prescaler; + + DEBUGASSERT(dev != NULL); + + /* Disable Timer? */ + + if (freq == 0) + { + stm32wl5_tim_disable(dev); + return 0; + } + + /* Get the input clock frequency for this timer. These vary with + * different timer clock sources, MCU-specific timer configuration, and + * board-specific clock configuration. The correct input clock frequency + * must be defined in the board.h header file. + */ + + switch (((struct stm32wl5_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32WL5_TIM1 + case STM32WL5_TIM1_BASE: + freqin = BOARD_TIM1_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM2 + case STM32WL5_TIM2_BASE: + freqin = BOARD_TIM2_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM3 + case STM32WL5_TIM3_BASE: + freqin = BOARD_TIM3_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM4 + case STM32WL5_TIM4_BASE: + freqin = BOARD_TIM4_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM5 + case STM32WL5_TIM5_BASE: + freqin = BOARD_TIM5_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM6 + case STM32WL5_TIM6_BASE: + freqin = BOARD_TIM6_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM7 + case STM32WL5_TIM7_BASE: + freqin = BOARD_TIM7_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM8 + case STM32WL5_TIM8_BASE: + freqin = BOARD_TIM8_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM15 + case STM32WL5_TIM15_BASE: + freqin = BOARD_TIM15_FREQUENCY; + break; +#endif +#ifdef CONFIG_STM32WL5_TIM16 + case STM32WL5_TIM16_BASE: + freqin = BOARD_TIM16_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM17 + case STM32WL5_TIM17_BASE: + freqin = BOARD_TIM17_FREQUENCY; + break; +#endif + + default: + return -EINVAL; + } + + /* Select a pre-scaler value for this timer using the input clock + * frequency. + */ + + prescaler = freqin / freq; + + /* We need to decrement value for '1', but only, if that will not to + * cause underflow. + */ + + if (prescaler > 0) + { + prescaler--; + } + + /* Check for overflow as well. */ + + if (prescaler > 0xffff) + { + prescaler = 0xffff; + } + + stm32wl5_putreg16(dev, STM32WL5_GTIM_PSC_OFFSET, prescaler); + stm32wl5_tim_enable(dev); + + return prescaler; +} + +/**************************************************************************** + * Name: stm32wl5_tim_getclock + ****************************************************************************/ + +static uint32_t stm32wl5_tim_getclock(FAR struct stm32wl5_tim_dev_s *dev) +{ + uint32_t freqin; + uint32_t clock; + DEBUGASSERT(dev != NULL); + + /* Get the input clock frequency for this timer. These vary with + * different timer clock sources, MCU-specific timer configuration, and + * board-specific clock configuration. The correct input clock frequency + * must be defined in the board.h header file. + */ + + switch (((struct stm32wl5_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32WL5_TIM1 + case STM32WL5_TIM1_BASE: + freqin = BOARD_TIM1_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM2 + case STM32WL5_TIM2_BASE: + freqin = BOARD_TIM2_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM3 + case STM32WL5_TIM3_BASE: + freqin = BOARD_TIM3_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM4 + case STM32WL5_TIM4_BASE: + freqin = BOARD_TIM4_FREQUENCY; + break; +#endif +#ifdef CONFIG_STM32WL5_TIM5 + case STM32WL5_TIM5_BASE: + freqin = BOARD_TIM5_FREQUENCY; + break; +#endif +#ifdef CONFIG_STM32WL5_TIM6 + case STM32WL5_TIM6_BASE: + freqin = BOARD_TIM6_FREQUENCY; + break; +#endif +#ifdef CONFIG_STM32WL5_TIM7 + case STM32WL5_TIM7_BASE: + freqin = BOARD_TIM7_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM8 + case STM32WL5_TIM8_BASE: + freqin = BOARD_TIM8_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM15 + case STM32WL5_TIM15_BASE: + freqin = BOARD_TIM15_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM16 + case STM32WL5_TIM16_BASE: + freqin = BOARD_TIM16_FREQUENCY; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM17 + case STM32WL5_TIM17_BASE: + freqin = BOARD_TIM17_FREQUENCY; + break; +#endif + default: + return -EINVAL; + } + + /* From chip datasheet, at page 1179. */ + + clock = freqin / (stm32wl5_getreg16(dev, STM32WL5_GTIM_PSC_OFFSET) + 1); + return clock; +} + +/**************************************************************************** + * Name: stm32wl5_tim_setperiod + ****************************************************************************/ + +static void stm32wl5_tim_setperiod(FAR struct stm32wl5_tim_dev_s *dev, + uint32_t period) +{ + DEBUGASSERT(dev != NULL); + stm32wl5_putreg32(dev, STM32WL5_GTIM_ARR_OFFSET, period); +} + +/**************************************************************************** + * Name: stm32wl5_tim_getperiod + ****************************************************************************/ + +static uint32_t stm32wl5_tim_getperiod (FAR struct stm32wl5_tim_dev_s *dev) +{ + DEBUGASSERT(dev != NULL); + return stm32wl5_getreg32 (dev, STM32WL5_GTIM_ARR_OFFSET); +} + +/**************************************************************************** + * Name: stm32wl5_tim_getcounter + ****************************************************************************/ + +static uint32_t stm32wl5_tim_getcounter(FAR struct stm32wl5_tim_dev_s *dev) +{ + DEBUGASSERT(dev != NULL); + uint32_t counter = stm32wl5_getreg32(dev, STM32WL5_GTIM_CNT_OFFSET); + + /* In datasheet page 988, there is a useless bit named UIFCPY in TIMx_CNT. + * reset it it result when not TIM2 or TIM5. + */ + +#if defined(CONFIG_STM32WL5_TIM2) || defined(CONFIG_STM32WL5_TIM5) + switch (((struct stm32wl5_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32WL5_TIM2 + case STM32WL5_TIM2_BASE: +#endif +#ifdef CONFIG_STM32WL5_TIM5 + case STM32WL5_TIM5_BASE: +#endif + return counter; + + default: + return counter & 0x0000ffff; + } +#else + return counter & 0x0000ffff; +#endif +} + +/**************************************************************************** + * Name: stm32wl5_tim_setchannel + ****************************************************************************/ + +static int stm32wl5_tim_setchannel(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t channel, + enum stm32wl5_tim_channel_e mode) +{ + uint16_t ccmr_orig = 0; + uint16_t ccmr_val = 0; + uint16_t ccmr_mask = 0xff; + uint16_t ccer_val; + uint8_t ccmr_offset = STM32WL5_GTIM_CCMR1_OFFSET; + + DEBUGASSERT(dev != NULL); + + /* Further we use range as 0..3; if channel=0 it will also overflow here */ + + if (--channel > 4) + { + return -EINVAL; + } + + /* Assume that channel is disabled and polarity is active high */ + + ccer_val = stm32wl5_getreg16(dev, STM32WL5_GTIM_CCER_OFFSET); + ccer_val &= ~((GTIM_CCER_CC1P | GTIM_CCER_CC1E) << + GTIM_CCER_CCXBASE(channel)); + + /* This function is not supported on basic timers. To enable or + * disable it, simply set its clock to valid frequency or zero. + */ + +#if STM32WL5_NBTIM > 0 + if (((struct stm32wl5_tim_priv_s *)dev)->base == STM32WL5_TIM6_BASE +#endif +#if STM32WL5_NBTIM > 1 + || ((struct stm32wl5_tim_priv_s *)dev)->base == STM32WL5_TIM7_BASE +#endif +#if STM32WL5_NBTIM > 0 + ) + { + return -EINVAL; + } +#endif + + /* Decode configuration */ + + switch (mode & STM32WL5_TIM_CH_MODE_MASK) + { + case STM32WL5_TIM_CH_DISABLED: + break; + + case STM32WL5_TIM_CH_OUTPWM: + ccmr_val = (GTIM_CCMR_MODE_PWM1 << GTIM_CCMR1_OC1M_SHIFT) + + GTIM_CCMR1_OC1PE; + ccer_val |= GTIM_CCER_CC1E << GTIM_CCER_CCXBASE(channel); + break; + + default: + return -EINVAL; + } + + /* Set polarity */ + + if (mode & STM32WL5_TIM_CH_POLARITY_NEG) + { + ccer_val |= GTIM_CCER_CC1P << GTIM_CCER_CCXBASE(channel); + } + + /* Define its position (shift) and get register offset */ + + if (channel & 1) + { + ccmr_val <<= 8; + ccmr_mask <<= 8; + } + + if (channel > 1) + { + ccmr_offset = STM32WL5_GTIM_CCMR2_OFFSET; + } + + ccmr_orig = stm32wl5_getreg16(dev, ccmr_offset); + ccmr_orig &= ~ccmr_mask; + ccmr_orig |= ccmr_val; + stm32wl5_putreg16(dev, ccmr_offset, ccmr_orig); + stm32wl5_putreg16(dev, STM32WL5_GTIM_CCER_OFFSET, ccer_val); + + /* set GPIO */ + + switch (((struct stm32wl5_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32WL5_TIM1 + case STM32WL5_TIM1_BASE: + switch (channel) + { +#if defined(GPIO_TIM1_CH1OUT) + case 0: + stm32wl5_tim_gpioconfig(GPIO_TIM1_CH1OUT, mode); + break; +#endif + +#if defined(GPIO_TIM1_CH2OUT) + case 1: + stm32wl5_tim_gpioconfig(GPIO_TIM1_CH2OUT, mode); + break; +#endif + +#if defined(GPIO_TIM1_CH3OUT) + case 2: + stm32wl5_tim_gpioconfig(GPIO_TIM1_CH3OUT, mode); + break; +#endif + +#if defined(GPIO_TIM1_CH4OUT) + case 3: + stm32wl5_tim_gpioconfig(GPIO_TIM1_CH4OUT, mode); + break; +#endif + + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32WL5_TIM2 + case STM32WL5_TIM2_BASE: + switch (channel) + { +#if defined(GPIO_TIM2_CH1OUT) + case 0: + stm32wl5_tim_gpioconfig(GPIO_TIM2_CH1OUT, mode); + break; +#endif + +#if defined(GPIO_TIM2_CH2OUT) + case 1: + stm32wl5_tim_gpioconfig(GPIO_TIM2_CH2OUT, mode); + break; +#endif + +#if defined(GPIO_TIM2_CH3OUT) + case 2: + stm32wl5_tim_gpioconfig(GPIO_TIM2_CH3OUT, mode); + break; +#endif + +#if defined(GPIO_TIM2_CH4OUT) + case 3: + stm32wl5_tim_gpioconfig(GPIO_TIM2_CH4OUT, mode); + break; +#endif + + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32WL5_TIM3 + case STM32WL5_TIM3_BASE: + switch (channel) + { +#if defined(GPIO_TIM3_CH1OUT) + case 0: + stm32wl5_tim_gpioconfig(GPIO_TIM3_CH1OUT, mode); + break; +#endif + +#if defined(GPIO_TIM3_CH2OUT) + case 1: + stm32wl5_tim_gpioconfig(GPIO_TIM3_CH2OUT, mode); + break; +#endif + +#if defined(GPIO_TIM3_CH3OUT) + case 2: + stm32wl5_tim_gpioconfig(GPIO_TIM3_CH3OUT, mode); + break; +#endif + +#if defined(GPIO_TIM3_CH4OUT) + case 3: + stm32wl5_tim_gpioconfig(GPIO_TIM3_CH4OUT, mode); + break; +#endif + + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32WL5_TIM4 + case STM32WL5_TIM4_BASE: + switch (channel) + { +#if defined(GPIO_TIM4_CH1OUT) + case 0: + stm32wl5_tim_gpioconfig(GPIO_TIM4_CH1OUT, mode); + break; +#endif + +#if defined(GPIO_TIM4_CH2OUT) + case 1: + stm32wl5_tim_gpioconfig(GPIO_TIM4_CH2OUT, mode); + break; +#endif +#if defined(GPIO_TIM4_CH3OUT) + case 2: + stm32wl5_tim_gpioconfig(GPIO_TIM4_CH3OUT, mode); + break; +#endif + +#if defined(GPIO_TIM4_CH4OUT) + case 3: + stm32wl5_tim_gpioconfig(GPIO_TIM4_CH4OUT, mode); + break; +#endif + + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32WL5_TIM5 + case STM32WL5_TIM5_BASE: + switch (channel) + { +#if defined(GPIO_TIM5_CH1OUT) + case 0: + stm32wl5_tim_gpioconfig(GPIO_TIM5_CH1OUT, mode); + break; +#endif + +#if defined(GPIO_TIM5_CH2OUT) + case 1: + stm32wl5_tim_gpioconfig(GPIO_TIM5_CH2OUT, mode); + break; +#endif + +#if defined(GPIO_TIM5_CH3OUT) + case 2: + stm32wl5_tim_gpioconfig(GPIO_TIM5_CH3OUT, mode); + break; +#endif + +#if defined(GPIO_TIM5_CH4OUT) + case 3: + stm32wl5_tim_gpioconfig(GPIO_TIM5_CH4OUT, mode); + break; +#endif + + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32WL5_TIM8 + case STM32WL5_TIM8_BASE: + switch (channel) + { +#if defined(GPIO_TIM8_CH1OUT) + case 0: + stm32wl5_tim_gpioconfig(GPIO_TIM8_CH1OUT, mode); + break; +#endif + +#if defined(GPIO_TIM8_CH2OUT) + case 1: + stm32wl5_tim_gpioconfig(GPIO_TIM8_CH2OUT, mode); + break; +#endif + +#if defined(GPIO_TIM8_CH3OUT) + case 2: + stm32wl5_tim_gpioconfig(GPIO_TIM8_CH3OUT, mode); + break; +#endif + +#if defined(GPIO_TIM8_CH4OUT) + case 3: + stm32wl5_tim_gpioconfig(GPIO_TIM8_CH4OUT, mode); + break; +#endif + + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32WL5_TIM15 + case STM32WL5_TIM15_BASE: + switch (channel) + { +#if defined(GPIO_TIM15_CH1OUT) + case 0: + stm32wl5_tim_gpioconfig(GPIO_TIM15_CH1OUT, mode); + break; +#endif + +#if defined(GPIO_TIM15_CH2OUT) + case 1: + stm32wl5_tim_gpioconfig(GPIO_TIM15_CH2OUT, mode); + break; +#endif + +#if defined(GPIO_TIM15_CH3OUT) + case 2: + stm32wl5_tim_gpioconfig(GPIO_TIM15_CH3OUT, mode); + break; +#endif + +#if defined(GPIO_TIM15_CH4OUT) + case 3: + stm32wl5_tim_gpioconfig(GPIO_TIM15_CH4OUT, mode); + break; +#endif + + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32WL5_TIM16 + case STM32WL5_TIM16_BASE: + switch (channel) + { +#if defined(GPIO_TIM16_CH1OUT) + case 0: + stm32wl5_tim_gpioconfig(GPIO_TIM16_CH1OUT, mode); + break; +#endif + +#if defined(GPIO_TIM16_CH2OUT) + case 1: + stm32wl5_tim_gpioconfig(GPIO_TIM16_CH2OUT, mode); + break; +#endif + +#if defined(GPIO_TIM16_CH3OUT) + case 2: + stm32wl5_tim_gpioconfig(GPIO_TIM16_CH3OUT, mode); + break; +#endif + +#if defined(GPIO_TIM16_CH4OUT) + case 3: + stm32wl5_tim_gpioconfig(GPIO_TIM16_CH4OUT, mode); + break; +#endif + + default: + return -EINVAL; + } + break; +#endif +#ifdef CONFIG_STM32WL5_TIM17 + case STM32WL5_TIM17_BASE: + switch (channel) + { +#if defined(GPIO_TIM17_CH1OUT) + case 0: + stm32wl5_tim_gpioconfig(GPIO_TIM17_CH1OUT, mode); + break; +#endif + +#if defined(GPIO_TIM17_CH2OUT) + case 1: + stm32wl5_tim_gpioconfig(GPIO_TIM17_CH2OUT, mode); + break; +#endif + +#if defined(GPIO_TIM17_CH3OUT) + case 2: + stm32wl5_tim_gpioconfig(GPIO_TIM17_CH3OUT, mode); + break; +#endif + +#if defined(GPIO_TIM17_CH4OUT) + case 3: + stm32wl5_tim_gpioconfig(GPIO_TIM17_CH4OUT, mode); + break; +#endif + + default: + return -EINVAL; + } + break; +#endif + + default: + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Name: stm32wl5_tim_setcompare + ****************************************************************************/ + +static int stm32wl5_tim_setcompare(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t channel, uint32_t compare) +{ + DEBUGASSERT(dev != NULL); + + switch (channel) + { + case 1: + stm32wl5_putreg32(dev, STM32WL5_GTIM_CCR1_OFFSET, compare); + break; + + case 2: + stm32wl5_putreg32(dev, STM32WL5_GTIM_CCR2_OFFSET, compare); + break; + + case 3: + stm32wl5_putreg32(dev, STM32WL5_GTIM_CCR3_OFFSET, compare); + break; + + case 4: + stm32wl5_putreg32(dev, STM32WL5_GTIM_CCR4_OFFSET, compare); + break; + + default: + return -EINVAL; + } + + return OK; +} + +/**************************************************************************** + * Name: stm32wl5_tim_getcapture + ****************************************************************************/ + +static int stm32wl5_tim_getcapture(FAR struct stm32wl5_tim_dev_s *dev, + uint8_t channel) +{ + DEBUGASSERT(dev != NULL); + + switch (channel) + { + case 1: + return stm32wl5_getreg32(dev, STM32WL5_GTIM_CCR1_OFFSET); + + case 2: + return stm32wl5_getreg32(dev, STM32WL5_GTIM_CCR2_OFFSET); + + case 3: + return stm32wl5_getreg32(dev, STM32WL5_GTIM_CCR3_OFFSET); + + case 4: + return stm32wl5_getreg32(dev, STM32WL5_GTIM_CCR4_OFFSET); + } + + return -EINVAL; +} + +/**************************************************************************** + * Name: stm32wl5_tim_setisr + ****************************************************************************/ + +static int stm32wl5_tim_setisr(FAR struct stm32wl5_tim_dev_s *dev, + xcpt_t handler, void *arg, int source) +{ + int vectorno; + + DEBUGASSERT(dev != NULL); + DEBUGASSERT(source == 0); + + switch (((struct stm32wl5_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32WL5_TIM1 + case STM32WL5_TIM1_BASE: + vectorno = STM32WL5_IRQ_TIM1UP; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM2 + case STM32WL5_TIM2_BASE: + vectorno = STM32WL5_IRQ_TIM2; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM3 + case STM32WL5_TIM3_BASE: + vectorno = STM32WL5_IRQ_TIM3; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM4 + case STM32WL5_TIM4_BASE: + vectorno = STM32WL5_IRQ_TIM4; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM5 + case STM32WL5_TIM5_BASE: + vectorno = STM32WL5_IRQ_TIM5; + break; +#endif +#ifdef CONFIG_STM32WL5_TIM6 + case STM32WL5_TIM6_BASE: + vectorno = STM32WL5_IRQ_TIM6; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM7 + case STM32WL5_TIM7_BASE: + vectorno = STM32WL5_IRQ_TIM7; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM8 + case STM32WL5_TIM8_BASE: + vectorno = STM32WL5_IRQ_TIM8UP; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM15 + case STM32WL5_TIM15_BASE: + vectorno = STM32WL5_IRQ_TIM15; + break; +#endif +#ifdef CONFIG_STM32WL5_TIM16 + case STM32WL5_TIM16_BASE: + vectorno = STM32WL5_IRQ_TIM16; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM17 + case STM32WL5_TIM17_BASE: + vectorno = STM32WL5_IRQ_TIM17; + break; +#endif + + default: + return -EINVAL; + } + + /* Disable interrupt when callback is removed */ + + if (!handler) + { + up_disable_irq(vectorno); + irq_detach(vectorno); + return OK; + } + + /* Otherwise set callback and enable interrupt */ + + irq_attach(vectorno, handler, arg); + up_enable_irq(vectorno); + + return OK; +} + +/**************************************************************************** + * Name: stm32wl5_tim_enableint + ****************************************************************************/ + +static void stm32wl5_tim_enableint(FAR struct stm32wl5_tim_dev_s *dev, + int source) +{ + DEBUGASSERT(dev != NULL); + stm32wl5_modifyreg16(dev, STM32WL5_GTIM_DIER_OFFSET, 0, GTIM_DIER_UIE); +} + +/**************************************************************************** + * Name: stm32wl5_tim_disableint + ****************************************************************************/ + +static void stm32wl5_tim_disableint(FAR struct stm32wl5_tim_dev_s *dev, + int source) +{ + DEBUGASSERT(dev != NULL); + stm32wl5_modifyreg16(dev, STM32WL5_GTIM_DIER_OFFSET, GTIM_DIER_UIE, 0); +} + +/**************************************************************************** + * Name: stm32wl5_tim_ackint + ****************************************************************************/ + +static void stm32wl5_tim_ackint(FAR struct stm32wl5_tim_dev_s *dev, + int source) +{ + stm32wl5_putreg16(dev, STM32WL5_GTIM_SR_OFFSET, ~GTIM_SR_UIF); +} + +/**************************************************************************** + * Name: stm32wl5_tim_checkint + ****************************************************************************/ + +static int stm32wl5_tim_checkint(FAR struct stm32wl5_tim_dev_s *dev, + int source) +{ + uint16_t regval = stm32wl5_getreg16(dev, STM32WL5_GTIM_SR_OFFSET); + return (regval & GTIM_SR_UIF) ? 1 : 0; +} + +/**************************************************************************** + * Pubic Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_tim_init + ****************************************************************************/ + +FAR struct stm32wl5_tim_dev_s *stm32wl5_tim_init(int timer) +{ + struct stm32wl5_tim_dev_s *dev = NULL; + + /* Get structure and enable power */ + + switch (timer) + { +#ifdef CONFIG_STM32WL5_TIM1 + case 1: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim1_priv; + modifyreg32(STM32WL5_RCC_APB2ENR, 0, RCC_APB2ENR_TIM1EN); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM2 + case 2: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim2_priv; + modifyreg32(STM32WL5_RCC_APB1ENR1, 0, RCC_APB1ENR1_TIM2EN); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM3 + case 3: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim3_priv; + modifyreg32(STM32WL5_RCC_APB1ENR1, 0, RCC_APB1ENR1_TIM3EN); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM4 + case 4: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim4_priv; + modifyreg32(STM32WL5_RCC_APB1ENR1, 0, RCC_APB1ENR1_TIM4EN); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM5 + case 5: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim5_priv; + modifyreg32(STM32WL5_RCC_APB1ENR1, 0, RCC_APB1ENR1_TIM5EN); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM6 + case 6: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim6_priv; + modifyreg32(STM32WL5_RCC_APB1ENR1, 0, RCC_APB1ENR1_TIM6EN); + break; +#endif +#ifdef CONFIG_STM32WL5_TIM7 + case 7: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim7_priv; + modifyreg32(STM32WL5_RCC_APB1ENR1, 0, RCC_APB1ENR1_TIM7EN); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM8 + case 8: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim8_priv; + modifyreg32(STM32WL5_RCC_APB2ENR, 0, RCC_APB2ENR_TIM8EN); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM15 + case 15: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim15_priv; + modifyreg32(STM32WL5_RCC_APB2ENR, 0, RCC_APB2ENR_TIM15EN); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM16 + case 16: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim16_priv; + modifyreg32(STM32WL5_RCC_APB2ENR, 0, RCC_APB2ENR_TIM16EN); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM17 + case 17: + dev = (struct stm32wl5_tim_dev_s *)&stm32wl5_tim17_priv; + modifyreg32(STM32WL5_RCC_APB2ENR, 0, RCC_APB2ENR_TIM17EN); + break; +#endif + + default: + return NULL; + } + + /* Is device already allocated */ + + if (((struct stm32wl5_tim_priv_s *)dev)->mode != STM32WL5_TIM_MODE_UNUSED) + { + return NULL; + } + + stm32wl5_tim_reset(dev); + + return dev; +} + +/**************************************************************************** + * Name: stm32wl5_tim_deinit + * + * TODO: Detach interrupts, and close down all TIM Channels + * + ****************************************************************************/ + +int stm32wl5_tim_deinit(FAR struct stm32wl5_tim_dev_s *dev) +{ + DEBUGASSERT(dev != NULL); + + /* Disable power */ + + switch (((struct stm32wl5_tim_priv_s *)dev)->base) + { +#ifdef CONFIG_STM32WL5_TIM1 + case STM32WL5_TIM1_BASE: + modifyreg32(STM32WL5_RCC_APB2ENR, RCC_APB2ENR_TIM1EN, 0); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM2 + case STM32WL5_TIM2_BASE: + modifyreg32(STM32WL5_RCC_APB1ENR1, RCC_APB1ENR1_TIM2EN, 0); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM3 + case STM32WL5_TIM3_BASE: + modifyreg32(STM32WL5_RCC_APB1ENR1, RCC_APB1ENR1_TIM3EN, 0); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM4 + case STM32WL5_TIM4_BASE: + modifyreg32(STM32WL5_RCC_APB1ENR1, RCC_APB1ENR1_TIM4EN, 0); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM5 + case STM32WL5_TIM5_BASE: + modifyreg32(STM32WL5_RCC_APB1ENR1, RCC_APB1ENR1_TIM5EN, 0); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM6 + case STM32WL5_TIM6_BASE: + modifyreg32(STM32WL5_RCC_APB1ENR1, RCC_APB1ENR1_TIM6EN, 0); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM7 + case STM32WL5_TIM7_BASE: + modifyreg32(STM32WL5_RCC_APB1ENR1, RCC_APB1ENR1_TIM7EN, 0); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM8 + case STM32WL5_TIM8_BASE: + modifyreg32(STM32WL5_RCC_APB2ENR, RCC_APB2ENR_TIM8EN, 0); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM15 + case STM32WL5_TIM15_BASE: + modifyreg32(STM32WL5_RCC_APB2ENR, RCC_APB2ENR_TIM15EN, 0); + break; +#endif +#ifdef CONFIG_STM32WL5_TIM16 + case STM32WL5_TIM16_BASE: + modifyreg32(STM32WL5_RCC_APB2ENR, RCC_APB2ENR_TIM16EN, 0); + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM17 + case STM32WL5_TIM17_BASE: + modifyreg32(STM32WL5_RCC_APB2ENR, RCC_APB2ENR_TIM17EN, 0); + break; +#endif + + default: + return -EINVAL; + } + + /* Mark it as free */ + + ((struct stm32wl5_tim_priv_s *)dev)->mode = STM32WL5_TIM_MODE_UNUSED; + + return OK; +} + +#endif /* defined(CONFIG_STM32WL5_TIM1 || ... || TIM17) */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_tim.h b/arch/arm/src/stm32wl5/stm32wl5_tim.h new file mode 100644 index 0000000000..0426978a5d --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_tim.h @@ -0,0 +1,208 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_tim.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_TIM_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_TIM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "chip.h" +#include "hardware/stm32wl5_tim.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Helpers ******************************************************************/ + +#define STM32WL5_TIM_SETMODE(d,mode) ((d)->ops->setmode(d,mode)) +#define STM32WL5_TIM_SETCLOCK(d,freq) ((d)->ops->setclock(d,freq)) +#define STM32WL5_TIM_GETCLOCK(d) ((d)->ops->getclock(d)) +#define STM32WL5_TIM_SETPERIOD(d,period) ((d)->ops->setperiod(d,period)) +#define STM32WL5_TIM_GETPERIOD(d) ((d)->ops->getperiod(d)) +#define STM32WL5_TIM_GETCOUNTER(d) ((d)->ops->getcounter(d)) +#define STM32WL5_TIM_SETCHANNEL(d,ch,mode) ((d)->ops->setchannel(d,ch,mode)) +#define STM32WL5_TIM_SETCOMPARE(d,ch,comp) ((d)->ops->setcompare(d,ch,comp)) +#define STM32WL5_TIM_GETCAPTURE(d,ch) ((d)->ops->getcapture(d,ch)) +#define STM32WL5_TIM_SETISR(d,hnd,arg,s) ((d)->ops->setisr(d,hnd,arg,s)) +#define STM32WL5_TIM_ENABLEINT(d,s) ((d)->ops->enableint(d,s)) +#define STM32WL5_TIM_DISABLEINT(d,s) ((d)->ops->disableint(d,s)) +#define STM32WL5_TIM_ACKINT(d,s) ((d)->ops->ackint(d,s)) +#define STM32WL5_TIM_CHECKINT(d,s) ((d)->ops->checkint(d,s)) + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/* TIM Device Structure */ + +struct stm32wl5_tim_dev_s +{ + struct stm32wl5_tim_ops_s *ops; +}; + +/* TIM Modes of Operation */ + +enum stm32wl5_tim_mode_e +{ + STM32WL5_TIM_MODE_UNUSED = -1, + + /* One of the following */ + + STM32WL5_TIM_MODE_MASK = 0x0310, + STM32WL5_TIM_MODE_DISABLED = 0x0000, + STM32WL5_TIM_MODE_UP = 0x0100, + STM32WL5_TIM_MODE_DOWN = 0x0110, + STM32WL5_TIM_MODE_UPDOWN = 0x0200, + STM32WL5_TIM_MODE_PULSE = 0x0300, + + /* One of the following */ + + STM32WL5_TIM_MODE_CK_INT = 0x0000, +#if 0 + STM32WL5_TIM_MODE_CK_INT_TRIG = 0x0400, + STM32WL5_TIM_MODE_CK_EXT = 0x0800, + STM32WL5_TIM_MODE_CK_EXT_TRIG = 0x0c00, +#endif + + /* Clock sources, OR'ed with CK_EXT */ + +#if 0 + STM32WL5_TIM_MODE_CK_CHINVALID = 0x0000, + STM32WL5_TIM_MODE_CK_CH1 = 0x0001, + STM32WL5_TIM_MODE_CK_CH2 = 0x0002, + STM32WL5_TIM_MODE_CK_CH3 = 0x0003, + STM32WL5_TIM_MODE_CK_CH4 = 0x0004 +#endif + + /* Todo: external trigger block */ +}; + +/* TIM Channel Modes */ + +enum stm32wl5_tim_channel_e +{ + STM32WL5_TIM_CH_DISABLED = 0x00, + + /* Common configuration */ + + STM32WL5_TIM_CH_POLARITY_POS = 0x00, + STM32WL5_TIM_CH_POLARITY_NEG = 0x01, + + /* MODES: */ + + STM32WL5_TIM_CH_MODE_MASK = 0x06, + + /* Output Compare Modes */ + + STM32WL5_TIM_CH_OUTPWM = 0x04, /* Enable standard PWM mode, active high when counter < compare */ +#if 0 + STM32WL5_TIM_CH_OUTCOMPARE = 0x06, +#endif +}; + +/* TIM Operations */ + +struct stm32wl5_tim_ops_s +{ + /* Basic Timers */ + + int (*setmode)(FAR struct stm32wl5_tim_dev_s *dev, + enum stm32wl5_tim_mode_e mode); + int (*setclock)(FAR struct stm32wl5_tim_dev_s *dev, uint32_t freq); + uint32_t (*getclock)(FAR struct stm32wl5_tim_dev_s *dev); + void (*setperiod)(FAR struct stm32wl5_tim_dev_s *dev, uint32_t period); + uint32_t (*getperiod)(FAR struct stm32wl5_tim_dev_s *dev); + uint32_t (*getcounter)(FAR struct stm32wl5_tim_dev_s *dev); + + /* General and Advanced Timers Adds */ + + int (*setchannel)(FAR struct stm32wl5_tim_dev_s *dev, uint8_t channel, + enum stm32wl5_tim_channel_e mode); + int (*setcompare)(FAR struct stm32wl5_tim_dev_s *dev, uint8_t channel, + uint32_t compare); + int (*getcapture)(FAR struct stm32wl5_tim_dev_s *dev, uint8_t channel); + + /* Timer interrupts */ + + int (*setisr)(FAR struct stm32wl5_tim_dev_s *dev, + xcpt_t handler, void *arg, int source); + void (*enableint)(FAR struct stm32wl5_tim_dev_s *dev, int source); + void (*disableint)(FAR struct stm32wl5_tim_dev_s *dev, int source); + void (*ackint)(FAR struct stm32wl5_tim_dev_s *dev, int source); + int (*checkint)(FAR struct stm32wl5_tim_dev_s *dev, int source); +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Power-up timer and get its structure */ + +FAR struct stm32wl5_tim_dev_s *stm32wl5_tim_init(int timer); + +/* Power-down timer, mark it as unused */ + +int stm32wl5_tim_deinit(FAR struct stm32wl5_tim_dev_s *dev); + +/**************************************************************************** + * Name: stm32wl5_timer_initialize + * + * Description: + * Bind the configuration timer to a timer lower half instance and + * register the timer drivers at 'devpath' + * + * Input Parameters: + * devpath - The full path to the timer device. This should be of the form + * /dev/timer0 + * timer - the timer number. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +#ifdef CONFIG_TIMER +int stm32wl5_timer_initialize(FAR const char *devpath, int timer); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_TIM_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_tim_lowerhalf.c b/arch/arm/src/stm32wl5/stm32wl5_tim_lowerhalf.c new file mode 100644 index 0000000000..4a805bdc81 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_tim_lowerhalf.c @@ -0,0 +1,605 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_tim_lowerhalf.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include "stm32wl5_tim.h" + +#if defined(CONFIG_TIMER) && \ + (defined(CONFIG_STM32WL5_TIM1) || defined(CONFIG_STM32WL5_TIM2) || \ + defined(CONFIG_STM32WL5_TIM3) || defined(CONFIG_STM32WL5_TIM4) || \ + defined(CONFIG_STM32WL5_TIM5) || defined(CONFIG_STM32WL5_TIM6) || \ + defined(CONFIG_STM32WL5_TIM7) || defined(CONFIG_STM32WL5_TIM8) || \ + defined(CONFIG_STM32WL5_TIM15) || defined(CONFIG_STM32WL5_TIM16) || \ + defined(CONFIG_STM32WL5_TIM17)) + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define STM32WL5_TIM1_RES 16 +#define STM32WL5_TIM2_RES 32 +#define STM32WL5_TIM3_RES 16 +#define STM32WL5_TIM4_RES 16 +#define STM32WL5_TIM5_RES 32 +#define STM32WL5_TIM6_RES 16 +#define STM32WL5_TIM7_RES 16 +#define STM32WL5_TIM8_RES 16 +#define STM32WL5_TIM15_RES 16 +#define STM32WL5_TIM16_RES 16 +#define STM32WL5_TIM17_RES 16 + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This structure provides the private representation of the "lower-half" + * driver state structure. This structure must be cast-compatible with the + * timer_lowerhalf_s structure. + */ + +struct stm32wl5_lowerhalf_s +{ + FAR const struct timer_ops_s *ops; /* Lower half operations */ + FAR struct stm32wl5_tim_dev_s *tim; /* stm32 timer driver */ + tccb_t callback; /* Current upper half interrupt callback */ + FAR void *arg; /* Argument passed to upper half callback */ + bool started; /* True: Timer has been started */ + const uint8_t resolution; /* Number of bits in the timer (16 or 32 bits) */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/* Interrupt handling *******************************************************/ + +static int stm32wl5_timer_handler(int irq, void *context, void *arg); + +/* "Lower half" driver methods **********************************************/ + +static int stm32wl5_start(FAR struct timer_lowerhalf_s *lower); +static int stm32wl5_stop(FAR struct timer_lowerhalf_s *lower); +static int stm32wl5_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status); +static int stm32wl5_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout); +static void stm32wl5_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/* "Lower half" driver methods */ + +static const struct timer_ops_s g_timer_ops = +{ + .start = stm32wl5_start, + .stop = stm32wl5_stop, + .getstatus = stm32wl5_getstatus, + .settimeout = stm32wl5_settimeout, + .setcallback = stm32wl5_setcallback, + .ioctl = NULL, +}; + +#ifdef CONFIG_STM32WL5_TIM1 +static struct stm32wl5_lowerhalf_s g_tim1_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM1_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM2 +static struct stm32wl5_lowerhalf_s g_tim2_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM2_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM3 +static struct stm32wl5_lowerhalf_s g_tim3_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM3_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM4 +static struct stm32wl5_lowerhalf_s g_tim4_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM4_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM5 +static struct stm32wl5_lowerhalf_s g_tim5_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM5_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM6 +static struct stm32wl5_lowerhalf_s g_tim6_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM6_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM7 +static struct stm32wl5_lowerhalf_s g_tim7_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM7_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM8 +static struct stm32wl5_lowerhalf_s g_tim8_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM8_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM15 +static struct stm32wl5_lowerhalf_s g_tim15_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM15_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM16 +static struct stm32wl5_lowerhalf_s g_tim16_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM16_RES, +}; +#endif + +#ifdef CONFIG_STM32WL5_TIM17 +static struct stm32wl5_lowerhalf_s g_tim17_lowerhalf = +{ + .ops = &g_timer_ops, + .resolution = STM32WL5_TIM17_RES, +}; +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_timer_handler + * + * Description: + * timer interrupt handler + * + * Input Parameters: + * + * Returned Value: + * + ****************************************************************************/ + +static int stm32wl5_timer_handler(int irq, void *context, void *arg) +{ + FAR struct stm32wl5_lowerhalf_s *lower = + (FAR struct stm32wl5_lowerhalf_s *)arg; + uint32_t next_interval_us = 0; + + STM32WL5_TIM_ACKINT(lower->tim, 0); + + if (lower->callback(&next_interval_us, lower->arg)) + { + if (next_interval_us > 0) + { + STM32WL5_TIM_SETPERIOD(lower->tim, next_interval_us); + } + } + else + { + stm32wl5_stop((struct timer_lowerhalf_s *)lower); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32wl5_start + * + * Description: + * Start the timer, resetting the time to the current timeout, + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32wl5_start(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct stm32wl5_lowerhalf_s *priv = + (FAR struct stm32wl5_lowerhalf_s *)lower; + + if (!priv->started) + { + STM32WL5_TIM_SETMODE(priv->tim, STM32WL5_TIM_MODE_UP); + + if (priv->callback != NULL) + { + STM32WL5_TIM_SETISR(priv->tim, stm32wl5_timer_handler, priv, 0); + STM32WL5_TIM_ENABLEINT(priv->tim, 0); + } + + priv->started = true; + return OK; + } + + /* Return EBUSY to indicate that the timer was already running */ + + return -EBUSY; +} + +/**************************************************************************** + * Name: stm32wl5_stop + * + * Description: + * Stop the timer + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32wl5_stop(FAR struct timer_lowerhalf_s *lower) +{ + FAR struct stm32wl5_lowerhalf_s *priv = + (FAR struct stm32wl5_lowerhalf_s *)lower; + + if (priv->started) + { + STM32WL5_TIM_SETMODE(priv->tim, STM32WL5_TIM_MODE_DISABLED); + STM32WL5_TIM_DISABLEINT(priv->tim, 0); + STM32WL5_TIM_SETISR(priv->tim, NULL, NULL, 0); + priv->started = false; + return OK; + } + + /* Return ENODEV to indicate that the timer was not running */ + + return -ENODEV; +} + +/**************************************************************************** + * Name: stm32wl5_getstatus + * + * Description: + * get timer status + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the "lower- + * half" driver state structure. + * status - The location to return the status information. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32wl5_getstatus(FAR struct timer_lowerhalf_s *lower, + FAR struct timer_status_s *status) +{ + FAR struct stm32wl5_lowerhalf_s *priv = + (FAR struct stm32wl5_lowerhalf_s *)lower; + uint64_t maxtimeout; + uint32_t timeout; + uint32_t clock; + uint32_t period; + uint32_t clock_factor; + + DEBUGASSERT(priv); + + /* Return the status bit */ + + status->flags = 0; + if (priv->started) + { + status->flags |= TCFLAGS_ACTIVE; + } + + if (priv->callback) + { + status->flags |= TCFLAGS_HANDLER; + } + + /* Get timeout */ + + maxtimeout = (1 << priv->resolution) - 1; + clock = STM32WL5_TIM_GETCLOCK(priv->tim); + period = STM32WL5_TIM_GETPERIOD(priv->tim); + + if (clock == 1000000) + { + timeout = period; + } + else + { + timeout = (maxtimeout * 1000000) / clock; + } + + status->timeout = timeout; + + /* Get the time remaining until the timer expires (in microseconds) */ + + clock_factor = (clock == 1000000)? 1: (clock / 1000000); + status->timeleft = (timeout - STM32WL5_TIM_GETCOUNTER(priv->tim)) * + clock_factor; + return OK; +} + +/**************************************************************************** + * Name: stm32wl5_settimeout + * + * Description: + * Set a new timeout value (and reset the timer) + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * timeout - The new timeout value in microseconds. + * + * Returned Value: + * Zero on success; a negated errno value on failure. + * + ****************************************************************************/ + +static int stm32wl5_settimeout(FAR struct timer_lowerhalf_s *lower, + uint32_t timeout) +{ + FAR struct stm32wl5_lowerhalf_s *priv = + (FAR struct stm32wl5_lowerhalf_s *)lower; + uint64_t maxtimeout; + + if (priv->started) + { + return -EPERM; + } + + maxtimeout = (1 << priv->resolution) - 1; + if (timeout > maxtimeout) + { + uint64_t freq = (maxtimeout * 1000000) / timeout; + STM32WL5_TIM_SETCLOCK(priv->tim, freq); + STM32WL5_TIM_SETPERIOD(priv->tim, maxtimeout); + } + else + { + STM32WL5_TIM_SETCLOCK(priv->tim, 1000000); + STM32WL5_TIM_SETPERIOD(priv->tim, timeout); + } + + return OK; +} + +/**************************************************************************** + * Name: stm32wl5_sethandler + * + * Description: + * Call this user provided timeout handler. + * + * Input Parameters: + * lower - A pointer the publicly visible representation of the + * "lower-half" driver state structure. + * callback - The new timer expiration function pointer. If this + * function pointer is NULL, then the reset-on-expiration + * behavior is restored, + * arg - Argument that will be provided in the callback + * + * Returned Value: + * The previous timer expiration function pointer or NULL is there was + * no previous function pointer. + * + ****************************************************************************/ + +static void stm32wl5_setcallback(FAR struct timer_lowerhalf_s *lower, + tccb_t callback, FAR void *arg) +{ + FAR struct stm32wl5_lowerhalf_s *priv = + (FAR struct stm32wl5_lowerhalf_s *)lower; + irqstate_t flags = enter_critical_section(); + + /* Save the new callback */ + + priv->callback = callback; + priv->arg = arg; + + if (callback != NULL && priv->started) + { + STM32WL5_TIM_SETISR(priv->tim, stm32wl5_timer_handler, priv, 0); + STM32WL5_TIM_ENABLEINT(priv->tim, 0); + } + else + { + STM32WL5_TIM_DISABLEINT(priv->tim, 0); + STM32WL5_TIM_SETISR(priv->tim, NULL, NULL, 0); + } + + leave_critical_section(flags); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_timer_initialize + * + * Description: + * Bind the configuration timer to a timer lower half instance and + * register the timer drivers at 'devpath' + * + * Input Parameters: + * devpath - The full path to the timer device. This should be of the + * form /dev/timer0 + * timer - the timer's number. + * + * Returned Value: + * Zero (OK) is returned on success; A negated errno value is returned + * to indicate the nature of any failure. + * + ****************************************************************************/ + +int stm32wl5_timer_initialize(FAR const char *devpath, int timer) +{ + FAR struct stm32wl5_lowerhalf_s *lower; + + switch (timer) + { +#ifdef CONFIG_STM32WL5_TIM1 + case 1: + lower = &g_tim1_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM2 + case 2: + lower = &g_tim2_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM3 + case 3: + lower = &g_tim3_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM4 + case 4: + lower = &g_tim4_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM5 + case 5: + lower = &g_tim5_lowerhalf; + break; +#endif +#ifdef CONFIG_STM32WL5_TIM6 + case 6: + lower = &g_tim6_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM7 + case 7: + lower = &g_tim7_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM8 + case 8: + lower = &g_tim8_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM15 + case 15: + lower = &g_tim15_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM16 + case 16: + lower = &g_tim16_lowerhalf; + break; +#endif + +#ifdef CONFIG_STM32WL5_TIM17 + case 17: + lower = &g_tim17_lowerhalf; + break; +#endif + + default: + return -ENODEV; + } + + /* Initialize the elements of lower half state structure */ + + lower->started = false; + lower->callback = NULL; + lower->tim = stm32wl5_tim_init(timer); + + if (lower->tim == NULL) + { + return -EINVAL; + } + + /* Register the timer driver as /dev/timerX. The returned value from + * timer_register is a handle that could be used with timer_unregister(). + * REVISIT: The returned handle is discard here. + */ + + FAR void *drvr = timer_register(devpath, + (FAR struct timer_lowerhalf_s *)lower); + if (drvr == NULL) + { + /* The actual cause of the failure may have been a failure to allocate + * perhaps a failure to register the timer driver (such as if the + * 'depath' were not unique). We know here but we return EEXIST to + * indicate the failure (implying the non-unique devpath). + */ + + return -EEXIST; + } + + return OK; +} + +#endif /* CONFIG_TIMER */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_timerisr.c b/arch/arm/src/stm32wl5/stm32wl5_timerisr.c new file mode 100644 index 0000000000..37a9e19636 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_timerisr.c @@ -0,0 +1,149 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_timerisr.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include "nvic.h" +#include "clock/clock.h" +#include "arm_internal.h" +#include "arm_internal.h" + +#include "chip.h" +#include "stm32wl5.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* The desired timer interrupt frequency is provided by the definition + * CLK_TCK (see include/time.h). CLK_TCK defines the desired number of + * system clock ticks per second. That value is a user configurable setting + * that defaults to 100 (100 ticks per second = 10 MS interval). + * + * The RCC feeds the Cortex System Timer (SysTick) with the AHB clock (HCLK) + * divided by 8. The SysTick can work either with this clock or with the + * Cortex clock (HCLK), configurable in the SysTick Control and Status + * register. + */ + +/* Power up default is HCLK, not HCLK/8. + * And I don't know now to re-configure it yet + */ + +#undef CONFIG_STM32WL5_SYSTICK_HCLKd8 + +#ifdef CONFIG_STM32WL5_SYSTICK_HCLKd8 +# define SYSTICK_RELOAD ((STM32WL5_HCLK_FREQUENCY / 8 / CLK_TCK) - 1) +#else +# define SYSTICK_RELOAD ((STM32WL5_HCLK_FREQUENCY / CLK_TCK) - 1) +#endif + +/* The size of the reload field is 24 bits. Verify that the reload value + * will fit in the reload register. + */ + +#if SYSTICK_RELOAD > 0x00ffffff +# error SYSTICK_RELOAD exceeds the range of the RELOAD register +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: stm32wl5_timerisr + * + * Description: + * The timer ISR will perform a variety of services for various portions + * of the systems. + * + ****************************************************************************/ + +static int stm32wl5_timerisr(int irq, uint32_t *regs, void *arg) +{ + /* Process timer interrupt */ + + nxsched_process_timer(); + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Function: up_timer_initialize + * + * Description: + * This function is called during start-up to initialize + * the timer interrupt. + * + ****************************************************************************/ + +void up_timer_initialize(void) +{ + uint32_t regval; + + /* Set the SysTick interrupt to the default priority */ + + regval = getreg32(NVIC_SYSH12_15_PRIORITY); + regval &= ~NVIC_SYSH_PRIORITY_PR15_MASK; + regval |= (NVIC_SYSH_PRIORITY_DEFAULT << NVIC_SYSH_PRIORITY_PR15_SHIFT); + putreg32(regval, NVIC_SYSH12_15_PRIORITY); + + /* Make sure that the SYSTICK clock source is set correctly */ + +#if 0 /* Does not work. Comes up with HCLK source and I can't change it */ + regval = getreg32(NVIC_SYSTICK_CTRL); +#ifdef CONFIG_STM32WL5_SYSTICK_HCLKd8 + regval &= ~NVIC_SYSTICK_CTRL_CLKSOURCE; +#else + regval |= NVIC_SYSTICK_CTRL_CLKSOURCE; +#endif + putreg32(regval, NVIC_SYSTICK_CTRL); +#endif + + /* Configure SysTick to interrupt at the requested rate */ + + putreg32(SYSTICK_RELOAD, NVIC_SYSTICK_RELOAD); + + /* Attach the timer interrupt vector */ + + (void)irq_attach(STM32WL5_IRQ_SYSTICK, (xcpt_t)stm32wl5_timerisr, NULL); + + /* Enable SysTick interrupts */ + + putreg32((NVIC_SYSTICK_CTRL_CLKSOURCE | NVIC_SYSTICK_CTRL_TICKINT | + NVIC_SYSTICK_CTRL_ENABLE), NVIC_SYSTICK_CTRL); + + /* And enable the timer interrupt */ + + up_enable_irq(STM32WL5_IRQ_SYSTICK); +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_uart.h b/arch/arm/src/stm32wl5/stm32wl5_uart.h new file mode 100644 index 0000000000..26bdfa834a --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_uart.h @@ -0,0 +1,225 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_uart.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_STC_STM32WL5_STM32WL5_UART_H +#define __ARCH_ARM_STC_STM32WL5_STM32WL5_UART_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +#include "chip.h" + +#include "hardware/stm32wl5_uart.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Make sure that we have not enabled more U[S]ARTs than are supported by the + * device. + */ + +#if !defined(CONFIG_STM32WL5_HAVE_USART2) +# undef CONFIG_STM32WL5_USART2 +#endif +#if !defined(CONFIG_STM32WL5_HAVE_USART1) +# undef CONFIG_STM32WL5_USART1 +#endif +#if !defined(CONFIG_STM32WL5_HAVE_LPUART1) +# undef CONFIG_STM32WL5_LPUART1 +#endif + +/* Sanity checks */ + +#if !defined(CONFIG_STM32WL5_LPUART1) +# undef CONFIG_STM32WL5_LPUART1_SERIALDRIVER +# undef CONFIG_STM32WL5_LPUART1_1WIREDRIVER +#endif +#if !defined(CONFIG_STM32WL5_USART1) +# undef CONFIG_STM32WL5_USART1_SERIALDRIVER +# undef CONFIG_STM32WL5_USART1_1WIREDRIVER +#endif +#if !defined(CONFIG_STM32WL5_USART2) +# undef CONFIG_STM32WL5_USART2_SERIALDRIVER +# undef CONFIG_STM32WL5_USART2_1WIREDRIVER +#endif + +/* Is there a USART enabled? */ + +#if defined(CONFIG_STM32WL5_LPUART1) || \ + defined(CONFIG_STM32WL5_USART1) || \ + defined(CONFIG_STM32WL5_USART2) +# define HAVE_UART 1 +#endif + +/* Is there a serial console? */ + +#if defined(CONFIG_LPUART1_SERIAL_CONSOLE) && defined(CONFIG_STM32WL5_LPUART1_SERIALDRIVER) +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# define CONSOLE_UART 1 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART1_SERIAL_CONSOLE) && defined(CONFIG_STM32WL5_USART1_SERIALDRIVER) +# undef CONFIG_LPUART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# define CONSOLE_UART 2 +# define HAVE_CONSOLE 1 +#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_STM32WL5_USART2_SERIALDRIVER) +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# define CONSOLE_UART 3 +# define HAVE_CONSOLE 1 +#else +# undef CONFIG_USART1_SERIAL_CONSOLE +# undef CONFIG_USART2_SERIAL_CONSOLE +# undef CONFIG_USART3_SERIAL_CONSOLE +# undef CONFIG_UART4_SERIAL_CONSOLE +# undef CONFIG_UART5_SERIAL_CONSOLE +# define CONSOLE_UART 0 +# undef HAVE_CONSOLE +#endif + +/* DMA support is only provided if CONFIG_ARCH_DMA is in the NuttX + * configuration + */ + +#if !defined(HAVE_UART) || !defined(CONFIG_ARCH_DMA) +# undef CONFIG_USART1_RXDMA +# undef CONFIG_USART2_RXDMA +#endif + +/* Disable the DMA configuration on all unused USARTs */ + +#ifndef CONFIG_STM32WL5_LPUART1_SERIALDRIVER +# undef CONFIG_LPUART1_RXDMA +#endif + +#ifndef CONFIG_STM32WL5_USART1_SERIALDRIVER +# undef CONFIG_USART1_RXDMA +#endif + +#ifndef CONFIG_STM32WL5_USART2_SERIALDRIVER +# undef CONFIG_USART2_RXDMA +#endif + +/* Is DMA available on any (enabled) USART? */ + +#undef SERIAL_HAVE_DMA +#if defined(CONFIG_LPUART1_RXDMA) || \ + defined(CONFIG_USART1_RXDMA) || \ + defined(CONFIG_USART2_RXDMA) +# define SERIAL_HAVE_DMA 1 +#endif + +/* Is DMA used on the console UART? */ + +#undef SERIAL_HAVE_CONSOLE_DMA +#if defined(CONFIG_LPUART1_SERIAL_CONSOLE) && defined(CONFIG_LPUART1_RXDMA) +# define SERIAL_HAVE_CONSOLE_DMA 1 +#elif defined(CONFIG_USART1_SERIAL_CONSOLE) && defined(CONFIG_USART1_RXDMA) +# define SERIAL_HAVE_CONSOLE_DMA 1 +#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_USART2_RXDMA) +# define SERIAL_HAVE_CONSOLE_DMA 1 +#endif + +/* Is DMA used on all (enabled) USARTs */ + +#define SERIAL_HAVE_ONLY_DMA 1 +#if defined(CONFIG_STM32WL5_LPUART1_SERIALDRIVER) && !defined(CONFIG_LPUART1_RXDMA) +# undef SERIAL_HAVE_ONLY_DMA +#elif defined(CONFIG_STM32WL5_USART1_SERIALDRIVER) && !defined(CONFIG_USART1_RXDMA) +# undef SERIAL_HAVE_ONLY_DMA +#elif defined(CONFIG_STM32WL5_USART2_SERIALDRIVER) && !defined(CONFIG_USART2_RXDMA) +# undef SERIAL_HAVE_ONLY_DMA +#endif + +/* Is RS-485 used? */ + +#if defined(CONFIG_LPUART1_RS485) || \ + defined(CONFIG_USART1_RS485) || \ + defined(CONFIG_USART2_RS485) +# define HAVE_RS485 1 +#endif + +#ifdef HAVE_RS485 +# define USART_CR1_USED_INTS (USART_CR1_RXNEIE | USART_CR1_TXEIE | USART_CR1_PEIE | USART_CR1_TCIE) +#else +# define USART_CR1_USED_INTS (USART_CR1_RXNEIE | USART_CR1_TXEIE | USART_CR1_PEIE) +#endif + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_serial_dma_poll + * + * Description: + * Must be called periodically if any STM32 UART is configured for DMA. + * The DMA callback is triggered for each fifo size/2 bytes, but this can + * result in some bytes being transferred but not collected if the incoming + * data is not a whole multiple of half the FIFO size. + * + * May be safely called from either interrupt or thread context. + * + ****************************************************************************/ + +#ifdef SERIAL_HAVE_DMA +void stm32wl5_serial_dma_poll(void); +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_STC_STM32WL5_STM32WL5_UART_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_uid.c b/arch/arm/src/stm32wl5/stm32wl5_uid.c new file mode 100644 index 0000000000..a44d89e429 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_uid.c @@ -0,0 +1,62 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_uid.c + * + * Copyright (C) 2015 Marawan Ragab. All rights reserved. + * Author: Marawan Ragab + * dev@ziggurat9.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "hardware/stm32wl5_memorymap.h" +#include "stm32wl5_uid.h" + +#ifdef STM32WL5_SYSMEM_UID + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void stm32wl5_get_uniqueid(uint8_t uniqueid[12]) +{ + int i; + + for (i = 0; i < 12; i++) + { + uniqueid[i] = *((uint8_t *)(STM32WL5_SYSMEM_UID)+i); + } +} + +#endif /* STM32WL5_SYSMEM_UID */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_uid.h b/arch/arm/src/stm32wl5/stm32wl5_uid.h new file mode 100644 index 0000000000..e1ab3ceae2 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_uid.h @@ -0,0 +1,52 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_uid.h + * + * Copyright (C) 2015 Marawan Ragab. All rights reserved. + * Author: Marawan Ragab + * dev@ziggurat9.com + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_UID_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_UID_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +void stm32wl5_get_uniqueid(uint8_t uniqueid[12]); + +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_UID_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_userspace.c b/arch/arm/src/stm32wl5/stm32wl5_userspace.c new file mode 100644 index 0000000000..489e523dfc --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_userspace.c @@ -0,0 +1,91 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_userspace.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include + +#include + +#include "stm32wl5_mpuinit.h" +#include "stm32wl5_userspace.h" + +#ifdef CONFIG_BUILD_PROTECTED + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_userspace + * + * Description: + * For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + * + ****************************************************************************/ + +void stm32wl5_userspace(void) +{ + uint8_t *src; + uint8_t *dest; + uint8_t *end; + + /* Clear all of user-space .bss */ + + DEBUGASSERT(USERSPACE->us_bssstart != 0 && USERSPACE->us_bssend != 0 && + USERSPACE->us_bssstart <= USERSPACE->us_bssend); + + dest = (uint8_t *)USERSPACE->us_bssstart; + end = (uint8_t *)USERSPACE->us_bssend; + + while (dest != end) + { + *dest++ = 0; + } + + /* Initialize all of user-space .data */ + + DEBUGASSERT(USERSPACE->us_datasource != 0 && + USERSPACE->us_datastart != 0 && USERSPACE->us_dataend != 0 && + USERSPACE->us_datastart <= USERSPACE->us_dataend); + + src = (uint8_t *)USERSPACE->us_datasource; + dest = (uint8_t *)USERSPACE->us_datastart; + end = (uint8_t *)USERSPACE->us_dataend; + + while (dest != end) + { + *dest++ = *src++; + } + + /* Configure the MPU to permit user-space access to its FLASH and RAM */ + + stm32wl5_mpuinitialize(); +} + +#endif /* CONFIG_BUILD_PROTECTED */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_userspace.h b/arch/arm/src/stm32wl5/stm32wl5_userspace.h new file mode 100644 index 0000000000..ab3e08336f --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_userspace.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_userspace.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_USERSPACE_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_USERSPACE_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32wl5_userspace + * + * Description: + * For the case of the separate user-/kernel-space build, perform whatever + * platform specific initialization of the user memory is required. + * Normally this just means initializing the user space .data and .bss + * segments. + * + ****************************************************************************/ + +#ifdef CONFIG_BUILD_PROTECTED +void stm32wl5_userspace(void); +#endif + +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_USERSPACE_H */ diff --git a/arch/arm/src/stm32wl5/stm32wl5_waste.c b/arch/arm/src/stm32wl5/stm32wl5_waste.c new file mode 100644 index 0000000000..84a065015c --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_waste.c @@ -0,0 +1,42 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_waste.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include "stm32wl5_waste.h" + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +uint32_t idle_wastecounter = 0; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +void stm32wl5_waste(void) +{ + idle_wastecounter++; +} diff --git a/arch/arm/src/stm32wl5/stm32wl5_waste.h b/arch/arm/src/stm32wl5/stm32wl5_waste.h new file mode 100644 index 0000000000..01534495a0 --- /dev/null +++ b/arch/arm/src/stm32wl5/stm32wl5_waste.h @@ -0,0 +1,63 @@ +/**************************************************************************** + * arch/arm/src/stm32wl5/stm32wl5_waste.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_STM32WL5_STM32WL5_WASTE_H +#define __ARCH_ARM_SRC_STM32WL5_STM32WL5_WASTE_H + +/* Waste CPU Time */ + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/* Waste CPU Time + * + * stm32wl5_waste() is the logic that will be executed when portions of + * kernel or user-app is polling some register or similar, waiting for + * desired status. This time is wasted away. This function offers a measure + * of badly written piece of software or some undesired behavior. At + * the same time this function adds to some IDLE time which portion cannot + * be used for other purposes (yet). + */ + +void stm32wl5_waste(void); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ARCH_ARM_SRC_STM32WL5_STM32WL5_WASTE_H */