|
@@ -0,0 +1,405 @@
|
|
|
+/**
|
|
|
+ ******************************************************************************
|
|
|
+ * @file system_stm32f4xx.c
|
|
|
+ * @author MCD Application Team
|
|
|
+ * @version V1.8.1
|
|
|
+ * @date 27-January-2022
|
|
|
+ * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
|
|
|
+ * This file contains the system clock configuration for STM32F4xx devices.
|
|
|
+ *
|
|
|
+ * 1. This file provides two functions and one global variable to be called from
|
|
|
+ * user application:
|
|
|
+ * - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
|
|
|
+ * and Divider factors, AHB/APBx prescalers and Flash settings),
|
|
|
+ * depending on the configuration made in the clock xls tool.
|
|
|
+ * This function is called at startup just after reset and
|
|
|
+ * before branch to main program. This call is made inside
|
|
|
+ * the "startup_stm32f4xx.s" file.
|
|
|
+ *
|
|
|
+ * - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
|
|
|
+ * by the user application to setup the SysTick
|
|
|
+ * timer or configure other parameters.
|
|
|
+ *
|
|
|
+ * - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and mus
|
|
|
+ * be called whenever the core clock is changed
|
|
|
+ * during program execution.
|
|
|
+ *
|
|
|
+ * 2. After each device reset the HSI (16 MHz) is used as system clock source.
|
|
|
+ * Then SystemInit() function is called, in "startup_stm32f4xx.s" file, to
|
|
|
+ * configure the system clock before to branch to main program.
|
|
|
+ *
|
|
|
+ * 3. If the system clock source selected by user fails to startup, the SystemInit()
|
|
|
+ * function will do nothing and HSI still used as system clock source. User can
|
|
|
+ * add some code to deal with this issue inside the SetSysClock() function.
|
|
|
+ *
|
|
|
+ * 4. The default value of HSE crystal is set to 25MHz, refer to "HSE_VALUE" define
|
|
|
+ * in "stm32f4xx.h" file. When HSE is used as system clock source, directly or
|
|
|
+ * through PLL, and you are using different crystal you have to adapt the HSE
|
|
|
+ * value to your own configuration.
|
|
|
+ *
|
|
|
+ * 5. This file configures the system clock as follows:
|
|
|
+ *=============================================================================
|
|
|
+ *=============================================================================
|
|
|
+ * System Clock source | PLL (HSE)
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * SYSCLK(Hz) | 100000000
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * HCLK(Hz) | 100000000
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * AHB Prescaler | 1
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * APB1 Prescaler | 4
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * APB2 Prescaler | 2
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * HSE Frequency(Hz) | 25000000
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * PLL_M | 16
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * PLL_N | 200
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * PLL_P | 2
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * PLL_Q | 15
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * PLLI2S_N | 192
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * PLLI2S_R | 5
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * I2S input clock(Hz) | 38400000
|
|
|
+ * |
|
|
|
+ * To achieve the following I2S config: |
|
|
|
+ * - Master clock output (MCKO): OFF |
|
|
|
+ * - Frame wide : 16bit |
|
|
|
+ * - Audio sampling freq (KHz) : 32 |
|
|
|
+ * - Error % : 1.3158 |
|
|
|
+ * - Prescaler Odd factor (ODD): 0 |
|
|
|
+ * - Linear prescaler (DIV) : 2 |
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * VDD(V) | 1.8
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * Main regulator output voltage | Scale1 mode
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * Flash Latency(WS) | 4
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * Prefetch Buffer | OFF
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * Instruction cache | ON
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * Data cache | ON
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ * Require 48MHz for USB OTG FS, | Disabled
|
|
|
+ * SDIO and RNG clock |
|
|
|
+ *-----------------------------------------------------------------------------
|
|
|
+ *=============================================================================
|
|
|
+ ******************************************************************************
|
|
|
+ * @attention
|
|
|
+ *
|
|
|
+ * Copyright (c) 2016 STMicroelectronics.
|
|
|
+ * All rights reserved.
|
|
|
+ *
|
|
|
+ * This software is licensed under terms that can be found in the LICENSE file
|
|
|
+ * in the root directory of this software component.
|
|
|
+ * If no LICENSE file comes with this software, it is provided AS-IS.
|
|
|
+ *
|
|
|
+ ******************************************************************************
|
|
|
+ */
|
|
|
+
|
|
|
+/** @addtogroup CMSIS
|
|
|
+ * @{
|
|
|
+ */
|
|
|
+
|
|
|
+/** @addtogroup stm32f4xx_system
|
|
|
+ * @{
|
|
|
+ */
|
|
|
+
|
|
|
+/** @addtogroup STM32F4xx_System_Private_Includes
|
|
|
+ * @{
|
|
|
+ */
|
|
|
+
|
|
|
+#define STM32F4_COMPATIBLE
|
|
|
+#include <mcu.h>
|
|
|
+
|
|
|
+/**
|
|
|
+ * @}
|
|
|
+ */
|
|
|
+
|
|
|
+/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
|
|
|
+ * @{
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @}
|
|
|
+ */
|
|
|
+
|
|
|
+/** @addtogroup STM32F4xx_System_Private_Defines
|
|
|
+ * @{
|
|
|
+ */
|
|
|
+
|
|
|
+/*!< Uncomment the following line if you need to relocate your vector Table in
|
|
|
+ Internal SRAM. */
|
|
|
+/* #define VECT_TAB_SRAM */
|
|
|
+#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
|
|
|
+ This value must be a multiple of 0x200. */
|
|
|
+/******************************************************************************/
|
|
|
+
|
|
|
+/************************* PLL Parameters *************************************/
|
|
|
+
|
|
|
+/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
|
|
|
+#define PLL_M 16
|
|
|
+
|
|
|
+/* USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ */
|
|
|
+#define PLL_Q 15
|
|
|
+
|
|
|
+#define PLL_N 200
|
|
|
+/* SYSCLK = PLL_VCO / PLL_P */
|
|
|
+#define PLL_P 2
|
|
|
+
|
|
|
+/* PLLI2S_VCO = (HSE_VALUE Or HSI_VALUE / PLL_M) * PLLI2S_N
|
|
|
+ I2SCLK = PLLI2S_VCO / PLLI2S_R */
|
|
|
+#define PLLI2S_N 192
|
|
|
+#define PLLI2S_R 5
|
|
|
+
|
|
|
+/******************************************************************************/
|
|
|
+
|
|
|
+/**
|
|
|
+ * @}
|
|
|
+ */
|
|
|
+
|
|
|
+/** @addtogroup STM32F4xx_System_Private_Macros
|
|
|
+ * @{
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @}
|
|
|
+ */
|
|
|
+
|
|
|
+/** @addtogroup STM32F4xx_System_Private_Variables
|
|
|
+ * @{
|
|
|
+ */
|
|
|
+
|
|
|
+uint32_t SystemCoreClock = 100000000;
|
|
|
+
|
|
|
+__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
|
|
|
+
|
|
|
+/**
|
|
|
+ * @}
|
|
|
+ */
|
|
|
+
|
|
|
+/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
|
|
|
+ * @{
|
|
|
+ */
|
|
|
+
|
|
|
+static void SetSysClock(void);
|
|
|
+
|
|
|
+/**
|
|
|
+ * @}
|
|
|
+ */
|
|
|
+
|
|
|
+/** @addtogroup STM32F4xx_System_Private_Functions
|
|
|
+ * @{
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Setup the microcontroller system
|
|
|
+ * Initialize the Embedded Flash Interface, the PLL and update the
|
|
|
+ * SystemFrequency variable.
|
|
|
+ * @param None
|
|
|
+ * @retval None
|
|
|
+ */
|
|
|
+void SystemInit(void)
|
|
|
+{
|
|
|
+ /* Reset the RCC clock configuration to the default reset state ------------*/
|
|
|
+ /* Set HSION bit */
|
|
|
+ RCC->CR |= (uint32_t)0x00000001;
|
|
|
+
|
|
|
+ /* Reset CFGR register */
|
|
|
+ RCC->CFGR = 0x00000000;
|
|
|
+
|
|
|
+ /* Reset HSEON, CSSON and PLLON bits */
|
|
|
+ RCC->CR &= (uint32_t)0xFEF6FFFF;
|
|
|
+
|
|
|
+ /* Reset PLLCFGR register */
|
|
|
+ RCC->PLLCFGR = 0x24003010;
|
|
|
+
|
|
|
+ /* Reset HSEBYP bit */
|
|
|
+ RCC->CR &= (uint32_t)0xFFFBFFFF;
|
|
|
+
|
|
|
+ /* Disable all interrupts */
|
|
|
+ RCC->CIR = 0x00000000;
|
|
|
+
|
|
|
+ /* Configure the System clock source, PLL Multiplier and Divider factors,
|
|
|
+ AHB/APBx prescalers and Flash settings ----------------------------------*/
|
|
|
+ SetSysClock();
|
|
|
+
|
|
|
+ /* Configure the Vector Table location add offset address ------------------*/
|
|
|
+#ifdef VECT_TAB_SRAM
|
|
|
+ SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
|
|
|
+#else
|
|
|
+ SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Update SystemCoreClock variable according to Clock Register Values.
|
|
|
+ * The SystemCoreClock variable contains the core clock (HCLK), it can
|
|
|
+ * be used by the user application to setup the SysTick timer or configure
|
|
|
+ * other parameters.
|
|
|
+ *
|
|
|
+ * @note Each time the core clock (HCLK) changes, this function must be called
|
|
|
+ * to update SystemCoreClock variable value. Otherwise, any configuration
|
|
|
+ * based on this variable will be incorrect.
|
|
|
+ *
|
|
|
+ * @note - The system frequency computed by this function is not the real
|
|
|
+ * frequency in the chip. It is calculated based on the predefined
|
|
|
+ * constant and the selected clock source:
|
|
|
+ *
|
|
|
+ * - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
|
|
|
+ *
|
|
|
+ * - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
|
|
|
+ *
|
|
|
+ * - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
|
|
|
+ * or HSI_VALUE(*) multiplied/divided by the PLL factors.
|
|
|
+ *
|
|
|
+ * (*) HSI_VALUE is a constant defined in stm32f4xx.h file (default value
|
|
|
+ * 16 MHz) but the real value may vary depending on the variations
|
|
|
+ * in voltage and temperature.
|
|
|
+ *
|
|
|
+ * (**) HSE_VALUE is a constant defined in stm32f4xx.h file (default value
|
|
|
+ * 25 MHz), user has to ensure that HSE_VALUE is same as the real
|
|
|
+ * frequency of the crystal used. Otherwise, this function may
|
|
|
+ * have wrong result.
|
|
|
+ *
|
|
|
+ * - The result of this function could be not correct when using fractional
|
|
|
+ * value for HSE crystal.
|
|
|
+ *
|
|
|
+ * @param None
|
|
|
+ * @retval None
|
|
|
+ */
|
|
|
+void SystemCoreClockUpdate(void)
|
|
|
+{
|
|
|
+ uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
|
|
|
+
|
|
|
+ /* Get SYSCLK source -------------------------------------------------------*/
|
|
|
+ tmp = RCC->CFGR & RCC_CFGR_SWS;
|
|
|
+
|
|
|
+ switch (tmp)
|
|
|
+ {
|
|
|
+ case 0x00: /* HSI used as system clock source */
|
|
|
+ SystemCoreClock = HSI_VALUE;
|
|
|
+ break;
|
|
|
+ case 0x04: /* HSE used as system clock source */
|
|
|
+ SystemCoreClock = HSE_VALUE;
|
|
|
+ break;
|
|
|
+ case 0x08: /* PLL P used as system clock source */
|
|
|
+ /* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
|
|
|
+ SYSCLK = PLL_VCO / PLL_P
|
|
|
+ */
|
|
|
+ pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
|
|
|
+ pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
|
|
|
+
|
|
|
+ if (pllsource != 0)
|
|
|
+ {
|
|
|
+ /* HSE used as PLL clock source */
|
|
|
+ pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* HSI used as PLL clock source */
|
|
|
+ pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
|
|
|
+ }
|
|
|
+
|
|
|
+ pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
|
|
|
+ SystemCoreClock = pllvco/pllp;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ SystemCoreClock = HSI_VALUE;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ /* Compute HCLK frequency --------------------------------------------------*/
|
|
|
+ /* Get HCLK prescaler */
|
|
|
+ tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
|
|
|
+ /* HCLK frequency */
|
|
|
+ SystemCoreClock >>= tmp;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief Configures the System clock source, PLL Multiplier and Divider factors,
|
|
|
+ * AHB/APBx prescalers and Flash settings
|
|
|
+ * @Note This function should be called only once the RCC clock configuration
|
|
|
+ * is reset to the default reset state (done in SystemInit() function).
|
|
|
+ * @param None
|
|
|
+ * @retval None
|
|
|
+ */
|
|
|
+static void SetSysClock(void)
|
|
|
+{
|
|
|
+/******************************************************************************/
|
|
|
+/* PLL (clocked by HSI) used as System clock source */
|
|
|
+/******************************************************************************/
|
|
|
+
|
|
|
+ /* At this stage the HSI is already enabled and used as System clock source */
|
|
|
+
|
|
|
+ /* Select regulator voltage output Scale 1 mode */
|
|
|
+ RCC->APB1ENR |= RCC_APB1ENR_PWREN;
|
|
|
+ PWR->CR |= PWR_CR_VOS;
|
|
|
+
|
|
|
+ /* HCLK = SYSCLK / 1*/
|
|
|
+ RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
|
|
+
|
|
|
+ /* PCLK2 = HCLK / 2*/
|
|
|
+ RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
|
|
|
+
|
|
|
+ /* PCLK1 = HCLK / 4*/
|
|
|
+ RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
|
|
|
+
|
|
|
+ /* Enable the main PLL */
|
|
|
+ RCC->CR |= RCC_CR_PLLON;
|
|
|
+
|
|
|
+ /* Wait till the main PLL is ready */
|
|
|
+ while((RCC->CR & RCC_CR_PLLRDY) == 0)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Configure Flash prefetch, Instruction cache, Data cache and wait state */
|
|
|
+ FLASH->ACR = FLASH_ACR_PRFTEN | FLASH_ACR_ICEN |FLASH_ACR_DCEN |FLASH_ACR_LATENCY_4WS;
|
|
|
+
|
|
|
+ /* Select the main PLL as system clock source */
|
|
|
+ RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
|
|
|
+ RCC->CFGR |= RCC_CFGR_SW_PLL;
|
|
|
+
|
|
|
+ /* Wait till the main PLL is used as system clock source */
|
|
|
+ while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS ) != RCC_CFGR_SWS_PLL)
|
|
|
+ {
|
|
|
+ /* Do nothing. */
|
|
|
+ }
|
|
|
+
|
|
|
+#if STM32F429_439xx // We only use the I2S clock for processors without a DFSDM peripheral
|
|
|
+ /******************************************************************************/
|
|
|
+ /* I2S clock configuration */
|
|
|
+ /******************************************************************************/
|
|
|
+ /* PLLI2S clock used as I2S clock source */
|
|
|
+ RCC->CFGR &= ~RCC_CFGR_I2SSRC;
|
|
|
+
|
|
|
+ /* Configure PLLI2S */
|
|
|
+ RCC->PLLI2SCFGR = (PLLI2S_N << 6) | (PLLI2S_R << 28);
|
|
|
+
|
|
|
+ /* Enable PLLI2S */
|
|
|
+ RCC->CR |= ((uint32_t)RCC_CR_PLLI2SON);
|
|
|
+
|
|
|
+ /* Wait till PLLI2S is ready */
|
|
|
+ while((RCC->CR & RCC_CR_PLLI2SRDY) == 0) {
|
|
|
+ }
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @}
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @}
|
|
|
+ */
|
|
|
+
|
|
|
+/**
|
|
|
+ * @}
|
|
|
+ */
|