- flash_loader_t fl;
-
- /* check addr range is inside the flash */
- if (addr < sl->flash_base) {
- fprintf(stderr, "addr too low\n");
- return -1;
- } else if ((addr + len) < addr) {
- fprintf(stderr, "addr overruns\n");
- return -1;
- } else if ((addr + len) > (sl->flash_base + sl->flash_size)) {
- fprintf(stderr, "addr too high\n");
- return -1;
- } else if ((addr & 1) || (len & 1)) {
- fprintf(stderr, "unaligned addr or size\n");
- return -1;
- }
-
- /* needed for specializing loader */
- stlink_core_id(sl);
-
- if (sl->core_id == 0x2ba01477) /* stm32l */
- {
- /* use fast word write. todo: half page. */
- /* todo, factorize with stlink_fwrite_flash */
-
- uint32_t val;
- uint32_t off;
-
- for (off = 0; off < len; off += sl->flash_pgsz) {
- /* addr must be an addr inside the page */
- if (stlink_erase_flash_page(sl, addr + off) == -1) {
- fprintf(stderr, "erase_flash_page(0x%zx) == -1\n", addr + off);
- return -1;
- }
- }
-
- /* 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))
- {
- 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 ;
- }
- }
-
- /* 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));
-