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 2018/11/21 11:32:07 UTC

[mynewt-core] 01/02: [STM32] Unify flash drivers

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 44488a3e8e8e5fd576ddba18831f73928a491f07
Author: Fabio Utzig <ut...@apache.org>
AuthorDate: Mon Nov 12 15:52:16 2018 -0200

    [STM32] Unify flash drivers
    
    This updates the STM32 MCUs to be based on a single flash driver for the
    most part, leaving just the erase operation in a MCU specific flash driver.
    
    Some new syscfgs were added that should be used to provided the
    configuration:
    
    * STM32_FLASH_SIZE_KB: Total size of the flash per BSP.
    * STM32_FLASH_IS_LINEAR: 1 if all sectors are sized equaly, 0 otherwise.
    * STM32_FLASH_NUM_AREAS: Number of sectors if this flash is not linear.
    * STM32_FLASH_SECTOR_SIZE: Size of sectors if the flash is linear.
    * MCU_FLASH_ERASED_VAL: Value read from erased flash per MCU family.
    
    A `const uint32_t stm32_flash_sectors[]` array of sector beginning
    addresses should be provided by MCUs that have non-linear flash.
    
    Signed-off-by: Fabio Utzig <ut...@apache.org>
---
 hw/bsp/b-l072z-lrwan1/src/hal_bsp.c             |   3 +-
 hw/bsp/b-l072z-lrwan1/syscfg.yml                |   4 +
 hw/bsp/bluepill/src/hal_bsp.c                   |   3 +-
 hw/bsp/bluepill/syscfg.yml                      |   4 +
 hw/bsp/nucleo-f030r8/src/hal_bsp.c              |   3 +-
 hw/bsp/nucleo-f030r8/syscfg.yml                 |   4 +
 hw/bsp/nucleo-f303k8/src/hal_bsp.c              |   3 +-
 hw/bsp/nucleo-f303k8/syscfg.yml                 |   4 +
 hw/bsp/nucleo-f303re/src/hal_bsp.c              |   3 +-
 hw/bsp/nucleo-f303re/syscfg.yml                 |   4 +
 hw/bsp/nucleo-f401re/src/hal_bsp.c              |  21 +-
 hw/bsp/nucleo-f401re/syscfg.yml                 |   8 +
 hw/bsp/nucleo-f413zh/src/hal_bsp.c              |  27 +--
 hw/bsp/nucleo-f413zh/syscfg.yml                 |   8 +
 hw/bsp/nucleo-f746zg/src/hal_bsp.c              |  20 +-
 hw/bsp/nucleo-f746zg/syscfg.yml                 |   8 +
 hw/bsp/nucleo-f767zi/src/hal_bsp.c              |  25 ++-
 hw/bsp/nucleo-f767zi/syscfg.yml                 |   8 +
 hw/bsp/nucleo-l476rg/src/hal_bsp.c              |   3 +-
 hw/bsp/nucleo-l476rg/syscfg.yml                 |   4 +
 hw/bsp/olimex-p103/src/hal_bsp.c                |   3 +-
 hw/bsp/olimex-p103/syscfg.yml                   |   4 +
 hw/bsp/olimex_stm32-e407_devboard/src/hal_bsp.c |  21 +-
 hw/bsp/olimex_stm32-e407_devboard/syscfg.yml    |   9 +
 hw/bsp/stm32f3discovery/src/hal_bsp.c           |   3 +-
 hw/bsp/stm32f3discovery/syscfg.yml              |   6 +-
 hw/bsp/stm32f429discovery/src/hal_bsp.c         |  22 +--
 hw/bsp/stm32f429discovery/syscfg.yml            |   9 +
 hw/bsp/stm32f4discovery/src/hal_bsp.c           |  27 +--
 hw/bsp/stm32f4discovery/syscfg.yml              |   9 +
 hw/bsp/stm32f7discovery/src/hal_bsp.c           |  20 +-
 hw/bsp/stm32f7discovery/syscfg.yml              |   8 +
 hw/bsp/stm32l152discovery/src/hal_bsp.c         |   3 +-
 hw/bsp/stm32l152discovery/syscfg.yml            |   4 +
 hw/mcu/stm/stm32_common/src/hal_flash.c         | 249 ++++++++++++++++++++++++
 hw/mcu/stm/stm32f0xx/include/mcu/stm32_hal.h    |  16 ++
 hw/mcu/stm/stm32f0xx/src/hal_flash.c            |  94 +--------
 hw/mcu/stm/stm32f0xx/syscfg.yml                 |  12 ++
 hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h    |  17 ++
 hw/mcu/stm/stm32f1xx/src/hal_flash.c            |  91 +--------
 hw/mcu/stm/stm32f1xx/syscfg.yml                 |  14 +-
 hw/mcu/stm/stm32f3xx/include/mcu/stm32_hal.h    |  17 ++
 hw/mcu/stm/stm32f3xx/src/hal_flash.c            |  97 +--------
 hw/mcu/stm/stm32f3xx/syscfg.yml                 |  12 ++
 hw/mcu/stm/stm32f4xx/include/mcu/stm32_hal.h    |  19 ++
 hw/mcu/stm/stm32f4xx/src/hal_flash.c            | 125 ------------
 hw/mcu/stm/stm32f4xx/syscfg.yml                 |   8 +
 hw/mcu/stm/stm32f7xx/include/mcu/stm32_hal.h    |  19 ++
 hw/mcu/stm/stm32f7xx/src/hal_flash.c            | 142 --------------
 hw/mcu/stm/stm32f7xx/syscfg.yml                 |   8 +
 hw/mcu/stm/stm32l0xx/include/mcu/stm32_hal.h    |  30 +++
 hw/mcu/stm/stm32l0xx/src/hal_flash.c            | 156 ++-------------
 hw/mcu/stm/stm32l0xx/syscfg.yml                 |  12 ++
 hw/mcu/stm/stm32l1xx/include/mcu/stm32_hal.h    |  15 ++
 hw/mcu/stm/stm32l1xx/src/hal_flash.c            | 127 +-----------
 hw/mcu/stm/stm32l1xx/syscfg.yml                 |  12 ++
 hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h    |  11 ++
 hw/mcu/stm/stm32l4xx/src/hal_flash.c            | 113 +----------
 hw/mcu/stm/stm32l4xx/syscfg.yml                 |  12 ++
 59 files changed, 739 insertions(+), 1004 deletions(-)

diff --git a/hw/bsp/b-l072z-lrwan1/src/hal_bsp.c b/hw/bsp/b-l072z-lrwan1/src/hal_bsp.c
index 16d6aab..d700a07 100644
--- a/hw/bsp/b-l072z-lrwan1/src/hal_bsp.c
+++ b/hw/bsp/b-l072z-lrwan1/src/hal_bsp.c
@@ -94,6 +94,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     },
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -103,7 +104,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32l0_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/b-l072z-lrwan1/syscfg.yml b/hw/bsp/b-l072z-lrwan1/syscfg.yml
index e69c957..ada6a40 100644
--- a/hw/bsp/b-l072z-lrwan1/syscfg.yml
+++ b/hw/bsp/b-l072z-lrwan1/syscfg.yml
@@ -18,6 +18,10 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 192
+
     UART_0:
         description: 'Whether to enable UART0'
         value:  1
diff --git a/hw/bsp/bluepill/src/hal_bsp.c b/hw/bsp/bluepill/src/hal_bsp.c
index e25affe..1a0912f 100644
--- a/hw/bsp/bluepill/src/hal_bsp.c
+++ b/hw/bsp/bluepill/src/hal_bsp.c
@@ -109,6 +109,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     },
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -118,7 +119,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f1_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/bluepill/syscfg.yml b/hw/bsp/bluepill/syscfg.yml
index d58f466..ee2a793 100644
--- a/hw/bsp/bluepill/syscfg.yml
+++ b/hw/bsp/bluepill/syscfg.yml
@@ -18,6 +18,10 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 128
+
     UART_0:
         description: 'UART 0'
         value:  1
diff --git a/hw/bsp/nucleo-f030r8/src/hal_bsp.c b/hw/bsp/nucleo-f030r8/src/hal_bsp.c
index a90ea52..30a7e04 100644
--- a/hw/bsp/nucleo-f030r8/src/hal_bsp.c
+++ b/hw/bsp/nucleo-f030r8/src/hal_bsp.c
@@ -101,6 +101,7 @@ hal_bsp_mem_dump dump_cfg[] = {
     },
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -110,7 +111,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f0_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/nucleo-f030r8/syscfg.yml b/hw/bsp/nucleo-f030r8/syscfg.yml
index 2ca209e..7d55e21 100644
--- a/hw/bsp/nucleo-f030r8/syscfg.yml
+++ b/hw/bsp/nucleo-f030r8/syscfg.yml
@@ -18,6 +18,10 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 64
+
     UART_0:
         description: 'Whether to enable UART2'
         value:  0
diff --git a/hw/bsp/nucleo-f303k8/src/hal_bsp.c b/hw/bsp/nucleo-f303k8/src/hal_bsp.c
index 28e6cf6..472400a 100644
--- a/hw/bsp/nucleo-f303k8/src/hal_bsp.c
+++ b/hw/bsp/nucleo-f303k8/src/hal_bsp.c
@@ -136,6 +136,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     }
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -145,7 +146,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return stm32f3_flash_dev();
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/nucleo-f303k8/syscfg.yml b/hw/bsp/nucleo-f303k8/syscfg.yml
index 4279478..dd0b72c 100644
--- a/hw/bsp/nucleo-f303k8/syscfg.yml
+++ b/hw/bsp/nucleo-f303k8/syscfg.yml
@@ -18,6 +18,10 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 64
+
     UART_0:
         description: 'Whether to enable UART0'
         value:  1
diff --git a/hw/bsp/nucleo-f303re/src/hal_bsp.c b/hw/bsp/nucleo-f303re/src/hal_bsp.c
index f667c57..5ee9626 100644
--- a/hw/bsp/nucleo-f303re/src/hal_bsp.c
+++ b/hw/bsp/nucleo-f303re/src/hal_bsp.c
@@ -136,6 +136,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     }
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -145,7 +146,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return stm32f3_flash_dev();
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/nucleo-f303re/syscfg.yml b/hw/bsp/nucleo-f303re/syscfg.yml
index 4279478..96a0bd4 100644
--- a/hw/bsp/nucleo-f303re/syscfg.yml
+++ b/hw/bsp/nucleo-f303re/syscfg.yml
@@ -18,6 +18,10 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 512
+
     UART_0:
         description: 'Whether to enable UART0'
         value:  1
diff --git a/hw/bsp/nucleo-f401re/src/hal_bsp.c b/hw/bsp/nucleo-f401re/src/hal_bsp.c
index fbc6ef2..e8aba90 100644
--- a/hw/bsp/nucleo-f401re/src/hal_bsp.c
+++ b/hw/bsp/nucleo-f401re/src/hal_bsp.c
@@ -26,7 +26,6 @@
 
 #include <hal/hal_bsp.h>
 #include <hal/hal_gpio.h>
-#include <hal/hal_flash_int.h>
 #include <hal/hal_i2c.h>
 #include <hal/hal_timer.h>
 #if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_0_SLAVE)
@@ -39,7 +38,7 @@
 #include "bsp/bsp.h"
 #include <assert.h>
 
