You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ut...@apache.org on 2019/12/05 09:10:44 UTC

[mynewt-core] 01/06: mcu: stm32l4: update to syscfg based clock system

This is an automated email from the ASF dual-hosted git repository.

utzig pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit 47948f3adec28512e7ca1e62f24687a36fa58497
Author: Fabio Utzig <ut...@apache.org>
AuthorDate: Tue Nov 26 10:58:08 2019 -0300

    mcu: stm32l4: update to syscfg based clock system
---
 .../include/bsp/stm32l4xx_hal_conf.h               |   8 +-
 hw/bsp/b-l475e-iot01a/src/system_stm32l4xx.c       | 334 --------------------
 hw/bsp/b-l475e-iot01a/syscfg.yml                   |  23 ++
 .../nucleo-l476rg/include/bsp/stm32l4xx_hal_conf.h |   8 +-
 hw/bsp/nucleo-l476rg/src/system_stm32l4xx.c        | 349 ---------------------
 hw/bsp/nucleo-l476rg/syscfg.yml                    |  23 ++
 hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h       |  45 +--
 hw/mcu/stm/stm32l4xx/src/clock_stm32l4xx.c         | 304 ++++++++++++++++++
 hw/mcu/stm/stm32l4xx/src/system_stm32l4xx.c        | 213 +++++++++++++
 hw/mcu/stm/stm32l4xx/syscfg.yml                    |  96 ++++++
 10 files changed, 685 insertions(+), 718 deletions(-)

diff --git a/hw/bsp/b-l475e-iot01a/include/bsp/stm32l4xx_hal_conf.h b/hw/bsp/b-l475e-iot01a/include/bsp/stm32l4xx_hal_conf.h
index c713494..cbe064d 100644
--- a/hw/bsp/b-l475e-iot01a/include/bsp/stm32l4xx_hal_conf.h
+++ b/hw/bsp/b-l475e-iot01a/include/bsp/stm32l4xx_hal_conf.h
@@ -39,6 +39,8 @@
 #ifndef __STM32L4xx_HAL_CONF_H
 #define __STM32L4xx_HAL_CONF_H
 
