diff --git a/targets/TARGET_STM/TARGET_STM32G4/TARGET_STM32G431xB/system_clock.c b/targets/TARGET_STM/TARGET_STM32G4/TARGET_STM32G431xB/system_clock.c new file mode 100644 index 0000000000..4d3cc14ef4 --- /dev/null +++ b/targets/TARGET_STM/TARGET_STM32G4/TARGET_STM32G431xB/system_clock.c @@ -0,0 +1,208 @@ +/* mbed Microcontroller Library + * SPDX-License-Identifier: BSD-3-Clause + ****************************************************************************** + * + * Copyright (c) 2019 STMicroelectronics. + * All rights reserved. + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/** + * This file configures the system clock as follows: + *----------------------------------------------------------------- + * System clock source | 1- USE_PLL_HSE_EXTC (external 8 MHz clock) + * | 2- USE_PLL_HSE_XTAL (external 8 MHz xtal) + * | 3- USE_PLL_HSI (internal 16 MHz) + *----------------------------------------------------------------- + * SYSCLK(MHz) | 64 + * AHBCLK (MHz) | 64 + * APB1CLK (MHz) | 64 + * USB capable | NO + *----------------------------------------------------------------- + */ + +#include "stm32g4xx.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 0x00U /*!< Vector Table base offset field. + This value must be a multiple of 0x100. */ + +#define USE_PLL_HSE_EXTC 0x8 // Use external clock (ST Link MCO) +#define USE_PLL_HSE_XTAL 0x4 // Use external xtal (X3 on board) +#define USE_PLL_HSI 0x2 // Use HSI internal clock + +#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) */ + + +/** + * @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 + { + { + error("SetSysClock failed\n"); + } + } + } + } + + /* Output clock on MCO1 pin(PA8) for debugging purpose */ + //HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_SYSCLK, RCC_MCODIV_1); + //HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI48, RCC_MCODIV_1); +} + +#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_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = { 0 }; + + /** Configure the main internal regulator output voltage + */ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST); + /** Initializes the CPU, AHB and APB busses clocks + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; + RCC_OscInitStruct.HSEState = RCC_HSE_ON; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; + RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV6; + //! 170MHz as a core frequency for FDCAN is not suitable for many frequencies, + //! as it provides low accuracy. When no FDCAN is used, the full capacity of 170 MHz + //! should be standard. +#if DEVICE_CAN + RCC_OscInitStruct.PLL.PLLN = 80; +#else + RCC_OscInitStruct.PLL.PLLN = 85; +#endif + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + + // For USB: Default to USB driven by HSI48 Clock. (USB needs a 48 MHz Clock). + // Code below enables the HSI48 Clock + // (Sidenote: RNG is also driven (and according to STM specs) verified with the 48MHz HSI48) + RCC_OscInitStruct.OscillatorType |= RCC_OSCILLATORTYPE_HSI48; + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; + + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + return 0; // FAIL + } + + // For USB: Default to USB driven by HSI48 Clock. + // Code below connects USB (and RNG) to the HSI48 Clock. + RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; + RCC_PeriphCLKInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct) != HAL_OK) { + return 0; // FAIL + } + + /** Initializes the CPU, AHB and APB busses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + // This is an assumption: Using same Flash Latency as for G474RE + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8) != HAL_OK) { + return 0; // FAIL + } + + 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_OscInitTypeDef RCC_OscInitStruct = {0}; + RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; + RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = { 0 }; + + /** Configure the main internal regulator output voltage + */ + HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1); + /** Initializes the CPU, AHB and APB busses clocks + */ + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + 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; + RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4; + RCC_OscInitStruct.PLL.PLLN = 85; + RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; + RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2; + RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2; + RCC_OscInitStruct.OscillatorType |= RCC_OSCILLATORTYPE_HSI48; // Enable HSI48 and feed it to USB/RNG. + RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; // USB needs - and RNG is verified with - the 48Mhz HSI48. + if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { + return 0; // FAIL + } + RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB; // Connect HSI48 clock to USB (and RNG) + RCC_PeriphCLKInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; + if (HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct) != HAL_OK) { + return 0; // FAIL + } + + /** Initializes the CPU, AHB and APB busses clocks + */ + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK + | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + + if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_8) != HAL_OK) { + return 0; // FAIL + } + + return 1; // OK +} +#endif /* ((CLOCK_SOURCE) & USE_PLL_HSI) */