+ ILOG("Finished erasing %d pages of %d (%#x) bytes\n",
+ page_count, sl->flash_pgsz, sl->flash_pgsz);
+
+ if (sl->chip_id == STM32F4_CHIP_ID) {
+ /* todo: check write operation */
+
+ /* First unlock the cr */
+ unlock_flash_if(sl);
+
+ /* set parallelisim to 32 bit*/
+ write_flash_cr_psiz(sl, 2);
+
+ /* set programming mode */
+ set_flash_cr_pg(sl);
+
+#define PROGRESS_CHUNK_SIZE 0x1000
+ /* write a word in program memory */
+ for (off = 0; off < len; off += sizeof(uint32_t)) {
+ if (sl->verbose >= 1) {
+ if ((off & (PROGRESS_CHUNK_SIZE - 1)) == 0) {
+ /* show progress. writing procedure is slow
+ and previous errors are misleading */
+ const uint32_t pgnum = (off / PROGRESS_CHUNK_SIZE)+1;
+ const uint32_t pgcount = len / PROGRESS_CHUNK_SIZE;
+ fprintf(stdout, "Writing %ukB chunk %u out of %u\n", PROGRESS_CHUNK_SIZE/1024, pgnum, pgcount);
+ }
+ }
+
+ memcpy(sl->q_buf, (const void*)(base + off), sizeof(uint32_t));
+ stlink_write_mem32(sl, addr + off, sizeof(uint32_t));
+
+ /* wait for sr.busy to be cleared */
+ wait_flash_busy(sl);
+
+ }
+ /* Relock flash */
+ lock_flash(sl);
+
+#if 0 /* todo: debug mode */
+ fprintf(stdout, "Final CR:0x%x\n", read_flash_cr(sl));
+#endif
+
+
+
+ } //STM32F4END
+
+ else if (sl->core_id == STM32L_CORE_ID) {
+ /* use fast word write. todo: half page. */
+ uint32_t val;
+
+#if 0 /* todo: check write operation */
+
+ uint32_t nwrites = sl->flash_pgsz;
+
+ redo_write:
+
+#endif /* todo: check write operation */
+
+ /* disable pecr protection */
+ write_uint32(sl->q_buf, 0x89abcdef);
+ stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t));
+ write_uint32(sl->q_buf, 0x02030405);
+ stlink_write_mem32(sl, STM32L_FLASH_PEKEYR, sizeof(uint32_t));
+
+ /* check pecr.pelock is cleared */
+ stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+ val = read_uint32(sl->q_buf, 0);
+ if (val & (1 << 0)) {
+ fprintf(stderr, "pecr.pelock not clear\n");
+ return -1;
+ }
+
+ /* unlock program memory */
+ write_uint32(sl->q_buf, 0x8c9daebf);
+ stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t));
+ write_uint32(sl->q_buf, 0x13141516);
+ stlink_write_mem32(sl, STM32L_FLASH_PRGKEYR, sizeof(uint32_t));
+
+ /* check pecr.prglock is cleared */
+ stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+ val = read_uint32(sl->q_buf, 0);
+ if (val & (1 << 1)) {
+ fprintf(stderr, "pecr.prglock not clear\n");
+ return -1;
+ }
+
+ /* write a word in program memory */
+ for (off = 0; off < len; off += sizeof(uint32_t)) {
+ 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, "%u pages written out of %u\n", pgnum, pgcount);
+ }
+ }
+
+ memcpy(sl->q_buf, (const void*)(base + off), sizeof(uint32_t));
+ stlink_write_mem32(sl, addr + off, sizeof(uint32_t));
+
+ /* wait for sr.busy to be cleared */
+ while (1) {
+ stlink_read_mem32(sl, STM32L_FLASH_SR, sizeof(uint32_t));
+ if ((read_uint32(sl->q_buf, 0) & (1 << 0)) == 0) break ;
+ }
+
+#if 0 /* todo: check redo write operation */
+
+ /* check written bytes. todo: should be on a per page basis. */
+ stlink_read_mem32(sl, addr + off, sizeof(uint32_t));
+ if (memcmp(sl->q_buf, base + off, sizeof(uint32_t))) {
+ /* re erase the page and redo the write operation */
+ uint32_t page;
+ uint32_t val;
+
+ /* fail if successive write count too low */
+ if (nwrites < sl->flash_pgsz) {
+ fprintf(stderr, "writes operation failure count too high, aborting\n");
+ return -1;
+ }
+
+ nwrites = 0;
+
+ /* assume addr aligned */
+ if (off % sl->flash_pgsz) off &= ~(sl->flash_pgsz - 1);
+ page = addr + off;
+
+ fprintf(stderr, "invalid write @0x%x(0x%x): 0x%x != 0x%x. retrying.\n",
+ page, addr + off, read_uint32(base + off, 0), read_uint32(sl->q_buf, 0));
+
+ /* reset lock bits */
+ stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+ val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2);
+ write_uint32(sl->q_buf, val);
+ stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+
+ stlink_erase_flash_page(sl, page);
+
+ goto redo_write;
+ }
+
+ /* increment successive writes counter */
+ ++nwrites;
+
+#endif /* todo: check redo write operation */
+ }
+ /* reset lock bits */
+ stlink_read_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+ val = read_uint32(sl->q_buf, 0) | (1 << 0) | (1 << 1) | (1 << 2);
+ write_uint32(sl->q_buf, val);
+ stlink_write_mem32(sl, STM32L_FLASH_PECR, sizeof(uint32_t));
+ } else if (sl->core_id == STM32VL_CORE_ID) {
+ ILOG("Starting Flash write for VL core id\n");
+ /* flash loader initialization */
+ if (init_flash_loader(sl, &fl) == -1) {
+ WLOG("init_flash_loader() == -1\n");
+ return -1;
+ }