X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fstlink-common.c;h=87dfc02fbb45ea8b863b4c06ea245bddb2e0c02b;hb=41e7c16cf2f9c6db6b4cc4d61af86a359646d6be;hp=0c391129c1df43cee52e3c508080b08443d79fd2;hpb=72966d19122b54ce39a29c4b8a6f44170cce82c1;p=fw%2Fstlink diff --git a/src/stlink-common.c b/src/stlink-common.c index 0c39112..87dfc02 100644 --- a/src/stlink-common.c +++ b/src/stlink-common.c @@ -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 @@ -179,7 +181,7 @@ static int unlock_flash_if(stlink_t *sl) { return -1; } } - ILOG("Successfully unlocked flash\n"); + DLOG("Successfully unlocked flash\n"); return 0; } @@ -403,9 +405,9 @@ int stlink_load_device_params(stlink_t *sl) { chip_id = 0x413; } - sl->chip_id = chip_id; + sl->chip_id = chip_id & 0xfff; for(size_t i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) { - if(devices[i].chip_id == (chip_id & 0xFFF)) { + if(devices[i].chip_id == sl->chip_id) { params = &devices[i]; break; } @@ -420,9 +422,9 @@ int stlink_load_device_params(stlink_t *sl) { sl->sram_base = STM32_SRAM_BASE; // read flash size from hardware, if possible... - if ((chip_id & 0xFFF) == STM32_CHIPID_F2) { + if (sl->chip_id == STM32_CHIPID_F2) { sl->flash_size = 0; // FIXME - need to work this out some other way, just set to max possible? - } else if ((chip_id & 0xFFF) == STM32_CHIPID_F4) { + } else if (sl->chip_id == STM32_CHIPID_F4) { sl->flash_size = 0x100000; //todo: RM0090 error; size register same address as unique ID } else { uint32_t flash_size = stlink_read_debug32(sl, params->flash_size_reg) & 0xffff; @@ -797,6 +799,11 @@ int stlink_fwrite_sram /* success */ error = 0; + /* set stack*/ + stlink_write_reg(sl, stlink_read_debug32(sl, addr ),13); + /* Set PC to the reset routine*/ + stlink_write_reg(sl, stlink_read_debug32(sl, addr + 4),15); + stlink_run(sl); on_error: unmap_file(&mf); @@ -864,8 +871,16 @@ on_error: int write_buffer_to_sram(stlink_t *sl, flash_loader_t* fl, const uint8_t* buf, size_t size) { /* write the buffer right after the loader */ - memcpy(sl->q_buf, buf, size); - stlink_write_mem8(sl, fl->buf_addr, size); + size_t chunk = size & ~0x3; + size_t rem = size & 0x3; + if (chunk) { + memcpy(sl->q_buf, buf, chunk); + stlink_write_mem32(sl, fl->buf_addr, chunk); + } + if (rem) { + memcpy(sl->q_buf, buf+chunk, rem); + stlink_write_mem8(sl, (fl->buf_addr)+chunk, rem); + } return 0; } @@ -1175,7 +1190,7 @@ int stlink_fcheck_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { */ int stlink_verify_write_flash(stlink_t *sl, stm32_addr_t address, uint8_t *data, unsigned length) { size_t off; - if ((sl->chip_id & 0xFFF) == STM32_CHIPID_F4) { + if (sl->chip_id == STM32_CHIPID_F4) { DLOG("(FIXME)Skipping verification for F4, not enough ram (yet)\n"); return 0; } @@ -1204,6 +1219,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; @@ -1238,7 +1304,8 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned WLOG("Failed to erase_flash_page(%#zx) == -1\n", addr + off); return -1; } - fprintf(stdout,"\rFlash page at addr: 0x%08lx erased", addr + off); + fprintf(stdout,"\rFlash page at addr: 0x%08lx erased", + (unsigned long)addr + off); fflush(stdout); page_count++; } @@ -1324,24 +1391,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 a 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) { } @@ -1398,15 +1460,11 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned return -1; } - /* write each page. above WRITE_BLOCK_SIZE fails? */ -#define WRITE_BLOCK_SIZE 0x40 int write_block_count = 0; - for (off = 0; off < len; off += WRITE_BLOCK_SIZE) { - ILOG("Writing flash block %d of size %d (%#x)\n", write_block_count, - WRITE_BLOCK_SIZE, WRITE_BLOCK_SIZE); + for (off = 0; off < len; off += sl->flash_pgsz) { /* adjust last write size */ - size_t size = WRITE_BLOCK_SIZE; - if ((off + WRITE_BLOCK_SIZE) > len) size = len - off; + size_t size = sl->flash_pgsz; + if ((off + sl->flash_pgsz) > len) size = len - off; /* unlock and set programming mode */ unlock_flash_if(sl); @@ -1417,8 +1475,14 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, unsigned return -1; } lock_flash(sl); - DLOG("Finished writing block %d\n", write_block_count++); + if (sl->verbose >= 1) { + /* show progress. writing procedure is slow + and previous errors are misleading */ + fprintf(stdout, "\r%3u/%lu pages written", write_block_count++, (unsigned long)len/sl->flash_pgsz); + fflush(stdout); + } } + fprintf(stdout, "\n"); } else { WLOG("unknown coreid, not sure how to write: %x\n", sl->core_id); return -1; @@ -1455,6 +1519,11 @@ int stlink_fwrite_flash(stlink_t *sl, const char* path, stm32_addr_t addr) { mf.len -= num_empty; } err = stlink_write_flash(sl, addr, mf.base, mf.len); + /* set stack*/ + stlink_write_reg(sl, stlink_read_debug32(sl, addr ),13); + /* Set PC to the reset routine*/ + stlink_write_reg(sl, stlink_read_debug32(sl, addr + 4),15); + stlink_run(sl); unmap_file(&mf); return err; } @@ -1462,6 +1531,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) { @@ -1479,7 +1549,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) { @@ -1503,8 +1572,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) {