Flash loader for STM32L4
authorDave Vandervies <dj3vande@terse.ca>
Mon, 20 Jul 2015 19:15:25 +0000 (15:15 -0400)
committerDave Vandervies <dj3vande@terse.ca>
Sat, 1 Aug 2015 14:01:42 +0000 (10:01 -0400)
flashloaders/stm32l4.s [new file with mode: 0644]
src/stlink-common.c

diff --git a/flashloaders/stm32l4.s b/flashloaders/stm32l4.s
new file mode 100644 (file)
index 0000000..4b90863
--- /dev/null
@@ -0,0 +1,39 @@
+.global start
+.syntax unified
+
+@ Adapted from stm32f4.s
+@ STM32L4's flash controller expects double-word writes, has the flash
+@ controller mapped in a different location with the registers we care about
+@ moved down from the base address, and has BSY moved to bit 16 of SR.
+@ r0 = source
+@ r1 = target
+@ r2 = wordcount
+@ r3 = flash_base
+@ r4 = temp
+@ r5 = temp
+
+start:
+    ldr     r3, flash_base
+next:
+    cbz     r2, done
+    ldr     r4, [r0]            /* copy doubleword from source to target */
+    ldr     r5, [r0, #4]
+    str     r4, [r1]
+    str     r5, [r1, #4]
+
+wait:
+    ldrh    r4, [r3, #0x12]     /* high half of status register */
+    tst     r4, #1              /* BSY = bit 16 */
+    bne     wait
+
+    add     r0, #8
+    add     r1, #8
+    sub     r2, #2
+    b       next
+done:
+    bkpt
+
+.align 2
+
+flash_base:
+    .word 0x40022000
index 07b8d6765aedc7028c2dad397e8abb323aaf631c..37beb905fca067d827e95c4528b9f8e0d5dcb02f 100644 (file)
@@ -1503,6 +1503,25 @@ 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_stm32l4[] = {
+        // flashloaders/stm32l4.s
+        0x08, 0x4b,             // start: ldr   r3, [pc, #32] ; <flash_base>
+        0x72, 0xb1,             // next:  cbz   r2, <done>
+        0x04, 0x68,             //        ldr   r4, [r0, #0]
+        0x45, 0x68,             //        ldr   r5, [r0, #4]
+        0x0c, 0x60,             //        str   r4, [r1, #0]
+        0x4d, 0x60,             //        str   r5, [r1, #4]
+        0x5c, 0x8a,             // wait:  ldrh  r4, [r3, #18]
+        0x14, 0xf0, 0x01, 0x0f, //        tst.w r4, #1
+        0xfb, 0xd1,             //        bne.n <wait>
+        0x00, 0xf1, 0x08, 0x00, //        add.w r0, r0, #8
+        0x01, 0xf1, 0x08, 0x01, //        add.w r1, r1, #8
+        0xa2, 0xf1, 0x02, 0x02, //        add.w r2, r2, #2
+        0xef, 0xe7,             //        b.n   <next>
+        0x00, 0xbe,             // done:  bkpt  0x0000
+        0x00, 0x20, 0x02, 0x40  // flash_base:  .word 0x40022000
+    };
+
     const uint8_t* loader_code;
     size_t loader_size;
 
@@ -1535,6 +1554,9 @@ int write_loader_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t* size) {
     } else if (sl->chip_id == STM32_CHIPID_L0) {
         loader_code = loader_code_stm32l0;
         loader_size = sizeof(loader_code_stm32l0);
+    } else if (sl->chip_id == STM32_CHIPID_L4) {
+        loader_code = loader_code_stm32l4;
+        loader_size = sizeof(loader_code_stm32l4);
     } else {
         ELOG("unknown coreid, not sure what flash loader to use, aborting!: %x\n", sl->core_id);
         return -1;
@@ -1710,10 +1732,11 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
         (sl->chip_id == STM32_CHIPID_F4_LP) ||
         (sl->chip_id == STM32_CHIPID_F4_HD) ||
         (sl->chip_id == STM32_CHIPID_F411RE) ||
-        (sl->chip_id == STM32_CHIPID_F446)) {
+        (sl->chip_id == STM32_CHIPID_F446) ||
+        (sl->chip_id == STM32_CHIPID_L4)) {
         /* todo: check write operation */
 
-        ILOG("Starting Flash write for F2/F4\n");
+        ILOG("Starting Flash write for F2/F4/L4\n");
         /* flash loader initialization */
         if (init_flash_loader(sl, &fl) == -1) {
             ELOG("init_flash_loader() == -1\n");
@@ -1724,14 +1747,23 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
         unlock_flash_if(sl);
 
         /* TODO: Check that Voltage range is 2.7 - 3.6 V */
-        /* set parallelisim to 32 bit*/
-        int voltage = stlink_target_voltage(sl);
-        if (voltage > 2700) {
-            printf("enabling 32-bit flash writes\n");
-            write_flash_cr_psiz(sl, 2);
+        if (sl->chip_id != STM32_CHIPID_L4) {
+            /* set parallelisim to 32 bit*/
+            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);
+            }
         } 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);
+            /* L4 does not have a byte-write mode */
+            int voltage = stlink_target_voltage(sl);
+            if (voltage <= 2700) {
+                printf("Target voltage (%d mV) too low for flash writes!\n", voltage);
+                return -1;
+            }
         }
 
         /* set programming mode */
@@ -1960,10 +1992,13 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
 
     } 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) ||
-            (sl->chip_id == STM32_CHIPID_F446)) {
+            (sl->chip_id == STM32_CHIPID_F446) || (sl->chip_id == STM32_CHIPID_L4)) {
 
         size_t count = size / sizeof(uint32_t);
         if (size % sizeof(uint32_t)) ++count;
+        if (sl->chip_id == STM32_CHIPID_L4) {
+            if (count % 2) ++count;
+        }
 
         /* setup core */
         stlink_write_reg(sl, fl->buf_addr, 0); /* source */
@@ -2021,7 +2056,7 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
 
     } 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) ||
-            (sl->chip_id == STM32_CHIPID_F446)) {
+            (sl->chip_id == STM32_CHIPID_F446) || (sl->chip_id == STM32_CHIPID_L4)) {
 
         stlink_read_reg(sl, 2, &rr);
         if (rr.r[2] != 0) {