+#include <syscfg/syscfg.h>
+
 #ifdef __cplusplus
  extern "C" {
 #endif
@@ -176,9 +178,9 @@
 #define  VDD_VALUE                    3300U /*!< Value of VDD in mv */
 #define  TICK_INT_PRIORITY            0x0FU /*!< tick interrupt priority */
 #define  USE_RTOS                     0U
-#define  PREFETCH_ENABLE              0U
-#define  INSTRUCTION_CACHE_ENABLE     1U
-#define  DATA_CACHE_ENABLE            1U
+#define  PREFETCH_ENABLE              MYNEWT_VAL(STM32_FLASH_PREFETCH_ENABLE)
+#define  INSTRUCTION_CACHE_ENABLE     MYNEWT_VAL(STM32_INSTRUCTION_CACHE_ENABLE)
+#define  DATA_CACHE_ENABLE            MYNEWT_VAL(STM32_DATA_CACHE_ENABLE)
 
 /* ########################## Assert Selection ############################## */
 /**
diff --git a/hw/bsp/b-l475e-iot01a/src/system_stm32l4xx.c b/hw/bsp/b-l475e-iot01a/src/system_stm32l4xx.c
deleted file mode 100644
index 7676115..0000000
--- a/hw/bsp/b-l475e-iot01a/src/system_stm32l4xx.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    system_stm32l4xx.c
-  * @author  MCD Application Team
-  * @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                    | MSI
-  *-----------------------------------------------------------------------------
-  *        SYSCLK(Hz)                             | 4000000
-  *-----------------------------------------------------------------------------
-  *        HCLK(Hz)                               | 4000000
-  *-----------------------------------------------------------------------------
-  *        AHB Prescaler                          | 1
-  *-----------------------------------------------------------------------------
-  *        APB1 Prescaler                         | 1
-  *-----------------------------------------------------------------------------
-  *        APB2 Prescaler                         | 1
-  *-----------------------------------------------------------------------------
-  *        PLL_M                                  | 1
-  *-----------------------------------------------------------------------------
-  *        PLL_N                                  | 8
-  *-----------------------------------------------------------------------------
-  *        PLL_P                                  | 7
-  *-----------------------------------------------------------------------------
-  *        PLL_Q                                  | 2
-  *-----------------------------------------------------------------------------
-  *        PLL_R                                  | 2
-  *-----------------------------------------------------------------------------
-  *        PLLSAI1_P                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI1_Q                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI1_R                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI2_P                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI2_Q                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI2_R                              | NA
-  *-----------------------------------------------------------------------------
-  *        Require 48MHz for USB OTG FS,          | Disabled
-  *        SDIO and RNG clock                     |
-  *-----------------------------------------------------------------------------
-  *=============================================================================
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * 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
-  *
-  ******************************************************************************
-  */
-
-/** @addtogroup CMSIS
-  * @{
-  */
-
-/** @addtogroup stm32l4xx_system
-  * @{
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Includes
-  * @{
-  */
-
-#include "stm32l4xx.h"
-#include "mcu/cmsis_nvic.h"
-
-#if !defined  (HSE_VALUE)
-  #define HSE_VALUE    8000000U  /*!< Value of the External oscillator in Hz */
-#endif /* HSE_VALUE */
-
-#if !defined  (MSI_VALUE)
-  #define MSI_VALUE    4000000U  /*!< Value of the Internal oscillator in Hz*/
-#endif /* MSI_VALUE */
-
-#if !defined  (HSI_VALUE)
-  #define HSI_VALUE    16000000U /*!< Value of the Internal oscillator in Hz*/
-#endif /* HSI_VALUE */
-
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_TypesDefinitions
-  * @{
-  */
-
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Defines
-  * @{
-  */
-
-/************************* Miscellaneous Configuration ************************/
-/*!< 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. */
-/******************************************************************************/
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Macros
-  * @{
-  */
-
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Variables
-  * @{
-  */
-  /* The SystemCoreClock variable is updated in three ways:
-      1) by calling CMSIS function SystemCoreClockUpdate()
-      2) by calling HAL API function HAL_RCC_GetHCLKFreq()
-      3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
-         Note: If you use this function to configure the system clock; then there
-               is no need to call the 2 first functions listed above, since SystemCoreClock
-               variable is updated automatically.
-  */
-  uint32_t SystemCoreClock = 4000000U;
-
-  const uint8_t  AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U};
-  const uint8_t  APBPrescTable[8] =  {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U};
-  const uint32_t MSIRangeTable[12] = {100000U,   200000U,   400000U,   800000U,  1000000U,  2000000U, \
-                                      4000000U, 8000000U, 16000000U, 24000000U, 32000000U, 48000000U};
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_FunctionPrototypes
-  * @{
-  */
-
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Functions
-  * @{
-  */
-
-/**
-  * @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 = 0x00000000U;
-
-  /* Reset HSEON, CSSON , HSION, and PLLON bits */
-  RCC->CR &= 0xEAF6FFFFU;
-
-  /* Reset PLLCFGR register */
-  RCC->PLLCFGR = 0x00001000U;
-
-  /* Reset HSEBYP bit */
-  RCC->CR &= 0xFFFBFFFFU;
-
-  /* Disable all interrupts */
-  RCC->CIER = 0x00000000U;
-
-  /* Relocate the vector table */
-  NVIC_Relocate();
-}
-
-/**
-  * @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 MSI, SystemCoreClock will contain the MSI_VALUE(*)
-  *
-  *           - 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(*) or MSI_VALUE(*) multiplied/divided by the PLL factors.
-  *
-  *         (*) MSI_VALUE is a constant defined in stm32l4xx_hal.h file (default value
-  *             4 MHz) but the real value may vary depending on the variations
-  *             in voltage and temperature.
-  *
-  *         (**) HSI_VALUE is a constant defined in stm32l4xx_hal.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 stm32l4xx_hal.h file (default value
-  *              8 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 = 0U, msirange = 0U, pllvco = 0U, pllr = 2U, pllsource = 0U, pllm = 2U;
-
-  /* Get MSI Range frequency--------------------------------------------------*/
-  if((RCC->CR & RCC_CR_MSIRGSEL) == RESET)
-  { /* MSISRANGE from RCC_CSR applies */
-    msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> 8U;
-  }
-  else
-  { /* MSIRANGE from RCC_CR applies */
-    msirange = (RCC->CR & RCC_CR_MSIRANGE) >> 4U;
-  }
-  /*MSI frequency range in HZ*/
-  msirange = MSIRangeTable[msirange];
-
-  /* Get SYSCLK source -------------------------------------------------------*/
-  switch (RCC->CFGR & RCC_CFGR_SWS)
-  {
-    case 0x00:  /* MSI used as system clock source */
-      SystemCoreClock = msirange;
-      break;
-
-    case 0x04:  /* HSI used as system clock source */
-      SystemCoreClock = HSI_VALUE;
-      break;
-
-    case 0x08:  /* HSE used as system clock source */
-      SystemCoreClock = HSE_VALUE;
-      break;
-
-    case 0x0C:  /* PLL used as system clock  source */
-      /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
-         SYSCLK = PLL_VCO / PLLR
-         */
-      pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
-      pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4U) + 1U ;
-
-      switch (pllsource)
-      {
-        case 0x02:  /* HSI used as PLL clock source */
-          pllvco = (HSI_VALUE / pllm);
-          break;
-
-        case 0x03:  /* HSE used as PLL clock source */
-          pllvco = (HSE_VALUE / pllm);
-          break;
-
-        default:    /* MSI used as PLL clock source */
-          pllvco = (msirange / pllm);
-          break;
-      }
-      pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8U);
-      pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25U) + 1U) * 2U;
-      SystemCoreClock = pllvco/pllr;
-      break;
-
-    default:
-      SystemCoreClock = msirange;
-      break;
-  }
-  /* Compute HCLK clock frequency --------------------------------------------*/
-  /* Get HCLK prescaler */
-  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)];
-  /* HCLK clock frequency */
-  SystemCoreClock >>= tmp;
-}
-
-
-/**
-  * @}
-  */
-
-/**
-  * @}
-  */
-
-/**
-  * @}
-  */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/hw/bsp/b-l475e-iot01a/syscfg.yml b/hw/bsp/b-l475e-iot01a/syscfg.yml
index 4e0b844..6cd42ef 100644
--- a/hw/bsp/b-l475e-iot01a/syscfg.yml
+++ b/hw/bsp/b-l475e-iot01a/syscfg.yml
@@ -48,3 +48,26 @@ syscfg.vals:
     NFFS_FLASH_AREA: FLASH_AREA_NFFS
     COREDUMP_FLASH_AREA: FLASH_AREA_IMAGE_1
     BOOTUTIL_MAX_IMG_SECTORS: 256
+    STM32_CLOCK_VOLTAGESCALING_CONFIG: 'PWR_REGULATOR_VOLTAGE_SCALE1'
+    STM32_CLOCK_LSI: 1
+    STM32_CLOCK_LSE: 0
+    STM32_CLOCK_LSE_BYPASS: 0
+    STM32_CLOCK_MSI: 1
+    STM32_CLOCK_MSI_CALIBRATION: 'RCC_MSICALIBRATION_DEFAULT'
+    STM32_CLOCK_MSI_CLOCK_RANGE: 'RCC_MSIRANGE_8'  # 16MHz
+    STM32_CLOCK_HSI: 0
+    STM32_CLOCK_HSI_CALIBRATION: 'RCC_HSICALIBRATION_DEFAULT'
+    STM32_CLOCK_HSE: 0
+    STM32_CLOCK_HSE_BYPASS: 0
+    STM32_CLOCK_PLL_PLLM: 1   # 16 / 1 = 16MHz
+    STM32_CLOCK_PLL_PLLN: 24  # 16 * 24 = 384MHz
+    STM32_CLOCK_PLL_PLLP: 7   # 384 / 7 = 54.85MHz
+    STM32_CLOCK_PLL_PLLR: 6   # 384 / 6 = 64MHz
+    STM32_CLOCK_PLL_PLLQ: 8   # 384 / 8 = 48MHz
+    STM32_CLOCK_AHB_DIVIDER: 'RCC_SYSCLK_DIV1'
+    STM32_CLOCK_APB1_DIVIDER: 'RCC_HCLK_DIV1'
+    STM32_CLOCK_APB2_DIVIDER: 'RCC_HCLK_DIV1'
+    STM32_FLASH_LATENCY: 'FLASH_LATENCY_3'  # max 64MHz
+    STM32_FLASH_PREFETCH_ENABLE: 0
+    STM32_INSTRUCTION_CACHE_ENABLE: 1
+    STM32_DATA_CACHE_ENABLE: 1
diff --git a/hw/bsp/nucleo-l476rg/include/bsp/stm32l4xx_hal_conf.h b/hw/bsp/nucleo-l476rg/include/bsp/stm32l4xx_hal_conf.h
index c713494..cbe064d 100644
--- a/hw/bsp/nucleo-l476rg/include/bsp/stm32l4xx_hal_conf.h
+++ b/hw/bsp/nucleo-l476rg/include/bsp/stm32l4xx_hal_conf.h
@@ -39,6 +39,8 @@
 #ifndef __STM32L4xx_HAL_CONF_H
 #define __STM32L4xx_HAL_CONF_H
 