-const uint32_t stm32f4_flash_sectors[] = {
+const uint32_t stm32_flash_sectors[] = {
     0x08000000,     /* 16kB */
     0x08004000,     /* 16kB */
     0x08008000,     /* 16kB */
@@ -51,18 +50,9 @@ const uint32_t stm32f4_flash_sectors[] = {
     0x08080000,     /* End of flash */
 };
 
-#define NAREAS (sizeof(stm32f4_flash_sectors) / sizeof(stm32f4_flash_sectors[0]))
-
-extern const struct hal_flash_funcs stm32f4_flash_funcs;
-
-const struct hal_flash stm32f4_flash_dev = {
-    .hf_itf = &stm32f4_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = 512 * 1024,
-    .hf_sector_cnt = NAREAS - 1,
-    .hf_align = 1,
-    .hf_erased_val = 0xff,
-};
+#define SZ (sizeof(stm32_flash_sectors) / sizeof(stm32_flash_sectors[0]))
+_Static_assert(MYNEWT_VAL(STM32_FLASH_NUM_AREAS) == SZ,
+        "STM32_FLASH_NUM_AREAS does not match flash sectors");
 
 #if MYNEWT_VAL(UART_0)
 static struct uart_dev hal_uart0;
@@ -118,6 +108,7 @@ struct stm32_hal_spi_cfg spi0_cfg = {
 };
 #endif
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -127,7 +118,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f4_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/nucleo-f401re/syscfg.yml b/hw/bsp/nucleo-f401re/syscfg.yml
index 72bf3b2..073ed2d 100644
--- a/hw/bsp/nucleo-f401re/syscfg.yml
+++ b/hw/bsp/nucleo-f401re/syscfg.yml
@@ -18,6 +18,14 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 512
+
+    STM32_FLASH_NUM_AREAS:
+        description: 'Amount of flash sectors for a non-linear STM32 MCU.'
+        value: 9
+
     UART_0:
         description: 'Whether to enable UART0'
         value:  1
diff --git a/hw/bsp/nucleo-f413zh/src/hal_bsp.c b/hw/bsp/nucleo-f413zh/src/hal_bsp.c
index eb2e56e..583fec5 100644
--- a/hw/bsp/nucleo-f413zh/src/hal_bsp.c
+++ b/hw/bsp/nucleo-f413zh/src/hal_bsp.c
@@ -28,7 +28,6 @@
 
 #include <hal/hal_bsp.h>
 #include <hal/hal_gpio.h>
-#include <hal/hal_flash_int.h>
 #include <hal/hal_timer.h>
 
 #include <stm32f4xx_hal_gpio_ex.h>
@@ -40,7 +39,7 @@
 
 #include "bsp/bsp.h"
 
-const uint32_t stm32f4_flash_sectors[] = {
+const uint32_t stm32_flash_sectors[] = {
     0x08000000,     /* 16kB */
     0x08004000,     /* 16kB */
     0x08008000,     /* 16kB */
@@ -60,18 +59,9 @@ const uint32_t stm32f4_flash_sectors[] = {
     0x08180000,     /* End of flash */
 };
 
-#define NAREAS (sizeof(stm32f4_flash_sectors) / sizeof(stm32f4_flash_sectors[0]))
-
-extern const struct hal_flash_funcs stm32f4_flash_funcs;
-
-const struct hal_flash stm32f4_flash_dev = {
-    .hf_itf = &stm32f4_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = 1536 * 1024,
-    .hf_sector_cnt = NAREAS - 1,
-    .hf_align = 1,
-    .hf_erased_val = 0xff,
-};
+#define SZ (sizeof(stm32_flash_sectors) / sizeof(stm32_flash_sectors[0]))
+_Static_assert(MYNEWT_VAL(STM32_FLASH_NUM_AREAS) == SZ,
+        "STM32_FLASH_NUM_AREAS does not match flash sectors");
 
 #if MYNEWT_VAL(UART_0)
 static struct uart_dev hal_uart0;
@@ -96,11 +86,11 @@ static struct stm32_hal_i2c_cfg i2c_cfg0 = {
     .hic_i2c = I2C1,
     .hic_rcc_reg = &RCC->APB1ENR,
     .hic_rcc_dev = RCC_APB1ENR_I2C1EN,
-    .hic_pin_sda = MCU_GPIO_PORTB(9),		/* PB9 */
-    .hic_pin_scl = MCU_GPIO_PORTB(8),		/* PB8 */
+    .hic_pin_sda = MCU_GPIO_PORTB(9),       /* PB9 */
+    .hic_pin_scl = MCU_GPIO_PORTB(8),       /* PB8 */
     .hic_pin_af = GPIO_AF4_I2C1,
     .hic_10bit = 0,
-    .hic_speed = 100000				/* 100kHz */
+    .hic_speed = 100000,                    /* 100kHz */
 };
 #endif
 
@@ -138,6 +128,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     }
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -147,7 +138,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f4_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/nucleo-f413zh/syscfg.yml b/hw/bsp/nucleo-f413zh/syscfg.yml
index 7d9521f..33d0d0c 100644
--- a/hw/bsp/nucleo-f413zh/syscfg.yml
+++ b/hw/bsp/nucleo-f413zh/syscfg.yml
@@ -18,6 +18,14 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 1536
+
+    STM32_FLASH_NUM_AREAS:
+        description: 'Amount of flash sectors for a non-linear STM32 MCU.'
+        value: 17
+
     UART_0:
         description: 'UART 0'
         value:  1
diff --git a/hw/bsp/nucleo-f746zg/src/hal_bsp.c b/hw/bsp/nucleo-f746zg/src/hal_bsp.c
index 5225006..5ec5c87 100644
--- a/hw/bsp/nucleo-f746zg/src/hal_bsp.c
+++ b/hw/bsp/nucleo-f746zg/src/hal_bsp.c
@@ -80,8 +80,23 @@ static struct stm32_pwm_conf  stm32_pwm_config[PWM_CNT] = {
 #endif
 };
 
+#endif /* PWM_CNT */
+
+const uint32_t stm32_flash_sectors[] = {
+    0x08000000,     /* 32kB  */
+    0x08008000,     /* 32kB  */
+    0x08010000,     /* 32kB  */
+    0x08018000,     /* 32kB  */
+    0x08020000,     /* 128kB */
+    0x08040000,     /* 256kB */
+    0x08080000,     /* 256kB */
+    0x080c0000,     /* 256kB */
+    0x08100000,     /* End of flash */
+};
 
-#endif
+#define SZ (sizeof(stm32_flash_sectors) / sizeof(stm32_flash_sectors[0]))
+_Static_assert(MYNEWT_VAL(STM32_FLASH_NUM_AREAS) == SZ,
+        "STM32_FLASH_NUM_AREAS does not match flash sectors");
 
 #if MYNEWT_VAL(TRNG)
 static struct trng_dev os_bsp_trng;
@@ -185,6 +200,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     },
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -194,7 +210,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f7_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/nucleo-f746zg/syscfg.yml b/hw/bsp/nucleo-f746zg/syscfg.yml
index 5fe108d..292bdb9 100644
--- a/hw/bsp/nucleo-f746zg/syscfg.yml
+++ b/hw/bsp/nucleo-f746zg/syscfg.yml
@@ -18,6 +18,14 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 1024
+
+    STM32_FLASH_NUM_AREAS:
+        description: 'Amount of flash sectors for a non-linear STM32 MCU.'
+        value: 9
+
     UART_0:
         description: 'Uart 0'
         value:  1
diff --git a/hw/bsp/nucleo-f767zi/src/hal_bsp.c b/hw/bsp/nucleo-f767zi/src/hal_bsp.c
index d202630..56fbf0a 100644
--- a/hw/bsp/nucleo-f767zi/src/hal_bsp.c
+++ b/hw/bsp/nucleo-f767zi/src/hal_bsp.c
@@ -80,8 +80,28 @@ static struct stm32_pwm_conf  stm32_pwm_config[PWM_CNT] = {
 #endif
 };
 
+#endif /* PWM_CNT */
+
+/* FIXME: this works but shouldn't it be dual bank? */
+const uint32_t stm32_flash_sectors[] = {
+    0x08000000,     /* 32kB  */
+    0x08008000,     /* 32kB  */
+    0x08010000,     /* 32kB  */
+    0x08018000,     /* 32kB  */
+    0x08020000,     /* 128kB */
+    0x08040000,     /* 256kB */
+    0x08080000,     /* 256kB */
+    0x080c0000,     /* 256kB */
+    0x08100000,     /* 256kB */
+    0x08140000,     /* 256kB */
+    0x08180000,     /* 256kB */
+    0x081c0000,     /* 256kB */
+    0x08200000,     /* End of flash */
+};
 
-#endif
+#define SZ (sizeof(stm32_flash_sectors) / sizeof(stm32_flash_sectors[0]))
+_Static_assert(MYNEWT_VAL(STM32_FLASH_NUM_AREAS) == SZ,
+        "STM32_FLASH_NUM_AREAS does not match flash sectors");
 
 #if MYNEWT_VAL(TRNG)
 static struct trng_dev os_bsp_trng;
@@ -185,6 +205,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     },
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -194,7 +215,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f7_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/nucleo-f767zi/syscfg.yml b/hw/bsp/nucleo-f767zi/syscfg.yml
index 5fe108d..f57ceb2 100644
--- a/hw/bsp/nucleo-f767zi/syscfg.yml
+++ b/hw/bsp/nucleo-f767zi/syscfg.yml
@@ -18,6 +18,14 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 2048
+
+    STM32_FLASH_NUM_AREAS:
+        description: 'Amount of flash sectors for a non-linear STM32 MCU.'
+        value: 13
+
     UART_0:
         description: 'Uart 0'
         value:  1
diff --git a/hw/bsp/nucleo-l476rg/src/hal_bsp.c b/hw/bsp/nucleo-l476rg/src/hal_bsp.c
index c90aed1..dcb45b0 100644
--- a/hw/bsp/nucleo-l476rg/src/hal_bsp.c
+++ b/hw/bsp/nucleo-l476rg/src/hal_bsp.c
@@ -100,6 +100,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     },
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -109,7 +110,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32l4_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/nucleo-l476rg/syscfg.yml b/hw/bsp/nucleo-l476rg/syscfg.yml
index 5fe0ade..7475557 100644
--- a/hw/bsp/nucleo-l476rg/syscfg.yml
+++ b/hw/bsp/nucleo-l476rg/syscfg.yml
@@ -18,6 +18,10 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 1024
+
     UART_0:
         description: 'Whether to enable UART0'
         value:  1
diff --git a/hw/bsp/olimex-p103/src/hal_bsp.c b/hw/bsp/olimex-p103/src/hal_bsp.c
index e25affe..1a0912f 100644
--- a/hw/bsp/olimex-p103/src/hal_bsp.c
+++ b/hw/bsp/olimex-p103/src/hal_bsp.c
@@ -109,6 +109,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     },
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -118,7 +119,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f1_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/olimex-p103/syscfg.yml b/hw/bsp/olimex-p103/syscfg.yml
index 1536235..15c4ba2 100644
--- a/hw/bsp/olimex-p103/syscfg.yml
+++ b/hw/bsp/olimex-p103/syscfg.yml
@@ -18,6 +18,10 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 128
+
     UART_0:
         description: 'UART 0'
         value:  1
diff --git a/hw/bsp/olimex_stm32-e407_devboard/src/hal_bsp.c b/hw/bsp/olimex_stm32-e407_devboard/src/hal_bsp.c
index 818e5c4..a05b169 100644
--- a/hw/bsp/olimex_stm32-e407_devboard/src/hal_bsp.c
+++ b/hw/bsp/olimex_stm32-e407_devboard/src/hal_bsp.c
@@ -40,7 +40,6 @@
 #include "hal/hal_timer.h"
 #include "hal/hal_bsp.h"
 #include "hal/hal_gpio.h"
-#include "hal/hal_flash_int.h"
 #if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_0_SLAVE)
 #include "hal/hal_spi.h"
 #endif
@@ -52,7 +51,7 @@
 #include "mcu/stm32f4_bsp.h"
 #include "mcu/stm32f4xx_mynewt_hal.h"
 
