aboutsummaryrefslogtreecommitdiffstats
path: root/iceprog/iceprog.c
diff options
context:
space:
mode:
Diffstat (limited to 'iceprog/iceprog.c')
-rw-r--r--iceprog/iceprog.c77
1 files changed, 71 insertions, 6 deletions
diff --git a/iceprog/iceprog.c b/iceprog/iceprog.c
index f38b133..c5243b9 100644
--- a/iceprog/iceprog.c
+++ b/iceprog/iceprog.c
@@ -310,6 +310,28 @@ static void flash_bulk_erase()
flash_chip_deselect();
}
+static void flash_4kB_sector_erase(int addr)
+{
+ fprintf(stderr, "erase 4kB sector at 0x%06X..\n", addr);
+
+ uint8_t command[4] = { FC_SE, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
+
+ flash_chip_select();
+ mpsse_send_spi(command, 4);
+ flash_chip_deselect();
+}
+
+static void flash_32kB_sector_erase(int addr)
+{
+ fprintf(stderr, "erase 64kB sector at 0x%06X..\n", addr);
+
+ uint8_t command[4] = { FC_BE32, (uint8_t)(addr >> 16), (uint8_t)(addr >> 8), (uint8_t)addr };
+
+ flash_chip_select();
+ mpsse_send_spi(command, 4);
+ flash_chip_deselect();
+}
+
static void flash_64kB_sector_erase(int addr)
{
fprintf(stderr, "erase 64kB sector at 0x%06X..\n", addr);
@@ -448,7 +470,9 @@ static void help(const char *progname)
fprintf(stderr, " (append 'k' to the argument for size in kilobytes,\n");
fprintf(stderr, " or 'M' for size in megabytes)\n");
fprintf(stderr, " -s slow SPI (50 kHz instead of 6 MHz)\n");
+ fprintf(stderr, " -k keep flash in powered up state (i.e. skip power down command)\n");
fprintf(stderr, " -v verbose output\n");
+ fprintf(stderr, " -i [4,32,64] select erase block size [default: 64k]\n");
fprintf(stderr, "\n");
fprintf(stderr, "Mode of operation:\n");
fprintf(stderr, " [default] write file contents to flash, then verify\n");
@@ -509,6 +533,7 @@ int main(int argc, char **argv)
my_name = argv[0] + i + 1;
int read_size = 256 * 1024;
+ int erase_block_size = 64;
int erase_size = 0;
int rw_offset = 0;
@@ -522,6 +547,7 @@ int main(int argc, char **argv)
bool slow_clock = false;
bool disable_protect = false;
bool disable_verify = false;
+ bool disable_powerdown = false;
const char *filename = NULL;
const char *devstr = NULL;
int ifnum = 0;
@@ -539,11 +565,23 @@ int main(int argc, char **argv)
/* Decode command line parameters */
int opt;
char *endptr;
- while ((opt = getopt_long(argc, argv, "d:I:rR:e:o:cbnStvspX", long_options, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "d:i:I:rR:e:o:cbnStvspXk", long_options, NULL)) != -1) {
switch (opt) {
case 'd': /* device string */
devstr = optarg;
break;
+ case 'i': /* block erase size */
+ if (!strcmp(optarg, "4"))
+ erase_block_size = 4;
+ else if (!strcmp(optarg, "32"))
+ erase_block_size = 32;
+ else if (!strcmp(optarg, "64"))
+ erase_block_size = 64;
+ else {
+ fprintf(stderr, "%s: `%s' is not a valid erase block size (must be `4', `32' or `64')\n", my_name, optarg);
+ return EXIT_FAILURE;
+ }
+ break;
case 'I': /* FTDI Chip interface select */
if (!strcmp(optarg, "A"))
ifnum = 0;
@@ -629,6 +667,9 @@ int main(int argc, char **argv)
case 'X': /* disable verification */
disable_verify = true;
break;
+ case 'k': /* disable power down command */
+ disable_powerdown = true;
+ break;
case -2:
help(argv[0]);
return EXIT_SUCCESS;
@@ -888,12 +929,24 @@ int main(int argc, char **argv)
{
fprintf(stderr, "file size: %ld\n", file_size);
- int begin_addr = rw_offset & ~0xffff;
- int end_addr = (rw_offset + file_size + 0xffff) & ~0xffff;
+ int block_size = erase_block_size << 10;
+ int block_mask = block_size - 1;
+ int begin_addr = rw_offset & ~block_mask;
+ int end_addr = (rw_offset + file_size + block_mask) & ~block_mask;
- for (int addr = begin_addr; addr < end_addr; addr += 0x10000) {
+ for (int addr = begin_addr; addr < end_addr; addr += block_size) {
flash_write_enable();
- flash_64kB_sector_erase(addr);
+ switch(erase_block_size) {
+ case 4:
+ flash_4kB_sector_erase(addr);
+ break;
+ case 32:
+ flash_32kB_sector_erase(addr);
+ break;
+ case 64:
+ flash_64kB_sector_erase(addr);
+ break;
+ }
if (verbose) {
fprintf(stderr, "Status after block erase:\n");
flash_read_status();
@@ -913,10 +966,14 @@ int main(int argc, char **argv)
rc = fread(buffer, 1, page_size, f);
if (rc <= 0)
break;
+ fprintf(stderr, " \r");
+ fprintf(stderr, "addr 0x%06X %3ld%%\r", rw_offset + addr, addr / (file_size / 100));
flash_write_enable();
flash_prog(rw_offset + addr, buffer, rc);
flash_wait();
}
+ fprintf(stderr, " \r");
+ fprintf(stderr, "done.\n");
/* seek to the beginning for second pass */
fseek(f, 0, SEEK_SET);
@@ -931,9 +988,13 @@ int main(int argc, char **argv)
fprintf(stderr, "reading..\n");
for (int addr = 0; addr < read_size; addr += 256) {
uint8_t buffer[256];
+ fprintf(stderr, " \r");
+ fprintf(stderr, "addr 0x%06X %3d%%\r", rw_offset + addr, addr / (read_size / 100));
flash_read(rw_offset + addr, buffer, 256);
fwrite(buffer, read_size - addr > 256 ? 256 : read_size - addr, 1, f);
}
+ fprintf(stderr, " \r");
+ fprintf(stderr, "done.\n");
} else if (!erase_mode && !disable_verify) {
fprintf(stderr, "reading..\n");
for (int addr = 0; true; addr += 256) {
@@ -941,6 +1002,8 @@ int main(int argc, char **argv)
int rc = fread(buffer_file, 1, 256, f);
if (rc <= 0)
break;
+ fprintf(stderr, " \r");
+ fprintf(stderr, "addr 0x%06X %3ld%%\r", rw_offset + addr, addr / (file_size / 100));
flash_read(rw_offset + addr, buffer_flash, rc);
if (memcmp(buffer_file, buffer_flash, rc)) {
fprintf(stderr, "Found difference between flash and file!\n");
@@ -948,6 +1011,7 @@ int main(int argc, char **argv)
}
}
+ fprintf(stderr, " \r");
fprintf(stderr, "VERIFY OK\n");
}
@@ -956,7 +1020,8 @@ int main(int argc, char **argv)
// Reset
// ---------------------------------------------------------
- flash_power_down();
+ if (!disable_powerdown)
+ flash_power_down();
set_cs_creset(1, 1);
usleep(250000);