+#include <syscfg/syscfg.h>
+
 #ifdef __cplusplus
  extern "C" {
 #endif
@@ -176,9 +178,9 @@
 #define  VDD_VALUE                    3300U /*!< Value of VDD in mv */
 #define  TICK_INT_PRIORITY            0x0FU /*!< tick interrupt priority */
 #define  USE_RTOS                     0U
-#define  PREFETCH_ENABLE              0U
-#define  INSTRUCTION_CACHE_ENABLE     1U
-#define  DATA_CACHE_ENABLE            1U
+#define  PREFETCH_ENABLE              MYNEWT_VAL(STM32_FLASH_PREFETCH_ENABLE)
+#define  INSTRUCTION_CACHE_ENABLE     MYNEWT_VAL(STM32_INSTRUCTION_CACHE_ENABLE)
+#define  DATA_CACHE_ENABLE            MYNEWT_VAL(STM32_DATA_CACHE_ENABLE)
 
 /* ########################## Assert Selection ############################## */
 /**
diff --git a/hw/bsp/nucleo-l476rg/src/system_stm32l4xx.c b/hw/bsp/nucleo-l476rg/src/system_stm32l4xx.c
deleted file mode 100644
index 2caad67..0000000
--- a/hw/bsp/nucleo-l476rg/src/system_stm32l4xx.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    system_stm32l4xx.c
-  * @author  MCD Application Team
-  * @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                    | MSI
-  *-----------------------------------------------------------------------------
-  *        SYSCLK(Hz)                             | 4000000
-  *-----------------------------------------------------------------------------
-  *        HCLK(Hz)                               | 4000000
-  *-----------------------------------------------------------------------------
-  *        AHB Prescaler                          | 1
-  *-----------------------------------------------------------------------------
-  *        APB1 Prescaler                         | 1
-  *-----------------------------------------------------------------------------
-  *        APB2 Prescaler                         | 1
-  *-----------------------------------------------------------------------------
-  *        PLL_M                                  | 1
-  *-----------------------------------------------------------------------------
-  *        PLL_N                                  | 8
-  *-----------------------------------------------------------------------------
-  *        PLL_P                                  | 7
-  *-----------------------------------------------------------------------------
-  *        PLL_Q                                  | 2
-  *-----------------------------------------------------------------------------
-  *        PLL_R                                  | 2
-  *-----------------------------------------------------------------------------
-  *        PLLSAI1_P                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI1_Q                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI1_R                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI2_P                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI2_Q                              | NA
-  *-----------------------------------------------------------------------------
-  *        PLLSAI2_R                              | NA
-  *-----------------------------------------------------------------------------
-  *        Require 48MHz for USB OTG FS,          | Disabled
-  *        SDIO and RNG clock                     |
-  *-----------------------------------------------------------------------------
-  *=============================================================================
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
-  *
-  * 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 of STMicroelectronics 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 HOLDER 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.
-  *
-  ******************************************************************************
-  */
-
-/** @addtogroup CMSIS
-  * @{
-  */
-
-/** @addtogroup stm32l4xx_system
-  * @{
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Includes
-  * @{
-  */
-
-#include "stm32l4xx.h"
-#include "mcu/cmsis_nvic.h"
-
-#if !defined  (HSE_VALUE)
-  #define HSE_VALUE    ((uint32_t)8000000) /*!< Value of the External oscillator in Hz */
-#endif /* HSE_VALUE */
-
-#if !defined  (MSI_VALUE)
-  #define MSI_VALUE    ((uint32_t)4000000) /*!< Value of the Internal oscillator in Hz*/
-#endif /* MSI_VALUE */
-
-#if !defined  (HSI_VALUE)
-  #define HSI_VALUE    ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
-#endif /* HSI_VALUE */
-
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_TypesDefinitions
-  * @{
-  */
-
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Defines
-  * @{
-  */
-
-/************************* Miscellaneous Configuration ************************/
-/*!< 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. */
-/******************************************************************************/
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Macros
-  * @{
-  */
-
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Variables
-  * @{
-  */
-  /* The SystemCoreClock variable is updated in three ways:
-      1) by calling CMSIS function SystemCoreClockUpdate()
-      2) by calling HAL API function HAL_RCC_GetHCLKFreq()
-      3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
-         Note: If you use this function to configure the system clock; then there
-               is no need to call the 2 first functions listed above, since SystemCoreClock
-               variable is updated automatically.
-  */
-  uint32_t SystemCoreClock = 4000000;
-
-  const uint8_t  AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
-  const uint8_t  APBPrescTable[8] =  {0, 0, 0, 0, 1, 2, 3, 4};
-  const uint32_t MSIRangeTable[12] = {100000, 200000, 400000, 800000, 1000000, 2000000, \
-                                      4000000, 8000000, 16000000, 24000000, 32000000, 48000000};
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_FunctionPrototypes
-  * @{
-  */
-
-/**
-  * @}
-  */
-
-/** @addtogroup STM32L4xx_System_Private_Functions
-  * @{
-  */
-
-/**
-  * @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;
-
-  /* Relocate the vector table */
-  NVIC_Relocate();
-}
-
-/**
-  * @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 MSI, SystemCoreClock will contain the MSI_VALUE(*)
-  *
-  *           - 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(*) or MSI_VALUE(*) multiplied/divided by the PLL factors.
-  *
-  *         (*) MSI_VALUE is a constant defined in stm32l4xx_hal.h file (default value
-  *             4 MHz) but the real value may vary depending on the variations
-  *             in voltage and temperature.
-  *
-  *         (**) HSI_VALUE is a constant defined in stm32l4xx_hal.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 stm32l4xx_hal.h file (default value
-  *              8 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, msirange = 0, pllvco = 0, pllr = 2, pllsource = 0, pllm = 2;
-
-  /* Get MSI Range frequency--------------------------------------------------*/
-  if((RCC->CR & RCC_CR_MSIRGSEL) == RESET)
-  { /* MSISRANGE from RCC_CSR applies */
-    msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> 8;
-  }
-  else
-  { /* MSIRANGE from RCC_CR applies */
-    msirange = (RCC->CR & RCC_CR_MSIRANGE) >> 4;
-  }
-  /*MSI frequency range in HZ*/
-  msirange = MSIRangeTable[msirange];
-
-  /* Get SYSCLK source -------------------------------------------------------*/
-  switch (RCC->CFGR & RCC_CFGR_SWS)
-  {
-    case 0x00:  /* MSI used as system clock source */
-      SystemCoreClock = msirange;
-      break;
-
-    case 0x04:  /* HSI used as system clock source */
-      SystemCoreClock = HSI_VALUE;
-      break;
-
-    case 0x08:  /* HSE used as system clock source */
-      SystemCoreClock = HSE_VALUE;
-      break;
-
-    case 0x0C:  /* PLL used as system clock  source */
-      /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
-         SYSCLK = PLL_VCO / PLLR
-         */
-      pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
-      pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4) + 1 ;
-
-      switch (pllsource)
-      {
-        case 0x02:  /* HSI used as PLL clock source */
-          pllvco = (HSI_VALUE / pllm);
-          break;
-
-        case 0x03:  /* HSE used as PLL clock source */
-          pllvco = (HSE_VALUE / pllm);
-          break;
-
-        default:    /* MSI used as PLL clock source */
-          pllvco = (msirange / pllm);
-          break;
-      }
-      pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8);
-      pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25) + 1) * 2;
-      SystemCoreClock = pllvco/pllr;
-      break;
-
-    default:
-      SystemCoreClock = msirange;
-      break;
-  }
-  /* Compute HCLK clock frequency --------------------------------------------*/
-  /* Get HCLK prescaler */
-  tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
-  /* HCLK clock frequency */
-  SystemCoreClock >>= tmp;
-}
-
-
-/**
-  * @}
-  */
-
-/**
-  * @}
-  */
-
-/**
-  * @}
-  */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/hw/bsp/nucleo-l476rg/syscfg.yml b/hw/bsp/nucleo-l476rg/syscfg.yml
index 658a453..69e781a 100644
--- a/hw/bsp/nucleo-l476rg/syscfg.yml
+++ b/hw/bsp/nucleo-l476rg/syscfg.yml
@@ -72,3 +72,26 @@ syscfg.vals:
     NFFS_FLASH_AREA: FLASH_AREA_NFFS
     COREDUMP_FLASH_AREA: FLASH_AREA_IMAGE_1
     BOOTUTIL_MAX_IMG_SECTORS: 256