-const uint32_t stm32f4_flash_sectors[] = {
+const uint32_t stm32_flash_sectors[] = {
     0x08000000,     /* 16kB */
     0x08004000,     /* 16kB */
     0x08008000,     /* 16kB */
@@ -68,18 +67,9 @@ const uint32_t stm32f4_flash_sectors[] = {
     0x08100000,     /* End of flash */
 };
 
-#define NAREAS (sizeof(stm32f4_flash_sectors) / sizeof(stm32f4_flash_sectors[0]))
-
-extern const struct hal_flash_funcs stm32f4_flash_funcs;
-
-const struct hal_flash stm32f4_flash_dev = {
-    .hf_itf = &stm32f4_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = 1024 * 1024,
-    .hf_sector_cnt = NAREAS - 1,
-    .hf_align = 1,
-    .hf_erased_val = 0xff,
-};
+#define SZ (sizeof(stm32_flash_sectors) / sizeof(stm32_flash_sectors[0]))
+_Static_assert(MYNEWT_VAL(STM32_FLASH_NUM_AREAS) == SZ,
+        "STM32_FLASH_NUM_AREAS does not match flash sectors");
 
 #if MYNEWT_VAL(TRNG)
 static struct trng_dev os_bsp_trng;
@@ -366,6 +356,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     }
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -375,7 +366,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f4_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/olimex_stm32-e407_devboard/syscfg.yml b/hw/bsp/olimex_stm32-e407_devboard/syscfg.yml
index d9adcd7..0bb96c9 100644
--- a/hw/bsp/olimex_stm32-e407_devboard/syscfg.yml
+++ b/hw/bsp/olimex_stm32-e407_devboard/syscfg.yml
@@ -17,6 +17,14 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 1024
+
+    STM32_FLASH_NUM_AREAS:
+        description: 'Amount of flash sectors for a non-linear STM32 MCU.'
+        value: 13
+
     ADC_1:
         description: "ADC_1"
         value:  0
@@ -26,6 +34,7 @@ syscfg.defs:
     ADC_3:
         description: "ADC_3"
         value:  0
+
     UART_0:
         description: 'Whether to enable UART0'
         value:  1
diff --git a/hw/bsp/stm32f3discovery/src/hal_bsp.c b/hw/bsp/stm32f3discovery/src/hal_bsp.c
index 21815be..c1a935b 100644
--- a/hw/bsp/stm32f3discovery/src/hal_bsp.c
+++ b/hw/bsp/stm32f3discovery/src/hal_bsp.c
@@ -119,6 +119,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     }
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -128,7 +129,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return stm32f3_flash_dev();
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/stm32f3discovery/syscfg.yml b/hw/bsp/stm32f3discovery/syscfg.yml
index dc199f8..7d2bfca 100644
--- a/hw/bsp/stm32f3discovery/syscfg.yml
+++ b/hw/bsp/stm32f3discovery/syscfg.yml
@@ -18,6 +18,10 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 1024
+
     UART_0:
         description: 'Whether to enable UART0'
         value:  1
@@ -29,11 +33,9 @@ syscfg.defs:
     TIMER_0:
         description: 'Support for timer 0'
         value: 1
-
     TIMER_1:
         description: 'Support for timer 1'
         value: 0
-
     TIMER_2:
         description: 'Support for timer 2'
         value: 0
diff --git a/hw/bsp/stm32f429discovery/src/hal_bsp.c b/hw/bsp/stm32f429discovery/src/hal_bsp.c
index c5a4a3c..f210f3f 100644
--- a/hw/bsp/stm32f429discovery/src/hal_bsp.c
+++ b/hw/bsp/stm32f429discovery/src/hal_bsp.c
@@ -32,14 +32,12 @@
 
 #include <hal/hal_bsp.h>
 #include <hal/hal_gpio.h>
-#include <hal/hal_flash.h>
-#include <hal/hal_flash_int.h>
 #include <hal/hal_timer.h>
 #include <hal/hal_system.h>
 
 #include <mcu/stm32f4_bsp.h>
 
-const uint32_t stm32f4_flash_sectors[] = {
+const uint32_t stm32_flash_sectors[] = {
     /* Bank 1 */
     0x08000000,     /* 16kB */
     0x08004000,     /* 16kB */
@@ -69,18 +67,9 @@ const uint32_t stm32f4_flash_sectors[] = {
     0x08200000,     /* End of flash */
 };
 
-#define NAREAS (sizeof(stm32f4_flash_sectors) / sizeof(stm32f4_flash_sectors[0]))
-
-extern const struct hal_flash_funcs stm32f4_flash_funcs;
-
-const struct hal_flash stm32f4_flash_dev = {
-    .hf_itf = &stm32f4_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = 2048 * 1024,
-    .hf_sector_cnt = NAREAS - 1,
-    .hf_align = 1,
-    .hf_erased_val = 0xff,
-};
+#define SZ (sizeof(stm32_flash_sectors) / sizeof(stm32_flash_sectors[0]))
+_Static_assert(MYNEWT_VAL(STM32_FLASH_NUM_AREAS) == SZ,
+        "STM32_FLASH_NUM_AREAS does not match flash sectors");
 
 #if MYNEWT_VAL(UART_0)
 static struct uart_dev hal_uart0;
@@ -112,6 +101,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     }
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -121,7 +111,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f4_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/stm32f429discovery/syscfg.yml b/hw/bsp/stm32f429discovery/syscfg.yml
index d2eecb3..3d9f141 100644
--- a/hw/bsp/stm32f429discovery/syscfg.yml
+++ b/hw/bsp/stm32f429discovery/syscfg.yml
@@ -18,9 +18,18 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 2048
+
+    STM32_FLASH_NUM_AREAS:
+        description: 'Amount of flash sectors for a non-linear STM32 MCU.'
+        value: 25
+
     UART_0:
         description: 'UART 0'
         value: 1
+
     TIMER_0:
         description: 'Timer 0'
         value: 1
diff --git a/hw/bsp/stm32f4discovery/src/hal_bsp.c b/hw/bsp/stm32f4discovery/src/hal_bsp.c
index 4f9d35d..62a4f88 100644
--- a/hw/bsp/stm32f4discovery/src/hal_bsp.c
+++ b/hw/bsp/stm32f4discovery/src/hal_bsp.c
@@ -27,7 +27,6 @@
 
 #include <hal/hal_bsp.h>
 #include <hal/hal_gpio.h>
-#include <hal/hal_flash_int.h>
 #include <hal/hal_timer.h>
 
 #if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_0_SLAVE)
@@ -41,7 +40,7 @@
 
 #include "bsp/bsp.h"
 
-const uint32_t stm32f4_flash_sectors[] = {
+const uint32_t stm32_flash_sectors[] = {
     0x08000000,     /* 16kB */
     0x08004000,     /* 16kB */
     0x08008000,     /* 16kB */
@@ -57,18 +56,9 @@ const uint32_t stm32f4_flash_sectors[] = {
     0x08100000,     /* End of flash */
 };
 
-#define NAREAS (sizeof(stm32f4_flash_sectors) / sizeof(stm32f4_flash_sectors[0]))
-
-extern const struct hal_flash_funcs stm32f4_flash_funcs;
-
-const struct hal_flash stm32f4_flash_dev = {
-    .hf_itf = &stm32f4_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = 1024 * 1024,
-    .hf_sector_cnt = NAREAS - 1,
-    .hf_align = 1,
-    .hf_erased_val = 0xff,
-};
+#define SZ (sizeof(stm32_flash_sectors) / sizeof(stm32_flash_sectors[0]))
+_Static_assert(MYNEWT_VAL(STM32_FLASH_NUM_AREAS) == SZ,
+        "STM32_FLASH_NUM_AREAS does not match flash sectors");
 
 #if MYNEWT_VAL(UART_0)
 static struct uart_dev hal_uart0;
@@ -93,11 +83,11 @@ static struct stm32_hal_i2c_cfg i2c_cfg0 = {
     .hic_i2c = I2C1,
     .hic_rcc_reg = &RCC->APB1ENR,
     .hic_rcc_dev = RCC_APB1ENR_I2C1EN,
-    .hic_pin_sda = MCU_GPIO_PORTB(9),		/* PB9 */
-    .hic_pin_scl = MCU_GPIO_PORTB(8),		/* PB8 */
+    .hic_pin_sda = MCU_GPIO_PORTB(9),       /* PB9 */
+    .hic_pin_scl = MCU_GPIO_PORTB(8),       /* PB8 */
     .hic_pin_af = GPIO_AF4_I2C1,
     .hic_10bit = 0,
-    .hic_speed = 100000				/* 100kHz */
+    .hic_speed = 100000,                    /* 100kHz */
 };
 #endif
 
@@ -122,6 +112,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     }
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -131,7 +122,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f4_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/stm32f4discovery/syscfg.yml b/hw/bsp/stm32f4discovery/syscfg.yml
index e6e6299..b92ec7a 100644
--- a/hw/bsp/stm32f4discovery/syscfg.yml
+++ b/hw/bsp/stm32f4discovery/syscfg.yml
@@ -18,9 +18,18 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 1024
+
+    STM32_FLASH_NUM_AREAS:
+        description: 'Amount of flash sectors for a non-linear STM32 MCU.'
+        value: 13
+
     UART_0:
         description: 'UART 0'
         value:  1
+
     TIMER_0:
         description: 'Timer 0'
         value:  0
diff --git a/hw/bsp/stm32f7discovery/src/hal_bsp.c b/hw/bsp/stm32f7discovery/src/hal_bsp.c
index d521574..f5e7564 100644
--- a/hw/bsp/stm32f7discovery/src/hal_bsp.c
+++ b/hw/bsp/stm32f7discovery/src/hal_bsp.c
@@ -69,8 +69,23 @@ static struct stm32_pwm_conf  stm32_pwm_config[PWM_CNT] = {
 #endif
 };
 
+#endif /* PWM_CNT */
+
+const uint32_t stm32_flash_sectors[] = {
+    0x08000000,     /* 32kB  */
+    0x08008000,     /* 32kB  */
+    0x08010000,     /* 32kB  */
+    0x08018000,     /* 32kB  */
+    0x08020000,     /* 128kB */
+    0x08040000,     /* 256kB */
+    0x08080000,     /* 256kB */
+    0x080c0000,     /* 256kB */
+    0x08100000,     /* End of flash */
+};
+
+const uint32_t STM32_FLASH_NUM_AREAS = (sizeof(stm32_flash_sectors) /
+                                        sizeof(stm32_flash_sectors[0]) - 1);
 
-#endif
 
 #if MYNEWT_VAL(UART_0)
 static struct uart_dev hal_uart0;
@@ -136,6 +151,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     },
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -145,7 +161,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32f7_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/stm32f7discovery/syscfg.yml b/hw/bsp/stm32f7discovery/syscfg.yml
index 5fe108d..2a757ee 100644
--- a/hw/bsp/stm32f7discovery/syscfg.yml
+++ b/hw/bsp/stm32f7discovery/syscfg.yml
@@ -18,6 +18,14 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 1024
+
+    STM32_FLASH_NUM_AREAS:
+        description: 'Amount of flash sectors for a non-linear STM32 MCU.'
+        value: 13
+
     UART_0:
         description: 'Uart 0'
         value:  1
diff --git a/hw/bsp/stm32l152discovery/src/hal_bsp.c b/hw/bsp/stm32l152discovery/src/hal_bsp.c
index c5521b8..78f832f 100644
--- a/hw/bsp/stm32l152discovery/src/hal_bsp.c
+++ b/hw/bsp/stm32l152discovery/src/hal_bsp.c
@@ -98,6 +98,7 @@ static const struct hal_bsp_mem_dump dump_cfg[] = {
     },
 };
 
+extern const struct hal_flash stm32_flash_dev;
 const struct hal_flash *
 hal_bsp_flash_dev(uint8_t id)
 {
@@ -107,7 +108,7 @@ hal_bsp_flash_dev(uint8_t id)
     if (id != 0) {
         return NULL;
     }
-    return &stm32l1_flash_dev;
+    return &stm32_flash_dev;
 }
 
 const struct hal_bsp_mem_dump *
diff --git a/hw/bsp/stm32l152discovery/syscfg.yml b/hw/bsp/stm32l152discovery/syscfg.yml
index 1536235..7e8fdb3 100644
--- a/hw/bsp/stm32l152discovery/syscfg.yml
+++ b/hw/bsp/stm32l152discovery/syscfg.yml
@@ -18,6 +18,10 @@
 #
 
 syscfg.defs:
+    STM32_FLASH_SIZE_KB:
+        description: 'Total flash size in KB.'
+        value: 256
+
     UART_0:
         description: 'UART 0'
         value:  1
diff --git a/hw/mcu/stm/stm32_common/src/hal_flash.c b/hw/mcu/stm/stm32_common/src/hal_flash.c
new file mode 100644
index 0000000..f2948b4
--- /dev/null
+++ b/hw/mcu/stm/stm32_common/src/hal_flash.c
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <os/mynewt.h>
+#include <mcu/stm32_hal.h>
+#include "hal/hal_flash_int.h"
+#include "hal/hal_watchdog.h"
+
+#define FLASH_IS_LINEAR    MYNEWT_VAL(STM32_FLASH_IS_LINEAR)
+#define FLASH_WRITE_SIZE   MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE)
+#define FLASH_ERASED_VAL   MYNEWT_VAL(MCU_FLASH_ERASED_VAL)
+
+#define _FLASH_SIZE         (MYNEWT_VAL(STM32_FLASH_SIZE_KB) * 1024)
+
+#if FLASH_IS_LINEAR
+#define _FLASH_SECTOR_SIZE  MYNEWT_VAL(STM32_FLASH_SECTOR_SIZE)
+#endif
+
+static int stm32_flash_read(const struct hal_flash *dev, uint32_t address,
+        void *dst, uint32_t num_bytes);
+static int stm32_flash_write(const struct hal_flash *dev, uint32_t address,
+        const void *src, uint32_t num_bytes);
+static int stm32_flash_erase_sector(const struct hal_flash *dev,
+        uint32_t sector_address);
+static int stm32_flash_sector_info(const struct hal_flash *dev, int idx,
+        uint32_t *address, uint32_t *sz);
+static int stm32_flash_init(const struct hal_flash *dev);
+
+const struct hal_flash_funcs stm32_flash_funcs = {
+    .hff_read = stm32_flash_read,
+    .hff_write = stm32_flash_write,
+    .hff_erase_sector = stm32_flash_erase_sector,
+    .hff_sector_info = stm32_flash_sector_info,
+    .hff_init = stm32_flash_init
+};
+
+#if !FLASH_IS_LINEAR
+extern const uint32_t stm32_flash_sectors[];
+#define FLASH_NUM_AREAS (MYNEWT_VAL(STM32_FLASH_NUM_AREAS) - 1)
+#else
+#define FLASH_NUM_AREAS (_FLASH_SIZE / _FLASH_SECTOR_SIZE)
+#endif
+
+const struct hal_flash stm32_flash_dev = {
+    .hf_itf = &stm32_flash_funcs,
+    .hf_base_addr = FLASH_BASE,
+    .hf_size = _FLASH_SIZE,
+    .hf_sector_cnt = FLASH_NUM_AREAS,
+    .hf_align = FLASH_WRITE_SIZE,
+    .hf_erased_val = FLASH_ERASED_VAL,
+};
+
+static int
+stm32_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
+        uint32_t num_bytes)
+{
+    memcpy(dst, (void *)address, num_bytes);
+    return 0;
+}
+
+#if FLASH_IS_LINEAR
+static int
+stm32_flash_write_linear(const struct hal_flash *dev, uint32_t address,
+        const void *src, uint32_t num_bytes)
+{
+    uint64_t val;
+    uint32_t i;
+    int rc;
+    uint8_t align;
+    uint32_t num_words;
+
+    align = dev->hf_align;
+
+#if MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 1
+    num_words = num_bytes;
+#elif MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 2
+    num_words = ((num_bytes - 1) >> 1) + 1;
+#elif MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 4
+    num_words = ((num_bytes - 1) >> 2) + 1;
+#elif MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 8
+    num_words = ((num_bytes - 1) >> 3) + 1;
+#else
+    #error "Unsupported MCU_FLASH_MIN_WRITE_SIZE"
+#endif
+
+    /* FIXME: L4 didn't have error clearing here, should check if other families
+     *        need this (or can be removed)! */
+    STM32_HAL_FLASH_CLEAR_ERRORS();
+
+    for (i = 0; i < num_words; i++) {
+        if (num_bytes < align) {
+            memcpy(&val, &((uint8_t *)src)[i * align], num_bytes);
+            memset((uint32_t *)&val + num_bytes, dev->hf_erased_val, align - num_bytes);
+        } else {
+            memcpy(&val, &((uint8_t *)src)[i * align], align);
+        }
+
+        /* FIXME: L1 was previously unlocking flash before erasing/programming,
+         * and locking again afterwards. Maybe all MCUs should do the same?
+         */
+        rc = HAL_FLASH_Program(FLASH_PROGRAM_TYPE, address, val);
+        if (rc != HAL_OK) {
+            return rc;
+        }
+
+        address += align;
+
+        /* underflowing is ok here... */
+        num_bytes -= align;
+
+        /*
+         * Long writes take excessive time, and stall the idle thread,
+         * so tickling the watchdog here to avoid reset...
+         */
+        if (!(i % 32)) {
+            hal_watchdog_tickle();
+        }
+    }
+
+    return 0;
+}
+#endif
+
+#if !FLASH_IS_LINEAR
+static int
+stm32_flash_write_non_linear(const struct hal_flash *dev, uint32_t address,
+        const void *src, uint32_t num_bytes)
+{
+    const uint8_t *sptr;
+    uint32_t i;
+    int rc;
+
+    sptr = src;
+    /*
+     * Clear status of previous operation.
+     */
+    STM32_HAL_FLASH_CLEAR_ERRORS();
+
+    for (i = 0; i < num_bytes; i++) {
+        rc = HAL_FLASH_Program(FLASH_PROGRAM_TYPE, address, sptr[i]);
+        if (rc != 0) {
+            return rc;
+        }
+
+        address++;
+    }
+
+    return 0;
+}
+#endif
+
+static int
+stm32_flash_write(const struct hal_flash *dev, uint32_t address,
+        const void *src, uint32_t num_bytes)
+{
+    if (!num_bytes) {
+        return -1;
+    }
+
+#if FLASH_IS_LINEAR
+    return stm32_flash_write_linear(dev, address, src, num_bytes);
+#else
+    return stm32_flash_write_non_linear(dev, address, src, num_bytes);
+#endif
+}
+
+#if !FLASH_IS_LINEAR
+static int
+stm32_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
+{
+    FLASH_EraseInitTypeDef eraseinit;
+    HAL_StatusTypeDef err;
+    uint32_t SectorError;
+    int i;
+
+    for (i = 0; i < dev->hf_sector_cnt; i++) {
+        if (stm32_flash_sectors[i] == sector_address) {
+            eraseinit.TypeErase = FLASH_TYPEERASE_SECTORS;
+#ifdef FLASH_OPTCR_nDBANK
+            eraseinit.Banks = FLASH_BANK_1; /* Only used for mass erase */
+#endif
+            eraseinit.Sector = i;
+            eraseinit.NbSectors = 1;
+            eraseinit.VoltageRange = FLASH_VOLTAGE_RANGE_1;
+
+            err = HAL_FLASHEx_Erase(&eraseinit, &SectorError);
+            if (err) {
+                return -1;
+            }
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+#else /* FLASH_IS_LINEAR */
+
+int stm32_mcu_flash_erase_sector(const struct hal_flash *, uint32_t);
+
+static int
+stm32_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
+{
+    return stm32_mcu_flash_erase_sector(dev, sector_address);
+}
+
+#endif
+
+static int
+stm32_flash_sector_info(const struct hal_flash *dev, int idx,
+        uint32_t *address, uint32_t *sz)
+{
+    (void)dev;
+
+#if FLASH_IS_LINEAR
+    *address = dev->hf_base_addr + _FLASH_SECTOR_SIZE * idx;
+    *sz = _FLASH_SECTOR_SIZE;
+#else
+    *address = stm32_flash_sectors[idx];
+    *sz = stm32_flash_sectors[idx + 1] - stm32_flash_sectors[idx];
+#endif
+
+    return 0;
+}
+
+static int
+stm32_flash_init(const struct hal_flash *dev)
+{
+    (void)dev;
+    STM32_HAL_FLASH_INIT();
+    return 0;
+}
diff --git a/hw/mcu/stm/stm32f0xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32f0xx/include/mcu/stm32_hal.h
index a639869..fe81c70 100644
--- a/hw/mcu/stm/stm32f0xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32f0xx/include/mcu/stm32_hal.h
@@ -74,6 +74,22 @@ struct stm32_hal_spi_cfg {
 
 #define STM32_HAL_TIMER_MAX     (3)
 
+/* hal_flash */
+#include "stm32f0xx_hal_def.h"
+#include "stm32f0xx_hal_flash.h"
+#include "stm32f0xx_hal_flash_ex.h"
+#define STM32_HAL_FLASH_INIT()        \
+    do {                              \
+        HAL_FLASH_Unlock();           \
+    } while (0)
+#define FLASH_PROGRAM_TYPE FLASH_TYPEPROGRAM_HALFWORD
+#define STM32_HAL_FLASH_CLEAR_ERRORS()            \
+    do {                                          \
+        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |   \
+                FLASH_FLAG_WRPERR |               \
+                FLASH_FLAG_PGERR);                \
+    } while (0)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/stm/stm32f0xx/src/hal_flash.c b/hw/mcu/stm/stm32f0xx/src/hal_flash.c
index 8d4b6c4..e8c9e82 100644
--- a/hw/mcu/stm/stm32f0xx/src/hal_flash.c
+++ b/hw/mcu/stm/stm32f0xx/src/hal_flash.c
@@ -18,80 +18,12 @@
  */
 
 #include <string.h>
-#include "stm32f0xx_hal_def.h"
-#include "stm32f0xx_hal_flash.h"
-#include "stm32f0xx_hal_flash_ex.h"
+#include <syscfg/syscfg.h>
+#include <mcu/stm32_hal.h>
 #include "hal/hal_flash_int.h"
 
-/*
- * Flash is organized in FLASH_PAGE_SIZE blocks, which for the
- * STM32F0 family is 2KB.
- * */
-#define HAL_FLASH_SECTOR_SIZE   FLASH_PAGE_SIZE
-#define HAL_FLASH_SIZE          (64 * 1024)
-
-
-static int stm32f0_flash_read(const struct hal_flash *dev, uint32_t address, 
-                              void *dst, uint32_t num_bytes);
-static int stm32f0_flash_write(const struct hal_flash *dev, uint32_t address,
-                               const void *src, uint32_t num_bytes);
-static int stm32f0_flash_erase_sector(const struct hal_flash *dev,
-                                      uint32_t sector_address);
-static int stm32f0_flash_sector_info(const struct hal_flash *dev, int idx,
-                                     uint32_t *address, uint32_t *sz);
-static int stm32f0_flash_init(const struct hal_flash *dev);
-
-static const struct hal_flash_funcs stm32f0_flash_funcs = {
-    .hff_read = stm32f0_flash_read,
-    .hff_write = stm32f0_flash_write,
-    .hff_erase_sector = stm32f0_flash_erase_sector,
-    .hff_sector_info = stm32f0_flash_sector_info,
-    .hff_init = stm32f0_flash_init
-};
-
-const struct hal_flash stm32f0_flash_dev = {
-    .hf_itf = &stm32f0_flash_funcs,
-    .hf_base_addr = FLASH_BASE,
-    .hf_size = HAL_FLASH_SIZE,
-    .hf_sector_cnt = HAL_FLASH_SIZE / HAL_FLASH_SECTOR_SIZE,
-    .hf_align = 2,
-    .hf_erased_val = 0xff,
-};
-
-
-static int
-stm32f0_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
-                   uint32_t num_bytes)
-{
-    memcpy(dst, (void *)address, num_bytes);
-    return 0;
-}
-
-static int
-stm32f0_flash_write(const struct hal_flash *dev, uint32_t address,
-                    const void *src, uint32_t num_bytes)
-{
-    const uint16_t *sptr;
-    uint32_t i, half_words;
-    int rc;
-
-    sptr = src;
-    half_words = (num_bytes + 1) / 2;
-
-    HAL_FLASH_Unlock();
-    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR);
-
-    for (i = 0, rc = HAL_OK; i < half_words && rc == HAL_OK; ++i) {
-        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, sptr[i]);
-        address += 2;
-    }
-    HAL_FLASH_Lock();
-
-    return rc == HAL_OK ? 0 : rc;
-}
-
-static int
-stm32f0_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
+int
+stm32_mcu_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 {
     FLASH_EraseInitTypeDef erase;
     int rc = -1;
@@ -101,27 +33,9 @@ stm32f0_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
     erase.PageAddress = sector_address;
     erase.NbPages = 1;
 
-    HAL_FLASH_Unlock();
     if (HAL_OK == HAL_FLASHEx_Erase(&erase, &errorPage)) {
       rc = 0;
     }
-    HAL_FLASH_Lock();
 
     return rc;
 }
