diff --git a/arch/arm/src/stm32f0l0/hardware/stm32_crs.h b/arch/arm/src/stm32f0l0/hardware/stm32_crs.h index b0c79e1b80f..8f95ff0f6c2 100644 --- a/arch/arm/src/stm32f0l0/hardware/stm32_crs.h +++ b/arch/arm/src/stm32f0l0/hardware/stm32_crs.h @@ -78,19 +78,19 @@ #define CRS_CFGR_SYNCDIV_SHIFT 24 /* Bits 24-26: SYNC divider */ #define CRS_CFGR_SYNCDIV_MASK (7 << CRS_CFGR_SYNCDIV_SHIFT) # define CRS_CFGR_SYNCDIV_d1 (0 << CRS_CFGR_SYNCDIV_SHIFT) /* Not divided */ -# define CRS_CFGR_SYNCDIV_d2 (1 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 2) */ -# define CRS_CFGR_SYNCDIV_d4 (2 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 4) */ -# define CRS_CFGR_SYNCDIV_d8 (3 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 8) */ -# define CRS_CFGR_SYNCDIV_d16 (4 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 16) */ -# define CRS_CFGR_SYNCDIV_d32 (5 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 32) */ -# define CRS_CFGR_SYNCDIV_d64 (6 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 64) */ -# define CRS_CFGR_SYNCDIV_d128 (6 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 128) */ +# define CRS_CFGR_SYNCDIV_d2 (1 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 2 */ +# define CRS_CFGR_SYNCDIV_d4 (2 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 4 */ +# define CRS_CFGR_SYNCDIV_d8 (3 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 8 */ +# define CRS_CFGR_SYNCDIV_d16 (4 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 16 */ +# define CRS_CFGR_SYNCDIV_d32 (5 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 32 */ +# define CRS_CFGR_SYNCDIV_d64 (6 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 64 */ +# define CRS_CFGR_SYNCDIV_d128 (7 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 128 */ #define CRS_CFGR_SYNCSRC_SHIFT 28 /* Bits 28-29: SYNC signal source selection */ #define CRS_CFGR_SYNCSRC_MASK (3 << CRS_CFGR_SYNCSRC_SHIFT) # define CRS_CFGR_SYNCSRC_GPIO (0 << CRS_CFGR_SYNCSRC_SHIFT) /* GPIO as SYNC signal source */ # define CRS_CFGR_SYNCSRC_LSE (1 << CRS_CFGR_SYNCSRC_SHIFT) /* LSE as SYNC signal source */ # define CRS_CFGR_SYNCSRC_USBSOF (2 << CRS_CFGR_SYNCSRC_SHIFT) /* USB SOF as SYNC signal source */ -#define CRS_CFGR_SYNCPOL (1 << 30) /* SYNC polarity selection */ +#define CRS_CFGR_SYNCPOL (1 << 31) /* SYNC polarity selection */ /* CRS interrupt and status register */ diff --git a/arch/arm/src/stm32f0l0/stm32_hsi48.h b/arch/arm/src/stm32f0l0/stm32_hsi48.h index a8772b6197a..b2f22e79420 100644 --- a/arch/arm/src/stm32f0l0/stm32_hsi48.h +++ b/arch/arm/src/stm32f0l0/stm32_hsi48.h @@ -1,5 +1,5 @@ /************************************************************************************ - * arch/arm/src/stm32f0l0/stm32_rcc.h + * arch/arm/src/stm32f0l0/stm32_hsi48.h * * Copyright (C) 2017 Gregory Nutt. All rights reserved. * Author: Gregory Nutt diff --git a/arch/arm/src/stm32l4/Kconfig b/arch/arm/src/stm32l4/Kconfig index f9c53007a3f..99ec2395c4c 100644 --- a/arch/arm/src/stm32l4/Kconfig +++ b/arch/arm/src/stm32l4/Kconfig @@ -475,6 +475,7 @@ config STM32L4_STM32L4X3 select STM32L4_HAVE_COMP select STM32L4_HAVE_SAI1 select STM32L4_HAVE_LCD if !(STM32L4_STM32L4X1 || STM32L4_STM32L4X2) + select STM32L4_HAVE_HSI48 config STM32L4_STM32L4X5 # STM32L4 USB OTG Lines (documented in RM0351) @@ -564,6 +565,7 @@ config STM32L4_STM32L4XR select STM32L4_HAVE_I2C4 select STM32L4_HAVE_DCMI select STM32L4_HAVE_DFSDM1 + select STM32L4_HAVE_HSI48 # Chip subfamilies: @@ -680,6 +682,7 @@ config STM32L4_STM32L496XX select STM32L4_HAVE_DCMI select STM32L4_HAVE_DMA2D select STM32L4_HAVE_DFSDM1 + select STM32L4_HAVE_HSI48 config STM32L4_STM32L4A6XX bool @@ -933,6 +936,10 @@ config STM32L4_HAVE_HASH bool default n +config STM32L4_HAVE_HSI48 + bool + default n + config STM32L4_HAVE_I2C4 bool default n diff --git a/arch/arm/src/stm32l4/Make.defs b/arch/arm/src/stm32l4/Make.defs index 73243cab3bd..20f5f6f509a 100644 --- a/arch/arm/src/stm32l4/Make.defs +++ b/arch/arm/src/stm32l4/Make.defs @@ -123,6 +123,10 @@ ifeq ($(CONFIG_BUILD_PROTECTED),y) CHIP_CSRCS += stm32l4_userspace.c stm32l4_mpuinit.c endif +ifeq ($(CONFIG_STM32L4_HAVE_HSI48),y) +CHIP_CSRCS += stm32l4_hsi48.c +endif + ifeq ($(CONFIG_STM32L4_ADC),y) CHIP_CSRCS += stm32l4_adc.c endif diff --git a/arch/arm/src/stm32l4/chip/stm32l4_crs.h b/arch/arm/src/stm32l4/chip/stm32l4_crs.h new file mode 100644 index 00000000000..df7830fb0d4 --- /dev/null +++ b/arch/arm/src/stm32l4/chip/stm32l4_crs.h @@ -0,0 +1,115 @@ +/************************************************************************************ + * arch/arm/src/stm32l4/chip/stm32l4_crs.h + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Alan Carvalho de Assis + * + * 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_STM32L4_CHIP_STM32L4_CRS_H +#define __ARCH_ARM_SRC_STM32L4_CHIP_STM32L4_CRS_H + +/************************************************************************************ + * Pre-processor Definitions + ************************************************************************************/ + +/* Register Offsets *****************************************************************/ + +#define STM32L4_CRS_CR_OFFSET 0x0000 /* CRS control register */ +#define STM32L4_CRS_CFGR_OFFSET 0x0004 /* CRS configuration register */ +#define STM32L4_CRS_ISR_OFFSET 0x0008 /* CRS interrupt and status register */ +#define STM32L4_CRS_ICR_OFFSET 0x000c /* CRS interrupt flag clear register */ + +/* Register Addresses ***************************************************************/ + +#define STM32L4_CRS_CR (STM32L4_CRS_BASE + STM32L4_CRS_CR_OFFSET) +#define STM32L4_CRS_CFGR (STM32L4_CRS_BASE + STM32L4_CRS_CFGR_OFFSET) +#define STM32L4_CRS_ISR (STM32L4_CRS_BASE + STM32L4_CRS_ISR_OFFSET) +#define STM32L4_CRS_ICR (STM32L4_CRS_BASE + STM32L4_CRS_ICR_OFFSET) + +/* Register Bitfield Definitions ****************************************************/ + +/* CRS control register */ + +#define CRS_CR_SYNCOKIE (1 << 0) /* Bit 0: SYNC event OK interrupt enable */ +#define CRS_CR_SYNCWARNIE (1 << 1) /* Bit 1: SYNC warning interrupt enable */ +#define CRS_CR_ERRIE (1 << 2) /* Bit 2: Syncronization or Trimming error interrupt enabled */ +#define CRS_CR_ESYNCIE (1 << 3) /* Bit 3: Expected SYNC interrupt enable */ +#define CRS_CR_CEN (1 << 5) /* Bit 5: Frequency error counter enable */ +#define CRS_CR_AUTOTRIMEN (1 << 6) /* Bit 6: Automatic trimming enabled */ +#define CRS_CR_SWSYNC (1 << 7) /* Bit 7: Generate sofware SYNC event */ +#define CRS_CR_TRIM_SHIFT 8 /* Bits 8-13: HSI48 oscillator smooth trimming */ +#define CRS_CR_TRIM_MASK (0x3f << CRS_CR_TRIM_SHIFT) + +/* CRS configuration register */ + +#define CRS_CFGR_RELOAD_SHIFT 0 /* Bits 0-15: Counter reload value */ +#define CRS_CFGR_RELOAD_MASK (0xffff << CRS_CFGR_RELOAD_SHIFT) +#define CRS_CFGR_FELIM_SHIFT 16 /* Bits 16-23: Frequency error limit */ +#define CRS_CFGR_FELIM_MASK (0xff << CRS_CFGR_FELIM_SHIFT) +#define CRS_CFGR_SYNCDIV_SHIFT 24 /* Bits 24-26: SYNC divider */ +#define CRS_CFGR_SYNCDIV_MASK (7 << CRS_CFGR_SYNCDIV_SHIFT) +# define CRS_CFGR_SYNCDIV_d1 (0 << CRS_CFGR_SYNCDIV_SHIFT) /* Not divided */ +# define CRS_CFGR_SYNCDIV_d2 (1 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 2 */ +# define CRS_CFGR_SYNCDIV_d4 (2 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 4 */ +# define CRS_CFGR_SYNCDIV_d8 (3 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 8 */ +# define CRS_CFGR_SYNCDIV_d16 (4 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 16 */ +# define CRS_CFGR_SYNCDIV_d32 (5 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 32 */ +# define CRS_CFGR_SYNCDIV_d64 (6 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 64 */ +# define CRS_CFGR_SYNCDIV_d128 (7 << CRS_CFGR_SYNCDIV_SHIFT) /* divided by 128 */ +#define CRS_CFGR_SYNCSRC_SHIFT 28 /* Bits 28-29: SYNC signal source selection */ +#define CRS_CFGR_SYNCSRC_MASK (3 << CRS_CFGR_SYNCSRC_SHIFT) +# define CRS_CFGR_SYNCSRC_GPIO (0 << CRS_CFGR_SYNCSRC_SHIFT) /* GPIO as SYNC signal source */ +# define CRS_CFGR_SYNCSRC_LSE (1 << CRS_CFGR_SYNCSRC_SHIFT) /* LSE as SYNC signal source */ +# define CRS_CFGR_SYNCSRC_USBSOF (2 << CRS_CFGR_SYNCSRC_SHIFT) /* USB SOF as SYNC signal source */ +#define CRS_CFGR_SYNCPOL (1 << 31) /* SYNC polarity selection */ + +/* CRS interrupt and status register */ + +#define CRS_ISR_SYNCOKF (1 << 0) /* Bit 0: SYNC event OK flag */ +#define CRS_ISR_SYNCWARNF (1 << 1) /* Bit 1: SYNC warning flag */ +#define CRS_ISR_ERRF (1 << 2) /* Bit 2: Errot flag */ +#define CRS_ISR_ESYNCF (1 << 3) /* Bit 3: Expected SYNC flag */ +#define CRS_ISR_SYNCERR (1 << 8) /* Bit 8: SYNC error */ +#define CRS_ISR_SYNCMISS (1 << 9) /* Bit 9: SYNC missed */ +#define CRS_ISR_TRIMOVF (1 << 10) /* Bit 10: Trimming overflow or underflow */ +#define CRS_ISR_FEDIR (1 << 15) /* Bit 15: Frequency error direction */ +#define CRS_ISR_FECAP_SHIFT 16 /* Bits 16-31: Frequency error capture */ +#define CRS_ISR_FECAP_MASK (0xffff << CRS_ISR_FECAP_SHIFT) + +/* CRS interrupt flag clear register */ + +#define CRS_ICR_SYNCOKC (1 << 0) /* Bit 0: SYNC event OK clear flag */ +#define CRS_ICR_SYNCWARNC (1 << 1) /* Bit 1: SYNC waring clear flag */ +#define CRS_ICR_ERRC (1 << 2) /* Bit 2: Error clear flag */ +#define CRS_ICR_ESYNCC (1 << 3) /* Bit 3: Expected SYNC clear flag */ + +#endif /* __ARCH_ARM_SRC_STM32L4_CHIP_STM32L4_CRS_H */ diff --git a/arch/arm/src/stm32l4/chip/stm32l4x3xx_rcc.h b/arch/arm/src/stm32l4/chip/stm32l4x3xx_rcc.h index 9092e540cb2..f01d85e7dd7 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4x3xx_rcc.h +++ b/arch/arm/src/stm32l4/chip/stm32l4x3xx_rcc.h @@ -705,7 +705,7 @@ #define RCC_CCIPR_CLK48SEL_SHIFT (26) #define RCC_CCIPR_CLK48SEL_MASK (3 << RCC_CCIPR_CLK48SEL_SHIFT) -# define RCC_CCIPR_CLK48SEL_NONE (0 << RCC_CCIPR_CLK48SEL_SHIFT) +# define RCC_CCIPR_CLK48SEL_HSI48 (0 << RCC_CCIPR_CLK48SEL_SHIFT) # define RCC_CCIPR_CLK48SEL_PLLSAI1 (1 << RCC_CCIPR_CLK48SEL_SHIFT) # define RCC_CCIPR_CLK48SEL_PLLMAIN (2 << RCC_CCIPR_CLK48SEL_SHIFT) # define RCC_CCIPR_CLK48SEL_MSI (3 << RCC_CCIPR_CLK48SEL_SHIFT) diff --git a/arch/arm/src/stm32l4/chip/stm32l4x6xx_rcc.h b/arch/arm/src/stm32l4/chip/stm32l4x6xx_rcc.h index 416e75bc327..9b60a684b83 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4x6xx_rcc.h +++ b/arch/arm/src/stm32l4/chip/stm32l4x6xx_rcc.h @@ -718,7 +718,11 @@ #define RCC_CCIPR_CLK48SEL_SHIFT (26) #define RCC_CCIPR_CLK48SEL_MASK (3 << RCC_CCIPR_CLK48SEL_SHIFT) +#if defined(CONFIG_STM32L4_STM32L496XX) +# define RCC_CCIPR_CLK48SEL_HSI48 (0 << RCC_CCIPR_CLK48SEL_SHIFT) +#else # define RCC_CCIPR_CLK48SEL_NONE (0 << RCC_CCIPR_CLK48SEL_SHIFT) +#endif # define RCC_CCIPR_CLK48SEL_PLLSAI1 (1 << RCC_CCIPR_CLK48SEL_SHIFT) # define RCC_CCIPR_CLK48SEL_PLLMAIN (2 << RCC_CCIPR_CLK48SEL_SHIFT) # define RCC_CCIPR_CLK48SEL_MSI (3 << RCC_CCIPR_CLK48SEL_SHIFT) diff --git a/arch/arm/src/stm32l4/chip/stm32l4xrxx_rcc.h b/arch/arm/src/stm32l4/chip/stm32l4xrxx_rcc.h index 07448e2aa5a..4168469ae9e 100644 --- a/arch/arm/src/stm32l4/chip/stm32l4xrxx_rcc.h +++ b/arch/arm/src/stm32l4/chip/stm32l4xrxx_rcc.h @@ -755,7 +755,7 @@ #define RCC_CCIPR_CLK48SEL_SHIFT (26) #define RCC_CCIPR_CLK48SEL_MASK (3 << RCC_CCIPR_CLK48SEL_SHIFT) -# define RCC_CCIPR_CLK48SEL_NONE (0 << RCC_CCIPR_CLK48SEL_SHIFT) +# define RCC_CCIPR_CLK48SEL_HSI48 (0 << RCC_CCIPR_CLK48SEL_SHIFT) # define RCC_CCIPR_CLK48SEL_PLLSAI1 (1 << RCC_CCIPR_CLK48SEL_SHIFT) # define RCC_CCIPR_CLK48SEL_PLLMAIN (2 << RCC_CCIPR_CLK48SEL_SHIFT) # define RCC_CCIPR_CLK48SEL_MSI (3 << RCC_CCIPR_CLK48SEL_SHIFT) diff --git a/arch/arm/src/stm32l4/stm32l4_hsi48.c b/arch/arm/src/stm32l4/stm32l4_hsi48.c new file mode 100644 index 00000000000..94ca03b40f5 --- /dev/null +++ b/arch/arm/src/stm32l4/stm32l4_hsi48.c @@ -0,0 +1,181 @@ +/**************************************************************************** + * arch/arm/src/stm32l4/stm32l4_hsi48.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 "up_arch.h" +#include "chip.h" +#include "chip/stm32l4_rcc.h" +#include "chip/stm32l4_crs.h" + +#include "stm32l4_hsi48.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: stm32l4_enable_hsi48 + * + * Description: + * On STM32L4X3, STM32L496xx/4A6xx and STM32L4XR devices only, the HSI48 + * clock signal is generated from an internal 48 MHz RC oscillator and can + * be used directly as a system clock or divided and be used as PLL input. + * + * The internal 48MHz RC oscillator is mainly dedicated to provide a high + * precision clock to the USB peripheral by means of a special Clock + * Recovery System (CRS) circuitry, which could use the USB SOF signal or + * the LSE or an external signal to automatically adjust the oscillator + * frequency on-fly, in a very small steps. This oscillator can also be + * used as a system clock source when the system is in run mode; it will + * be disabled as soon as the system enters in Stop or Standby mode. When + * the CRS is not used, the HSI48 RC oscillator runs on its default + * frequency which is subject to manufacturing process variations. + * + * Input Parameters: + * Identifies the syncrhonization source for the HSI48. When used as the + * USB source clock, this must be set to SYNCSRC_USB. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stm32l4_enable_hsi48(enum syncsrc_e syncsrc) +{ + uint32_t regval; + + /* Enable the HSI48 clock. + * + * The HSI48 RC can be switched on and off using the HSI48ON bit in the + * Clock control register (RCC_CRRCR). + * + * The USB clock may be derived from either the PLL clock or from the + * HSI48 clock. This oscillator will be also automatically enabled (by + * hardware forcing HSI48ON bit to one) as soon as it is chosen as a clock + * source for the USB and the peripheral is + * enabled. + */ + + regval = getreg32(STM32L4_RCC_CRRCR); + regval |= RCC_CRRCR_HSI48ON; + putreg32(regval, STM32L4_RCC_CRRCR); + + if (syncsrc == SYNCSRC_USB) + { + /* Select the HSI48 as the USB clock source */ + + /* For the STM32L4, this is done in RCC. */ + } + + /* Wait for the HSI48 clock to stabilize */ + + while ((getreg32(STM32L4_RCC_CRRCR) & RCC_CRRCR_HSI48RDY) == 0); + + + /* The CRS synchronization (SYNC) source, selectable through the CRS_CFGR + * register, can be the signal from the external CRS_SYNC pin, the LSE + * clock or the USB SOF signal. + */ + + regval = getreg32(STM32L4_CRS_CFGR); + regval &= ~CRS_CFGR_SYNCSRC_MASK; + + switch (syncsrc) + { + default: + case SYNCSRC_GPIO: /* GPIO selected as SYNC signal source */ + regval |= CRS_CFGR_SYNCSRC_GPIO; + break; + + case SYNCSRC_LSE: /* LSE selected as SYNC signal source */ + regval |= CRS_CFGR_SYNCSRC_LSE; + break; + + case SYNCSRC_USB: /* USB SOF selected as SYNC signal source */ + regval |= CRS_CFGR_SYNCSRC_USBSOF; + break; + } + + putreg32(regval, STM32L4_CRS_CFGR); + + /* Set the AUTOTRIMEN bit the CRS_CR register to enables the automatic + * hardware adjustment of TRIM bits according to the measured frequency + * error between the selected SYNC event. + */ + + regval = getreg32(STM32L4_CRS_CR); + regval |= CRS_CR_AUTOTRIMEN; + putreg32(regval, STM32L4_CRS_CR); +} + +/**************************************************************************** + * Name: stm32l4_disable_hsi48 + * + * Description: + * Disable the HSI48 clock. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stm32l4_disable_hsi48(void) +{ + uint32_t regval; + + /* Disable the HSI48 clock */ + + regval = getreg32(STM32L4_RCC_CRRCR); + regval &= ~RCC_CRRCR_HSI48ON; + putreg32(regval, STM32L4_RCC_CRRCR); + + /* Set other registers to the default settings. */ + + regval = getreg32(STM32L4_CRS_CFGR); + regval &= ~CRS_CFGR_SYNCSRC_MASK; + putreg32(regval, STM32L4_CRS_CFGR); + + regval = getreg32(STM32L4_CRS_CR); + regval &= ~CRS_CR_AUTOTRIMEN; + putreg32(regval, STM32L4_CRS_CR); +} diff --git a/arch/arm/src/stm32l4/stm32l4_hsi48.h b/arch/arm/src/stm32l4/stm32l4_hsi48.h new file mode 100644 index 00000000000..3ae970f2aae --- /dev/null +++ b/arch/arm/src/stm32l4/stm32l4_hsi48.h @@ -0,0 +1,109 @@ +/************************************************************************************ + * arch/arm/src/stm32l4/stm32l4_hsi48.h + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Alan Carvalho de Assis + * + * 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_STM32L4_STM32L4_HSI48_H +#define __ARCH_ARM_SRC_STM32L4_STM32L4_HSI48_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include + +#ifdef CONFIG_STM32L4_HAVE_HSI48 + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +enum syncsrc_e +{ + SYNCSRC_GPIO = 0, /* GPIO selected as SYNC signal source */ + SYNCSRC_LSE, /* LSE selected as SYNC signal source */ + SYNCSRC_USB, /* USB SOF selected as SYNC signal source */ +}; + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +/**************************************************************************** + * Name: stm32l4_enable_hsi48 + * + * Description: + * On STM32L4X3, STM32L496xx/4A6xx and STM32L4XR devices only, the HSI48 + * clock signal is generated from an internal 48 MHz RC oscillator and can + * be used directly as a system clock or divided and be used as PLL input. + * + * The internal 48MHz RC oscillator is mainly dedicated to provide a high + * precision clock to the USB peripheral by means of a special Clock + * Recovery System (CRS) circuitry, which could use the USB SOF signal or + * the LSE or an external signal to automatically adjust the oscillator + * frequency on-fly, in a very small steps. This oscillator can also be + * used as a system clock source when the system is in run mode; it will + * be disabled as soon as the system enters in Stop or Standby mode. When + * the CRS is not used, the HSI48 RC oscillator runs on its default + * frequency which is subject to manufacturing process variations. + * + * Input Parameters: + * Identifies the syncrhonization source for the HSI48. When used as the + * USB source clock, this must be set to SYNCSRC_USB. + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stm32l4_enable_hsi48(enum syncsrc_e syncsrc); + +/**************************************************************************** + * Name: stm32l4_disable_hsi48 + * + * Description: + * Disable the HSI48 clock. + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + ****************************************************************************/ + +void stm32l4_disable_hsi48(void); + +#endif /* CONFIG_STM32L4_HAVE_HSI48 */ +#endif /* __ARCH_ARM_SRC_STM32L4_STM32L4_HSI48_H */ diff --git a/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c b/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c index f2891edb5bf..ed634c249a0 100644 --- a/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4x3xx_rcc.c @@ -45,6 +45,7 @@ #include "stm32l4_pwr.h" #include "stm32l4_flash.h" +#include "stm32l4_hsi48.h" /**************************************************************************** * Pre-processor Definitions @@ -67,6 +68,14 @@ #define HSE_DIVISOR (STM32L4_HSE_FREQUENCY + 500000) / 1000000 +/* Determine if board wants to use HSI48 as 48 MHz oscillator. */ + +#if defined(CONFIG_STM32L4_HAVE_HSI48) && defined(STM32L4_USE_CLK48) +# if STM32L4_CLK48_SEL == RCC_CCIPR_CLK48SEL_HSI48 +# define STM32L4_USE_HSI48 +# endif +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -360,6 +369,12 @@ static inline void rcc_enableapb1(void) regval |= RCC_APB1ENR1_USBFSEN; #endif +#ifdef STM32L4_USE_HSI48 + /* Clock Recovery System clock enable */ + + regval |= RCC_APB1ENR1_CRSEN; +#endif + /* Power interface clock enable. The PWR block is always enabled so that * we can set the internal voltage regulator as required. */ @@ -877,7 +892,7 @@ static void stm32l4_stdclockconfig(void) regval |= RCC_CR_MSIPLLEN; putreg32(regval, STM32L4_RCC_CR); # endif -#endif +#endif /* STM32L4_USE_LSE */ } } #endif @@ -894,6 +909,10 @@ static inline void rcc_enableperipherals(void) rcc_enableahb3(); rcc_enableapb1(); rcc_enableapb2(); + +#ifdef STM32L4_USE_HSI48 + stm32l4_enable_hsi48(SYNCSRC_USB); +#endif } /**************************************************************************** diff --git a/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c b/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c index eea24cbfc41..6545eee029c 100644 --- a/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4x6xx_rcc.c @@ -44,6 +44,7 @@ #include "stm32l4_pwr.h" #include "stm32l4_flash.h" +#include "stm32l4_hsi48.h" /**************************************************************************** * Pre-processor Definitions @@ -66,6 +67,14 @@ #define HSE_DIVISOR (STM32L4_HSE_FREQUENCY + 500000) / 1000000 +/* Determine if board wants to use HSI48 as 48 MHz oscillator. */ + +#if defined(CONFIG_STM32L4_HAVE_HSI48) && defined(STM32L4_USE_CLK48) +# if STM32L4_CLK48_SEL == RCC_CCIPR_CLK48SEL_HSI48 +# define STM32L4_USE_HSI48 +# endif +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -416,6 +425,12 @@ static inline void rcc_enableapb1(void) regval |= RCC_APB1ENR1_CAN2EN; #endif +#ifdef STM32L4_USE_HSI48 + /* Clock Recovery System clock enable */ + + regval |= RCC_APB1ENR1_CRSEN; +#endif + /* Power interface clock enable. The PWR block is always enabled so that * we can set the internal voltage regulator as required. */ @@ -945,7 +960,7 @@ static void stm32l4_stdclockconfig(void) regval |= RCC_CR_MSIPLLEN; putreg32(regval, STM32L4_RCC_CR); # endif -#endif +#endif /* STM32L4_USE_LSE */ } } #endif @@ -962,6 +977,10 @@ static inline void rcc_enableperipherals(void) rcc_enableahb3(); rcc_enableapb1(); rcc_enableapb2(); + +#ifdef STM32L4_USE_HSI48 + stm32l4_enable_hsi48(SYNCSRC_USB); +#endif } /**************************************************************************** diff --git a/arch/arm/src/stm32l4/stm32l4xrxx_rcc.c b/arch/arm/src/stm32l4/stm32l4xrxx_rcc.c index c9fdbcdd726..e0bed47fad4 100644 --- a/arch/arm/src/stm32l4/stm32l4xrxx_rcc.c +++ b/arch/arm/src/stm32l4/stm32l4xrxx_rcc.c @@ -44,6 +44,7 @@ #include "stm32l4_pwr.h" #include "stm32l4_flash.h" +#include "stm32l4_hsi48.h" /**************************************************************************** * Pre-processor Definitions @@ -66,6 +67,14 @@ #define HSE_DIVISOR (STM32L4_HSE_FREQUENCY + 500000) / 1000000 +/* Determine if board wants to use HSI48 as 48 MHz oscillator. */ + +#if defined(CONFIG_STM32L4_HAVE_HSI48) && defined(STM32L4_USE_CLK48) +# if STM32L4_CLK48_SEL == RCC_CCIPR_CLK48SEL_HSI48 +# define STM32L4_USE_HSI48 +# endif +#endif + /**************************************************************************** * Private Data ****************************************************************************/ @@ -403,6 +412,12 @@ static inline void rcc_enableapb1(void) regval |= RCC_APB1ENR1_CAN1EN; #endif +#ifdef STM32L4_USE_HSI48 + /* Clock Recovery System clock enable */ + + regval |= RCC_APB1ENR1_CRSEN; +#endif + /* Power interface clock enable. The PWR block is always enabled so that * we can set the internal voltage regulator as required. */ @@ -938,7 +953,7 @@ static void stm32l4_stdclockconfig(void) regval |= RCC_CR_MSIPLLEN; putreg32(regval, STM32L4_RCC_CR); # endif -#endif +#endif /* STM32L4_USE_LSE */ } } #endif @@ -955,6 +970,10 @@ static inline void rcc_enableperipherals(void) rcc_enableahb3(); rcc_enableapb1(); rcc_enableapb2(); + +#ifdef STM32L4_USE_HSI48 + stm32l4_enable_hsi48(SYNCSRC_USB); +#endif } /****************************************************************************