Enable half_page write for STM32L
authorUwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
Tue, 17 Jan 2012 20:28:36 +0000 (21:28 +0100)
committerUwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
Tue, 17 Jan 2012 21:16:55 +0000 (22:16 +0100)
src/stlink-common.c

index 97bc3e14066e98b577e729a067e6f595aadb5e54..2ecddea3dd8bb1f7b93fc3ef71594a026d69703f 100644 (file)
@@ -61,6 +61,8 @@
 #define STM32L_FLASH_SR (STM32L_FLASH_REGS_ADDR + 0x18)
 #define STM32L_FLASH_OBR (STM32L_FLASH_REGS_ADDR + 0x1c)
 #define STM32L_FLASH_WRPR (STM32L_FLASH_REGS_ADDR + 0x20)
+#define FLASH_L1_FPRG 10
+#define FLASH_L1_PROG 3
 
 
 //STM32F4
@@ -1212,6 +1214,57 @@ int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data,
 
 }
 
+int stm32l1_write_half_pages(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned num_half_pages)
+{        
+    unsigned int count;
+    uint32_t val;
+    flash_loader_t fl;
+   
+    ILOG("Starting Half page flash write for STM32L core id\n");
+    /* flash loader initialization */
+    if (init_flash_loader(sl, &fl) == -1) {
+        WLOG("init_flash_loader() == -1\n");
+        return -1;
+    }
+    /* Unlock already done */
+    val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+    val |= (1 << FLASH_L1_FPRG);
+    stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
+    
+    val |= (1 << FLASH_L1_PROG);
+    stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
+    while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0) {}
+
+#define L1_WRITE_BLOCK_SIZE 0x80
+    for (count = 0; count  < num_half_pages; count ++) {
+        if (run_flash_loader(sl, &fl, addr + count * L1_WRITE_BLOCK_SIZE, base + count * L1_WRITE_BLOCK_SIZE, L1_WRITE_BLOCK_SIZE) == -1) {
+            WLOG("l1_run_flash_loader(%#zx) failed! == -1\n", addr + count * L1_WRITE_BLOCK_SIZE);
+            val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+            val &= ~((1 << FLASH_L1_FPRG) |(1 << FLASH_L1_PROG));
+            stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
+            return -1;
+        }
+        /* wait for sr.busy to be cleared */
+        if (sl->verbose >= 1) {
+            /* show progress. writing procedure is slow
+               and previous errors are misleading */
+            fprintf(stdout, "\r%3u/%u halfpages written", count, num_half_pages);
+            fflush(stdout);
+        }
+        while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0) {
+        }
+    }
+    fprintf(stdout, "\n");
+    val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+    val &= ~(1 << FLASH_L1_PROG);
+    stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
+    val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
+    val &= ~(1 << FLASH_L1_FPRG);
+    stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
+
+    return 0;
+}
+
 int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned len) {
     size_t off;
     flash_loader_t fl;
@@ -1332,24 +1385,19 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned
                fprintf(stderr, "pecr.prglock not clear\n");
                return -1;
        }
+        if (len > L1_WRITE_BLOCK_SIZE) {
+            if (stm32l1_write_half_pages(sl, addr, base, len/L1_WRITE_BLOCK_SIZE) == -1){
+                WLOG("\nwrite_half_pages failed == -1\n");
+                return -1;
+            }
+        }  
 
-       /* write word in program memory */
-       for (off = 0; off < len; off += sizeof(uint32_t)) {
+       /* write remainingword in program memory */
+       for (off = (len /L1_WRITE_BLOCK_SIZE)*L1_WRITE_BLOCK_SIZE; off < len; off += sizeof(uint32_t)) {
                uint32_t data;
                write_uint32((unsigned char*) &data, *(uint32_t*) (base + off));
                stlink_write_debug32(sl, addr + off, data);
 
-               if (sl->verbose >= 1) {
-                       if ((off & (sl->flash_pgsz - 1)) == 0) {
-                               /* show progress. writing procedure is slow
-                                  and previous errors are misleading */
-                               const uint32_t pgnum = off / sl->flash_pgsz;
-                               const uint32_t pgcount = len / sl->flash_pgsz;
-                               fprintf(stdout, "\r%3u/%u pages written", pgnum, pgcount);
-                                fflush(stdout);
-                       }
-               }
-
                /* wait for sr.busy to be cleared */
                while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0) {
                }
@@ -1470,6 +1518,7 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) {
 int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, const uint8_t* buf, size_t size) {
 
     reg rr;
+    int i = 0;
     DLOG("Running flash loader, write address:%#x, size: %zd\n", target, size);
     // FIXME This can never return -1
     if (write_buffer_to_sram(sl, fl, buf, size) == -1) {
@@ -1487,7 +1536,6 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
       stlink_write_reg(sl, target, 0); /* target */
       stlink_write_reg(sl, fl->buf_addr, 1); /* source */
       stlink_write_reg(sl, count, 2); /* count (32 bits words) */
-      stlink_write_reg(sl, 0, 3); /* output count */
       stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
 
     } else if (sl->core_id == STM32VL_CORE_ID) {
@@ -1511,8 +1559,16 @@ int run_flash_loader(stlink_t *sl, flash_loader_t* fl, stm32_addr_t target, cons
     stlink_run(sl);
 
     /* wait until done (reaches breakpoint) */
-    while (is_core_halted(sl) == 0) ;
+    while ((is_core_halted(sl) == 0) && (i <10000))
+    {
+        i++;
+    }
 
+    if ( i > 9999) {
+        fprintf(stderr, "run error\n");
+        return -1;
+    }
+        
     /* check written byte count */
     if (sl->core_id == STM32L_CORE_ID) {