diff --git a/boards/b-l475e-iot01a/include/periph_conf.h b/boards/b-l475e-iot01a/include/periph_conf.h
index 2045267b41597d29d5e9c7afa8a8e2090b7ea894..d5bebd9ce82a7ec43f36be78eaf9bd1d06b709bb 100644
--- a/boards/b-l475e-iot01a/include/periph_conf.h
+++ b/boards/b-l475e-iot01a/include/periph_conf.h
@@ -35,6 +35,12 @@ extern "C" {
 /* 0: no external low speed crystal available,
  * 1: external crystal available (always 32.768kHz) */
 #define CLOCK_LSE           (1)
+/* 0: enable MSI only if HSE isn't available
+ * 1: always enable MSI (e.g. if USB or RNG is used)*/
+#define CLOCK_MSI_ENABLE    (1)
+/* 0: disable Hardware auto calibration with LSE
+ * 1: enable Hardware auto calibration with LSE (PLL-mode)*/
+#define CLOCK_MSI_LSE_PLL   (1)
 /* give the target core clock (HCLK) frequency [in Hz], maximum: 80MHz */
 #define CLOCK_CORECLOCK     (80000000U)
 /* PLL configuration: make sure your values are legit!
diff --git a/boards/nucleo-l476/include/periph_conf.h b/boards/nucleo-l476/include/periph_conf.h
index 02e6859a7f874e8b8fac28b3ee6269f32c0b1579..8d82cf625fe45a5e1eb22bbaaa397e58d55272c1 100644
--- a/boards/nucleo-l476/include/periph_conf.h
+++ b/boards/nucleo-l476/include/periph_conf.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2017 Freie Universität Berlin
  *               2017 Inria
+ *               2017 HAW-Hamburg
  *
  * This file is subject to the terms and conditions of the GNU Lesser
  * General Public License v2.1. See the file LICENSE in the top level
@@ -16,6 +17,7 @@
  *
  * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
  * @author      Alexandre Abadie <alexandre.abadie@inria.fr>
+ * @author      Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
  */
 
 #ifndef PERIPH_CONF_H
@@ -34,9 +36,28 @@ extern "C" {
 /* 0: no external high speed crystal available
  * else: actual crystal frequency [in Hz] */
 #define CLOCK_HSE           (0)
+
+#ifndef CLOCK_LSE
 /* 0: no external low speed crystal available,
- * 1: external crystal available (always 32.768kHz) */
-#define CLOCK_LSE           (1)
+ * 1: external crystal available (always 32.768kHz)
+ * This defaults to 0 because hardware revision 'MB1136 C-01' of the nucleo-64
+ * board disconnects LSE by default. You may safely set this to 1 on revisions
+ * newer than 'MB1136 C-01' */
+#define CLOCK_LSE           (0)
+#endif
+
+/* 0: enable MSI only if HSE isn't available
+ * 1: always enable MSI (e.g. if USB or RNG is used)*/
+#define CLOCK_MSI_ENABLE    (1)
+
+#ifndef CLOCK_MSI_LSE_PLL
+/* 0: disable Hardware auto calibration with LSE
+ * 1: enable Hardware auto calibration with LSE (PLL-mode)
+ * Same as with CLOCK_LSE above this defaults to 0 because LSE is
+ * mandatory for MSI/LSE-trimming to work */
+#define CLOCK_MSI_LSE_PLL   (0)
+#endif
+
 /* give the target core clock (HCLK) frequency [in Hz], maximum: 80MHz */
 #define CLOCK_CORECLOCK     (80000000U)
 /* PLL configuration: make sure your values are legit!
diff --git a/boards/nucleo32-l432/include/periph_conf.h b/boards/nucleo32-l432/include/periph_conf.h
index 4fde7270e5b97db4b8c746895e5a204d5a357d68..2ddb8da62419ec9c2253c6d5b6ad1221725ec4ef 100644
--- a/boards/nucleo32-l432/include/periph_conf.h
+++ b/boards/nucleo32-l432/include/periph_conf.h
@@ -36,6 +36,12 @@ extern "C" {
 /* 0: no external low speed crystal available,
  * 1: external crystal available (always 32.768kHz) */
 #define CLOCK_LSE           (1)
+/* 0: enable MSI only if HSE isn't available
+ * 1: always enable MSI (e.g. if USB or RNG is used)*/
+#define CLOCK_MSI_ENABLE    (1)
+/* 0: disable Hardware auto calibration with LSE
+ * 1: enable Hardware auto calibration with LSE (PLL-mode)*/
+#define CLOCK_MSI_LSE_PLL   (1)
 /* give the target core clock (HCLK) frequency [in Hz], maximum: 80MHz */
 #define CLOCK_CORECLOCK     (80000000U)
 /* PLL configuration: make sure your values are legit!
diff --git a/cpu/stm32l4/cpu.c b/cpu/stm32l4/cpu.c
index b96b37d71b85316ee7b680ad1e8afb6ae8151bfa..66727deaff016566a7937d4b126e8ac224b54a2d 100644
--- a/cpu/stm32l4/cpu.c
+++ b/cpu/stm32l4/cpu.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2017 Freie Universität Berlin
+ *               2017 HAW-Hamburg
  *
  * This file is subject to the terms and conditions of the GNU Lesser
  * General Public License v2.1. See the file LICENSE in the top level
@@ -15,150 +16,15 @@
  *
  * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
  * @author      Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
+ * @author      Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
  * @}
  */
 
 #include <stdint.h>
 #include "cpu.h"
-#include "irq.h"
 #include "stmclk.h"
-#include "periph_conf.h"
 #include "periph/init.h"
 
-/* make sure we have all needed information about the clock configuration */
-#ifndef CLOCK_HSE
-#error "Please provide CLOCK_HSE in your board's perhip_conf.h"
-#endif
-#ifndef CLOCK_LSE
-#error "Please provide CLOCK_LSE in your board's periph_conf.h"
-#endif
-#if !defined(CLOCK_PLL_M) || !defined(CLOCK_PLL_N) || !defined(CLOCK_PLL_R)
-#error "Please provide the PLL configuration in your board's periph_conf.h"
-#endif
-
-/**
- * @name    PLL configuration
- * @{
- */
-/* figure out which input to use */
-#if (CLOCK_HSE)
-#define PLL_IN                      CLOCK_HSE
-#define PLL_SRC                     RCC_PLLCFGR_PLLSRC_HSE
-#else
-#define PLL_IN                      (48000000)      /* MSI @ 48MHz */
-#define PLL_SRC                     RCC_PLLCFGR_PLLSRC_MSI
-#endif
-
-/**check configuration and get the corresponding bitfields */
-#if (CLOCK_PLL_M < 1 || CLOCK_PLL_M > 8)
-#error "PLL configuration: PLL M value is out of range"
-#endif
-#define PLL_M                       ((CLOCK_PLL_M - 1) << RCC_PLLCFGR_PLLM_Pos)
-
-#if (CLOCK_PLL_N < 8 || CLOCK_PLL_N > 86)
-#error "PLL configuration: PLL N value is out of range"
-#endif
-#define PLL_N                       (CLOCK_PLL_N << RCC_PLLCFGR_PLLN_Pos)
-
-#if (CLOCK_PLL_R == 2)
-#define PLL_R                       (0)
-#elif (CLOCK_PLL_R == 4)
-#define PLL_R                       (RCC_PLLCFGR_PLLR_0)
-#elif (CLOCK_PLL_R == 6)
-#define PLL_R                       (RCC_PLLCFGR_PLLR_1)
-#elif (CLOCK_PLL_R == 8)
-#define PLL_R                       (RCC_PLLCFGR_PLLR_0 | RCC_PLLCFGR_PLLR_1)
-#else
-#error "PLL configuration: PLL R value is invalid"
-#endif
-/** @} */
-
-/**
- * @name    Deduct the needed flash wait states from the core clock frequency
- * @{
- */
-#if (CLOCK_CORECLOCK <= 16000000)
-#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_0WS
-#elif (CLOCK_CORECLOCK <= 32000000)
-#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_1WS
-#elif (CLOCK_CORECLOCK <= 48000000)
-#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_2WS
-#elif (CLOCK_CORECLOCK <= 64000000)
-#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_3WS
-#else
-#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_4WS
-#endif
-/** @} */
-
-/**
- * @brief   Configure the STM32L4's clock system
- *
- * We use the following configuration:
- * - we always enable the 32kHz low speed clock (LSI or LSE)
- * - we configure the MSI clock to 48MHz (for USB and RNG) and enable it
- * - if LSE present, we use it to stabilize the 48MHz MSI clock (MSIPLLEN)
- * - use either MSI @ 48MHz or HSE (4 to 48MHZ) as base clock
- * - we use the PLL as main clock provider
- * - we don't enable any ASI clock
- *
- * For the computation of the PLL configuration, see defines above.
- */
-static void cpu_clock_init(void)
-{
-    /* disable any interrupts. Global interrupts could be enabled if this is
-     * called from some kind of bootloader...  */
-    unsigned is = irq_disable();
-    RCC->CIER = 0;
-
-    /* for the duration of the configuration, we fall-back to the maximum number
-     * of flash wait states */
-    FLASH->ACR = (FLASH_ACR_LATENCY_4WS);
-
-    /* reset clock to MSI with 48MHz, disables all other clocks */
-    RCC->CR = (RCC_CR_MSIRANGE_11 | RCC_CR_MSION | RCC_CR_MSIRGSEL);
-    while (!(RCC->CR & RCC_CR_MSIRDY)) {}
-
-    /* use MSI as system clock while we do any further configuration and
-     * configure the AHB and APB clock dividers as configure by the board */
-    RCC->CFGR = (RCC_CFGR_SW_MSI | CLOCK_AHB_DIV |
-                 CLOCK_APB1_DIV | CLOCK_APB2_DIV);
-    while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_MSI) {}
-
-    /* configure the low speed clock domain (LSE vs LSI) */
-#if CLOCK_LSE
-    /* we enable the LSE clock if available for calibrating the MSI clock */
-    stmclk_enable_lfclk();
-    /* now we can enable the MSI PLL mode */
-    RCC->CR |= RCC_CR_MSIPLLEN;
-    while (!(RCC->CR & RCC_CR_MSIRDY)) {}
-#endif
-
-    /* select the MSI clock for the 48MHz clock tree (USB, RNG) */
-    RCC->CCIPR = (RCC_CCIPR_CLK48SEL_0 | RCC_CCIPR_CLK48SEL_1);
-
-    /* if configured: enable the HSE clock */
-#if CLOCK_HSE
-    RCC->CR |= RCC_CR_HSEON;
-    while (!(RCC->CR & RCC_CR_HSERDY)) {}
-#endif
-
-    /* next we configure and enable the PLL */
-    RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_R | RCC_PLLCFGR_PLLREN);
-    RCC->CR |= RCC_CR_PLLON;
-    while (!(RCC->CR & RCC_CR_PLLRDY)) {}
-
-    /* now tell the system to use the PLL as main clock */
-    RCC->CFGR |= RCC_CFGR_SW_PLL;
-    while ((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) {}
-
-    /* finally we enable I+D cashes, pre-fetch, and we set the actual number of
-     * needed flash wait states */
-    FLASH->ACR = (FLASH_ACR_ICEN | FLASH_ACR_DCEN |
-                  FLASH_ACR_PRFTEN | FLASH_WAITSTATES);
-
-    irq_restore(is);
-}
-
 /**
  * @brief   Initialize the CPU, set IRQ priorities
  */
@@ -167,7 +33,7 @@ void cpu_init(void)
     /* initialize the Cortex-M core */
     cortexm_init();
     /* initialize the clock system */
-    cpu_clock_init();
+    stmclk_init_sysclk();
     /* trigger static peripheral initialization */
     periph_init();
 }
