int main(int argc, char* argv[]) { int ret = 1; parser_err_t perr; (void) signal(SIGINT, caught_sigint); printf("stm32flash - http://stm32flash.googlecode.com/\n\n"); if (parse_options(argc, argv) != 0) goto close; if (wr) { /* first try hex */ if (!force_binary) { parser = &PARSER_HEX; p_st = parser->init(); if (!p_st) { fprintf(stderr, "%s Parser failed to initialize\n", parser->name); goto close; } } if (force_binary || (perr = parser->open(p_st, filename, 0)) != PARSER_ERR_OK) { if (force_binary || perr == PARSER_ERR_INVALID_FILE) { if (!force_binary) { parser->close(p_st); p_st = NULL; } /* now try binary */ parser = &PARSER_BINARY; p_st = parser->init(); if (!p_st) { fprintf(stderr, "%s Parser failed to initialize\n", parser->name); goto close; } perr = parser->open(p_st, filename, 0); } /* if still have an error, fail */ if (perr != PARSER_ERR_OK) { fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); if (perr == PARSER_ERR_SYSTEM) perror(filename); goto close; } } fprintf(stdout, "Using Parser : %s\n", parser->name); } else { parser = &PARSER_BINARY; p_st = parser->init(); if (!p_st) { fprintf(stderr, "%s Parser failed to initialize\n", parser->name); goto close; } } serial = serial_open(device); if (!serial) { perror(device); goto close; } if (serial_setup( serial, baudRate, SERIAL_BITS_8, SERIAL_PARITY_EVEN, SERIAL_STOPBIT_1 ) != SERIAL_ERR_OK) { perror(device); goto close; } printf("Serial Config: %s\n", serial_get_setup_str(serial)); if (!(stm = stm32_init(serial, init_flag))) goto close; printf("Version : 0x%02x\n", stm->bl_version); printf("Option 1 : 0x%02x\n", stm->option1); printf("Option 2 : 0x%02x\n", stm->option2); printf("Device ID : 0x%04x (%s)\n", stm->pid, stm->dev->name); printf("RAM : %dKiB (%db reserved by bootloader)\n", (stm->dev->ram_end - 0x20000000) / 1024, stm->dev->ram_start - 0x20000000); printf("Flash : %dKiB (sector size: %dx%d)\n", (stm->dev->fl_end - stm->dev->fl_start ) / 1024, stm->dev->fl_pps, stm->dev->fl_ps); printf("Option RAM : %db\n", stm->dev->opt_end - stm->dev->opt_start); printf("System RAM : %dKiB\n", (stm->dev->mem_end - stm->dev->mem_start) / 1024); uint8_t buffer[256]; uint32_t addr; unsigned int len; int failed = 0; if (rd) { printf("\n"); if ((perr = parser->open(p_st, filename, 1)) != PARSER_ERR_OK) { fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); if (perr == PARSER_ERR_SYSTEM) perror(filename); goto close; } addr = stm->dev->fl_start + (spage * stm->dev->fl_ps); fflush(stdout); fprintf(stdout, "\033[?25l"); while(addr < stm->dev->fl_end) { uint32_t left = stm->dev->fl_end - addr; len = sizeof(buffer) > left ? left : sizeof(buffer); if (!stm32_read_memory(stm, addr, buffer, len)) { fprintf(stderr, "Failed to read memory at address 0x%08x, target write-protected?\n", addr); goto close; } assert(parser->write(p_st, buffer, len) == PARSER_ERR_OK); addr += len; fprintf(stdout, "\033[1GRead address 0x%08x (%.2f%%) ", addr, (100.0f / (float)(stm->dev->fl_end - stm->dev->fl_start)) * (float)(addr - stm->dev->fl_start) ); fflush(stdout); } fprintf(stdout, "Done.\n"); fprintf(stdout, "\033[?25h"); ret = 0; goto close; } else if (wu) { fprintf(stdout, "Write-unprotecting flash\n"); /* the device automatically performs a reset after the sending the ACK */ reset_flag = 0; stm32_wunprot_memory(stm); fprintf(stdout, "Done.\n"); } else if (wr) { printf("\n"); off_t offset = 0; ssize_t r; unsigned int size = parser->size(p_st); if (size > stm->dev->fl_end - stm->dev->fl_start) { fprintf(stderr, "File provided larger then available flash space.\n"); goto close; } if (!stm32_erase_memory(stm, spage, npages)) { fprintf(stderr, "Failed to erase memory\n"); goto close; } addr = stm->dev->fl_start + (spage * stm->dev->fl_ps); fflush(stdout); fprintf(stdout, "\033[?25l"); while(addr < stm->dev->fl_end && offset < size) { uint32_t left = stm->dev->fl_end - addr; len = sizeof(buffer) > left ? left : sizeof(buffer); len = len > size - offset ? size - offset : len; if (parser->read(p_st, buffer, &len) != PARSER_ERR_OK) goto close; again: if (!stm32_write_memory(stm, addr, buffer, len)) { fprintf(stderr, "Failed to write memory at address 0x%08x\n", addr); goto close; } if (verify) { uint8_t compare[len]; if (!stm32_read_memory(stm, addr, compare, len)) { fprintf(stderr, "Failed to read memory at address 0x%08x\n", addr); goto close; } for(r = 0; r < len; ++r) if (buffer[r] != compare[r]) { if (failed == retry) { fprintf(stderr, "Failed to verify at address 0x%08x, expected 0x%02x and found 0x%02x\n", (uint32_t)(addr + r), buffer [r], compare[r] ); goto close; } ++failed; goto again; } failed = 0; } addr += len; offset += len; fprintf(stdout, "\033[1GWrote %saddress 0x%08x (%.2f%%) ", verify ? "and verified " : "\n", addr, (100.0f / size) * offset ); fflush(stdout); } fprintf(stdout, "Done.\n"); fprintf(stdout, "\033[?25h"); ret = 0; goto close; } else ret = 0; close: if (stm && exec_flag && ret == 0) { if (execute == 0) execute = stm->dev->fl_start; fprintf(stdout, "\nStarting execution at address 0x%08x... ", execute); fflush(stdout); if (stm32_go(stm, execute)) { reset_flag = 0; fprintf(stdout, "done.\n"); } else fprintf(stdout, "failed.\n"); } if (stm && reset_flag) { fprintf(stdout, "\nResetting device... "); fflush(stdout); if (stm32_reset_device(stm)) fprintf(stdout, "done.\n"); else fprintf(stdout, "failed.\n"); } cleanup(); printf("\n"); return ret; }
int main(int argc, char* argv[]) { int ret = 1; parser_err_t perr; FILE *diag = stdout; fprintf(diag, "stm32flash " VERSION "\n\n"); fprintf(diag, "http://stm32flash.googlecode.com/\n\n"); if (parse_options(argc, argv) != 0) goto close; if (rd && filename[0] == '-') { diag = stderr; } if (wr) { /* first try hex */ if (!force_binary) { parser = &PARSER_HEX; p_st = parser->init(); if (!p_st) { fprintf(stderr, "%s Parser failed to initialize\n", parser->name); goto close; } } if (force_binary || (perr = parser->open(p_st, filename, 0)) != PARSER_ERR_OK) { if (force_binary || perr == PARSER_ERR_INVALID_FILE) { if (!force_binary) { parser->close(p_st); p_st = NULL; } /* now try binary */ parser = &PARSER_BINARY; p_st = parser->init(); if (!p_st) { fprintf(stderr, "%s Parser failed to initialize\n", parser->name); goto close; } perr = parser->open(p_st, filename, 0); } /* if still have an error, fail */ if (perr != PARSER_ERR_OK) { fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); if (perr == PARSER_ERR_SYSTEM) perror(filename); goto close; } } fprintf(diag, "Using Parser : %s\n", parser->name); } else { parser = &PARSER_BINARY; p_st = parser->init(); if (!p_st) { fprintf(stderr, "%s Parser failed to initialize\n", parser->name); goto close; } } serial = serial_open(device); if (!serial) { fprintf(stderr, "Failed to open serial port: "); perror(device); goto close; } if (serial_setup( serial, baudRate, serial_get_bits(serial_mode), serial_get_parity(serial_mode), serial_get_stopbit(serial_mode) ) != SERIAL_ERR_OK) { perror(device); goto close; } fprintf(diag, "Serial Config: %s\n", serial_get_setup_str(serial)); if (init_flag && init_bl_entry(serial, gpio_seq) == 0) goto close; if (!(stm = stm32_init(serial, init_flag))) goto close; fprintf(diag, "Version : 0x%02x\n", stm->bl_version); fprintf(diag, "Option 1 : 0x%02x\n", stm->option1); fprintf(diag, "Option 2 : 0x%02x\n", stm->option2); fprintf(diag, "Device ID : 0x%04x (%s)\n", stm->pid, stm->dev->name); fprintf(diag, "- RAM : %dKiB (%db reserved by bootloader)\n", (stm->dev->ram_end - 0x20000000) / 1024, stm->dev->ram_start - 0x20000000); fprintf(diag, "- Flash : %dKiB (sector size: %dx%d)\n", (stm->dev->fl_end - stm->dev->fl_start ) / 1024, stm->dev->fl_pps, stm->dev->fl_ps); fprintf(diag, "- Option RAM : %db\n", stm->dev->opt_end - stm->dev->opt_start + 1); fprintf(diag, "- System RAM : %dKiB\n", (stm->dev->mem_end - stm->dev->mem_start) / 1024); uint8_t buffer[256]; uint32_t addr, start, end; unsigned int len; int failed = 0; if (rd) { fprintf(diag, "\n"); if ((perr = parser->open(p_st, filename, 1)) != PARSER_ERR_OK) { fprintf(stderr, "%s ERROR: %s\n", parser->name, parser_errstr(perr)); if (perr == PARSER_ERR_SYSTEM) perror(filename); goto close; } if (start_addr || readwrite_len) { start = start_addr; if (readwrite_len) end = start_addr + readwrite_len; else end = stm->dev->fl_end; } else { start = stm->dev->fl_start + (spage * stm->dev->fl_ps); end = stm->dev->fl_end; } addr = start; if (start < stm->dev->fl_start || end > stm->dev->fl_end) { fprintf(stderr, "Specified start & length are invalid\n"); goto close; } fflush(diag); while(addr < end) { uint32_t left = end - addr; len = sizeof(buffer) > left ? left : sizeof(buffer); if (!stm32_read_memory(stm, addr, buffer, len)) { fprintf(stderr, "Failed to read memory at address 0x%08x, target write-protected?\n", addr); goto close; } if (parser->write(p_st, buffer, len) != PARSER_ERR_OK) { fprintf(stderr, "Failed to write data to file\n"); goto close; } addr += len; fprintf(diag, "\rRead address 0x%08x (%.2f%%) ", addr, (100.0f / (float)(end - start)) * (float)(addr - start) ); fflush(diag); } fprintf(diag, "Done.\n"); ret = 0; goto close; } else if (rp) { fprintf(stdout, "Read-Protecting flash\n"); /* the device automatically performs a reset after the sending the ACK */ reset_flag = 0; stm32_readprot_memory(stm); fprintf(stdout, "Done.\n"); } else if (ur) { fprintf(stdout, "Read-UnProtecting flash\n"); /* the device automatically performs a reset after the sending the ACK */ reset_flag = 0; stm32_runprot_memory(stm); fprintf(stdout, "Done.\n"); } else if (eraseOnly) { ret = 0; fprintf(stdout, "Erasing flash\n"); if (start_addr || readwrite_len) { if ((start_addr % stm->dev->fl_ps) != 0 || (readwrite_len % stm->dev->fl_ps) != 0) { fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); ret = 1; goto close; } spage = (start_addr - stm->dev->fl_start) / stm->dev->fl_ps; if (readwrite_len) npages = readwrite_len / stm->dev->fl_ps; else npages = (stm->dev->fl_end - stm->dev->fl_start) / stm->dev->fl_ps; } if (!spage && !npages) npages = 0xff; /* mass erase */ if (!stm32_erase_memory(stm, spage, npages)) { fprintf(stderr, "Failed to erase memory\n"); ret = 1; goto close; } } else if (wu) { fprintf(diag, "Write-unprotecting flash\n"); /* the device automatically performs a reset after the sending the ACK */ reset_flag = 0; stm32_wunprot_memory(stm); fprintf(diag, "Done.\n"); } else if (wr) { fprintf(diag, "\n"); off_t offset = 0; ssize_t r; unsigned int size; /* Assume data from stdin is whole device */ if (filename[0] == '-') size = stm->dev->fl_end - stm->dev->fl_start; else size = parser->size(p_st); if (start_addr || readwrite_len) { start = start_addr; spage = (start_addr - stm->dev->fl_start) / stm->dev->fl_ps; if (readwrite_len) { end = start_addr + readwrite_len; npages = (end - stm->dev->fl_start + stm->dev->fl_ps - 1) / stm->dev->fl_ps - spage; } else { end = stm->dev->fl_end; if (spage) npages = (end - stm->dev->fl_start) / stm->dev->fl_ps - spage; else npages = 0xff; /* mass erase */ } } else if (!spage && !npages) { start = stm->dev->fl_start; end = stm->dev->fl_end; npages = 0xff; /* mass erase */ } else { start = stm->dev->fl_start + (spage * stm->dev->fl_ps); if (npages) end = start + npages * stm->dev->fl_ps; else end = stm->dev->fl_end; } addr = start; if (start < stm->dev->fl_start || end > stm->dev->fl_end) { fprintf(stderr, "Specified start & length are invalid\n"); goto close; } // TODO: It is possible to write to non-page boundaries, by reading out flash // from partial pages and combining with the input data // if ((start % stm->dev->fl_ps) != 0 || (end % stm->dev->fl_ps) != 0) { // fprintf(stderr, "Specified start & length are invalid (must be page aligned)\n"); // goto close; // } // TODO: If writes are not page aligned, we should probably read out existing flash // contents first, so it can be preserved and combined with new data if (!stm32_erase_memory(stm, spage, npages)) { fprintf(stderr, "Failed to erase memory\n"); goto close; } fflush(diag); while(addr < end && offset < size) { uint32_t left = end - addr; len = sizeof(buffer) > left ? left : sizeof(buffer); len = len > size - offset ? size - offset : len; if (parser->read(p_st, buffer, &len) != PARSER_ERR_OK) goto close; if (len == 0) { if (filename[0] == '-') { break; } else { fprintf(stderr, "Failed to read input file\n"); goto close; } } again: if (!stm32_write_memory(stm, addr, buffer, len)) { fprintf(stderr, "Failed to write memory at address 0x%08x\n", addr); goto close; } if (verify) { uint8_t compare[len]; if (!stm32_read_memory(stm, addr, compare, len)) { fprintf(stderr, "Failed to read memory at address 0x%08x\n", addr); goto close; } for(r = 0; r < len; ++r) if (buffer[r] != compare[r]) { if (failed == retry) { fprintf(stderr, "Failed to verify at address 0x%08x, expected 0x%02x and found 0x%02x\n", (uint32_t)(addr + r), buffer [r], compare[r] ); goto close; } ++failed; goto again; } failed = 0; } addr += len; offset += len; fprintf(diag, "\rWrote %saddress 0x%08x (%.2f%%) ", verify ? "and verified " : "", addr, (100.0f / size) * offset ); fflush(diag); } fprintf(diag, "Done.\n"); ret = 0; goto close; } else ret = 0; close: if (stm && exec_flag && ret == 0) { if (execute == 0) execute = stm->dev->fl_start; fprintf(diag, "\nStarting execution at address 0x%08x... ", execute); fflush(diag); if (stm32_go(stm, execute)) { reset_flag = 0; fprintf(diag, "done.\n"); } else fprintf(diag, "failed.\n"); } if (stm && reset_flag) { fprintf(diag, "\nResetting device... "); fflush(diag); if (init_bl_exit(stm, serial, gpio_seq)) fprintf(diag, "done.\n"); else fprintf(diag, "failed.\n"); } if (p_st ) parser->close(p_st); if (stm ) stm32_close (stm); if (serial) serial_close (serial); fprintf(diag, "\n"); return ret; }