diff --git a/cpu/stm32_common/include/periph_cpu_common.h b/cpu/stm32_common/include/periph_cpu_common.h
index 31e454ddd9e37e40816b39e569eee1da79aed888..95fa6df5927bacff41d9ff85adf71c6b05185a33 100644
--- a/cpu/stm32_common/include/periph_cpu_common.h
+++ b/cpu/stm32_common/include/periph_cpu_common.h
@@ -80,6 +80,14 @@ extern "C" {
 #if defined(CPU_FAM_STM32F1) || defined(CPU_FAM_STM32F2) \
     || defined(CPU_FAM_STM32F4) || defined(DOXYGEN)
 #define PM_NUM_MODES    (2U)
+
+/**
+ * @name    Power modes
+ * @{
+ */
+#define STM32_PM_STOP         (1U)
+#define STM32_PM_STANDBY      (0U)
+/** @} */
 #endif
 
 /**
diff --git a/cpu/stm32_common/periph/pm.c b/cpu/stm32_common/periph/pm.c
index c3a1339dbd42ef2c76a6ee20feef831c04b8d87a..82caa6e8796868f2a9a9e22c611992eda9023138 100644
--- a/cpu/stm32_common/periph/pm.c
+++ b/cpu/stm32_common/periph/pm.c
@@ -49,7 +49,7 @@ void pm_set(unsigned mode)
  * others... /KS */
 #if defined(CPU_FAM_STM32F1) || defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4)
     switch (mode) {
-        case 0:
+        case STM32_PM_STANDBY:
             /* Set PDDS to enter standby mode on deepsleep and clear flags */
             PWR->CR |= (PWR_CR_PDDS | PWR_CR_CWUF | PWR_CR_CSBF);
             /* Enable WKUP pin to use for wakeup from standby mode */
@@ -57,7 +57,7 @@ void pm_set(unsigned mode)
             /* Set SLEEPDEEP bit of system control block */
             deep = 1;
             break;
-        case 1:                 /* STM Stop mode */
+        case STM32_PM_STOP:
             /* Clear PDDS and LPDS bits to enter stop mode on */
             /* deepsleep with voltage regulator on */
             PWR->CR &= ~(PWR_CR_PDDS | PWR_CR_LPDS);
diff --git a/cpu/stm32_common/periph/spi.c b/cpu/stm32_common/periph/spi.c
index 843ed87439120a2b5f88403b6208d2246d191123..9cc5fc2a5ea78599e706c3ff6bf5bdc2aaeedad5 100644
--- a/cpu/stm32_common/periph/spi.c
+++ b/cpu/stm32_common/periph/spi.c
@@ -30,6 +30,7 @@
 #include "mutex.h"
 #include "assert.h"
 #include "periph/spi.h"
+#include "pm_layered.h"
 
 /**
  * @brief   Number of bits to shift the BR value in the CR1 register
@@ -119,6 +120,10 @@ int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
 {
     /* lock bus */
     mutex_lock(&locks[bus]);
+#ifdef STM32_PM_STOP
+    /* block STOP mode */
+    pm_block(STM32_PM_STOP);
+#endif
     /* enable SPI device clock */
     periph_clk_en(spi_config[bus].apbbus, spi_config[bus].rccmask);
     /* enable device */
@@ -140,6 +145,10 @@ void spi_release(spi_t bus)
     dev(bus)->CR1 = 0;
     dev(bus)->CR2 &= ~(SPI_CR2_SSOE);
     periph_clk_dis(spi_config[bus].apbbus, spi_config[bus].rccmask);
+#ifdef STM32_PM_STOP
+    /* unblock STOP mode */
+    pm_unblock(STM32_PM_STOP);
+#endif
     mutex_unlock(&locks[bus]);
 }
 
diff --git a/cpu/stm32_common/periph/uart.c b/cpu/stm32_common/periph/uart.c
index f5e76ae22639f270d795962455bea5ee57592030..2c67d35d79c18205d7363dfcf382f6ac516346a8 100644
--- a/cpu/stm32_common/periph/uart.c
+++ b/cpu/stm32_common/periph/uart.c
@@ -30,6 +30,7 @@
 #include "assert.h"
 #include "periph/uart.h"
 #include "periph/gpio.h"
+#include "pm_layered.h"
 
 #define RXENABLE            (USART_CR1_RE | USART_CR1_RXNEIE)
 
@@ -85,7 +86,7 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
 #endif
 
     /* enable the clock */
-    periph_clk_en(uart_config[uart].bus, uart_config[uart].rcc_mask);
+    uart_poweron(uart);
 
     /* reset UART configuration -> defaults to 8N1 mode */
     dev(uart)->CR1 = 0;
@@ -147,13 +148,24 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
 void uart_poweron(uart_t uart)
 {
     assert(uart < UART_NUMOF);
+#ifdef STM32_PM_STOP
+    if (isr_ctx[uart].rx_cb) {
+        pm_block(STM32_PM_STOP);
+    }
+#endif
     periph_clk_en(uart_config[uart].bus, uart_config[uart].rcc_mask);
 }
 
 void uart_poweroff(uart_t uart)
 {
     assert(uart < UART_NUMOF);
-    periph_clk_en(uart_config[uart].bus, uart_config[uart].rcc_mask);
+
+    periph_clk_dis(uart_config[uart].bus, uart_config[uart].rcc_mask);
+#ifdef STM32_PM_STOP
+    if (isr_ctx[uart].rx_cb) {
+        pm_unblock(STM32_PM_STOP);
+    }
+#endif
 }
 
 static inline void irq_handler(uart_t uart)
diff --git a/cpu/stm32f4/periph/i2c.c b/cpu/stm32f4/periph/i2c.c
index be3a2294e257d687bd4cbeeddafd9fb599095bf1..d15f915c3e6ec08303647f9e4865b2c05b4df612 100644
--- a/cpu/stm32f4/periph/i2c.c
+++ b/cpu/stm32f4/periph/i2c.c
@@ -32,6 +32,7 @@
 #include "mutex.h"
 #include "periph_conf.h"
 #include "periph/i2c.h"
+#include "pm_layered.h"
 
 #define ENABLE_DEBUG    (0)
 #include "debug.h"
@@ -227,6 +228,8 @@ int i2c_acquire(i2c_t dev)
         return -1;
     }
     mutex_lock(&locks[dev]);
+    /* block STOP mode */
+    pm_block(STM32_PM_STOP);
     return 0;
 }
 
@@ -235,6 +238,8 @@ int i2c_release(i2c_t dev)
     if (dev >= I2C_NUMOF) {
         return -1;
     }
+    /* unblock STOP mode */
+    pm_unblock(STM32_PM_STOP);
     mutex_unlock(&locks[dev]);
     return 0;
 }