-
-static int
-stm32f0_flash_sector_info(const struct hal_flash *dev, int idx,
-                          uint32_t *address, uint32_t *sz)
-{
-    *address = FLASH_BASE + HAL_FLASH_SECTOR_SIZE * idx;
-    *sz = HAL_FLASH_SECTOR_SIZE;
-    return 0;
-}
-
-static int
-stm32f0_flash_init(const struct hal_flash *dev)
-{
-    HAL_FLASH_Lock();
-    return 0;
-}
\ No newline at end of file
diff --git a/hw/mcu/stm/stm32f0xx/syscfg.yml b/hw/mcu/stm/stm32f0xx/syscfg.yml
index ae58049..1e0f87e 100644
--- a/hw/mcu/stm/stm32f0xx/syscfg.yml
+++ b/hw/mcu/stm/stm32f0xx/syscfg.yml
@@ -37,6 +37,18 @@ syscfg.defs:
         description: This MCU's UART uses ISR register (not SR) for status.
         value: 0
 
+    MCU_FLASH_ERASED_VAL:
+        description: Value read from erased flash.
+        value: 0xff
+
+    STM32_FLASH_IS_LINEAR:
+        description: This MCU's Flash has one single sector size.
+        value: 1
+
+    STM32_FLASH_SECTOR_SIZE:
+        description: This MCU's Flash sector size in bytes.
+        value: 2048
+
     MCU_SYSCLK_PLL_HSI:
         description: Configure PLL as sysclock driven by HSI.
         value: 0
diff --git a/hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h
index dc99bb9..3af1e23 100644
--- a/hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32f1xx/include/mcu/stm32_hal.h
@@ -69,6 +69,23 @@ struct stm32_hal_spi_cfg {
 
 #define STM32_HAL_TIMER_MAX     (3)
 
+/* hal_flash */
+#include "stm32f1xx_hal_def.h"
+#include "stm32f1xx_hal_flash.h"
+#include "stm32f1xx_hal_flash_ex.h"
+#define STM32_HAL_FLASH_INIT()        \
+    do {                              \
+        HAL_FLASH_Unlock();           \
+    } while (0)
+#define FLASH_PROGRAM_TYPE FLASH_TYPEPROGRAM_HALFWORD
+#define STM32_HAL_FLASH_CLEAR_ERRORS()           \
+    do {                                         \
+        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |  \
+                FLASH_FLAG_WRPERR |              \
+                FLASH_FLAG_PGERR |               \
+                FLASH_FLAG_BSY);                 \
+    } while (0)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/stm/stm32f1xx/src/hal_flash.c b/hw/mcu/stm/stm32f1xx/src/hal_flash.c
index 78a29ba..64d607d 100644
--- a/hw/mcu/stm/stm32f1xx/src/hal_flash.c
+++ b/hw/mcu/stm/stm32f1xx/src/hal_flash.c
@@ -18,79 +18,14 @@
  */
 
 #include <string.h>
-#include "stm32f1xx_hal_def.h"
-#include "stm32f1xx_hal_flash.h"
-#include "stm32f1xx_hal_flash_ex.h"
+#include <syscfg/syscfg.h>
+#include <mcu/stm32_hal.h>
 #include "hal/hal_flash_int.h"
 
-static int stm32f1_flash_read(const struct hal_flash *dev, uint32_t address,
-        void *dst, uint32_t num_bytes);
-static int stm32f1_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes);
-static int stm32f1_flash_erase_sector(const struct hal_flash *dev,
-        uint32_t sector_address);
-static int stm32f1_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz);
-static int stm32f1_flash_init(const struct hal_flash *dev);
+#define _FLASH_SECTOR_SIZE MYNEWT_VAL(STM32_FLASH_SECTOR_SIZE)
 
-static const struct hal_flash_funcs stm32f1_flash_funcs = {
-    .hff_read = stm32f1_flash_read,
-    .hff_write = stm32f1_flash_write,
-    .hff_erase_sector = stm32f1_flash_erase_sector,
-    .hff_sector_info = stm32f1_flash_sector_info,
-    .hff_init = stm32f1_flash_init,
-};
-
-#define _FLASH_SIZE            (128 * 1024)
-#define _FLASH_SECTOR_SIZE     1024
-
-const struct hal_flash stm32f1_flash_dev = {
-    .hf_itf = &stm32f1_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = _FLASH_SIZE,
-    .hf_sector_cnt = _FLASH_SIZE / _FLASH_SECTOR_SIZE,
-    .hf_align = 2,
-    .hf_erased_val = 0xff,
-};
-
-static int
-stm32f1_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
-        uint32_t num_bytes)
-{
-    memcpy(dst, (void *)address, num_bytes);
-    return 0;
-}
-
-static int
-stm32f1_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes)
-{
-    const uint16_t *sptr;
-    uint32_t i;
-    int rc;
-
-    /*
-     * Clear status of previous operation.
-     */
-    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |
-                           FLASH_FLAG_WRPERR |
-                           FLASH_FLAG_PGERR |
-                           FLASH_FLAG_BSY);
-
-    num_bytes /= 2;
-    for (i = 0, sptr = src; i < num_bytes; i++) {
-        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, sptr[i]);
-        if (rc != 0) {
-            return rc;
-        }
-        address += 2;
-    }
-
-    return 0;
-}
-
-static int
-stm32f1_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
+int
+stm32_mcu_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 {
     FLASH_EraseInitTypeDef eraseinit;
     uint32_t PageError;
@@ -109,19 +44,3 @@ stm32f1_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 
     return -1;
 }
-
-static int
-stm32f1_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz)
-{
-    *address = dev->hf_base_addr + _FLASH_SECTOR_SIZE * idx;
-    *sz = _FLASH_SECTOR_SIZE;
-    return 0;
-}
-
-static int
-stm32f1_flash_init(const struct hal_flash *dev)
-{
-    HAL_FLASH_Unlock();
-    return 0;
-}
diff --git a/hw/mcu/stm/stm32f1xx/syscfg.yml b/hw/mcu/stm/stm32f1xx/syscfg.yml
index a6becf1..cf211e0 100644
--- a/hw/mcu/stm/stm32f1xx/syscfg.yml
+++ b/hw/mcu/stm/stm32f1xx/syscfg.yml
@@ -21,7 +21,7 @@ syscfg.defs:
         description: >
             Specifies the required alignment for internal flash writes.
             Used internally by the newt tool.
-        value: 1
+        value: 2  # STM32F1 HW allows 1 but the HAL API only allows 2/4/8.
 
     MCU_STM32F1:
         description: MCUs are of STM32F1xx family
@@ -39,6 +39,18 @@ syscfg.defs:
         description: This MCU's UART uses SR register for status.
         value: 1
 
+    MCU_FLASH_ERASED_VAL:
+        description: Value read from erased flash.
+        value: 0xff
+
+    STM32_FLASH_IS_LINEAR:
+        description: This MCU's Flash has one single sector size.
+        value: 1
+
+    STM32_FLASH_SECTOR_SIZE:
+        description: This MCU's Flash sector size in bytes.
+        value: 1024
+
     I2C_0:
         description: 'I2C (TWI) interface 0'
         value:  0
diff --git a/hw/mcu/stm/stm32f3xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32f3xx/include/mcu/stm32_hal.h
index 1eddd45..530e40d 100644
--- a/hw/mcu/stm/stm32f3xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32f3xx/include/mcu/stm32_hal.h
@@ -75,6 +75,23 @@ struct stm32_hal_spi_cfg {
 
 #define STM32_HAL_TIMER_MAX     (3)
 
+/* hal_flash */
+#include "stm32f3xx_hal_def.h"
+#include "stm32f3xx_hal_flash.h"
+#include "stm32f3xx_hal_flash_ex.h"
+#define STM32_HAL_FLASH_INIT()
+#define FLASH_PROGRAM_TYPE FLASH_TYPEPROGRAM_HALFWORD
+#define STM32_HAL_FLASH_CLEAR_ERRORS()            \
+    do {                                          \
+        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |   \
+                FLASH_FLAG_WRPERR |               \
+                FLASH_FLAG_PGERR);                \
+    } while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/stm/stm32f3xx/src/hal_flash.c b/hw/mcu/stm/stm32f3xx/src/hal_flash.c
index 98d8fe8..9cb1813 100644
--- a/hw/mcu/stm/stm32f3xx/src/hal_flash.c
+++ b/hw/mcu/stm/stm32f3xx/src/hal_flash.c
@@ -18,72 +18,11 @@
  */
 
 #include <string.h>
-#include "stm32f3xx_hal_def.h"
-#include "stm32f3xx_hal_flash.h"
-#include "stm32f3xx_hal_flash_ex.h"
+#include <mcu/stm32_hal.h>
 #include "hal/hal_flash_int.h"
 
-/*
- * Flash is organized in FLASH_PAGE_SIZE blocks, which for the
- * STM32F3 family is 2KB.
- * */
-#define HAL_FLASH_SECTOR_SIZE   FLASH_PAGE_SIZE
-#define HAL_FLASH_SIZE          ((*((uint16_t*)FLASH_SIZE_DATA_REGISTER)) * 1024U)
-
-
-static int stm32f3_flash_read(const struct hal_flash *dev, uint32_t address,
-        void *dst, uint32_t num_bytes);
-static int stm32f3_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes);
-static int stm32f3_flash_erase_sector(const struct hal_flash *dev,
-        uint32_t sector_address);
-static int stm32f3_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz);
-static int stm32f3_flash_init(const struct hal_flash *dev);
-
-static const struct hal_flash_funcs stm32f3_flash_funcs = {
-    .hff_read = stm32f3_flash_read,
-    .hff_write = stm32f3_flash_write,
-    .hff_erase_sector = stm32f3_flash_erase_sector,
-    .hff_sector_info = stm32f3_flash_sector_info,
-    .hff_init = stm32f3_flash_init
-};
-
-struct hal_flash stm32f3_flash_dev_;
-
-static int
-stm32f3_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
-        uint32_t num_bytes)
-{
-    memcpy(dst, (void *)address, num_bytes);
-    return 0;
-}
-
-static int
-stm32f3_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes)
-{
-    const uint16_t *sptr;
-    uint32_t i, half_words;
-    int rc;
-
-    sptr = src;
-    half_words = (num_bytes + 1) / 2;
-
-    HAL_FLASH_Unlock();
-    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR);
-
-    for (i = 0, rc = HAL_OK; i < half_words && rc == HAL_OK; ++i) {
-        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, sptr[i]);
-        address += 2;
-    }
-    HAL_FLASH_Lock();
-
-    return rc == HAL_OK ? 0 : rc;
-}
-
-static int
-stm32f3_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
+int
+stm32_mcu_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 {
     FLASH_EraseInitTypeDef erase;
     int rc = -1;
@@ -101,33 +40,3 @@ stm32f3_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 
     return rc;
 }