+    STM32_CLOCK_VOLTAGESCALING_CONFIG: 'PWR_REGULATOR_VOLTAGE_SCALE1'
+    STM32_CLOCK_LSI: 1
+    STM32_CLOCK_LSE: 0
+    STM32_CLOCK_LSE_BYPASS: 0
+    STM32_CLOCK_MSI: 1
+    STM32_CLOCK_MSI_CALIBRATION: 'RCC_MSICALIBRATION_DEFAULT'
+    STM32_CLOCK_MSI_CLOCK_RANGE: 'RCC_MSIRANGE_8'  # 16MHz
+    STM32_CLOCK_HSI: 0
+    STM32_CLOCK_HSI_CALIBRATION: 'RCC_HSICALIBRATION_DEFAULT'
+    STM32_CLOCK_HSE: 0
+    STM32_CLOCK_HSE_BYPASS: 0
+    STM32_CLOCK_PLL_PLLM: 1   # 16 / 1 = 16MHz
+    STM32_CLOCK_PLL_PLLN: 24  # 16 * 24 = 384MHz
+    STM32_CLOCK_PLL_PLLP: 7   # 384 / 7 = 54.85MHz
+    STM32_CLOCK_PLL_PLLR: 6   # 384 / 6 = 64MHz
+    STM32_CLOCK_PLL_PLLQ: 8   # 384 / 8 = 48MHz
+    STM32_CLOCK_AHB_DIVIDER: 'RCC_SYSCLK_DIV1'
+    STM32_CLOCK_APB1_DIVIDER: 'RCC_HCLK_DIV1'
+    STM32_CLOCK_APB2_DIVIDER: 'RCC_HCLK_DIV1'
+    STM32_FLASH_LATENCY: 'FLASH_LATENCY_3'  # max 64MHz
+    STM32_FLASH_PREFETCH_ENABLE: 0
+    STM32_INSTRUCTION_CACHE_ENABLE: 1
+    STM32_DATA_CACHE_ENABLE: 1
diff --git a/hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h
index 75340f9..ce6f435 100644
--- a/hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h
@@ -28,31 +28,35 @@ extern "C" {
 
 #include "stm32l4xx_hal.h"
 #include "stm32l4xx_hal_def.h"
-
+#include "stm32l4xx.h"
+#include "stm32l4xx_hal_dma.h"
+#include "stm32l4xx_hal_spi.h"
+#include "stm32l4xx_hal_gpio.h"
+#include "stm32l4xx_hal_gpio_ex.h"
+#include "stm32l4xx_hal_rcc.h"
+#include "stm32l4xx_hal_iwdg.h"
+#include "stm32l4xx_hal_i2c.h"
+#include "stm32l4xx_hal_uart.h"
+#include "mcu/stm32l4_bsp.h"
+#include "stm32l4xx_hal_tim.h"
+#include "stm32l4xx_ll_bus.h"
+#include "stm32l4xx_ll_tim.h"
+#include "stm32l4xx_hal_def.h"
+#include "stm32l4xx_hal_flash.h"
+#include "stm32l4xx_hal_flash_ex.h"
 #include "stm32l4xx_mynewt_hal.h"
 
-/* hal_watchdog */
-#include "stm32l4xx_hal_iwdg.h"
 #define STM32_HAL_WATCHDOG_CUSTOM_INIT(x)           \
     do {                                            \
         (x)->Init.Window = IWDG_WINDOW_DISABLE;     \
     } while (0)
 
-/* hal_system_start */
 #define STM32_HAL_FLASH_REMAP()                  \
     do {                                         \
         SYSCFG->MEMRMP = 0;                      \
         __DSB();                                 \
     } while (0)
 
-/* hal_spi */
-#include "stm32l4xx.h"
-#include "stm32l4xx_hal_dma.h"
-#include "stm32l4xx_hal_spi.h"
-#include "stm32l4xx_hal_gpio.h"
-#include "stm32l4xx_hal_gpio_ex.h"
-#include "stm32l4xx_hal_rcc.h"
-
 struct stm32_hal_spi_cfg {
     int ss_pin;                     /* for slave mode */
     int sck_pin;
@@ -61,25 +65,8 @@ struct stm32_hal_spi_cfg {
     int irq_prio;
 };
 
-/* hal_i2c */
-#include "stm32l4xx_hal_i2c.h"
-#include "mcu/stm32l4xx_mynewt_hal.h"
-
-/* hal_uart */
-#include "stm32l4xx_hal_uart.h"
-#include "mcu/stm32l4_bsp.h"
-
-/* hal_timer */
-#include "stm32l4xx_hal_tim.h"
-#include "stm32l4xx_ll_bus.h"
-#include "stm32l4xx_ll_tim.h"
-
 #define STM32_HAL_TIMER_MAX     (3)
 
-/* hal_flash */
-#include "stm32l4xx_hal_def.h"
-#include "stm32l4xx_hal_flash.h"
-#include "stm32l4xx_hal_flash_ex.h"
 #define STM32_HAL_FLASH_INIT()        \
     do {                              \
         HAL_FLASH_Unlock();           \
diff --git a/hw/mcu/stm/stm32l4xx/src/clock_stm32l4xx.c b/hw/mcu/stm/stm32l4xx/src/clock_stm32l4xx.c
new file mode 100644
index 0000000..94ce0f6
--- /dev/null
+++ b/hw/mcu/stm/stm32l4xx/src/clock_stm32l4xx.c
@@ -0,0 +1,304 @@
+/*
+ * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
+ *
+ * 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 of STMicroelectronics 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 HOLDER 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.
+ */
+
+#include "stm32l4xx_hal_pwr_ex.h"
+#include "stm32l4xx_hal_rcc.h"
+#include "stm32l4xx_hal.h"
+#include <assert.h>
+
+/*
+ * This allows an user to have a custom clock configuration by zeroing
+ * every possible clock source in the syscfg.
+ */
+#if MYNEWT_VAL(STM32_CLOCK_MSI) || MYNEWT_VAL(STM32_CLOCK_HSE) || \
+    MYNEWT_VAL(STM32_CLOCK_LSE) || MYNEWT_VAL(STM32_CLOCK_HSI) || \
+    MYNEWT_VAL(STM32_CLOCK_HSI48) || MYNEWT_VAL(STM32_CLOCK_LSI)
+
+#define TRNG_ENABLED (MYNEWT_VAL(TRNG) != 0)
+
+/*
+ * HSI is turned on by default, but can be turned off and use HSE/HSI48 instead.
+ */
+#if (((MYNEWT_VAL(STM32_CLOCK_MSI) != 0) + \
+      (MYNEWT_VAL(STM32_CLOCK_HSE) != 0) + \
+      (MYNEWT_VAL(STM32_CLOCK_HSI) != 0) + \
+      (MYNEWT_VAL(STM32_CLOCK_HSI48) != 0)) < 1)
+#error "At least one of MSI, HSE, HSI or HSI48 clock sources must be enabled"
+#endif
+
+void
+SystemClock_Config(void)
+{
+    RCC_OscInitTypeDef osc_init;
+    RCC_ClkInitTypeDef clk_init;
+    HAL_StatusTypeDef status;
+#if TRNG_ENABLED
+    RCC_PeriphCLKInitTypeDef  pclk_init;
+#endif
+
+    /*
+     * The voltage scaling allows optimizing the power consumption when the
+     * device is clocked below the maximum system frequency, to update the
+     * voltage scaling value regarding system frequency refer to product
+     * datasheet.
+     */
+    __HAL_PWR_VOLTAGESCALING_CONFIG(MYNEWT_VAL(STM32_CLOCK_VOLTAGESCALING_CONFIG));
+
+    osc_init.OscillatorType = RCC_OSCILLATORTYPE_NONE;
+
+    /*
+     * LSI is used to clock the independent watchdog and optionally the RTC.
+     * It can be disabled per user request, but will be automatically enabled
+     * again when the IWDG is started.
+     *
+     * XXX currently the watchdog is not optional, so there's no point in
+     * disabling LSI through syscfg.
+     */
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_LSI;
+#if (MYNEWT_VAL(STM32_CLOCK_LSI) == 0)
+    osc_init.LSIState = RCC_LSI_OFF;
+#else
+    osc_init.LSIState = RCC_LSI_ON;
+#endif
+
+    /*
+     * LSE is only used to clock the RTC.
+     */
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_LSE;
+#if (MYNEWT_VAL(STM32_CLOCK_LSE) == 0)
+    osc_init.LSEState = RCC_LSE_OFF;
+#elif MYNEWT_VAL(STM32_CLOCK_LSE_BYPASS)
+    osc_init.LSEState = RCC_LSE_BYPASS;
+#else
+    osc_init.LSEState = RCC_LSE_ON;
+#endif
+
+    /*
+     * MSI Oscillator
+     */
+#if MYNEWT_VAL(STM32_CLOCK_MSI)
+
+#if (MYNEWT_VAL(STM32_CLOCK_MSI_CALIBRATION) > 255)
+#error "Invalid MSI calibration value"
+#endif
+#if !IS_RCC_MSI_CLOCK_RANGE(MYNEWT_VAL(STM32_CLOCK_MSI_CLOCK_RANGE))
+#error "Invalid MSI clock range"
+#endif
+
+    /* NOTE: MSI can't be disabled if it's the current PLL or SYSCLK source;
+     * leave it untouched in those cases, and disable later after a new source
+     * has been configured.
+     */
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_MSI;
+    osc_init.MSIState = RCC_MSI_ON;
+    osc_init.MSICalibrationValue = MYNEWT_VAL(STM32_CLOCK_MSI_CALIBRATION);
+    osc_init.MSIClockRange = MYNEWT_VAL(STM32_CLOCK_MSI_CLOCK_RANGE);
+#endif
+
+    /*
+     * HSE Oscillator (can be used as PLL, SYSCLK and RTC clock source)
+     */
+#if MYNEWT_VAL(STM32_CLOCK_HSE)
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSE;
+
+#if MYNEWT_VAL(STM32_CLOCK_HSE_BYPASS)
+    osc_init.HSEState = RCC_HSE_BYPASS;
+#else
+    osc_init.HSEState = RCC_HSE_ON;
+#endif
+
+#endif
+
+    /*
+     * HSI Oscillator (can be used as PLL and SYSCLK clock source). It is
+     * already turned on by default but a new calibration setting might be
+     * used. If the user chooses to turn it off, it must be turned off after
+     * SYSCLK was updated to use HSE/PLL.
+     */
+#if MYNEWT_VAL(STM32_CLOCK_HSI)
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSI;
+    osc_init.HSIState = RCC_HSI_ON;
+    /* HSI calibration is not optional when HSI is enabled */
+    osc_init.HSICalibrationValue = MYNEWT_VAL(STM32_CLOCK_HSI_CALIBRATION);
+
+#if (MYNEWT_VAL(STM32_CLOCK_HSI_CALIBRATION) > 127)
+#error "Invalid HSI calibration value"
+#endif
+#endif
+
+    /*
+     * HSI48 can be used to drive USB/SDMMC/RNG
+     */
+
+#if MYNEWT_VAL(STM32_CLOCK_HSI48) && !defined(RCC_HSI48_SUPPORT)
+#error "HSI48 is not supported on this target"
+#endif
+
+#if MYNEWT_VAL(STM32_CLOCK_HSI48)
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSI48;
+    osc_init.HSI48State = RCC_HSI48_ON;
+#endif
+
+    /*
+     * Default to MSI, HSE or HSI48 as PLL source when multiple high-speed
+     * sources are enabled.
+     */
+    osc_init.PLL.PLLState = RCC_PLL_ON;
+#if MYNEWT_VAL(STM32_CLOCK_MSI)
+    osc_init.PLL.PLLSource = RCC_PLLSOURCE_MSI;
+#elif MYNEWT_VAL(STM32_CLOCK_HSE)
+    osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSE;
+#else
+    osc_init.PLL.PLLSource = RCC_PLLSOURCE_HSI;
+#endif
+
+#if !IS_RCC_PLLM_VALUE(MYNEWT_VAL(STM32_CLOCK_PLL_PLLM))
+#error "PLLM value is invalid"
+#endif
+
+#if !IS_RCC_PLLN_VALUE(MYNEWT_VAL(STM32_CLOCK_PLL_PLLN))
+#error "PLLN value is invalid"
+#endif
+
+#if !defined(RCC_PLLP_SUPPORT) && MYNEWT_VAL(STM32_CLOCK_PLL_PLLP)
+#error "PLLP not supported on this target"
+#endif
+
+#if !IS_RCC_PLLP_VALUE(MYNEWT_VAL(STM32_CLOCK_PLL_PLLP))
+#error "PLLP value is invalid"
+#endif
+
+#if !IS_RCC_PLLQ_VALUE(MYNEWT_VAL(STM32_CLOCK_PLL_PLLQ))
+#error "PLLQ value is invalid"
+#endif
+
+#if !IS_RCC_PLLR_VALUE(MYNEWT_VAL(STM32_CLOCK_PLL_PLLR))
+#error "PLLR value is invalid"
+#endif
+
+    osc_init.PLL.PLLM = MYNEWT_VAL(STM32_CLOCK_PLL_PLLM);
+    osc_init.PLL.PLLN = MYNEWT_VAL(STM32_CLOCK_PLL_PLLN);
+    osc_init.PLL.PLLP = MYNEWT_VAL(STM32_CLOCK_PLL_PLLP);
+    osc_init.PLL.PLLQ = MYNEWT_VAL(STM32_CLOCK_PLL_PLLQ);
+    osc_init.PLL.PLLR = MYNEWT_VAL(STM32_CLOCK_PLL_PLLR);
+
+    status = HAL_RCC_OscConfig(&osc_init);
+    if (status != HAL_OK) {
+        assert(0);
+    }
+
+    /*
+     * Select PLL as system clock source and configure the HCLK*, PCLK* and
+     * SYSCLK clocks dividers. HSI, HSE and MSI are also valid system clock
+     * sources, although there is no much point in supporting them now.
+     */
+    clk_init.ClockType =  RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
+        RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
+    clk_init.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
+
+#if !IS_RCC_HCLK(MYNEWT_VAL(STM32_CLOCK_AHB_DIVIDER))
+#error "AHB clock divider is invalid"
+#endif
+
+#if !IS_RCC_PCLK(MYNEWT_VAL(STM32_CLOCK_APB1_DIVIDER))
+#error "APB1 clock divider is invalid"
+#endif
+
+#if !IS_RCC_PCLK(MYNEWT_VAL(STM32_CLOCK_APB2_DIVIDER))
+#error "APB2 clock divider is invalid"
+#endif
+
+    clk_init.AHBCLKDivider = MYNEWT_VAL(STM32_CLOCK_AHB_DIVIDER);
+    clk_init.APB1CLKDivider = MYNEWT_VAL(STM32_CLOCK_APB1_DIVIDER);
+    clk_init.APB2CLKDivider = MYNEWT_VAL(STM32_CLOCK_APB2_DIVIDER);
+
+#if !IS_FLASH_LATENCY(MYNEWT_VAL(STM32_FLASH_LATENCY))
+#error "Flash latency value is invalid"
+#endif
+
+    status = HAL_RCC_ClockConfig(&clk_init, MYNEWT_VAL(STM32_FLASH_LATENCY));
+    if (status != HAL_OK) {
+        assert(0);
+    }
+
+#if ((MYNEWT_VAL(STM32_CLOCK_HSI) == 0) || (MYNEWT_VAL(STM32_CLOCK_HSE) == 0) || \
+     (MYNEWT_VAL(STM32_CLOCK_HSI48) == 0) || (MYNEWT_VAL(STM32_CLOCK_MSI) == 0))
+    /*
+     * Turn off HSE/HSI/HSI48 oscillator; this must be done at the end because
+     * SYSCLK source has to be updated first.
+     */
+    osc_init.OscillatorType = RCC_OSCILLATORTYPE_NONE;
+#if (MYNEWT_VAL(STM32_CLOCK_HSE) == 0)
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSE;
+    osc_init.HSEState = RCC_HSE_OFF;
+#endif
+#if (MYNEWT_VAL(STM32_CLOCK_HSI) == 0)
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSI;
+    osc_init.HSIState = RCC_HSI_OFF;
+#endif
+#if (MYNEWT_VAL(STM32_CLOCK_HSI48) == 0) && defined(RCC_HSI48_SUPPORT)
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_HSI48;
+    osc_init.HSI48State = RCC_HSI48_OFF;
+#endif
+#if (MYNEWT_VAL(STM32_CLOCK_MSI) == 0)
+    osc_init.OscillatorType |= RCC_OSCILLATORTYPE_MSI;
+    osc_init.MSIState = RCC_MSI_OFF;
+#endif
+
+#endif
+
+    osc_init.PLL.PLLState = RCC_PLL_NONE;
+
+    status = HAL_RCC_OscConfig(&osc_init);
+    if (status != HAL_OK) {
+        assert(0);
+    }
+
+#if TRNG_ENABLED
+    pclk_init.PeriphClockSelection = RCC_PERIPHCLK_RNG;
+    /* Other clock sources are possible, but since right now we always
+     * configure the PLL, this should be ok
+     */
+    pclk_init.RngClockSelection = RCC_RNGCLKSOURCE_PLL;
+    status = HAL_RCCEx_PeriphCLKConfig(&pclk_init);
+    if (status != HAL_OK) {
+        assert(0);
+    }
+#endif
+
+#if PREFETCH_ENABLE
+    __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
+#endif
+
+#if INSTRUCTION_CACHE_ENABLE
+    __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
+#endif
+
+#if DATA_CACHE_ENABLE
+    __HAL_FLASH_DATA_CACHE_ENABLE();
+#endif
+}
+#endif
diff --git a/hw/mcu/stm/stm32l4xx/src/system_stm32l4xx.c b/hw/mcu/stm/stm32l4xx/src/system_stm32l4xx.c
new file mode 100644
index 0000000..1e5b5f6
--- /dev/null
+++ b/hw/mcu/stm/stm32l4xx/src/system_stm32l4xx.c
@@ -0,0 +1,213 @@
+/**
+  * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
+  * All rights reserved.</center></h2>
+  *
+  * 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
+  */
+
+#include <stdint.h>
+#include "bsp/stm32l4xx_hal_conf.h"
+#include "stm32l4xx.h"
+#include "mcu/cmsis_nvic.h"
+#include "mcu/stm32_hal.h"
+
+/* The SystemCoreClock variable is updated in three ways:
+  1) by calling CMSIS function SystemCoreClockUpdate()
+  2) by calling HAL API function HAL_RCC_GetHCLKFreq()
+  3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
+     Note: If you use this function to configure the system clock; then there
+           is no need to call the 2 first functions listed above, since SystemCoreClock
+           variable is updated automatically.
+*/
+
+uint32_t SystemCoreClock;
+const uint8_t AHBPrescTable[16] = {
+    0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U,
+};
+const uint8_t APBPrescTable[8] = {
+    0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U,
+};
+const uint32_t MSIRangeTable[12] = {
+    100000U,   200000U,   400000U,   800000U,  1000000U,  2000000U,
+    4000000U, 8000000U, 16000000U, 24000000U, 32000000U, 48000000U,
+};
+
+/*
+ * XXX BSP specific
+ */
+void SystemClock_Config(void);
+
+/**
+  * @brief  Setup the microcontroller system.
+  * @param  None
+  * @retval None
+  */
+void SystemInit(void)
+{
+    #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
+        /* set CP10 and CP11 Full Access */
+        SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2));
+    #endif
+
+    /*
+     * Reset the RCC clock configuration to the default reset state
+     */
+
+    /* Set MSION bit */
+    RCC->CR |= RCC_CR_MSION;
+
+    /* Reset CFGR register */
+    RCC->CFGR = 0x00000000U;
+
+    /* Reset HSEON, CSSON , HSION, and PLLON bits */
+    RCC->CR &= 0xEAF6FFFFU;
+
+    /* Reset PLLCFGR register */
+    RCC->PLLCFGR = 0x00001000U;
+
+    /* Reset HSEBYP bit */
+    RCC->CR &= 0xFFFBFFFFU;
+
+    /* Disable all interrupts */
+    RCC->CIER = 0x00000000U;
+
+    /* Configure System Clock */
+    SystemClock_Config();
+
+    /* Update SystemCoreClock global variable */
+    SystemCoreClockUpdate();
+
+    /* Relocate the vector table */
+    NVIC_Relocate();
+}
+
+/**
+  * @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 MSI, SystemCoreClock will contain the MSI_VALUE(*)
+  *
+  *           - 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(*) or MSI_VALUE(*) multiplied/divided by the PLL factors.
+  *
+  *         (*) MSI_VALUE is a constant defined in stm32l4xx_hal.h file (default value
+  *             4 MHz) but the real value may vary depending on the variations
+  *             in voltage and temperature.
+  *
+  *         (**) HSI_VALUE is a constant defined in stm32l4xx_hal.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 stm32l4xx_hal.h file (default value
+  *              8 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;
+    uint32_t msirange;
+    uint32_t pllvco;
+    uint32_t pllr;
+    uint32_t pllsource;
+    uint32_t pllm;
+
+    /*
+     * Get MSI Range frequency
+     */
+
+    if ((RCC->CR & RCC_CR_MSIRGSEL) == RESET) {
+        /* MSISRANGE from RCC_CSR applies */
+        msirange = (RCC->CSR & RCC_CSR_MSISRANGE) >> 8U;
+    } else {
+        /* MSIRANGE from RCC_CR applies */
+        msirange = (RCC->CR & RCC_CR_MSIRANGE) >> 4U;
+    }
+
+    /* MSI frequency range in HZ */
+    msirange = MSIRangeTable[msirange];
+
+    /*
+     * Get SYSCLK source
+     */
+    switch (RCC->CFGR & RCC_CFGR_SWS) {
+    /* HSI used as system clock source */
+    case 0x04:
+        SystemCoreClock = HSI_VALUE;
+        break;
+
+    /* HSE used as system clock source */
+    case 0x08:
+        SystemCoreClock = HSE_VALUE;
+        break;
+
+    /* PLL used as system clock source */
+    case 0x0C:
+        /* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
+         * SYSCLK = PLL_VCO / PLLR
+         */
+        pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC);
+        pllm = ((RCC->PLLCFGR & RCC_PLLCFGR_PLLM) >> 4U) + 1U;
+
+        switch (pllsource) {
+        /* HSI used as PLL clock source */
+        case 0x02:
+            pllvco = (HSI_VALUE / pllm);
+            break;
+
+        /* HSE used as PLL clock source */
+        case 0x03:
+            pllvco = (HSE_VALUE / pllm);
+            break;
+
+        /* MSI used as PLL clock source */
+        default:
+            pllvco = (msirange / pllm);
+            break;
+        }
+
+        pllvco = pllvco * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 8U);
+        pllr = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLR) >> 25U) + 1U) * 2U;
+        SystemCoreClock = pllvco / pllr;
+        break;
+
+    default:
+        SystemCoreClock = msirange;
+        break;
+    }
+
+    /*
+     * Compute HCLK clock frequency
+     */
+
+    /* Get HCLK prescaler */
+    tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4U)];
+
+    /* HCLK clock frequency */
+    SystemCoreClock >>= tmp;
+}
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/hw/mcu/stm/stm32l4xx/syscfg.yml b/hw/mcu/stm/stm32l4xx/syscfg.yml
index 73c3ced..375368b 100644
--- a/hw/mcu/stm/stm32l4xx/syscfg.yml
+++ b/hw/mcu/stm/stm32l4xx/syscfg.yml
@@ -63,6 +63,102 @@ syscfg.defs:
         description: MCUs are of STM32L4xx family
         value: 1
 
