123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- /**
- ******************************************************************************
- * @file system_stm32l4xx.c
- * @author MCD Application Team
- * @version V1.3.1
- * @date 21-April-2017
- * @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File
- *
- * This file provides two functions and one global variable to be called from
- * user application:
- * - SystemInit(): This function is called at startup just after reset and
- * before branch to main program. This call is made inside
- * the "startup_stm32l4xx.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 must
- * be called whenever the core clock is changed
- * during program execution.
- *
- * After each device reset the MSI (4 MHz) is used as system clock source.
- * Then SystemInit() function is called, in "startup_stm32l4xx.s" file, to
- * configure the system clock before to branch to main program.
- *
- * This file configures the system clock as follows:
- *=============================================================================
- * System clock source | 1- PLL_HSE_EXTC | 3- PLL_HSI
- * | (external 8 MHz clock) | (internal 16 MHz)
- * | 2- PLL_HSE_XTAL | or PLL_MSI
- * | (external 8 MHz xtal) | (internal 4 MHz)
- *-----------------------------------------------------------------------------
- * SYSCLK(MHz) | 48 | 80
- *-----------------------------------------------------------------------------
- * AHBCLK (MHz) | 48 | 80
- *-----------------------------------------------------------------------------
- * APB1CLK (MHz) | 48 | 80
- *-----------------------------------------------------------------------------
- * APB2CLK (MHz) | 48 | 80
- *-----------------------------------------------------------------------------
- * USB capable (48 MHz precise clock) | YES | NO
- *-----------------------------------------------------------------------------
- **/
- #include "stm32l4xx.h"
- #include "nvic_addr.h"
- #include "mbed_error.h"
- /*!< 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. */
- // clock source is selected with CLOCK_SOURCE in json config
- #define USE_PLL_HSE_EXTC 0x8 // Use external clock (ST Link MCO - not enabled by default)
- #define USE_PLL_HSE_XTAL 0x4 // Use external xtal (X3 on board - not provided by default)
- #define USE_PLL_HSI 0x2 // Use HSI internal clock
- #define USE_PLL_MSI 0x1 // Use MSI internal clock
- #define DEBUG_MCO (0) // Output the MCO on PA8 for debugging (0=OFF, 1=SYSCLK, 2=HSE, 3=HSI, 4=MSI)
- #if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) )
- uint8_t SetSysClock_PLL_HSE(uint8_t bypass);
- #endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */
- #if ((CLOCK_SOURCE) & USE_PLL_HSI)
- uint8_t SetSysClock_PLL_HSI(void);
- #endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */
- #if ((CLOCK_SOURCE) & USE_PLL_MSI)
- uint8_t SetSysClock_PLL_MSI(void);
- #endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */
- /**
- * @brief Setup the microcontroller system.
- * @param None
- * @retval None
- */
- void SystemInit(void)
- {
- /* FPU settings ------------------------------------------------------------*/
- #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
- SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); /* set CP10 and CP11 Full Access */
- #endif
- /* Reset the RCC clock configuration to the default reset state ------------*/
- /* Set MSION bit */
- RCC->CR |= RCC_CR_MSION;
- /* Reset CFGR register */
- RCC->CFGR = 0x00000000;
- /* Reset HSEON, CSSON , HSION, and PLLON bits */
- RCC->CR &= (uint32_t)0xEAF6FFFF;
- /* Reset PLLCFGR register */
- RCC->PLLCFGR = 0x00001000;
- /* Reset HSEBYP bit */
- RCC->CR &= (uint32_t)0xFFFBFFFF;
- /* Disable all interrupts */
- RCC->CIER = 0x00000000;
- /* 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 = NVIC_FLASH_VECTOR_ADDRESS; /* Vector Table Relocation in Internal FLASH */
- #endif
- }
- /**
- * @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
- */
- void SetSysClock(void)
- {
- #if ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC)
- /* 1- Try to start with HSE and external clock */
- if (SetSysClock_PLL_HSE(1) == 0)
- #endif
- {
- #if ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL)
- /* 2- If fail try to start with HSE and external xtal */
- if (SetSysClock_PLL_HSE(0) == 0)
- #endif
- {
- #if ((CLOCK_SOURCE) & USE_PLL_HSI)
- /* 3- If fail start with HSI clock */
- if (SetSysClock_PLL_HSI() == 0)
- #endif
- {
- #if ((CLOCK_SOURCE) & USE_PLL_MSI)
- /* 4- If fail start with MSI clock */
- if (SetSysClock_PLL_MSI() == 0)
- #endif
- {
- {
- error("SetSysClock failed\n");
- }
- }
- }
- }
- }
- // Output clock on MCO1 pin(PA8) for debugging purpose
- #if DEBUG_MCO == 1
- HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1);
- #endif
- }
- #if ( ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) )
- /******************************************************************************/
- /* PLL (clocked by HSE) used as System clock source */
- /******************************************************************************/
- uint8_t SetSysClock_PLL_HSE(uint8_t bypass)
- {
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0};
- // Used to gain time after DeepSleep in case HSI is used
- if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET) {
- return 0;
- }
- // Select MSI as system clock source to allow modification of the PLL configuration
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
- HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
- // Enable HSE oscillator and activate PLL with HSE as source
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI;
- if (bypass == 0) {
- RCC_OscInitStruct.HSEState = RCC_HSE_ON; // External 8 MHz xtal on OSC_IN/OSC_OUT
- } else {
- RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS; // External 8 MHz clock on OSC_IN
- }
- RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; // 8 MHz
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLM = 1; // VCO input clock = 8 MHz (8 MHz / 1)
- RCC_OscInitStruct.PLL.PLLN = 20; // VCO output clock = 160 MHz (8 MHz * 20)
- RCC_OscInitStruct.PLL.PLLP = 7; // PLLSAI3 clock = 22 MHz (160 MHz / 7)
- RCC_OscInitStruct.PLL.PLLQ = 2;
- RCC_OscInitStruct.PLL.PLLR = 2; // PLL clock = 80 MHz (160 MHz / 2)
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
- return 0; // FAIL
- }
- // Select PLL clock as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers
- RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 80 MHz or 48 MHz
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 80 MHz or 48 MHz
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // 80 MHz or 48 MHz
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 80 MHz or 48 MHz
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
- return 0; // FAIL
- }
- RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
- RCC_PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSE;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1M = 1;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1N = 12;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_48M2CLK;
- if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) {
- return 0; // FAIL
- }
- // Disable MSI Oscillator
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
- RCC_OscInitStruct.MSIState = RCC_MSI_OFF;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // No PLL update
- HAL_RCC_OscConfig(&RCC_OscInitStruct);
- // Output clock on MCO1 pin(PA8) for debugging purpose
- #if DEBUG_MCO == 2
- if (bypass == 0) {
- HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_2); // 4 MHz
- } else {
- HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_1); // 8 MHz
- }
- #endif
- return 1; // OK
- }
- #endif /* ((CLOCK_SOURCE) & USE_PLL_HSE_XTAL) || ((CLOCK_SOURCE) & USE_PLL_HSE_EXTC) */
- #if ((CLOCK_SOURCE) & USE_PLL_HSI)
- /******************************************************************************/
- /* PLL (clocked by HSI) used as System clock source */
- /******************************************************************************/
- uint8_t SetSysClock_PLL_HSI(void)
- {
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_PeriphCLKInitTypeDef RCC_PeriphClkInit = {0};
- // Select MSI as system clock source to allow modification of the PLL configuration
- RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
- HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
- // Enable HSI oscillator and activate PLL with HSI as source
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
- RCC_OscInitStruct.HSIState = RCC_HSI_ON;
- RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; // 16 MHz
- RCC_OscInitStruct.PLL.PLLM = 2; // VCO input clock = 8 MHz (16 MHz / 2)
- RCC_OscInitStruct.PLL.PLLN = 20; // VCO output clock = 160 MHz (8 MHz * 20)
- RCC_OscInitStruct.PLL.PLLP = 7; // PLLSAI3 clock = 22 MHz (160 MHz / 7)
- RCC_OscInitStruct.PLL.PLLQ = 2;
- RCC_OscInitStruct.PLL.PLLR = 2; // PLL clock = 80 MHz (160 MHz / 2)
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
- return 0; // FAIL
- }
- // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers
- RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; // 80 MHz
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; // 80 MHz
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; // 80 MHz
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; // 80 MHz
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
- return 0; // FAIL
- }
- RCC_PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
- RCC_PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_PLLSAI1;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1Source = RCC_PLLSOURCE_HSI;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1M = 2;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1N = 12;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1Q = RCC_PLLQ_DIV2;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
- RCC_PeriphClkInit.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_48M2CLK;
- if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphClkInit) != HAL_OK) {
- return 0; // FAIL
- }
- // Disable MSI Oscillator
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
- RCC_OscInitStruct.MSIState = RCC_MSI_OFF;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // No PLL update
- HAL_RCC_OscConfig(&RCC_OscInitStruct);
- // Output clock on MCO1 pin(PA8) for debugging purpose
- #if DEBUG_MCO == 3
- HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI, RCC_MCODIV_1); // 16 MHz
- #endif
- return 1; // OK
- }
- #endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */
- #if ((CLOCK_SOURCE) & USE_PLL_MSI)
- /******************************************************************************/
- /* PLL (clocked by MSI) used as System clock source */
- /******************************************************************************/
- uint8_t SetSysClock_PLL_MSI(void)
- {
- RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- RCC_OscInitTypeDef RCC_OscInitStruct = {0};
- RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
- // Enable LSE Oscillator to automatically calibrate the MSI clock
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // No PLL update
- RCC_OscInitStruct.LSEState = RCC_LSE_ON; // External 32.768 kHz clock on OSC_IN/OSC_OUT
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) == HAL_OK) {
- RCC->CR |= RCC_CR_MSIPLLEN; // Enable MSI PLL-mode
- }
- HAL_RCCEx_DisableLSECSS();
- /* Enable MSI Oscillator and activate PLL with MSI as source */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI | RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSE;
- RCC_OscInitStruct.MSIState = RCC_MSI_ON;
- RCC_OscInitStruct.HSEState = RCC_HSE_OFF;
- RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
- RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
- RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_11; /* 48 MHz */
- RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
- RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
- RCC_OscInitStruct.PLL.PLLM = 6; /* 8 MHz */
- RCC_OscInitStruct.PLL.PLLN = 40; /* 320 MHz */
- RCC_OscInitStruct.PLL.PLLP = 7; /* 45 MHz */
- RCC_OscInitStruct.PLL.PLLQ = 4; /* 80 MHz */
- RCC_OscInitStruct.PLL.PLLR = 4; /* 80 MHz */
- if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
- return 0; // FAIL
- }
- /* Enable MSI Auto-calibration through LSE */
- HAL_RCCEx_EnableMSIPLLMode();
- /* Select MSI output as USB clock source */
- PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
- PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_MSI; /* 48 MHz */
- HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
- // Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers
- RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; /* 80 MHz */
- RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; /* 80 MHz */
- RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; /* 80 MHz */
- RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; /* 80 MHz */
- if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) {
- return 0; // FAIL
- }
- // Output clock on MCO1 pin(PA8) for debugging purpose
- #if DEBUG_MCO == 4
- HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_MSI, RCC_MCODIV_2); // 2 MHz
- #endif
- return 1; // OK
- }
- #endif /* ((CLOCK_SOURCE) & USE_PLL_MSI) */
|