-
-static int
-stm32f3_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz)
-{
-    *address = FLASH_BASE + HAL_FLASH_SECTOR_SIZE * idx;
-    *sz = HAL_FLASH_SECTOR_SIZE;
-    return 0;
-}
-
-static int
-stm32f3_flash_init(const struct hal_flash *dev)
-{
-    HAL_FLASH_Lock();
-    return 0;
-}
-
-struct hal_flash*
-stm32f3_flash_dev()
-{
-    if (0 == stm32f3_flash_dev_.hf_itf) {
-        stm32f3_flash_dev_.hf_itf = &stm32f3_flash_funcs;
-        stm32f3_flash_dev_.hf_base_addr = FLASH_BASE;
-        stm32f3_flash_dev_.hf_size = HAL_FLASH_SIZE;
-        stm32f3_flash_dev_.hf_sector_cnt = HAL_FLASH_SIZE / HAL_FLASH_SECTOR_SIZE;
-        stm32f3_flash_dev_.hf_align = 2;
-        stm32f3_flash_dev_.hf_erased_val = 0xff;
-    }
-    return &stm32f3_flash_dev_;
-}
diff --git a/hw/mcu/stm/stm32f3xx/syscfg.yml b/hw/mcu/stm/stm32f3xx/syscfg.yml
index 4c78f61..38a90de 100644
--- a/hw/mcu/stm/stm32f3xx/syscfg.yml
+++ b/hw/mcu/stm/stm32f3xx/syscfg.yml
@@ -39,6 +39,18 @@ syscfg.defs:
         description: This MCU's UART uses ISR register (not SR) for status.
         value: 0
 
+    MCU_FLASH_ERASED_VAL:
+        description: Value read from erased flash.
+        value: 0xff
+
+    STM32_FLASH_IS_LINEAR:
+        description: This MCU's Flash has one single sector size.
+        value: 1
+
+    STM32_FLASH_SECTOR_SIZE:
+        description: This MCU's Flash sector size in bytes.
+        value: 2048
+
     MCU_SYSCLK_PLL_HSI:
         description: Configure PLL as sysclock driven by HSI.
         value: 0
diff --git a/hw/mcu/stm/stm32f4xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32f4xx/include/mcu/stm32_hal.h
index aec79d9..2f93fd7 100644
--- a/hw/mcu/stm/stm32f4xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32f4xx/include/mcu/stm32_hal.h
@@ -76,6 +76,25 @@ struct stm32_hal_spi_cfg {
 /* hal_trng */
 #include "stm32f4xx_hal_rng.h"
 
+/* hal_flash */
+#include "stm32f4xx_hal_def.h"
+#include "stm32f4xx_hal_flash.h"
+#include "stm32f4xx_hal_flash_ex.h"
+#define STM32_HAL_FLASH_INIT()        \
+    do {                              \
+        HAL_FLASH_Unlock();           \
+    } while (0)
+#define FLASH_PROGRAM_TYPE FLASH_TYPEPROGRAM_BYTE
+#define STM32_HAL_FLASH_CLEAR_ERRORS()            \
+    do {                                          \
+        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |   \
+                FLASH_FLAG_OPERR |                \
+                FLASH_FLAG_WRPERR |               \
+                FLASH_FLAG_PGAERR |               \
+                FLASH_FLAG_PGPERR |               \
+                FLASH_FLAG_PGSERR);               \
+    } while (0)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/stm/stm32f4xx/src/hal_flash.c b/hw/mcu/stm/stm32f4xx/src/hal_flash.c
deleted file mode 100644
index 9d94495..0000000
--- a/hw/mcu/stm/stm32f4xx/src/hal_flash.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <string.h>
-#include "stm32f4xx_hal_def.h"
-#include "stm32f4xx_hal_flash.h"
-#include "stm32f4xx_hal_flash_ex.h"
-#include "hal/hal_flash_int.h"
-
-static int stm32f4_flash_read(const struct hal_flash *dev, uint32_t address,
-        void *dst, uint32_t num_bytes);
-static int stm32f4_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes);
-static int stm32f4_flash_erase_sector(const struct hal_flash *dev,
-        uint32_t sector_address);
-static int stm32f4_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz);
-static int stm32f4_flash_init(const struct hal_flash *dev);
-
-const struct hal_flash_funcs stm32f4_flash_funcs = {
-    .hff_read = stm32f4_flash_read,
-    .hff_write = stm32f4_flash_write,
-    .hff_erase_sector = stm32f4_flash_erase_sector,
-    .hff_sector_info = stm32f4_flash_sector_info,
-    .hff_init = stm32f4_flash_init
-};
-
-extern const uint32_t stm32f4_flash_sectors[];
-extern const uint32_t STM32F4_FLASH_NUM_AREAS;
-
-static int
-stm32f4_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
-        uint32_t num_bytes)
-{
-    memcpy(dst, (void *)address, num_bytes);
-    return 0;
-}
-
-static int
-stm32f4_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes)
-{
-    const uint8_t *sptr;
-    uint32_t i;
-    int rc;
-
-    sptr = src;
-    /*
-     * Clear status of previous operation.
-     */
-    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
-      FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR| FLASH_FLAG_PGSERR);
-    for (i = 0; i < num_bytes; i++) {
-        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, sptr[i]);
-        if (rc != 0) {
-            return rc;
-        }
-
-        address++;
-    }
-
-    return 0;
-}
-
-static void
-stm32f4_flash_erase_sector_id(int sector_id)
-{
-    FLASH_EraseInitTypeDef eraseinit;
-    uint32_t SectorError;
-
-    eraseinit.TypeErase = FLASH_TYPEERASE_SECTORS;
-    eraseinit.Banks = 0;
-    eraseinit.Sector = sector_id;
-    eraseinit.NbSectors = 1;
-    eraseinit.VoltageRange = FLASH_VOLTAGE_RANGE_1;
-
-    HAL_FLASHEx_Erase(&eraseinit, &SectorError);
-}
-
-static int
-stm32f4_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
-{
-    int i;
-
-    for (i = 0; i < dev->hf_sector_cnt; i++) {
-        if (stm32f4_flash_sectors[i] == sector_address) {
-            stm32f4_flash_erase_sector_id(i);
-            return 0;
-        }
-    }
-
-    return -1;
-}
-
-static int
-stm32f4_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz)
-{
-    *address = stm32f4_flash_sectors[idx];
-    *sz = stm32f4_flash_sectors[idx + 1] - stm32f4_flash_sectors[idx];
-    return 0;
-}
-
-static int
-stm32f4_flash_init(const struct hal_flash *dev)
-{
-    HAL_FLASH_Unlock();
-    return 0;
-}
diff --git a/hw/mcu/stm/stm32f4xx/syscfg.yml b/hw/mcu/stm/stm32f4xx/syscfg.yml
index cac584b..08ed2ea 100644
--- a/hw/mcu/stm/stm32f4xx/syscfg.yml
+++ b/hw/mcu/stm/stm32f4xx/syscfg.yml
@@ -39,6 +39,14 @@ syscfg.defs:
         description: This MCU's UART uses SR register for status.
         value: 1
 
+    MCU_FLASH_ERASED_VAL:
+        description: Value read from erased flash.
+        value: 0xff
+
+    STM32_FLASH_IS_LINEAR:
+        description: This MCU's Flash has one single sector size.
+        value: 0
+
     I2C_0:
         description: 'I2C (TWI) interface 0'
         value:  0
diff --git a/hw/mcu/stm/stm32f7xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32f7xx/include/mcu/stm32_hal.h
index 8cdd6b4..bdb7d5b 100644
--- a/hw/mcu/stm/stm32f7xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32f7xx/include/mcu/stm32_hal.h
@@ -80,6 +80,25 @@ struct stm32_hal_spi_cfg {
 /* hal_trng */
 #include "stm32f7xx_hal_rng.h"
 
+/* hal_flash */
+#include "stm32f7xx_hal_def.h"
+#include "stm32f7xx_hal_flash.h"
+#include "stm32f7xx_hal_flash_ex.h"
+#define STM32_HAL_FLASH_INIT()        \
+    do {                              \
+        HAL_FLASH_Unlock();           \
+    } while (0)
+#define FLASH_PROGRAM_TYPE FLASH_TYPEPROGRAM_BYTE
+#define STM32_HAL_FLASH_CLEAR_ERRORS()            \
+    do {                                          \
+        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |   \
+                FLASH_FLAG_OPERR |                \
+                FLASH_FLAG_WRPERR |               \
+                FLASH_FLAG_PGAERR |               \
+                FLASH_FLAG_PGPERR |               \
+                FLASH_FLAG_ERSERR);               \
+    } while (0)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/stm/stm32f7xx/src/hal_flash.c b/hw/mcu/stm/stm32f7xx/src/hal_flash.c
deleted file mode 100644
index 017c722..0000000
--- a/hw/mcu/stm/stm32f7xx/src/hal_flash.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#include <string.h>
-#include "stm32f7xx_hal_def.h"
-#include "stm32f7xx_hal_flash.h"
-#include "stm32f7xx_hal_flash_ex.h"
-#include "hal/hal_flash_int.h"
-
-static int stm32f7_flash_read(const struct hal_flash *dev, uint32_t address,
-        void *dst, uint32_t num_bytes);
-static int stm32f7_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes);
-static int stm32f7_flash_erase_sector(const struct hal_flash *dev,
-        uint32_t sector_address);
-static int stm32f7_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz);
-static int stm32f7_flash_init(const struct hal_flash *dev);
-
-static const struct hal_flash_funcs stm32f7_flash_funcs = {
-    .hff_read = stm32f7_flash_read,
-    .hff_write = stm32f7_flash_write,
-    .hff_erase_sector = stm32f7_flash_erase_sector,
-    .hff_sector_info = stm32f7_flash_sector_info,
-    .hff_init = stm32f7_flash_init
-};
-
-static const uint32_t stm32f7_flash_sectors[] = {
-    0x08000000,     /* 32kB  */
-    0x08008000,     /* 32kB  */
-    0x08010000,     /* 32kB  */
-    0x08018000,     /* 32kB  */
-    0x08020000,     /* 128kB */
-    0x08040000,     /* 256kB */
-    0x08080000,     /* 256kB */
-    0x080c0000,     /* 256kB */
-    0x08100000,     /* 256kB */
-    0x08140000,     /* 256kB */
-    0x08180000,     /* 256kB */
-    0x081c0000,     /* 256kB */
-    0x08200000,     /* End of flash */
-};
-
-#define STM32F7_FLASH_NUM_AREAS                                         \
-    (int)(sizeof(stm32f7_flash_sectors) /                               \
-      sizeof(stm32f7_flash_sectors[0]))
-
-const struct hal_flash stm32f7_flash_dev = {
-    .hf_itf = &stm32f7_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = 2 * 1024 * 1024,
-    .hf_sector_cnt = STM32F7_FLASH_NUM_AREAS - 1,
-    .hf_align = 1,
-    .hf_erased_val = 0xff,
-};
-
-static int
-stm32f7_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
-        uint32_t num_bytes)
-{
-    memcpy(dst, (void *)address, num_bytes);
-    return 0;
-}
-
-static int
-stm32f7_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes)
-{
-    const uint8_t *sptr;
-    uint32_t i;
-    int rc;
-
-    sptr = src;
-    /*
-     * Clear status of previous operation.
-     */
-    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \
-      FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_ERSERR);
-    for (i = 0; i < num_bytes; i++) {
-        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, address, sptr[i]);
-        if (rc != 0) {
-            return rc;
-        }
-
-        address++;
-    }
-
-    return 0;
-}
-
-static void
-stm32f7_flash_erase_sector_id(int sector_id)
-{
-    FLASH_Erase_Sector(sector_id, FLASH_VOLTAGE_RANGE_1);
-}
-
-static int
-stm32f7_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
-{
-    int i;
-
-    for (i = 0; i < STM32F7_FLASH_NUM_AREAS - 1; i++) {
-        if (stm32f7_flash_sectors[i] == sector_address) {
-            stm32f7_flash_erase_sector_id(i);
-            return 0;
-        }
-    }
-
-    return -1;
-}
-
-static int
-stm32f7_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz)
-{
-    *address = stm32f7_flash_sectors[idx];
-    *sz = stm32f7_flash_sectors[idx + 1] - stm32f7_flash_sectors[idx];
-    return 0;
-}
-
-static int
-stm32f7_flash_init(const struct hal_flash *dev)
-{
-    HAL_FLASH_Unlock();
-    return 0;
-}
diff --git a/hw/mcu/stm/stm32f7xx/syscfg.yml b/hw/mcu/stm/stm32f7xx/syscfg.yml
index 9767dd4..4e8c3cd 100644
--- a/hw/mcu/stm/stm32f7xx/syscfg.yml
+++ b/hw/mcu/stm/stm32f7xx/syscfg.yml
@@ -39,6 +39,14 @@ syscfg.defs:
         description: This MCU's UART uses ISR register (not SR) for status.
         value: 0
 