+    STM32_CLOCK_VOLTAGESCALING_CONFIG:
+        description: Adjust voltage scale
+        value: 0
+
+    STM32_CLOCK_LSI:
+        description: Enable low-speed internal clock source
+        value: 0
+
+    STM32_CLOCK_LSE:
+        description: Enable low-speed external clock source (aka RTC xtal)
+        value: 0
+
+    STM32_CLOCK_LSE_BYPASS:
+        description: 0 for 32768 xtal; 1 for input clock
+        value: 0
+
+    STM32_CLOCK_MSI:
+        description: Enable multi-speed internal clock source
+        value: 1
+
+    STM32_CLOCK_MSI_CALIBRATION:
+        description: MSI calibration value
+        value: 'RCC_MSICALIBRATION_DEFAULT'
+
+    STM32_CLOCK_MSI_CLOCK_RANGE:
+        description: MSI clock range
+        value: 'RCC_MSICALIBRATION_DEFAULT'
+
+    STM32_CLOCK_HSE:
+        description: Enable high-speed external clock source
+        value: 0
+
+    STM32_CLOCK_HSE_BYPASS:
+        description: 0 for xtal; 1 for input clock
+        value: 0
+
+    STM32_CLOCK_HSI:
+        description: Enable high-speed internal clock source
+        value: 1
+
+    STM32_CLOCK_HSI_CALIBRATION:
+        description: HSI calibration value
+        value: 'RCC_HSICALIBRATION_DEFAULT'
+
+    STM32_CLOCK_HSI48:
+        description: Enable high-speed 48MHz internal clock source
+        value: 0
+
+    STM32_CLOCK_PLL_PLLM:
+        description: PLL config M parameter
+        value: 0
+
+    STM32_CLOCK_PLL_PLLN:
+        description: PLL config N parameter
+        value: 0
+
+    STM32_CLOCK_PLL_PLLP:
+        description: PLL config P parameter
+        value: 0
+
+    STM32_CLOCK_PLL_PLLQ:
+        description: PLL config Q parameter
+        value: 0
+
+    STM32_CLOCK_PLL_PLLR:
+        description: PLL config R parameter
+        value: 0
+
+    STM32_CLOCK_AHB_DIVIDER:
+        description: AHB CLK1 prescaler (64MHz max)
+        value: 0
+
+    STM32_CLOCK_APB1_DIVIDER:
+        description: APB low-speed prescaler (64MHz max)
+        value: 0
+
+    STM32_CLOCK_APB2_DIVIDER:
+        description: APB high-speed prescaler (64MHz max)
+        value: 0
+
+    STM32_FLASH_LATENCY:
+        description: Number of wait-states
+        value: 0
+
+    STM32_FLASH_PREFETCH_ENABLE:
+        description: Enable pre-fetch of instructions (when latency > 0)
+        value: 0
+
+    STM32_INSTRUCTION_CACHE_ENABLE:
+        description: Enable flash instruction cache
+        value: 0
+
+    STM32_DATA_CACHE_ENABLE:
+        description: Enable flash data cache
+        value: 0
+
     STM32_HAL_SPI_HAS_FIFO:
         description: This MCU has a SPI with FIFO
         value: 1