+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) {
+ }
+ }
+ 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;
+}
+