+    MCU_FLASH_ERASED_VAL:
+        description: Value read from erased flash.
+        value: 0xff
+
+    STM32_FLASH_IS_LINEAR:
+        description: This MCU's Flash has one single sector size.
+        value: 0
+
     MCU_SYSCLK_PLL_HSI:
         description: Configure PLL as sysclock driven by HSI.
         value: 0
diff --git a/hw/mcu/stm/stm32l0xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32l0xx/include/mcu/stm32_hal.h
index 5e895c3..e7f6921 100644
--- a/hw/mcu/stm/stm32l0xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32l0xx/include/mcu/stm32_hal.h
@@ -80,6 +80,36 @@ struct stm32_hal_spi_cfg {
 
 #define STM32_HAL_TIMER_MAX     (3)
 
+/* hal_flash */
+#include "stm32l0xx_hal_def.h"
+#include "stm32l0xx_hal_rcc.h"
+#include "stm32l0xx_hal_flash.h"
+#include "stm32l0xx_hal_flash_ex.h"
+/*
+ * FIXME: __HAL_FLASH_BUFFER_CACHE_DISABLE() ?
+ *        __HAL_FLASH_PREREAD_BUFFER_ENABLE() ?
+ *        __HAL_FLASH_PREFETCH_BUFFER_ENABLE() ?
+ */
+#define STM32_HAL_FLASH_INIT()        \
+    do {                              \
+        __HAL_RCC_MIF_CLK_ENABLE();   \
+        HAL_FLASH_Unlock();           \
+    } while (0)
+#define FLASH_PROGRAM_TYPE FLASH_TYPEPROGRAM_WORD
+#define STM32_HAL_FLASH_CLEAR_ERRORS()          \
+    do {                                        \
+        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | \
+                FLASH_FLAG_ENDHV |              \
+                FLASH_FLAG_READY |              \
+                FLASH_FLAG_WRPERR |             \
+                FLASH_FLAG_PGAERR |             \
+                FLASH_FLAG_SIZERR |             \
+                FLASH_FLAG_OPTVERR |            \
+                FLASH_FLAG_RDERR |              \
+                FLASH_FLAG_FWWERR |             \
+                FLASH_FLAG_NOTZEROERR);         \
+    } while (0)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/stm/stm32l0xx/src/hal_flash.c b/hw/mcu/stm/stm32l0xx/src/hal_flash.c
index 453c25a..aa20165 100644
--- a/hw/mcu/stm/stm32l0xx/src/hal_flash.c
+++ b/hw/mcu/stm/stm32l0xx/src/hal_flash.c
@@ -18,145 +18,47 @@
  */
 
 #include <string.h>
-#include "stm32l0xx_hal_def.h"
-#include "stm32l0xx_hal_rcc.h"
-#include "stm32l0xx_hal_flash.h"
-#include "stm32l0xx_hal_flash_ex.h"
+#include <syscfg/syscfg.h>
+#include <mcu/stm32_hal.h>
 #include "hal/hal_flash_int.h"
 #include "hal/hal_watchdog.h"
 
-static int stm32l0_flash_read(const struct hal_flash *dev, uint32_t address,
-        void *dst, uint32_t num_bytes);
-static int stm32l0_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes);
-static int stm32l0_flash_erase_sector(const struct hal_flash *dev,
-        uint32_t sector_address);
-static int stm32l0_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz);
-static int stm32l0_flash_init(const struct hal_flash *dev);
-
-static const struct hal_flash_funcs stm32l0_flash_funcs = {
-    .hff_read = stm32l0_flash_read,
-    .hff_write = stm32l0_flash_write,
-    .hff_erase_sector = stm32l0_flash_erase_sector,
-    .hff_sector_info = stm32l0_flash_sector_info,
-    .hff_init = stm32l0_flash_init,
-};
-
-#define _FLASH_SIZE              (192 * 1024)
 /*
  * NOTE: the actual page size if 128 bytes, but that would mean an
  * enormous amount of pages, so here make it look like 1K.
  */
-#define _FLASH_SECTOR_SIZE       1024
-#define _FLASH_PAGES_PER_SECTOR  8
-
-const struct hal_flash stm32l0_flash_dev = {
-    .hf_itf = &stm32l0_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = _FLASH_SIZE,
-    .hf_sector_cnt = _FLASH_SIZE / _FLASH_SECTOR_SIZE,
-    /* FIXME: 2 also ok? */
-    .hf_align = 4,
-    .hf_erased_val = 0,
-};
-
-static int
-stm32l0_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
-        uint32_t num_bytes)
-{
-    memcpy(dst, (void *)address, num_bytes);
-    return 0;
-}
-
-static int
-stm32l0_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes)
-{
-    uint64_t val;
-    uint8_t align;
-    uint32_t i;
-    int rc;
-    uint32_t num_words;
-
-    if (!num_bytes) {
-        return -1;
-    }
-
-    align = dev->hf_align;
-    num_words = ((num_bytes - 1) / align) + 1;
-
-    /* clear previous errors */
-    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |
-                    FLASH_FLAG_ENDHV      |
-                    FLASH_FLAG_READY      |
-                    FLASH_FLAG_WRPERR     |
-                    FLASH_FLAG_PGAERR     |
-                    FLASH_FLAG_SIZERR     |
-                    FLASH_FLAG_OPTVERR    |
-                    FLASH_FLAG_RDERR      |
-                    FLASH_FLAG_FWWERR     |
-                    FLASH_FLAG_NOTZEROERR);
-
-    for (i = 0; i < num_words; i++) {
-        //__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_PGSERR);
-
-        if (num_bytes < align) {
-            memcpy(&val, &((uint8_t *)src)[i * align], num_bytes);
-            memset((uint32_t *)&val + num_bytes, 0, align - num_bytes);
-        } else {
-            memcpy(&val, &((uint8_t *)src)[i * align], align);
-        }
-
-        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, val);
-        if (rc != HAL_OK) {
-            return rc;
-        }
-
-        address += align;
-
-        /* underflowing is ok here... */
-        num_bytes -= align;
-
-        /*
-         * Long writes take excessive time, and stall the idle thread, so
-         * tickling the watchdog here to avoid resetting during writes...
-         */
-        if (!(i % 32)) {
-            hal_watchdog_tickle();
-        }
-    }
+#define _REAL_SECTOR_SIZE    128
+#define _FLASH_SECTOR_SIZE   MYNEWT_VAL(STM32_FLASH_SECTOR_SIZE)
+#define _PAGES_PER_SECTOR    8
 
-    return 0;
-}
+/* Since the sectors on L0 are too small, avoid having the map each one
+ * of them by aggregating them into _PAGES_PER_SECTOR amount.
+ *
+ * This asserts the MCU constant is not changed, and if it's changed
+ * intentionally alerts the user that this code needs to be updated
+ * as well.
+ */
+_Static_assert(_FLASH_SECTOR_SIZE == (_REAL_SECTOR_SIZE * _PAGES_PER_SECTOR),
+    "STM32_FLASH_SECTOR_SIZE was changed; the erase function needs updating!");
 
-static int
-stm32l0_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
+int
+stm32_mcu_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 {
     FLASH_EraseInitTypeDef eraseinit;
     uint32_t PageError;
     HAL_StatusTypeDef rc;
 
     (void)PageError;
+    (void)dev;
 
     if (!(sector_address & (_FLASH_SECTOR_SIZE - 1))) {
         /* FIXME: why is an err flag set? */
-
         /* Clear status of previous operation. */
-        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP |
-                        FLASH_FLAG_ENDHV      |
-                        FLASH_FLAG_READY      |
-                        FLASH_FLAG_WRPERR     |
-                        FLASH_FLAG_PGAERR     |
-                        FLASH_FLAG_SIZERR     |
-                        FLASH_FLAG_OPTVERR    |
-                        FLASH_FLAG_RDERR      |
-                        FLASH_FLAG_FWWERR     |
-                        FLASH_FLAG_NOTZEROERR);
+        STM32_HAL_FLASH_CLEAR_ERRORS();
 
         eraseinit.TypeErase = FLASH_TYPEERASE_PAGES;
         eraseinit.PageAddress = sector_address;
-        eraseinit.NbPages = _FLASH_PAGES_PER_SECTOR;
+        eraseinit.NbPages = _PAGES_PER_SECTOR;
         rc = HAL_FLASHEx_Erase(&eraseinit, &PageError);
         if (rc == HAL_OK) {
             return 0;
@@ -165,23 +67,3 @@ stm32l0_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 
     return -1;
 }
-
-static int
-stm32l0_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz)
-{
-    *address = dev->hf_base_addr + _FLASH_SECTOR_SIZE * idx;
-    *sz = _FLASH_SECTOR_SIZE;
-    return 0;
-}
-
-static int
-stm32l0_flash_init(const struct hal_flash *dev)
-{
-    //__HAL_FLASH_BUFFER_CACHE_DISABLE();
-    //__HAL_FLASH_PREREAD_BUFFER_ENABLE();
-    //__HAL_FLASH_PREFETCH_BUFFER_ENABLE();
-    __HAL_RCC_MIF_CLK_ENABLE();
-    HAL_FLASH_Unlock();
-    return 0;
-}
diff --git a/hw/mcu/stm/stm32l0xx/syscfg.yml b/hw/mcu/stm/stm32l0xx/syscfg.yml
index 72a9ba1..ca84f9c 100644
--- a/hw/mcu/stm/stm32l0xx/syscfg.yml
+++ b/hw/mcu/stm/stm32l0xx/syscfg.yml
@@ -43,6 +43,18 @@ syscfg.defs:
         description: This MCU's UART uses SR register for status.
         value: 0
 
+    MCU_FLASH_ERASED_VAL:
+        description: Value read from erased flash.
+        value: 0
+
+    STM32_FLASH_IS_LINEAR:
+        description: This MCU's Flash has one single sector size.
+        value: 1
+
+    STM32_FLASH_SECTOR_SIZE:
+        description: This MCU's Flash sector size in bytes.
+        value: 1024 # this is a lie (should be 128)
+
     SPI_0_MASTER:
         description: 'SPI 0 master'
         value:  0
diff --git a/hw/mcu/stm/stm32l1xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32l1xx/include/mcu/stm32_hal.h
index 1b95ad9..50416e7 100644
--- a/hw/mcu/stm/stm32l1xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32l1xx/include/mcu/stm32_hal.h
@@ -73,6 +73,21 @@ struct stm32_hal_spi_cfg {
 
 #define STM32_HAL_TIMER_MAX     (3)
 
+/* hal_flash */
+#include "stm32l1xx_hal_def.h"
+#include "stm32l1xx_hal_flash.h"
+#include "stm32l1xx_hal_flash_ex.h"
+/* TODO: enable ACC64 + prefetch */
+#define STM32_HAL_FLASH_INIT()        \
+    do {                              \
+        HAL_FLASH_Unlock();           \
+    } while (0)
+#define FLASH_PROGRAM_TYPE FLASH_TYPEPROGRAMDATA_WORD
+#define STM32_HAL_FLASH_CLEAR_ERRORS()            \
+    do {                                          \
+        __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_MASK);  \
+    } while (0)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/stm/stm32l1xx/src/hal_flash.c b/hw/mcu/stm/stm32l1xx/src/hal_flash.c
index d0b6af6..7f56867 100644
--- a/hw/mcu/stm/stm32l1xx/src/hal_flash.c
+++ b/hw/mcu/stm/stm32l1xx/src/hal_flash.c
@@ -19,114 +19,13 @@
 
 #include <string.h>
 #include <syscfg/syscfg.h>
