STM32F4 8-bit support for 1.8v operation
[fw/stlink] / src / stlink-common.c
index 6e327f02877a854ed2cac3aed54923e7cdac21ba..972c9f31c66ab265fc66fe13c78cf9bf27f5433f 100644 (file)
@@ -65,6 +65,7 @@
 
 //STM32L0x flash register base and offsets
 //same as 32L1 above
+// RM0090 - DM00031020.pdf
 #define STM32L0_FLASH_REGS_ADDR ((uint32_t)0x40022000)
 #define FLASH_ACR_OFF     ((uint32_t) 0x00)
 #define FLASH_PECR_OFF    ((uint32_t) 0x04)
@@ -463,6 +464,8 @@ int stlink_load_device_params(stlink_t *sl) {
 
     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 == STM32_CHIPID_L1_CAT2) {
+        sl->flash_size = (flash_size & 0xff) * 1024;
     } else if ((sl->chip_id & 0xFFF) == STM32_CHIPID_L1_HIGH) {
         // 0 is 384k and 1 is 256k
         if ( flash_size == 0 ) {
@@ -934,8 +937,9 @@ 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  || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
-            || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE) ? 0:0xff;
+    unsigned char erased_pattern = (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_CAT2
+            || 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) {
@@ -1074,9 +1078,9 @@ 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 || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
-            || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE
-            || sl->chip_id == STM32_CHIPID_L0) {
+    } else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_CAT2
+            || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS || sl->chip_id == STM32_CHIPID_L1_HIGH
+            || sl->chip_id == STM32_CHIPID_L152_RE || sl->chip_id == STM32_CHIPID_L0) {
 
         uint32_t val;
         uint32_t flash_regs_base;
@@ -1145,6 +1149,7 @@ int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
     } 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_F303_HIGH
             || sl->chip_id == STM32_CHIPID_F37x
             || sl->chip_id == STM32_CHIPID_F334)  {
         /* wait for ongoing op to finish */
@@ -1178,9 +1183,9 @@ 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 || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS 
-            || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE
-            || sl->chip_id == STM32_CHIPID_L0) {
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_CAT2
+            || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS || sl->chip_id == STM32_CHIPID_L1_HIGH
+            || sl->chip_id == STM32_CHIPID_L152_RE || sl->chip_id == STM32_CHIPID_L0) {
         /* erase each page */
         int i = 0, num_pages = sl->flash_size/sl->flash_pgsz;
         for (i = 0; i < num_pages; i++) {
@@ -1338,7 +1343,7 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
         0x04, 0xe0,
 
         0x0c, 0x68,
-        0x04, 0x66,
+        0x04, 0x60,
         0x01, 0x33,
         0x04, 0x31,
         0x04, 0x30,
@@ -1370,28 +1375,61 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
         0x00, 0x3c, 0x02, 0x40,
     };
 
+    static const uint8_t loader_code_stm32f4_lv[] = {
+        // flashloaders/stm32f4lv.s
+        0x92, 0x00,
+
+        0x08, 0x4b,
+        0x62, 0xb1,
+        0x04, 0x78,
+        0x0c, 0x70,
+
+        0xdc, 0x89,
+        0x14, 0xf0, 0x01, 0x0f,
+        0xfb, 0xd1,
+        0x00, 0xf1, 0x01, 0x00,
+        0x01, 0xf1, 0x01, 0x01,
+        0xa2, 0xf1, 0x01, 0x02,
+        0xf1, 0xe7,
+
+        0x00, 0xbe,
+        0x00, 0xbf,
+
+        0x00, 0x3c, 0x02, 0x40,
+    };
+
     const uint8_t* loader_code;
     size_t loader_size;
 
-    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 */
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_CAT2
+            || 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 || sl->chip_id == STM32_CHIPID_F334) {
+    } else if (sl->core_id == STM32VL_CORE_ID 
+            || sl->chip_id == STM32_CHIPID_F3
+            || sl->chip_id == STM32_CHIPID_F303_HIGH
+            || sl->chip_id == STM32_CHIPID_F37x
+            || sl->chip_id == STM32_CHIPID_F334) {
         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 || (sl->chip_id == STM32_CHIPID_F4_DE) ||
             sl->chip_id == STM32_CHIPID_F4_LP || sl->chip_id == STM32_CHIPID_F4_HD || (sl->chip_id == STM32_CHIPID_F411RE)){
-        loader_code = loader_code_stm32f4;
-        loader_size = sizeof(loader_code_stm32f4);
-    } else if (sl->chip_id == STM32_CHIPID_F0 || sl->chip_id == STM32_CHIPID_F04 || sl->chip_id == STM32_CHIPID_F0_CAN || sl->chip_id == STM32_CHIPID_F0_SMALL) {
+        int voltage = stlink_target_voltage(sl);
+        if (voltage > 2700) {
+            loader_code = loader_code_stm32f4;
+            loader_size = sizeof(loader_code_stm32f4);
+        } else {
+            loader_code = loader_code_stm32f4_lv;
+            loader_size = sizeof(loader_code_stm32f4_lv);
+        }
+    } else if (sl->chip_id == STM32_CHIPID_F0 || sl->chip_id == STM32_CHIPID_F04 || sl->chip_id == STM32_CHIPID_F0_CAN || sl->chip_id == STM32_CHIPID_F0_SMALL || sl->chip_id == STM32_CHIPID_F09X) {
         loader_code = loader_code_stm32f0;
         loader_size = sizeof(loader_code_stm32f0);
     } else if (sl->chip_id == STM32_CHIPID_L0) {
-               loader_code = loader_code_stm32l0;
-               loader_size = sizeof(loader_code_stm32l0);
-       } else {
+        loader_code = loader_code_stm32l0;
+        loader_size = sizeof(loader_code_stm32l0);
+    } else {
         ELOG("unknown coreid, not sure what flash loader to use, aborting!: %x\n", sl->core_id);
         return -1;
     }