diff --git a/cpu/stm32l4/stmclk.c b/cpu/stm32l4/stmclk.c
new file mode 100644
index 0000000000000000000000000000000000000000..d40df4e00c991f61ad7ac1ebcf05d0ce30efdfcf
--- /dev/null
+++ b/cpu/stm32l4/stmclk.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2017 Freie Universität Berlin
+ *               2017 OTA keys S.A.
+ *               2017 HAW-Hamburg
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     cpu_stm32l4
+ * @{
+ *
+ * @file
+ * @brief       Implementation of STM32 clock configuration
+ *
+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
+ * @author      Nick van IJzendoorn <nijzendoorn@engineering-spirit.nl>
+ * @author      Vincent Dupont <vincent@otakeys.com>
+ * @author      Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
+ * @}
+ */
+
+#include "cpu.h"
+#include "stmclk.h"
+#include "periph_conf.h"
+
+/* make sure we have all needed information about the clock configuration */
+#ifndef CLOCK_HSE
+#error "Please provide CLOCK_HSE in your board's perhip_conf.h"
+#endif
+#ifndef CLOCK_LSE
+#error "Please provide CLOCK_LSE in your board's periph_conf.h"
+#endif
+#if !defined(CLOCK_PLL_M) || !defined(CLOCK_PLL_N) || !defined(CLOCK_PLL_R)
+#error "Please provide the PLL configuration in your board's periph_conf.h"
+#endif
+
+/**
+ * @name    PLL configuration
+ * @{
+ */
+/* figure out which input to use */
+#if (CLOCK_HSE)
+#define PLL_IN                      CLOCK_HSE
+#define PLL_SRC                     RCC_PLLCFGR_PLLSRC_HSE
+#else
+#define PLL_IN                      (48000000) /* MSI @ 48MHz */
+#define PLL_SRC                     RCC_PLLCFGR_PLLSRC_MSI
+#endif
+
+/**check configuration and get the corresponding bitfields */
+#if (CLOCK_PLL_M < 1 || CLOCK_PLL_M > 8)
+#error "PLL configuration: PLL M value is out of range"
+#endif
+#define PLL_M                       ((CLOCK_PLL_M - 1) << RCC_PLLCFGR_PLLM_Pos)
+
+#if (CLOCK_PLL_N < 8 || CLOCK_PLL_N > 86)
+#error "PLL configuration: PLL N value is out of range"
+#endif
+#define PLL_N                       (CLOCK_PLL_N << RCC_PLLCFGR_PLLN_Pos)
+
+#if (CLOCK_PLL_R == 2)
+#define PLL_R                       (0)
+#elif (CLOCK_PLL_R == 4)
+#define PLL_R                       (RCC_PLLCFGR_PLLR_0)
+#elif (CLOCK_PLL_R == 6)
+#define PLL_R                       (RCC_PLLCFGR_PLLR_1)
+#elif (CLOCK_PLL_R == 8)
+#define PLL_R                       (RCC_PLLCFGR_PLLR_0 | RCC_PLLCFGR_PLLR_1)
+#else
+#error "PLL configuration: PLL R value is invalid"
+#endif
+/** @} */
+
+/**
+ * @name    Deduct the needed flash wait states from the core clock frequency
+ * @{
+ */
+#if (CLOCK_CORECLOCK <= 16000000)
+#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_0WS
+#elif (CLOCK_CORECLOCK <= 32000000)
+#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_1WS
+#elif (CLOCK_CORECLOCK <= 48000000)
+#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_2WS
+#elif (CLOCK_CORECLOCK <= 64000000)
+#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_3WS
+#else
+#define FLASH_WAITSTATES            FLASH_ACR_LATENCY_4WS
+#endif
+/** @} */
+
+void stmclk_init_sysclk(void)
+{
+    /* disable any interrupts. Global interrupts could be enabled if this is
+     * called from some kind of bootloader...  */
+    unsigned is = irq_disable();
+    RCC->CIER = 0;
+
+    /* enable HSI clock for the duration of initialization */
+    stmclk_enable_hsi();
+
+    /* use HSI as system clock while we do any further configuration and
+     * configure the AHB and APB clock dividers as configure by the board */
+    RCC->CFGR = (RCC_CFGR_SW_HSI | CLOCK_AHB_DIV |
+                 CLOCK_APB1_DIV | CLOCK_APB2_DIV);
+    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI) {}
+
+    /* we enable I+D cashes, pre-fetch, and we set the actual number of
+     * needed flash wait states */
+    FLASH->ACR = (FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN |
+                  FLASH_WAITSTATES);
+
+    /* disable all active clocks except HSI -> resets the clk configuration
+     * Note: on STM32L4x5 & STM32L4x6 this disables the following:
+             PLLSAI2, PLLSAI1, Main PLL (via PLLON),
+             Clock security system (via CSSON), MSI clock PLL (via MSIPLLEN),
+             HSE crystal oscillator bypass (via HSEBYP), HSE,
+             HSI16 automatic start from Stop (via HSIASFS),
+             HSI16 always enable for peripheral kernels (via HSIKERON).
+
+             Additionally it configures the MSI clock range (MSIRANGE) to
+             ~100 kHz and the MSI clock to be based on MSISRANGE in RCC_CSR
+             (instead of MSIRANGE in the RCC_CR) */
+    RCC->CR = (RCC_CR_HSION);
+
+#if (CLOCK_HSE)
+    /* if configured, we need to enable the HSE clock now */
+    RCC->CR |= (RCC_CR_HSEON);
+    while (!(RCC->CR & RCC_CR_HSERDY)) {}
+#endif
+
+#if ((CLOCK_HSE == 0) || CLOCK_MSI_ENABLE)
+    /* reset clock to MSI with 48MHz, disables all other clocks */
+    RCC->CR = (RCC_CR_MSIRANGE_11 | RCC_CR_MSION | RCC_CR_MSIRGSEL);
+    while (!(RCC->CR & RCC_CR_MSIRDY)) {}
+    /* select the MSI clock for the 48MHz clock tree (USB, RNG) */
+    RCC->CCIPR = (RCC_CCIPR_CLK48SEL_0 | RCC_CCIPR_CLK48SEL_1);
+#if (CLOCK_MSI_LSE_PLL && CLOCK_LSE)
+    /* configure the low speed clock domain */
+    stmclk_enable_lfclk();
+    /* now we can enable the MSI PLL mode to enhance accuracy of the MSI*/
+    RCC->CR |= RCC_CR_MSIPLLEN;
+    while (!(RCC->CR & RCC_CR_MSIRDY)) {}
+#endif /* (CLOCK_MSI_LSE_PLL && CLOCK_LSE) */
+#endif /* ((CLOCK_HSE == 0) || CLOCK_MSI_ENABLE) */
+
+    /* now we can safely configure and start the PLL */
+    RCC->PLLCFGR = (PLL_SRC | PLL_M | PLL_N | PLL_R | RCC_PLLCFGR_PLLREN);
+    RCC->CR |= (RCC_CR_PLLON);
+    while (!(RCC->CR & RCC_CR_PLLRDY)) {}
+
+    /* now that the PLL is running, we use it as system clock */
+    RCC->CFGR |= (RCC_CFGR_SW_PLL);
+    while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL) {}
+
+    stmclk_disable_hsi();
+    irq_restore(is);
+}