Merge pull request #223 from troth/troth/fix-compiler-warning-32bit
[fw/stlink] / src / stlink-common.c
index 1ac3d6029a7d4f7cfb1be2db8de97b10d611d495..545434b4ef1374977c7957e005d1863dc461ce0f 100644 (file)
 #include "stlink-common.h"
 #include "uglylogging.h"
 
+#ifndef _WIN32
+#define O_BINARY 0
+#endif
+
+
 #define LOG_TAG __FILE__
 #define DLOG(format, args...)         ugly_log(UDEBUG, LOG_TAG, format, ## args)
 #define ILOG(format, args...)         ugly_log(UINFO, LOG_TAG, format, ## args)
@@ -138,7 +143,8 @@ static inline uint32_t read_flash_obr(stlink_t *sl) {
 
 static inline uint32_t read_flash_cr(stlink_t *sl) {
     uint32_t res;
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) ||(sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
         res = stlink_read_debug32(sl, FLASH_F4_CR);
     else
         res = stlink_read_debug32(sl, FLASH_CR);
@@ -150,7 +156,8 @@ static inline uint32_t read_flash_cr(stlink_t *sl) {
 
 static inline unsigned int is_flash_locked(stlink_t *sl) {
     /* return non zero for true */
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
         return read_flash_cr(sl) & (1 << FLASH_F4_CR_LOCK);
     else
         return read_flash_cr(sl) & (1 << FLASH_CR_LOCK);
@@ -162,7 +169,8 @@ static void unlock_flash(stlink_t *sl) {
        an invalid sequence results in a definitive lock of
        the FPEC block until next reset.
      */
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
        stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY1);
         stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY2);
     } else {
@@ -187,7 +195,8 @@ static int unlock_flash_if(stlink_t *sl) {
 }
 
 static void lock_flash(stlink_t *sl) {
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
        const uint32_t n = read_flash_cr(sl) | (1 << FLASH_F4_CR_LOCK);
        stlink_write_debug32(sl, FLASH_F4_CR, n);
     } else {
@@ -199,7 +208,8 @@ static void lock_flash(stlink_t *sl) {
 
 
 static void set_flash_cr_pg(stlink_t *sl) {
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
                uint32_t x = read_flash_cr(sl);
                x |= (1 << FLASH_CR_PG);
        stlink_write_debug32(sl, FLASH_F4_CR, x);
@@ -211,7 +221,8 @@ static void set_flash_cr_pg(stlink_t *sl) {
 
 static void __attribute__((unused)) clear_flash_cr_pg(stlink_t *sl) {
     const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PG);
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
        stlink_write_debug32(sl, FLASH_F4_CR, n);
     else
         stlink_write_debug32(sl, FLASH_CR, n);
@@ -228,7 +239,8 @@ static void __attribute__((unused)) clear_flash_cr_per(stlink_t *sl) {
 }
 
 static void set_flash_cr_mer(stlink_t *sl) {
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
         stlink_write_debug32(sl, FLASH_F4_CR,
                              stlink_read_debug32(sl, FLASH_F4_CR) | (1 << FLASH_CR_MER));
     else
@@ -237,7 +249,8 @@ static void set_flash_cr_mer(stlink_t *sl) {
 }
 
 static void __attribute__((unused)) clear_flash_cr_mer(stlink_t *sl) {
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
         stlink_write_debug32(sl, FLASH_F4_CR,
                              stlink_read_debug32(sl, FLASH_F4_CR) & ~(1 << FLASH_CR_MER));
     else
@@ -246,7 +259,8 @@ static void __attribute__((unused)) clear_flash_cr_mer(stlink_t *sl) {
 }
 
 static void set_flash_cr_strt(stlink_t *sl) {
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
         uint32_t x = read_flash_cr(sl);
         x |= (1 << FLASH_F4_CR_STRT);
         stlink_write_debug32(sl, FLASH_F4_CR, x);
@@ -262,7 +276,8 @@ static inline uint32_t read_flash_acr(stlink_t *sl) {
 
 static inline uint32_t read_flash_sr(stlink_t *sl) {
     uint32_t res;
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
         res = stlink_read_debug32(sl, FLASH_F4_SR);
     else
         res = stlink_read_debug32(sl, FLASH_SR);
@@ -271,7 +286,8 @@ static inline uint32_t read_flash_sr(stlink_t *sl) {
 }
 
 static inline unsigned int is_flash_busy(stlink_t *sl) {
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD))
         return read_flash_sr(sl) & (1 << FLASH_F4_SR_BSY);
     else
         return read_flash_sr(sl) & (1 << FLASH_SR_BSY);
@@ -418,6 +434,7 @@ int stlink_load_device_params(stlink_t *sl) {
     const chip_params_t *params = NULL;
     sl->core_id = stlink_core_id(sl);
     uint32_t chip_id = stlink_chip_id(sl);
+    uint32_t flash_size;
 
     sl->chip_id = chip_id & 0xfff;
     /* Fix chip_id for F4 rev A errata , Read CPU ID, as CoreID is the same for F2/F4*/
@@ -441,14 +458,21 @@ int stlink_load_device_params(stlink_t *sl) {
     // These are fixed...
     sl->flash_base = STM32_FLASH_BASE;
     sl->sram_base = STM32_SRAM_BASE;
-
-    // read flash size from hardware, if possible...
-    if (sl->chip_id == STM32_CHIPID_F2) {
-        sl->flash_size = 0x100000; /* Use maximum, User must care!*/
-    } else if (sl->chip_id == STM32_CHIPID_F4) {
-               sl->flash_size = 0x100000;                      //todo: RM0090 error; size register same address as unique ID
+    flash_size = stlink_read_debug32(sl,(params->flash_size_reg) & ~3);
+    if (params->flash_size_reg & 2)
+        flash_size = flash_size >>16;
+    flash_size = flash_size & 0xffff;
+
+    if ((sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS) && ( flash_size == 0 )) {
+            sl->flash_size = 128 * 1024;
+    } else if ((sl->chip_id & 0xFFF) == STM32_CHIPID_L1_HIGH) {
+        // 0 is 384k and 1 is 256k
+        if ( flash_size == 0 ) {
+            sl->flash_size = 384 * 1024;
+        } else {
+            sl->flash_size = 256 * 1024;
+        }
     } else {
-        uint32_t flash_size = stlink_read_debug32(sl, params->flash_size_reg) & 0xffff;
         sl->flash_size = flash_size * 1024;
     }
     sl->flash_pgsz = params->flash_pagesize;
@@ -528,6 +552,22 @@ void stlink_version(stlink_t *sl) {
     }
 }
 
+int stlink_target_voltage(stlink_t *sl) {
+    int voltage = -1;
+    DLOG("*** reading target voltage\n");
+    if (sl->backend->target_voltage != NULL) {
+        voltage = sl->backend->target_voltage(sl);
+       if (voltage != -1) {
+            DLOG("target voltage = %ldmV\n", voltage);
+       } else {
+            DLOG("error reading target voltage\n");
+       }
+    } else {
+        DLOG("reading voltage not supported by backend\n");
+    }
+    return voltage;
+}
+
 uint32_t stlink_read_debug32(stlink_t *sl, uint32_t addr) {
     uint32_t data = sl->backend->read_debug32(sl, addr);
     DLOG("*** stlink_read_debug32 %x is %#x\n", data, addr);
@@ -757,7 +797,7 @@ static int map_file(mapped_file_t* mf, const char* path) {
     int error = -1;
     struct stat st;
 
-    const int fd = open(path, O_RDONLY);
+    const int fd = open(path, O_RDONLY | O_BINARY);
     if (fd == -1) {
         fprintf(stderr, "open(%s) == -1\n", path);
         return -1;
@@ -829,6 +869,7 @@ int stlink_fwrite_sram
     size_t off;
     mapped_file_t mf = MAPPED_FILE_INITIALIZER;
 
+
     if (map_file(&mf, path) == -1) {
         fprintf(stderr, "map_file() == -1\n");
         return -1;
@@ -849,7 +890,6 @@ int stlink_fwrite_sram
         fprintf(stderr, "unaligned addr or size\n");
         goto on_error;
     }
-
     /* do the copy by 1k blocks */
     for (off = 0; off < mf.len; off += 1024) {
         size_t size = 1024;
@@ -890,7 +930,8 @@ int stlink_fread(stlink_t* sl, const char* path, stm32_addr_t addr, size_t size)
     int error = -1;
     size_t off;
     int num_empty = 0;
-    unsigned char erased_pattern = (sl->chip_id == STM32_CHIPID_L1_MEDIUM)?0:0xff;
+    unsigned char erased_pattern = (sl->chip_id == STM32_CHIPID_L1_MEDIUM  || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
+                                     || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) ? 0:0xff;
 
     const int fd = open(path, O_RDWR | O_TRUNC | O_CREAT, 00700);
     if (fd == -1) {
@@ -972,7 +1013,8 @@ uint32_t calculate_F4_sectornum(uint32_t flashaddr){
 }
 
 uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){
-       if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
+       if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+      (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
                uint32_t sector=calculate_F4_sectornum(flashaddr);
                if (sector<4) sl->flash_pgsz=0x4000;
                else if(sector<5) sl->flash_pgsz=0x10000;
@@ -989,7 +1031,8 @@ uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){
  */
 int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
 {
-  if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) ||  (sl->chip_id == STM32_CHIPID_F4_DE) ||
+      (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
     /* wait for ongoing op to finish */
     wait_flash_busy(sl);
 
@@ -1015,30 +1058,35 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
 #if DEBUG_FLASH
        fprintf(stdout, "Erase Final CR:0x%x\n", read_flash_cr(sl));
 #endif
-  } else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
+  } else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
+               || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) {
 
     uint32_t val;
 
-    /* disable pecr protection */
-    stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x89abcdef);
-    stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x02030405);
-
-    /* check pecr.pelock is cleared */
+    /* check if the locks are set */
     val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
-    if (val & (1 << 0)) {
-      WLOG("pecr.pelock not clear (%#x)\n", val);
-      return -1;
-    }
+    if((val & (1<<0))||(val & (1<<1))) {
+        /* disable pecr protection */
+        stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x89abcdef);
+        stlink_write_debug32(sl, STM32L_FLASH_PEKEYR, 0x02030405);
+
+        /* check pecr.pelock is cleared */
+        val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+        if (val & (1 << 0)) {
+            WLOG("pecr.pelock not clear (%#x)\n", val);
+            return -1;
+        }
 
-    /* unlock program memory */
-    stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x8c9daebf);
-    stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x13141516);
+        /* unlock program memory */
+        stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x8c9daebf);
+        stlink_write_debug32(sl, STM32L_FLASH_PRGKEYR, 0x13141516);
 
-    /* check pecr.prglock is cleared */
-    val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
-    if (val & (1 << 1)) {
-      WLOG("pecr.prglock not clear (%#x)\n", val);
-      return -1;
+        /* check pecr.prglock is cleared */
+        val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+        if (val & (1 << 1)) {
+            WLOG("pecr.prglock not clear (%#x)\n", val);
+            return -1;
+        }
     }
 
     /* unused: unlock the option byte block */
@@ -1085,7 +1133,10 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
     val = stlink_read_debug32(sl, STM32L_FLASH_PECR)
         | (1 << 0) | (1 << 1) | (1 << 2);
     stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
-  } else if (sl->core_id == STM32VL_CORE_ID || sl->core_id == STM32F0_CORE_ID || sl->chip_id == STM32_CHIPID_F3 || sl->chip_id == STM32_CHIPID_F37x) {
+  } else if (sl->core_id == STM32VL_CORE_ID 
+            || sl->core_id == STM32F0_CORE_ID 
+            || sl->chip_id == STM32_CHIPID_F3 
+            || sl->chip_id == STM32_CHIPID_F37x) {
     /* wait for ongoing op to finish */
     wait_flash_busy(sl);
 
@@ -1117,7 +1168,8 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
 }
 
 int stlink_erase_flash_mass(stlink_t *sl) {
-    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS 
+       || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) {
         /* erase each page */
         int i = 0, num_pages = sl->flash_size/sl->flash_pgsz;
         for (i = 0; i < num_pages; i++) {
@@ -1287,16 +1339,18 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
     const uint8_t* loader_code;
     size_t loader_size;
 
-    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) { /* stm32l */
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
+               || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) { /* stm32l */
         loader_code = loader_code_stm32l;
         loader_size = sizeof(loader_code_stm32l);
     } else if (sl->core_id == STM32VL_CORE_ID || sl->chip_id == STM32_CHIPID_F3  || sl->chip_id == STM32_CHIPID_F37x) {
         loader_code = loader_code_stm32vl;
         loader_size = sizeof(loader_code_stm32vl);
-    } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
+    } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4 || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+               sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD){
         loader_code = loader_code_stm32f4;
         loader_size = sizeof(loader_code_stm32f4);
-    } else if (sl->chip_id == STM32_CHIPID_F0) {
+    } else if (sl->chip_id == STM32_CHIPID_F0 || sl->chip_id == STM32_CHIPID_F0_CAN || sl->chip_id == STM32_CHIPID_F0_SMALL) {
         loader_code = loader_code_stm32f0;
         loader_size = sizeof(loader_code_stm32f0);
     } else {
@@ -1415,7 +1469,7 @@ int stm32l1_write_half_pages(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uns
     return 0;
 }
 
-int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned len) {
+int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t len) {
     size_t off;
     flash_loader_t fl;
     ILOG("Attempting to write %d (%#x) bytes to stm32 address: %u (%#x)\n",
@@ -1461,7 +1515,8 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned
     ILOG("Finished erasing %d pages of %d (%#x) bytes\n",
         page_count, sl->flash_pgsz, sl->flash_pgsz);
 
-    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
+    if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4) || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+        (sl->chip_id == STM32_CHIPID_F4_LP) || (sl->chip_id == STM32_CHIPID_F4_HD)) {
        /* todo: check write operation */
 
         ILOG("Starting Flash write for F2/F4\n");
@@ -1527,7 +1582,8 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned
 
     }  //STM32F4END
 
-    else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM)    {
+    else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
+               || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) {
        /* use fast word write. todo: half page. */
        uint32_t val;
 
@@ -1683,7 +1739,8 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) {
     /* write the file in flash at addr */
     int err;
     unsigned int num_empty = 0, index;
-    unsigned char erased_pattern =(sl->chip_id == STM32_CHIPID_L1_MEDIUM)?0:0xff;
+    unsigned char erased_pattern =(sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
+       || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE )?0:0xff;
     mapped_file_t mf = MAPPED_FILE_INITIALIZER;
     if (map_file(&mf, path) == -1) {
         ELOG("map_file() == -1\n");
@@ -1695,8 +1752,10 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) {
        else
            num_empty = 0;
     }
+    /* Round down to words */
+    num_empty -= (num_empty & 3);
     if(num_empty != 0) {
-       ILOG("Ignoring %d bytes of Zeros at end of file\n",num_empty);
+       ILOG("Ignoring %d bytes of 0x%02x at end of file\n", num_empty, erased_pattern);
        mf.len -= num_empty;
     }
     err = stlink_write_flash(sl, addr, mf.base, mf.len);
@@ -1721,7 +1780,8 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
         return -1;
     }
 
-    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM  || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
+       || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) {
 
         size_t count = size / sizeof(uint32_t);
         if (size % sizeof(uint32_t)) ++count;
@@ -1744,7 +1804,8 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
         stlink_write_reg(sl, 0, 3); /* flash bank 0 (input) */
         stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
 
-    } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
+    } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4 || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+               sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD) {
 
         size_t count = size / sizeof(uint32_t);
         if (size % sizeof(uint32_t)) ++count;
@@ -1763,20 +1824,22 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
     /* run loader */
     stlink_run(sl);
 
-#define WAIT_ROUNDS 1000
+#define WAIT_ROUNDS 10000
     /* wait until done (reaches breakpoint) */
     for (i = 0; i < WAIT_ROUNDS; i++) {
+        usleep(10);
         if (is_core_halted(sl))
             break;
     }
 
     if (i >= WAIT_ROUNDS) {
-        fatal("flash loader run error\n");
+        ELOG("flash loader run error\n");
         return -1;
     }
 
     /* check written byte count */
-    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
+       || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE ) {
 
       size_t count = size / sizeof(uint32_t);
       if (size % sizeof(uint32_t)) ++count;
@@ -1795,7 +1858,8 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
         return -1;
       }
 
-    } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
+    } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4 || (sl->chip_id == STM32_CHIPID_F4_DE) ||
+               sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD) {
 
         stlink_read_reg(sl, 2, &rr);
         if (rr.r[2] != 0) {