@@ -1580,7 +1618,14 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
 
         /* TODO: Check that Voltage range is 2.7 - 3.6 V */
         /* set parallelisim to 32 bit*/
-        write_flash_cr_psiz(sl, 2);
+        int voltage = stlink_target_voltage(sl);
+        if (voltage > 2700) {
+            printf("enabling 32-bit flash writes\n");
+            write_flash_cr_psiz(sl, 2);
+        } else {
+            printf("Target voltage (%d mV) too low for 32-bit flash, using 8-bit flash writes\n", voltage);
+            write_flash_cr_psiz(sl, 0);
+        }
 
         /* set programming mode */
         set_flash_cr_pg(sl);
@@ -1603,9 +1648,9 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
 
     }  //STM32F4END
 
-    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
-            || sl->chip_id == STM32_CHIPID_L0) {
+    else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_CAT2
+            || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS || sl->chip_id == STM32_CHIPID_L1_HIGH
+            || sl->chip_id == STM32_CHIPID_L152_RE || sl->chip_id == STM32_CHIPID_L0) {
         /* use fast word write. todo: half page. */
         uint32_t val;
         uint32_t flash_regs_base;
@@ -1682,6 +1727,7 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
     } 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_F303_HIGH ||
                 sl->chip_id == STM32_CHIPID_F334 ||
                 sl->chip_id == STM32_CHIPID_F37x) {
         ILOG("Starting Flash write for VL/F0/F3 core id\n");
@@ -1733,8 +1779,9 @@ 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 || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
-            || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE )?0:0xff;
+    unsigned char erased_pattern = (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_CAT2
+            || 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");
@@ -1774,9 +1821,9 @@ 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  || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS
-            || sl->chip_id == STM32_CHIPID_L1_HIGH || sl->chip_id == STM32_CHIPID_L152_RE
-            || sl->chip_id == STM32_CHIPID_L0) {
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_CAT2
+            || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS || sl->chip_id == STM32_CHIPID_L1_HIGH
+            || sl->chip_id == STM32_CHIPID_L152_RE || sl->chip_id == STM32_CHIPID_L0) {
 
         size_t count = size / sizeof(uint32_t);
         if (size % sizeof(uint32_t)) ++count;
@@ -1790,6 +1837,7 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
     } 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_F303_HIGH ||
                 sl->chip_id == STM32_CHIPID_F37x ||
                 sl->chip_id == STM32_CHIPID_F334) {
 
@@ -1837,9 +1885,9 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
     }
 
     /* check written byte count */
-    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
-            || sl->chip_id == STM32_CHIPID_L0) {
+    if (sl->chip_id == STM32_CHIPID_L1_MEDIUM || sl->chip_id == STM32_CHIPID_L1_CAT2
+            || sl->chip_id == STM32_CHIPID_L1_MEDIUM_PLUS || sl->chip_id == STM32_CHIPID_L1_HIGH
+            || sl->chip_id == STM32_CHIPID_L152_RE || sl->chip_id == STM32_CHIPID_L0) {
 
         size_t count = size / sizeof(uint32_t);
         if (size % sizeof(uint32_t)) ++count;
@@ -1853,6 +1901,7 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
     } 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_F303_HIGH ||
                 sl->chip_id == STM32_CHIPID_F37x ||
                 sl->chip_id == STM32_CHIPID_F334) {