diff --git a/cpu/stm32_common/Makefile.include b/cpu/stm32_common/Makefile.include
index e172bfbacf5f900550d44cf51c9959147e221bb6..1bb08442965d40b627c00d8de83db9d7478a2dc6 100644
--- a/cpu/stm32_common/Makefile.include
+++ b/cpu/stm32_common/Makefile.include
@@ -8,6 +8,12 @@ USEMODULE += periph_common
 # include stm32 common functions and stm32 common periph drivers
 USEMODULE += stm32_common stm32_common_periph
 
+# flashpage and eeprom periph implementations share flash lock/unlock functions
+# in periph_flash_common
+ifneq (,$(filter periph_flashpage periph_eeprom,$(FEATURES_REQUIRED)))
+  FEATURES_REQUIRED += periph_flash_common
+endif
+
 # For stm32 cpu's we use the stm32_common.ld linker script
 export LINKFLAGS += -L$(RIOTCPU)/stm32_common/ldscripts
 LINKER_SCRIPT ?= stm32_common.ld
diff --git a/cpu/stm32_common/periph/eeprom.c b/cpu/stm32_common/periph/eeprom.c
new file mode 100644
index 0000000000000000000000000000000000000000..470ae47276ca167a6d9725ccecdd205d594e9607
--- /dev/null
+++ b/cpu/stm32_common/periph/eeprom.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 Inria
+ *
+ * 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_stm32_common
+ * @ingroup     drivers_periph_eeprom
+ * @{
+ *
+ * @file
+ * @brief       Low-level eeprom driver implementation
+ *
+ * @author      Alexandre Abadie <alexandre.abadie@inria.fr>
+ *
+ * @}
+ */
+
+#include <assert.h>
+
+#include "cpu.h"
+
+#define ENABLE_DEBUG        (0)
+#include "debug.h"
+
+#include "periph/eeprom.h"
+
+extern void _lock(void);
+extern void _unlock(void);
+
+#ifndef EEPROM_START_ADDR
+#error "periph/eeprom: EEPROM_START_ADDR is not defined"
+#endif
+
+uint8_t eeprom_read_byte(uint32_t pos)
+{
+    assert(pos < EEPROM_SIZE);
+
+    DEBUG("Reading data from EEPROM at pos %lu\n", pos);
+    return *(uint8_t *)(EEPROM_START_ADDR + pos);
+}
+
+void eeprom_write_byte(uint32_t pos, uint8_t data)
+{
+    assert(pos < EEPROM_SIZE);
+
+    DEBUG("Writing data '%c' to EEPROM at pos %lu\n", data, pos);
+    _unlock();
+    *(uint8_t *)(EEPROM_START_ADDR + pos) = data;
+    _lock();
+}
diff --git a/cpu/stm32_common/periph/flash_common.c b/cpu/stm32_common/periph/flash_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..34f92e75f06fcf084e8485c88eb02733d881d529
--- /dev/null
+++ b/cpu/stm32_common/periph/flash_common.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 Inria
+ *
+ * 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_stm32_common
+ * @{
+ *
+ * @file
+ * @brief       Low-level flash lock/unlock implementation
+ *
+ * @author      Alexandre Abadie <alexandre.abadie@inria.fr>
+ *
+ * @}
+ */
+
+#include "cpu.h"
+
+#define ENABLE_DEBUG        (0)
+#include "debug.h"
+
+#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
+/* Data EEPROM and control register unlock keys */
+#define FLASH_KEY1             ((uint32_t)0x89ABCDEF)
+#define FLASH_KEY2             ((uint32_t)0x02030405)
+#define CNTRL_REG              (FLASH->PECR)
+#define CNTRL_REG_LOCK         (FLASH_PECR_PELOCK)
+#define KEY_REG                (FLASH->PEKEYR)
+#else
+#define CNTRL_REG              (FLASH->CR)
+#define CNTRL_REG_LOCK         (FLASH_CR_LOCK)
+#define KEY_REG                (FLASH->KEYR)
+#endif
+
+void _unlock(void)
+{
+    DEBUG("[flash-common] unlocking the flash module\n");
+    if (CNTRL_REG & CNTRL_REG_LOCK) {
+        KEY_REG = FLASH_KEY1;
+        KEY_REG = FLASH_KEY2;
+    }
+}
+
+void _lock(void)
+{
+    DEBUG("[flash-common] locking the flash module\n");
+    CNTRL_REG |= CNTRL_REG_LOCK;
+}
diff --git a/cpu/stm32_common/periph/flashpage.c b/cpu/stm32_common/periph/flashpage.c
index 1884579c11c0b6ab77ed68ef6327d8404acc8607..e4454b18183b3cbb6a8c5e0ce1589a8267d0a5bc 100644
--- a/cpu/stm32_common/periph/flashpage.c
+++ b/cpu/stm32_common/periph/flashpage.c
@@ -32,32 +32,26 @@
 #include "periph/flashpage.h"
 
 #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
-/* Data EEPROM and control register unlock keys */
-#define FLASH_KEY1             ((uint32_t)0x89ABCDEF)
-#define FLASH_KEY2             ((uint32_t)0x02030405)
 /* Program memory unlock keys */
 #define FLASH_PRGKEY1          ((uint32_t)0x8C9DAEBF)
 #define FLASH_PRGKEY2          ((uint32_t)0x13141516)
 #define CNTRL_REG              (FLASH->PECR)
 #define CNTRL_REG_LOCK         (FLASH_PECR_PELOCK)
-#define KEY_REG                (FLASH->PEKEYR)
 #define FLASH_CR_PER           (FLASH_PECR_ERASE | FLASH_PECR_PROG)
 #define FLASH_CR_PG            (FLASH_PECR_FPRG | FLASH_PECR_PROG)
 #define FLASHPAGE_DIV          (4U) /* write 4 bytes in one go */
 #else
 #define CNTRL_REG              (FLASH->CR)
 #define CNTRL_REG_LOCK         (FLASH_CR_LOCK)
-#define KEY_REG                (FLASH->KEYR)
 #define FLASHPAGE_DIV          (2U)
 #endif
 
-static void _unlock(void)
+extern void _lock(void);
+extern void _unlock(void);
+
+static void _unlock_flash(void)
 {
-    DEBUG("[flashpage] unlocking the flash module\n");
-    if (CNTRL_REG & CNTRL_REG_LOCK) {
-        KEY_REG = FLASH_KEY1;
-        KEY_REG = FLASH_KEY2;
-    }
+    _unlock();
 
 #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
     DEBUG("[flashpage] unlocking the flash program memory\n");
@@ -71,12 +65,6 @@ static void _unlock(void)
 #endif
 }
 
-static void _lock(void)
-{
-    DEBUG("[flashpage] locking the flash module\n");
-    CNTRL_REG |= CNTRL_REG_LOCK;
-}
-
 static void _erase_page(void *page_addr)
 {
 #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)
@@ -90,7 +78,7 @@ static void _erase_page(void *page_addr)
 #endif
 
    /* unlock the flash module */
-    _unlock();
+    _unlock_flash();
 
     /* make sure no flash operation is ongoing */
     DEBUG("[flashpage] erase: waiting for any operation to finish\n");
@@ -153,7 +141,7 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len)
 #endif
 
     DEBUG("[flashpage_raw] unlocking the flash module\n");
-    _unlock();
+    _unlock_flash();
 
     DEBUG("[flashpage] write: now writing the data\n");
 #if !(defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1))