#define DLOG(format, args...) ugly_log(UDEBUG, LOG_TAG, format, ## args)
#define ILOG(format, args...) ugly_log(UINFO, LOG_TAG, format, ## args)
#define WLOG(format, args...) ugly_log(UWARN, LOG_TAG, format, ## args)
+#define ELOG(format, args...) ugly_log(UERROR, LOG_TAG, format, ## args)
#define fatal(format, args...) ugly_log(UFATAL, LOG_TAG, format, ## args)
/* todo: stm32l15xxx flash memory, pm0062 manual */
/* stm32f FPEC flash controller interface, pm0063 manual */
// TODO - all of this needs to be abstracted out....
+// STM32F05x is identical, based on RM0091 (DM00031936, Doc ID 018940 Rev 2, August 2012)
#define FLASH_REGS_ADDR 0x40022000
#define FLASH_REGS_SIZE 0x28
#define FLASH_OBR (FLASH_REGS_ADDR + 0x1c)
#define FLASH_WRPR (FLASH_REGS_ADDR + 0x20)
+// For STM32F05x, the RDPTR_KEY may be wrong, but as it is not used anywhere...
#define FLASH_RDPTR_KEY 0x00a5
#define FLASH_KEY1 0x45670123
#define FLASH_KEY2 0xcdef89ab
}
static inline uint32_t read_flash_cr(stlink_t *sl) {
- uint32_t res;
- if((sl->chip_id==STM32_CHIPID_F2) ||(sl->chip_id==STM32_CHIPID_F4))
- res = stlink_read_debug32(sl, FLASH_F4_CR);
- else
- res = stlink_read_debug32(sl, FLASH_CR);
+ uint32_t res;
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+ res = stlink_read_debug32(sl, FLASH_F4_CR);
+ else
+ res = stlink_read_debug32(sl, FLASH_CR);
#if DEBUG_FLASH
- fprintf(stdout, "CR:0x%x\n", res);
+ fprintf(stdout, "CR:0x%x\n", res);
#endif
- return res;
+ return res;
}
static inline unsigned int is_flash_locked(stlink_t *sl) {
/* return non zero for true */
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
- return read_flash_cr(sl) & (1 << FLASH_F4_CR_LOCK);
- else
- return read_flash_cr(sl) & (1 << FLASH_CR_LOCK);
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+ return read_flash_cr(sl) & (1 << FLASH_F4_CR_LOCK);
+ else
+ return read_flash_cr(sl) & (1 << FLASH_CR_LOCK);
}
static void unlock_flash(stlink_t *sl) {
an invalid sequence results in a definitive lock of
the FPEC block until next reset.
*/
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY1);
- stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY2);
- }
- else {
+ stlink_write_debug32(sl, FLASH_F4_KEYR, FLASH_KEY2);
+ } else {
stlink_write_debug32(sl, FLASH_KEYR, FLASH_KEY1);
- stlink_write_debug32(sl, FLASH_KEYR, FLASH_KEY2);
- }
+ stlink_write_debug32(sl, FLASH_KEYR, FLASH_KEY2);
+ }
}
}
static void lock_flash(stlink_t *sl) {
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
const uint32_t n = read_flash_cr(sl) | (1 << FLASH_F4_CR_LOCK);
stlink_write_debug32(sl, FLASH_F4_CR, n);
- }
- else {
+ } else {
/* write to 1 only. reset by hw at unlock sequence */
const uint32_t n = read_flash_cr(sl) | (1 << FLASH_CR_LOCK);
stlink_write_debug32(sl, FLASH_CR, n);
static void set_flash_cr_pg(stlink_t *sl) {
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
uint32_t x = read_flash_cr(sl);
x |= (1 << FLASH_CR_PG);
stlink_write_debug32(sl, FLASH_F4_CR, x);
- }
- else {
+ } else {
const uint32_t n = 1 << FLASH_CR_PG;
stlink_write_debug32(sl, FLASH_CR, n);
}
static void __attribute__((unused)) clear_flash_cr_pg(stlink_t *sl) {
const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PG);
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
stlink_write_debug32(sl, FLASH_F4_CR, n);
else
stlink_write_debug32(sl, FLASH_CR, n);
}
static void set_flash_cr_mer(stlink_t *sl) {
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
stlink_write_debug32(sl, FLASH_F4_CR,
stlink_read_debug32(sl, FLASH_F4_CR) | (1 << FLASH_CR_MER));
- else
+ else
stlink_write_debug32(sl, FLASH_CR,
stlink_read_debug32(sl, FLASH_CR) | (1 << FLASH_CR_MER));
}
static void __attribute__((unused)) clear_flash_cr_mer(stlink_t *sl) {
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
stlink_write_debug32(sl, FLASH_F4_CR,
stlink_read_debug32(sl, FLASH_F4_CR) & ~(1 << FLASH_CR_MER));
- else
+ else
stlink_write_debug32(sl, FLASH_CR,
stlink_read_debug32(sl, FLASH_CR) & ~(1 << FLASH_CR_MER));
}
static void set_flash_cr_strt(stlink_t *sl) {
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
- {
- uint32_t x = read_flash_cr(sl);
- x |= (1 << FLASH_F4_CR_STRT);
- stlink_write_debug32(sl, FLASH_F4_CR, x);
- }
- else {
- stlink_write_debug32(
- sl, FLASH_CR,
- stlink_read_debug32(sl,FLASH_CR) |(1 << FLASH_CR_STRT) );
- }
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
+ uint32_t x = read_flash_cr(sl);
+ x |= (1 << FLASH_F4_CR_STRT);
+ stlink_write_debug32(sl, FLASH_F4_CR, x);
+ } else {
+ stlink_write_debug32(sl, FLASH_CR,
+ stlink_read_debug32(sl, FLASH_CR) | (1 << FLASH_CR_STRT) );
+ }
}
static inline uint32_t read_flash_acr(stlink_t *sl) {
}
static inline uint32_t read_flash_sr(stlink_t *sl) {
- uint32_t res;
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
- res = stlink_read_debug32(sl, FLASH_F4_SR);
- else
- res = stlink_read_debug32(sl, FLASH_SR);
+ uint32_t res;
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+ res = stlink_read_debug32(sl, FLASH_F4_SR);
+ else
+ res = stlink_read_debug32(sl, FLASH_SR);
//fprintf(stdout, "SR:0x%x\n", *(uint32_t*) sl->q_buf);
return res;
}
static inline unsigned int is_flash_busy(stlink_t *sl) {
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
- return read_flash_sr(sl) & (1 << FLASH_F4_SR_BSY);
- else
- return read_flash_sr(sl) & (1 << FLASH_SR_BSY);
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4))
+ return read_flash_sr(sl) & (1 << FLASH_F4_SR_BSY);
+ else
+ return read_flash_sr(sl) & (1 << FLASH_SR_BSY);
}
static void wait_flash_busy(stlink_t *sl) {
int i = 0;
fprintf(stdout, "Mass erasing");
fflush(stdout);
- while (is_flash_busy(sl))
- {
+ while (is_flash_busy(sl)) {
usleep(10000);
i++;
if (i % 100 == 0) {
const chip_params_t *params = NULL;
sl->core_id = stlink_core_id(sl);
uint32_t chip_id = stlink_chip_id(sl);
-
+
sl->chip_id = chip_id & 0xfff;
/* Fix chip_id for F4 rev A errata , Read CPU ID, as CoreID is the same for F2/F4*/
if (sl->chip_id == 0x411) {
uint32_t cpuid = stlink_read_debug32(sl, 0xE000ED00);
- if((cpuid & 0xfff0) == 0xc240)
+ if ((cpuid & 0xfff0) == 0xc240)
sl->chip_id = 0x413;
}
- for(size_t i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
+ for (size_t i = 0; i < sizeof(devices) / sizeof(devices[0]); i++) {
if(devices[i].chip_id == sl->chip_id) {
params = &devices[i];
break;
WLOG("unknown chip id! %#x\n", chip_id);
return -1;
}
-
+
// These are fixed...
sl->flash_base = STM32_FLASH_BASE;
sl->sram_base = STM32_SRAM_BASE;
-
+
// read flash size from hardware, if possible...
if (sl->chip_id == STM32_CHIPID_F2) {
sl->flash_size = 0x100000; /* Use maximum, User must care!*/
sl->sram_size = params->sram_size;
sl->sys_base = params->bootrom_base;
sl->sys_size = params->bootrom_size;
-
+
ILOG("Device connected is: %s, id %#x\n", params->description, chip_id);
// TODO make note of variable page size here.....
ILOG("SRAM size: %#x bytes (%d KiB), Flash: %#x bytes (%d KiB) in pages of %zd bytes\n",
- sl->sram_size, sl->sram_size / 1024, sl->flash_size, sl->flash_size / 1024,
+ sl->sram_size, sl->sram_size / 1024, sl->flash_size, sl->flash_size / 1024,
sl->flash_pgsz);
return 0;
}
DLOG("*** looking up stlink version\n");
sl->backend->version(sl);
_parse_version(sl, &sl->version);
-
+
DLOG("st vid = 0x%04x (expect 0x%04x)\n", sl->version.st_vid, USB_ST_VID);
DLOG("stlink pid = 0x%04x\n", sl->version.stlink_pid);
DLOG("stlink version = 0x%x\n", sl->version.stlink_v);
DLOG("*** stlink_write_mem32 %u bytes to %#x\n", len, addr);
if (len % 4 != 0) {
fprintf(stderr, "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n", len % 4);
- return;
+ abort();
}
sl->backend->write_mem32(sl, addr, len);
}
if (len % 4 != 0) { // !!! never ever: fw gives just wrong values
fprintf(stderr, "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n",
len % 4);
- return;
+ abort();
}
sl->backend->read_mem32(sl, addr, len);
}
if (len > 0x40 ) { // !!! never ever: Writing more then 0x40 bytes gives unexpected behaviour
fprintf(stderr, "Error: Data length > 64: +%d byte.\n",
len);
- return;
+ abort();
}
sl->backend->write_mem8(sl, addr, len);
}
int error = -1;
size_t off;
int num_empty = 0;
- unsigned char erased_pattern =(sl->chip_id == STM32_CHIPID_L1_MEDIUM)?0:0xff;
+ unsigned char erased_pattern = (sl->chip_id == STM32_CHIPID_L1_MEDIUM)?0:0xff;
const int fd = open(path, O_RDWR | O_TRUNC | O_CREAT, 00700);
if (fd == -1) {
}
/* Ignore NULL Bytes at end of file */
- ftruncate(fd, size - num_empty);
+ if (!ftruncate(fd, size - num_empty)) {
+ error = -1;
+ }
/* success */
error = 0;
}
uint32_t stlink_calculate_pagesize(stlink_t *sl, uint32_t flashaddr){
- if((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
uint32_t sector=calculate_F4_sectornum(flashaddr);
if (sector<4) sl->flash_pgsz=0x4000;
else if(sector<5) sl->flash_pgsz=0x10000;
*/
int stlink_erase_flash_page(stlink_t *sl, stm32_addr_t flashaddr)
{
- if ((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4))
- {
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
/* wait for ongoing op to finish */
wait_flash_busy(sl);
#if DEBUG_FLASH
fprintf(stdout, "Erase Final CR:0x%x\n", read_flash_cr(sl));
#endif
- }
- else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM)
- {
+ } else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
uint32_t val;
/* check pecr.pelock is cleared */
val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
- if (val & (1 << 0))
- {
+ if (val & (1 << 0)) {
WLOG("pecr.pelock not clear (%#x)\n", val);
return -1;
}
/* check pecr.prglock is cleared */
val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
- if (val & (1 << 1))
- {
+ if (val & (1 << 1)) {
WLOG("pecr.prglock not clear (%#x)\n", val);
return -1;
}
/* check pecr.optlock is cleared */
val = stlink_read_debug32(sl, STM32L_FLASH_PECR);
- if (val & (1 << 2))
- {
+ if (val & (1 << 2)) {
fprintf(stderr, "pecr.prglock not clear\n");
return -1;
}
it. If someone has a problem, please drop an email.
*/
while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0)
- {
- }
+ ;
#endif /* fix_to_be_confirmed */
Test shows that a few iterations is performed in the following loop
before busy bit is cleared.*/
while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0)
- {
- }
+ ;
/* reset lock bits */
val = stlink_read_debug32(sl, STM32L_FLASH_PECR)
| (1 << 0) | (1 << 1) | (1 << 2);
stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
- }
- else if (sl->core_id == STM32VL_CORE_ID)
- {
+ } else if (sl->core_id == STM32VL_CORE_ID || sl->core_id == STM32F0_CORE_ID || sl->chip_id == STM32_CHIPID_F3) {
/* wait for ongoing op to finish */
wait_flash_busy(sl);
/* relock the flash */
lock_flash(sl);
- }
-
- else {
- WLOG("unknown coreid: %x\n", sl->core_id);
+ } else {
+ WLOG("unknown coreid %x, page erase failed\n", sl->core_id);
return -1;
}
}
int stlink_erase_flash_mass(stlink_t *sl) {
- if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
- /* erase each page */
- int i = 0, num_pages = sl->flash_size/sl->flash_pgsz;
- for (i = 0; i < num_pages; i++) {
- /* addr must be an addr inside the page */
- stm32_addr_t addr = sl->flash_base + i * sl->flash_pgsz;
- if (stlink_erase_flash_page(sl, addr) == -1) {
- WLOG("Failed to erase_flash_page(%#zx) == -1\n", addr);
- return -1;
- }
- fprintf(stdout,"\rFlash page at %5d/%5d erased", i, num_pages);
- fflush(stdout);
- }
- fprintf(stdout, "\n");
- }
- else {
- /* wait for ongoing op to finish */
- wait_flash_busy(sl);
-
- /* unlock if locked */
- unlock_flash_if(sl);
-
- /* set the mass erase bit */
- set_flash_cr_mer(sl);
-
- /* start erase operation, reset by hw with bsy bit */
- set_flash_cr_strt(sl);
-
- /* wait for completion */
- wait_flash_busy_progress(sl);
-
- /* relock the flash */
- lock_flash(sl);
-
- /* todo: verify the erased memory */
- }
+ if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
+ /* erase each page */
+ int i = 0, num_pages = sl->flash_size/sl->flash_pgsz;
+ for (i = 0; i < num_pages; i++) {
+ /* addr must be an addr inside the page */
+ stm32_addr_t addr = sl->flash_base + i * sl->flash_pgsz;
+ if (stlink_erase_flash_page(sl, addr) == -1) {
+ WLOG("Failed to erase_flash_page(%#zx) == -1\n", addr);
+ return -1;
+ }
+ fprintf(stdout,"\rFlash page at %5d/%5d erased", i, num_pages);
+ fflush(stdout);
+ }
+ fprintf(stdout, "\n");
+ } else {
+ /* wait for ongoing op to finish */
+ wait_flash_busy(sl);
+
+ /* unlock if locked */
+ unlock_flash_if(sl);
+
+ /* set the mass erase bit */
+ set_flash_cr_mer(sl);
+
+ /* start erase operation, reset by hw with bsy bit */
+ set_flash_cr_strt(sl);
+
+ /* wait for completion */
+ wait_flash_busy_progress(sl);
+
+ /* relock the flash */
+ lock_flash(sl);
+
+ /* todo: verify the erased memory */
+ }
return 0;
}
0x00, 0x20, 0x02, 0x40, /* STM32_FLASH_BASE: .word 0x40022000 */
};
+ /* flashloaders/stm32f0.s -- thumb1 only, same sequence as for STM32VL, bank ignored */
+ static const uint8_t loader_code_stm32f0[] = {
+#if 1
+ /*
+ * These two NOPs here are a safety precaution, added by Pekka Nikander
+ * while debugging the STM32F05x support. They may not be needed, but
+ * there were strange problems with simpler programs, like a program
+ * that had just a breakpoint or a program that first moved zero to register r2
+ * and then had a breakpoint. So, it appears safest to have these two nops.
+ *
+ * Feel free to remove them, if you dare, but then please do test the result
+ * rigorously. Also, if you remove these, it may be a good idea first to
+ * #if 0 them out, with a comment when these were taken out, and to remove
+ * these only a few months later... But YMMV.
+ */
+ 0x00, 0x30, // nop /* add r0,#0 */
+ 0x00, 0x30, // nop /* add r0,#0 */
+#endif
+ 0x0A, 0x4C, // ldr r4, STM32_FLASH_BASE
+ 0x01, 0x25, // mov r5, #1 /* FLASH_CR_PG, FLASH_SR_BUSY */
+ 0x04, 0x26, // mov r6, #4 /* PGERR */
+ // write_half_word:
+ 0x23, 0x69, // ldr r3, [r4, #16] /* FLASH->CR */
+ 0x2B, 0x43, // orr r3, r5
+ 0x23, 0x61, // str r3, [r4, #16] /* FLASH->CR |= FLASH_CR_PG */
+ 0x03, 0x88, // ldrh r3, [r0] /* r3 = *sram */
+ 0x0B, 0x80, // strh r3, [r1] /* *flash = r3 */
+ // busy:
+ 0xE3, 0x68, // ldr r3, [r4, #12] /* FLASH->SR */
+ 0x2B, 0x42, // tst r3, r5 /* FLASH_SR_BUSY */
+ 0xFC, 0xD0, // beq busy
+
+ 0x33, 0x42, // tst r3, r6 /* PGERR */
+ 0x04, 0xD1, // bne exit
+
+ 0x02, 0x30, // add r0, r0, #2 /* sram += 2 */
+ 0x02, 0x31, // add r1, r1, #2 /* flash += 2 */
+ 0x01, 0x3A, // sub r2, r2, #0x01 /* count-- */
+ 0x00, 0x2A, // cmp r2, #0
+ 0xF0, 0xD1, // bne write_half_word
+ // exit:
+ 0x23, 0x69, // ldr r3, [r4, #16] /* FLASH->CR */
+ 0xAB, 0x43, // bic r3, r5
+ 0x23, 0x61, // str r3, [r4, #16] /* FLASH->CR &= ~FLASH_CR_PG */
+ 0x00, 0xBE, // bkpt #0x00
+ 0x00, 0x20, 0x02, 0x40, /* STM32_FLASH_BASE: .word 0x40022000 */
+ };
+
static const uint8_t loader_code_stm32l[] = {
- /* openocd.git/contrib/loaders/flash/stm32lx.S
- r0, input, dest addr
- r1, input, source addr
- r2, input, word count
- r3, output, word count
- */
+ /* openocd.git/contrib/loaders/flash/stm32lx.S
+ r0, input, dest addr
+ r1, input, source addr
+ r2, input, word count
+ r3, output, word count
+ */
- 0x00, 0x23,
- 0x04, 0xe0,
+ 0x00, 0x23,
+ 0x04, 0xe0,
- 0x51, 0xf8, 0x04, 0xcb,
- 0x40, 0xf8, 0x04, 0xcb,
- 0x01, 0x33,
+ 0x51, 0xf8, 0x04, 0xcb,
+ 0x40, 0xf8, 0x04, 0xcb,
+ 0x01, 0x33,
- 0x93, 0x42,
- 0xf8, 0xd3,
- 0x00, 0xbe
+ 0x93, 0x42,
+ 0xf8, 0xd3,
+ 0x00, 0xbe
};
- static const uint8_t loader_code_stm32f4[] = {
- // flashloaders/stm32f4.s
+ static const uint8_t loader_code_stm32f4[] = {
+ // flashloaders/stm32f4.s
- 0x07, 0x4b,
+ 0x07, 0x4b,
- 0x62, 0xb1,
- 0x04, 0x68,
- 0x0c, 0x60,
+ 0x62, 0xb1,
+ 0x04, 0x68,
+ 0x0c, 0x60,
- 0xdc, 0x89,
- 0x14, 0xf0, 0x01, 0x0f,
- 0xfb, 0xd1,
- 0x00, 0xf1, 0x04, 0x00,
- 0x01, 0xf1, 0x04, 0x01,
- 0xa2, 0xf1, 0x01, 0x02,
- 0xf1, 0xe7,
+ 0xdc, 0x89,
+ 0x14, 0xf0, 0x01, 0x0f,
+ 0xfb, 0xd1,
+ 0x00, 0xf1, 0x04, 0x00,
+ 0x01, 0xf1, 0x04, 0x01,
+ 0xa2, 0xf1, 0x01, 0x02,
+ 0xf1, 0xe7,
- 0x00, 0xbe,
+ 0x00, 0xbe,
- 0x00, 0x3c, 0x02, 0x40,
- };
+ 0x00, 0x3c, 0x02, 0x40,
+ };
const uint8_t* loader_code;
size_t loader_size;
- if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) /* stm32l */
- {
- loader_code = loader_code_stm32l;
- loader_size = sizeof(loader_code_stm32l);
- }
- else if (sl->core_id == STM32VL_CORE_ID)
- {
- loader_code = loader_code_stm32vl;
- loader_size = sizeof(loader_code_stm32vl);
- }
- else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4)
- {
- loader_code = loader_code_stm32f4;
- loader_size = sizeof(loader_code_stm32f4);
- }
- else
- {
- WLOG("unknown coreid, not sure what flash loader to use, aborting!: %x\n", sl->core_id);
- return -1;
+ if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) { /* stm32l */
+ loader_code = loader_code_stm32l;
+ loader_size = sizeof(loader_code_stm32l);
+ } else if (sl->core_id == STM32VL_CORE_ID || sl->chip_id == STM32_CHIPID_F3) {
+ loader_code = loader_code_stm32vl;
+ loader_size = sizeof(loader_code_stm32vl);
+ } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
+ loader_code = loader_code_stm32f4;
+ loader_size = sizeof(loader_code_stm32f4);
+ } else if (sl->chip_id == STM32_CHIPID_F0) {
+ loader_code = loader_code_stm32f0;
+ loader_size = sizeof(loader_code_stm32f0);
+ } else {
+ ELOG("unknown coreid, not sure what flash loader to use, aborting!: %x\n", sl->core_id);
+ return -1;
}
memcpy(sl->q_buf, loader_code, loader_size);
stlink_read_mem32(sl, address + off, aligned_size);
if (memcmp(sl->q_buf, data + off, cmp_size)) {
- WLOG("Verification of flash failed at offset: %zd\n", off);
+ ELOG("Verification of flash failed at offset: %zd\n", off);
return -1;
}
}
}
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;
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) {}
/* check addr range is inside the flash */
stlink_calculate_pagesize(sl, addr);
if (addr < sl->flash_base) {
- WLOG("addr too low %#x < %#x\n", addr, sl->flash_base);
+ ELOG("addr too low %#x < %#x\n", addr, sl->flash_base);
return -1;
} else if ((addr + len) < addr) {
- WLOG("addr overruns\n");
+ ELOG("addr overruns\n");
return -1;
} else if ((addr + len) > (sl->flash_base + sl->flash_size)) {
- WLOG("addr too high\n");
+ ELOG("addr too high\n");
return -1;
- } else if ((addr & 1) || (len & 1)) {
- WLOG("unaligned addr or size\n");
+ } else if (addr & 1) {
+ ELOG("unaligned addr 0x%x\n", addr);
return -1;
+ } else if (len & 1) {
+ WLOG("unaligned len 0x%x -- padding with zero\n", len);
+ len += 1;
} else if (addr & (sl->flash_pgsz - 1)) {
- WLOG("addr not a multiple of pagesize, not supported\n");
+ ELOG("addr not a multiple of pagesize, not supported\n");
return -1;
}
for (off = 0; off < len; off += stlink_calculate_pagesize(sl, addr + off)) {
/* addr must be an addr inside the page */
if (stlink_erase_flash_page(sl, addr + off) == -1) {
- WLOG("Failed to erase_flash_page(%#zx) == -1\n", addr + off);
+ ELOG("Failed to erase_flash_page(%#zx) == -1\n", addr + off);
return -1;
}
fprintf(stdout,"\rFlash page at addr: 0x%08lx erased",
page_count++;
}
fprintf(stdout,"\n");
- ILOG("Finished erasing %d pages of %d (%#x) bytes\n",
+ ILOG("Finished erasing %d pages of %d (%#x) bytes\n",
page_count, sl->flash_pgsz, sl->flash_pgsz);
- if ((sl->chip_id == STM32_CHIPID_F2) ||(sl->chip_id == STM32_CHIPID_F4)) {
+ if ((sl->chip_id == STM32_CHIPID_F2) || (sl->chip_id == STM32_CHIPID_F4)) {
/* todo: check write operation */
- ILOG("Starting Flash write for F2/F4\n");
- /* flash loader initialization */
- if (init_flash_loader(sl, &fl) == -1) {
- WLOG("init_flash_loader() == -1\n");
- return -1;
- }
+ ILOG("Starting Flash write for F2/F4\n");
+ /* flash loader initialization */
+ if (init_flash_loader(sl, &fl) == -1) {
+ ELOG("init_flash_loader() == -1\n");
+ return -1;
+ }
/* First unlock the cr */
unlock_flash_if(sl);
/* set programming mode */
set_flash_cr_pg(sl);
- for(off = 0; off < len;) {
- size_t size = len - off > 0x8000 ? 0x8000 : len - off;
+ for(off = 0; off < len;) {
+ size_t size = len - off > 0x8000 ? 0x8000 : len - off;
- printf("size: %u\n", size);
+ printf("size: %zu\n", size);
- if (run_flash_loader(sl, &fl, addr + off, base + off, size) == -1) {
- WLOG("run_flash_loader(%#zx) failed! == -1\n", addr + off);
- return -1;
- }
+ if (run_flash_loader(sl, &fl, addr + off, base + off, size) == -1) {
+ ELOG("run_flash_loader(%#zx) failed! == -1\n", addr + off);
+ return -1;
+ }
- off += size;
- }
+ off += size;
+ }
#if 0
#define PROGRESS_CHUNK_SIZE 0x1000
/* write a word in program memory */
for (off = 0; off < len; off += sizeof(uint32_t)) {
- uint32_t data;
- 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 +1;
- fprintf(stdout, "Writing %ukB chunk %u out of %u\n", PROGRESS_CHUNK_SIZE/1024, pgnum, pgcount);
- }
- }
-
- write_uint32((unsigned char*) &data, *(uint32_t*) (base + off));
- stlink_write_debug32(sl, addr + off, data);
-
- /* wait for sr.busy to be cleared */
+ uint32_t data;
+ 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 +1;
+ fprintf(stdout, "Writing %ukB chunk %u out of %u\n",
+ PROGRESS_CHUNK_SIZE/1024, pgnum, pgcount);
+ }
+ }
+
+ write_uint32((unsigned char*) &data, *(uint32_t*) (base + off));
+ stlink_write_debug32(sl, addr + off, data);
+
+ /* wait for sr.busy to be cleared */
wait_flash_busy(sl);
}
fprintf(stdout, "Final CR:0x%x\n", read_flash_cr(sl));
#endif
-
-
} //STM32F4END
else if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
}
off = 0;
if (len > L1_WRITE_BLOCK_SIZE) {
- if (stm32l1_write_half_pages(sl, addr, base, len/L1_WRITE_BLOCK_SIZE) == -1){
+ if (stm32l1_write_half_pages(sl, addr, base, len/L1_WRITE_BLOCK_SIZE) == -1) {
/* This may happen on a blank device! */
WLOG("\nwrite_half_pages failed == -1\n");
- }
- else{
+ } else {
off = (len /L1_WRITE_BLOCK_SIZE)*L1_WRITE_BLOCK_SIZE;
}
}
/* write remainingword in program memory */
for ( ; off < len; off += sizeof(uint32_t)) {
- uint32_t data;
- if (off > 254)
- fprintf(stdout, "\r");
+ uint32_t data;
+ if (off > 254)
+ fprintf(stdout, "\r");
- if ((off % sl->flash_pgsz) > (sl->flash_pgsz -5)) {
- fprintf(stdout, "\r%3zd/%3zd pages written",
- off/sl->flash_pgsz, len/sl->flash_pgsz);
- fflush(stdout);
- }
+ if ((off % sl->flash_pgsz) > (sl->flash_pgsz -5)) {
+ fprintf(stdout, "\r%3zd/%3zd pages written",
+ off/sl->flash_pgsz, len/sl->flash_pgsz);
+ fflush(stdout);
+ }
- write_uint32((unsigned char*) &data, *(uint32_t*) (base + off));
- stlink_write_debug32(sl, addr + off, data);
+ write_uint32((unsigned char*) &data, *(uint32_t*) (base + off));
+ stlink_write_debug32(sl, addr + off, data);
- /* wait for sr.busy to be cleared */
- while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0) {
- }
+ /* wait for sr.busy to be cleared */
+ while ((stlink_read_debug32(sl, STM32L_FLASH_SR) & (1 << 0)) != 0)
+ ;
#if 0 /* todo: check redo write operation */
- /* check written bytes. todo: should be on a per page basis. */
- data = stlink_read_debug32(sl, addr + off);
- if (data == *(uint32_t*)(base + off)) {
- /* re erase the page and redo the write operation */
- uint32_t page;
- uint32_t val;
+ /* check written bytes. todo: should be on a per page basis. */
+ data = stlink_read_debug32(sl, addr + off);
+ if (data == *(uint32_t*)(base + off)) {
+ /* 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;
- }
+ /* 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;
+ nwrites = 0;
- /* assume addr aligned */
- if (off % sl->flash_pgsz) off &= ~(sl->flash_pgsz - 1);
- page = addr + off;
+ /* 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));
+ 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 */
- val = stlink_read_debug32(sl, STM32L_FLASH_PECR)
- | (1 << 0) | (1 << 1) | (1 << 2);
- stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
+ /* reset lock bits */
+ val = stlink_read_debug32(sl, STM32L_FLASH_PECR)
+ | (1 << 0) | (1 << 1) | (1 << 2);
+ stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
- stlink_erase_flash_page(sl, page);
+ stlink_erase_flash_page(sl, page);
- goto redo_write;
- }
+ goto redo_write;
+ }
- /* increment successive writes counter */
- ++nwrites;
+ /* increment successive writes counter */
+ ++nwrites;
#endif /* todo: check redo write operation */
}
val = stlink_read_debug32(sl, STM32L_FLASH_PECR)
| (1 << 0) | (1 << 1) | (1 << 2);
stlink_write_debug32(sl, STM32L_FLASH_PECR, val);
- } else if (sl->core_id == STM32VL_CORE_ID) {
- ILOG("Starting Flash write for VL core id\n");
+ } else if (sl->core_id == STM32VL_CORE_ID || sl->core_id == STM32F0_CORE_ID || sl->chip_id == STM32_CHIPID_F3) {
+ ILOG("Starting Flash write for VL/F0 core id\n");
/* flash loader initialization */
if (init_flash_loader(sl, &fl) == -1) {
- WLOG("init_flash_loader() == -1\n");
+ ELOG("init_flash_loader() == -1\n");
return -1;
}
set_flash_cr_pg(sl);
//DLOG("Finished setting flash cr pg, running loader!\n");
if (run_flash_loader(sl, &fl, addr + off, base + off, size) == -1) {
- WLOG("run_flash_loader(%#zx) failed! == -1\n", addr + off);
+ ELOG("run_flash_loader(%#zx) failed! == -1\n", addr + off);
return -1;
}
lock_flash(sl);
}
fprintf(stdout, "\n");
} else {
- WLOG("unknown coreid, not sure how to write: %x\n", sl->core_id);
+ ELOG("unknown coreid, not sure how to write: %x\n", sl->core_id);
return -1;
}
-
+
return stlink_verify_write_flash(sl, addr, base, len);
}
unsigned char erased_pattern =(sl->chip_id == STM32_CHIPID_L1_MEDIUM)?0:0xff;
mapped_file_t mf = MAPPED_FILE_INITIALIZER;
if (map_file(&mf, path) == -1) {
- WLOG("map_file() == -1\n");
+ ELOG("map_file() == -1\n");
return -1;
}
for(index = 0; index < mf.len; index ++) {
// FIXME This can never return -1
if (write_buffer_to_sram(sl, fl, buf, size) == -1) {
// IMPOSSIBLE!
- WLOG("write_buffer_to_sram() == -1\n");
+ ELOG("write_buffer_to_sram() == -1\n");
return -1;
}
if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
- size_t count = size / sizeof(uint32_t);
- if (size % sizeof(uint32_t)) ++count;
+ size_t count = size / sizeof(uint32_t);
+ if (size % sizeof(uint32_t)) ++count;
- /* setup core */
- 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, fl->loader_addr, 15); /* pc register */
+ /* setup core */
+ 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, fl->loader_addr, 15); /* pc register */
- } else if (sl->core_id == STM32VL_CORE_ID) {
+ } else if (sl->core_id == STM32VL_CORE_ID || sl->core_id == STM32F0_CORE_ID || sl->chip_id == STM32_CHIPID_F3) {
- size_t count = size / sizeof(uint16_t);
- if (size % sizeof(uint16_t)) ++count;
+ size_t count = size / sizeof(uint16_t);
+ if (size % sizeof(uint16_t)) ++count;
- /* setup core */
- stlink_write_reg(sl, fl->buf_addr, 0); /* source */
- stlink_write_reg(sl, target, 1); /* target */
- stlink_write_reg(sl, count, 2); /* count (16 bits half words) */
- stlink_write_reg(sl, 0, 3); /* flash bank 0 (input) */
- stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
+ /* setup core */
+ stlink_write_reg(sl, fl->buf_addr, 0); /* source */
+ stlink_write_reg(sl, target, 1); /* target */
+ stlink_write_reg(sl, count, 2); /* count (16 bits half words) */
+ stlink_write_reg(sl, 0, 3); /* flash bank 0 (input) */
+ stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
- } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
+ } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
- size_t count = size / sizeof(uint32_t);
- if (size % sizeof(uint32_t)) ++count;
+ size_t count = size / sizeof(uint32_t);
+ if (size % sizeof(uint32_t)) ++count;
- /* setup core */
- stlink_write_reg(sl, fl->buf_addr, 0); /* source */
- stlink_write_reg(sl, target, 1); /* target */
- stlink_write_reg(sl, count, 2); /* count (32 bits words) */
- stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
+ /* setup core */
+ stlink_write_reg(sl, fl->buf_addr, 0); /* source */
+ stlink_write_reg(sl, target, 1); /* target */
+ stlink_write_reg(sl, count, 2); /* count (32 bits words) */
+ stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
} else {
- fprintf(stderr, "unknown coreid: 0x%x\n", sl->core_id);
- return -1;
+ fprintf(stderr, "unknown coreid 0x%x, don't know what flash loader to use\n", sl->core_id);
+ return -1;
}
/* run loader */
stlink_run(sl);
+#define WAIT_ROUNDS 1000
/* wait until done (reaches breakpoint) */
- while ((is_core_halted(sl) == 0) && (i <1000))
- {
- i++;
+ for (i = 0; i < WAIT_ROUNDS; i++) {
+ if (is_core_halted(sl))
+ break;
}
- if ( i > 999) {
- fprintf(stderr, "run error\n");
+ if (i >= WAIT_ROUNDS) {
+ fatal("flash loader run error\n");
return -1;
}
-
+
/* check written byte count */
if (sl->chip_id == STM32_CHIPID_L1_MEDIUM) {
return -1;
}
- } else if (sl->core_id == STM32VL_CORE_ID) {
+ } else if (sl->core_id == STM32VL_CORE_ID || sl->core_id == STM32F0_CORE_ID || sl->chip_id == STM32_CHIPID_F3) {
stlink_read_reg(sl, 2, &rr);
if (rr.r[2] != 0) {
return -1;
}
- } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
+ } else if (sl->chip_id == STM32_CHIPID_F2 || sl->chip_id == STM32_CHIPID_F4) {
- stlink_read_reg(sl, 2, &rr);
- if (rr.r[2] != 0) {
- fprintf(stderr, "write error, count == %u\n", rr.r[2]);
- return -1;
- }
+ stlink_read_reg(sl, 2, &rr);
+ if (rr.r[2] != 0) {
+ fprintf(stderr, "write error, count == %u\n", rr.r[2]);
+ return -1;
+ }
} else {
- fprintf(stderr, "unknown coreid: 0x%x\n", sl->core_id);
+ fprintf(stderr, "unknown coreid 0x%x, can't check written byte count\n", sl->core_id);
return -1;
}