-#include "stm32l1xx_hal_def.h"
-#include "stm32l1xx_hal_flash.h"
-#include "stm32l1xx_hal_flash_ex.h"
+#include <mcu/stm32_hal.h>
 #include "hal/hal_flash_int.h"
-#include "hal/hal_watchdog.h"
 
-static int stm32l1_flash_read(const struct hal_flash *dev, uint32_t address,
-        void *dst, uint32_t num_bytes);
-static int stm32l1_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes);
-static int stm32l1_flash_erase_sector(const struct hal_flash *dev,
-        uint32_t sector_address);
-static int stm32l1_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz);
-static int stm32l1_flash_init(const struct hal_flash *dev);
+#define _FLASH_SECTOR_SIZE  MYNEWT_VAL(STM32_FLASH_SECTOR_SIZE)
 
-static const struct hal_flash_funcs stm32l1_flash_funcs = {
-    .hff_read = stm32l1_flash_read,
-    .hff_write = stm32l1_flash_write,
-    .hff_erase_sector = stm32l1_flash_erase_sector,
-    .hff_sector_info = stm32l1_flash_sector_info,
-    .hff_init = stm32l1_flash_init,
-};
-
-#define _FLASH_SIZE            (256 * 1024)
-#define _FLASH_SECTOR_SIZE     4096
-
-const struct hal_flash stm32l1_flash_dev = {
-    .hf_itf = &stm32l1_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = _FLASH_SIZE,
-    .hf_sector_cnt = _FLASH_SIZE / _FLASH_SECTOR_SIZE,
-    .hf_align = MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE),
-    .hf_erased_val = 0,
-};
-
-static int
-stm32l1_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
-        uint32_t num_bytes)
-{
-    memcpy(dst, (void *)address, num_bytes);
-    return 0;
-}
-
-static int
-stm32l1_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes)
-{
-    uint32_t val;
-    uint32_t i;
-    int rc;
-    uint8_t align;
-    uint32_t num_words;
-
-    if (!num_bytes) {
-        return -1;
-    }
-
-    align = dev->hf_align;
-
-#if MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 1
-    num_words = num_bytes;
-#elif MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 2
-    num_words = ((num_bytes - 1) >> 1) + 1;
-#elif MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 4
-    num_words = ((num_bytes - 1) >> 2) + 1;
-#elif MYNEWT_VAL(MCU_FLASH_MIN_WRITE_SIZE) == 8
-    num_words = ((num_bytes - 1) >> 3) + 1;
-#else
-    #error "Unsupported MCU_FLASH_MIN_WRITE_SIZE"
-#endif
-
-    /* Clear status of previous operation. */
-    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_MASK);
-
-    for (i = 0; i < num_words; i++) {
-        if (num_bytes < align) {
-            memcpy(&val, &((uint8_t *)src)[i * align], num_bytes);
-            /* NOTE: 0 is the erased value for L1 */
-            memset((uint32_t *)&val + num_bytes, 0, align - num_bytes);
-        } else {
-            memcpy(&val, &((uint8_t *)src)[i * align], align);
-        }
-
-        HAL_FLASH_Unlock();
-        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAMDATA_WORD, address, val);
-        HAL_FLASH_Lock();
-        if (rc != HAL_OK) {
-            return rc;
-        }
-
-        address += align;
-        num_bytes -= align;
-
-        /*
-         * Long writes take excessive time, and stall the idle thread,
-         * so tickling the watchdog here to avoid reset...
-         */
-        if (!(i % 32)) {
-            hal_watchdog_tickle();
-        }
-    }
-
-    return 0;
-}
-
-static int
-stm32l1_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
+int
+stm32_mcu_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 {
     FLASH_EraseInitTypeDef eraseinit;
     uint32_t PageError;
@@ -144,9 +43,7 @@ stm32l1_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
         eraseinit.PageAddress = sector_address;
         eraseinit.NbPages = _FLASH_SECTOR_SIZE / FLASH_PAGE_SIZE;
 
-        HAL_FLASH_Unlock();
         rc = HAL_FLASHEx_Erase(&eraseinit, &PageError);
-        HAL_FLASH_Lock();
         if (rc == HAL_OK) {
             return 0;
         }
@@ -154,19 +51,3 @@ stm32l1_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 
     return -1;
 }
-
-static int
-stm32l1_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz)
-{
-    *address = dev->hf_base_addr + _FLASH_SECTOR_SIZE * idx;
-    *sz = _FLASH_SECTOR_SIZE;
-    return 0;
-}
-
-static int
-stm32l1_flash_init(const struct hal_flash *dev)
-{
-    /* TODO: enable ACC64 + prefetch */
-    return 0;
-}
diff --git a/hw/mcu/stm/stm32l1xx/syscfg.yml b/hw/mcu/stm/stm32l1xx/syscfg.yml
index 0f38087..c83ba8c 100644
--- a/hw/mcu/stm/stm32l1xx/syscfg.yml
+++ b/hw/mcu/stm/stm32l1xx/syscfg.yml
@@ -43,6 +43,18 @@ syscfg.defs:
         description: This MCU's UART uses SR register for status.
         value: 1
 
+    MCU_FLASH_ERASED_VAL:
+        description: Value read from erased flash.
+        value: 0
+
+    STM32_FLASH_IS_LINEAR:
+        description: This MCU's Flash has one single sector size.
+        value: 1
+
+    STM32_FLASH_SECTOR_SIZE:
+        description: This MCU's Flash sector size in bytes.
+        value: 4096
+
     SPI_0_MASTER:
         description: 'SPI 0 master'
         value:  0
diff --git a/hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h b/hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h
index e3e7fca..75340f9 100644
--- a/hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h
+++ b/hw/mcu/stm/stm32l4xx/include/mcu/stm32_hal.h
@@ -76,6 +76,17 @@ struct stm32_hal_spi_cfg {
 
 #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();           \
+    } while (0)
+#define FLASH_PROGRAM_TYPE FLASH_TYPEPROGRAM_DOUBLEWORD
+#define STM32_HAL_FLASH_CLEAR_ERRORS()
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/mcu/stm/stm32l4xx/src/hal_flash.c b/hw/mcu/stm/stm32l4xx/src/hal_flash.c
index 07d2745..7330d59 100644
--- a/hw/mcu/stm/stm32l4xx/src/hal_flash.c
+++ b/hw/mcu/stm/stm32l4xx/src/hal_flash.c
@@ -18,99 +18,15 @@
  */
 
 #include <string.h>
-#include "stm32l4xx_hal_def.h"
-#include "stm32l4xx_hal_flash.h"
-#include "stm32l4xx_hal_flash_ex.h"
+#include <syscfg/syscfg.h>
+#include <mcu/stm32_hal.h>
 #include "hal/hal_flash_int.h"
-#include "hal/hal_watchdog.h"
 
-static int stm32l4_flash_read(const struct hal_flash *dev, uint32_t address,
-        void *dst, uint32_t num_bytes);
-static int stm32l4_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes);
-static int stm32l4_flash_erase_sector(const struct hal_flash *dev,
-        uint32_t sector_address);
-static int stm32l4_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz);
-static int stm32l4_flash_init(const struct hal_flash *dev);
+#define _FLASH_SIZE         (MYNEWT_VAL(STM32_FLASH_SIZE_KB) * 1024)
+#define _FLASH_SECTOR_SIZE  MYNEWT_VAL(STM32_FLASH_SECTOR_SIZE)
 
-static const struct hal_flash_funcs stm32l4_flash_funcs = {
-    .hff_read = stm32l4_flash_read,
-    .hff_write = stm32l4_flash_write,
-    .hff_erase_sector = stm32l4_flash_erase_sector,
-    .hff_sector_info = stm32l4_flash_sector_info,
-    .hff_init = stm32l4_flash_init,
-};
-
-#define _FLASH_SIZE            (1024 * 1024)
-#define _FLASH_SECTOR_SIZE     2048
-
-const struct hal_flash stm32l4_flash_dev = {
-    .hf_itf = &stm32l4_flash_funcs,
-    .hf_base_addr = 0x08000000,
-    .hf_size = _FLASH_SIZE,
-    .hf_sector_cnt = _FLASH_SIZE / _FLASH_SECTOR_SIZE,
-    .hf_align = 8,
-    .hf_erased_val = 0xff,
-};
-
-static int
-stm32l4_flash_read(const struct hal_flash *dev, uint32_t address, void *dst,
-        uint32_t num_bytes)
-{
-    memcpy(dst, (void *)address, num_bytes);
-    return 0;
-}
-
-static int
-stm32l4_flash_write(const struct hal_flash *dev, uint32_t address,
-        const void *src, uint32_t num_bytes)
-{
-    uint64_t val;
-    uint8_t align;
-    uint32_t i;
-    int rc;
-    uint32_t num_dwords;
-
-    if (!num_bytes) {
-        return -1;
-    }
-
-    align = dev->hf_align;
-    num_dwords = ((num_bytes - 1) / align) + 1;
-
-    for (i = 0; i < num_dwords; i++) {
-        if (num_bytes < 8) {
-            memcpy(&val, &((uint8_t *)src)[i * align], num_bytes);
-            memset((uint64_t *)&val + num_bytes, 0xff, align - num_bytes);
-        } else {
-            memcpy(&val, &((uint8_t *)src)[i * align], align);
-        }
-
-        rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, val);
-        if (rc != HAL_OK) {
-            return rc;
-        }
-
-        address += align;
-
-        /* underflowing is ok here... */
-        num_bytes -= align;
-
-        /*
-         * Long writes take excessive time, and stall the idle thread, so
-         * tickling the watchdog here to avoid resetting during writes...
-         */
-        if (!(i % 32)) {
-            hal_watchdog_tickle();
-        }
-    }
-
-    return 0;
-}
-
-static int
-stm32l4_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
+int
+stm32_mcu_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 {
     FLASH_EraseInitTypeDef eraseinit;
     uint32_t PageError;
@@ -135,20 +51,3 @@ stm32l4_flash_erase_sector(const struct hal_flash *dev, uint32_t sector_address)
 
     return -1;
 }
-
-static int
-stm32l4_flash_sector_info(const struct hal_flash *dev, int idx,
-        uint32_t *address, uint32_t *sz)
-{
-    *address = dev->hf_base_addr + _FLASH_SECTOR_SIZE * idx;
-    *sz = _FLASH_SECTOR_SIZE;
-    return 0;
-}
-
-static int
-stm32l4_flash_init(const struct hal_flash *dev)
-{
-    HAL_FLASH_Unlock();
-    /* TODO: enable ACC64 + prefetch */
-    return 0;
-}
diff --git a/hw/mcu/stm/stm32l4xx/syscfg.yml b/hw/mcu/stm/stm32l4xx/syscfg.yml
index 3bd9d88..0d0ba08 100644
--- a/hw/mcu/stm/stm32l4xx/syscfg.yml
+++ b/hw/mcu/stm/stm32l4xx/syscfg.yml
@@ -43,6 +43,18 @@ syscfg.defs:
         description: This MCU's UART uses ISR register (not SR) for status.
         value: 0
 
+    MCU_FLASH_ERASED_VAL:
+        description: Value read from erased flash.
+        value: 0xff
+
+    STM32_FLASH_IS_LINEAR:
+        description: This MCU's Flash has one single sector size.
+        value: 1
+
+    STM32_FLASH_SECTOR_SIZE:
+        description: This MCU's Flash sector size in bytes.
+        value: 2048
+
     SPI_0_MASTER:
         description: 'SPI 0 master'
         value:  0