From c097fb8900ff2b788e6d3969a4fa6a8615565e7c Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 2 Sep 2020 23:14:19 +0300 Subject: [PATCH] attempt to add 8bit flash support --- flashkit.c | 203 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 154 insertions(+), 49 deletions(-) diff --git a/flashkit.c b/flashkit.c index 3e687fc..5d8a587 100644 --- a/flashkit.c +++ b/flashkit.c @@ -119,17 +119,38 @@ static int read_serial(int fd, void *data, size_t size) return 0; } -static void set_addr(int fd, uint32_t addr) +/* addr arg is always byte address */ +static void set_addr8(int fd, uint32_t addr) { uint8_t cmd[6] = { - CMD_ADDR, addr >> 17, - CMD_ADDR, addr >> 9, - CMD_ADDR, addr >> 1 + CMD_ADDR, addr >> 16, + CMD_ADDR, addr >> 8, + CMD_ADDR, addr >> 0 + }; + write_serial(fd, cmd, sizeof(cmd)); +} + +static void set_addr16(int fd, uint32_t addr) +{ + set_addr8(fd, addr >> 1); +} + +static uint16_t read_bus8(int fd, uint32_t addr) +{ + uint8_t cmd[7] = { + CMD_ADDR, addr >> 16, + CMD_ADDR, addr >> 8, + CMD_ADDR, addr >> 0, + CMD_RD | PAR_SINGE | PAR_MODE8 }; + uint8_t r; + write_serial(fd, cmd, sizeof(cmd)); + read_serial(fd, &r, sizeof(r)); + return r; } -static uint16_t read_word(int fd, uint32_t addr) +static uint16_t read_bus16(int fd, uint32_t addr) { uint8_t cmd[7] = { CMD_ADDR, addr >> 17, @@ -144,7 +165,20 @@ static uint16_t read_word(int fd, uint32_t addr) return ntohs(r); } -static void write_word(int fd, uint32_t addr, uint16_t d) +static void write_bus8(int fd, uint32_t addr, uint16_t d) +{ + uint8_t cmd[8] = { + CMD_ADDR, addr >> 16, + CMD_ADDR, addr >> 8, + CMD_ADDR, addr >> 0, + CMD_WR | PAR_SINGE | PAR_MODE8, + d + }; + + write_serial(fd, cmd, sizeof(cmd)); +} + +static void write_bus16(int fd, uint32_t addr, uint16_t d) { uint8_t cmd[9] = { CMD_ADDR, addr >> 17, @@ -157,42 +191,71 @@ static void write_word(int fd, uint32_t addr, uint16_t d) write_serial(fd, cmd, sizeof(cmd)); } -static void read_block(int fd, void *dst, uint32_t size) +static void read_block8(int fd, void *dst, uint32_t size) { + // PAR_MODE8 does not work, so read as 16bit and throw away MSB + uint8_t tmp[0x10000], *d8 = dst; uint8_t cmd[5] = { - CMD_LEN, size >> 9, - CMD_LEN, size >> 1, + CMD_LEN, size >> 8, + CMD_LEN, size >> 0, CMD_RD | PAR_INC }; + int i; assert(size <= 0x10000); write_serial(fd, cmd, sizeof(cmd)); read_serial(fd, dst, size); + read_serial(fd, tmp, size); + + for (i = 0; i < size / 2; i++) + d8[i] = d8[i * 2 + 1]; + d8 += size / 2; + for (i = 0; i < size / 2; i++) + d8[i] = tmp[i * 2 + 1]; } -static uint16_t flash_seq_r(int fd, uint8_t cmd, uint32_t addr) +static void read_block16(int fd, void *dst, uint32_t size) { - // unlock - write_word(fd, 0xaaa, 0xaa); - write_word(fd, 0x555, 0x55); + uint8_t cmd[5] = { + CMD_LEN, size >> 9, + CMD_LEN, size >> 1, + CMD_RD | PAR_INC + }; - write_word(fd, 0xaaa, cmd); - return read_word(fd, addr); + assert(size <= 0x10000); + write_serial(fd, cmd, sizeof(cmd)); + read_serial(fd, dst, size); } -static void flash_seq_erase(int fd, uint32_t addr) +static void flash_seq_write8(int fd, uint32_t addr, const uint8_t *d) { - // printf("erase %06x\n", addr); - write_word(fd, 0xaaa, 0xaa); - write_word(fd, 0x555, 0x55); - write_word(fd, 0xaaa, 0x80); + uint8_t cmd[] = { + // unlock + CMD_ADDR, 0, + CMD_ADDR, 0x0a, + CMD_ADDR, 0xaa, + CMD_WR | PAR_SINGE | PAR_MODE8, 0xaa, + CMD_ADDR, 0, + CMD_ADDR, 0x05, + CMD_ADDR, 0x55, + CMD_WR | PAR_SINGE | PAR_MODE8, 0x55, + // program setup + CMD_ADDR, 0, + CMD_ADDR, 0x0a, + CMD_ADDR, 0xaa, + CMD_WR | PAR_SINGE | PAR_MODE8, 0xa0, + // program data + CMD_ADDR, addr >> 16, + CMD_ADDR, addr >> 8, + CMD_ADDR, addr >> 0, + CMD_WR | PAR_SINGE | PAR_MODE8, *d, + CMD_RY + }; - write_word(fd, 0xaaa, 0xaa); - write_word(fd, 0x555, 0x55); - write_word(fd, addr, 0x30); + write_serial(fd, cmd, sizeof(cmd)); } -static void flash_seq_write(int fd, uint32_t addr, uint8_t *d) +static void flash_seq_write16(int fd, uint32_t addr, const uint8_t *d) { uint8_t cmd[] = { // unlock @@ -220,6 +283,44 @@ static void flash_seq_write(int fd, uint32_t addr, uint8_t *d) write_serial(fd, cmd, sizeof(cmd)); } +static const struct iof +{ + void (*set_addr)(int fd, uint32_t addr); + uint16_t (*read_bus)(int fd, uint32_t addr); + void (*write_bus)(int fd, uint32_t addr, uint16_t d); + void (*read_block)(int fd, void *dst, uint32_t size); + void (*flash_seq_write)(int fd, uint32_t addr, const uint8_t *d); +} +io_ops[] = +{ + { set_addr8, read_bus8, write_bus8, read_block8, flash_seq_write8 }, + { set_addr16, read_bus16, write_bus16, read_block16, flash_seq_write16 }, +}; + +static const struct iof *io = &io_ops[1]; + +static uint16_t flash_seq_r(int fd, uint8_t cmd, uint32_t addr) +{ + // unlock + io->write_bus(fd, 0xaaa, 0xaa); + io->write_bus(fd, 0x555, 0x55); + + io->write_bus(fd, 0xaaa, cmd); + return io->read_bus(fd, addr); +} + +static void flash_seq_erase(int fd, uint32_t addr) +{ + // printf("erase %06x\n", addr); + io->write_bus(fd, 0xaaa, 0xaa); + io->write_bus(fd, 0x555, 0x55); + io->write_bus(fd, 0xaaa, 0x80); + + io->write_bus(fd, 0xaaa, 0xaa); + io->write_bus(fd, 0x555, 0x55); + io->write_bus(fd, addr, 0x30); +} + // status wait + dummy read to cause a wait? static uint16_t ry_read(int fd) { @@ -259,29 +360,29 @@ static void read_info(int fd) uint32_t i, a; info.mid = flash_seq_r(fd, 0x90, 0); // autoselect - info.did = read_word(fd, 2); + info.did = io->read_bus(fd, 2); // could enter CFI directly, but there seems to be a "stack" // of modes, so 2 exits would be needed - write_word(fd, 0, 0xf0); + io->write_bus(fd, 0, 0xf0); - write_word(fd, 0xaa, 0x98); // CFI Query - resp[0] = read_word(fd, 0x20); - resp[1] = read_word(fd, 0x22); - resp[2] = read_word(fd, 0x24); + io->write_bus(fd, 0xaa, 0x98); // CFI Query + resp[0] = io->read_bus(fd, 0x20); + resp[1] = io->read_bus(fd, 0x22); + resp[2] = io->read_bus(fd, 0x24); if (memcmp(resp, qry, sizeof(resp))) { fprintf(stderr, "unexpected CFI response: %04x %04x %04x\n", resp[0], resp[1], resp[2]); exit(1); } - info.size = 1u << read_word(fd, 0x4e); - info.region_cnt = read_word(fd, 0x58); + info.size = 1u << io->read_bus(fd, 0x4e); + info.region_cnt = io->read_bus(fd, 0x58); assert(0 < info.region_cnt && info.region_cnt <= 4); for (i = 0, a = 0x5a; i < info.region_cnt; i++, a += 8) { - info.region[i].block_count = read_word(fd, a + 0) + 1; - info.region[i].block_count += read_word(fd, a + 2) << 8; - info.region[i].block_size = read_word(fd, a + 4) << 8; - info.region[i].block_size |= read_word(fd, a + 6) << 16; + info.region[i].block_count = io->read_bus(fd, a + 0) + 1; + info.region[i].block_count += io->read_bus(fd, a + 2) << 8; + info.region[i].block_size = io->read_bus(fd, a + 4) << 8; + info.region[i].block_size |= io->read_bus(fd, a + 6) << 16; info.region[i].start = total; info.region[i].size = info.region[i].block_size * info.region[i].block_count; @@ -289,7 +390,7 @@ static void read_info(int fd) total += info.region[i].size; } - write_word(fd, 0, 0xf0); // flash reset + io->write_bus(fd, 0, 0xf0); // flash reset printf("Flash info:\n"); printf("Manufacturer ID: %04x\n", info.mid); @@ -328,10 +429,7 @@ static void print_progress(uint32_t done, uint32_t total) { int i, step; - printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); - printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); /* 20 */ - printf("\b\b\b\b\b\b"); - printf("%06x/%06x |", done, total); + printf("\r%06x/%06x |", done, total); step = (total + 19) / 20; for (i = step; i <= total; i += step) @@ -351,6 +449,7 @@ static void usage(const char *argv0) " -w [size] flash the cart (file size)\n" " -e erase (rounds to block size)\n" " -a cart start address (default 0)\n" + " -8 8bit flash\n" " -v verify written data\n" " -i get info about the flash chip\n" , argv0); @@ -389,6 +488,7 @@ int main(int argc, char *argv[]) long a, a_blk, end; int do_info = 0; int do_verify = 0; + int write_step = 2; FILE *f_w = NULL; FILE *f_r = NULL; uint8_t id[2] = { 0, 0 }; @@ -435,6 +535,11 @@ int main(int argc, char *argv[]) invarg(argc, argv, arg); continue; } + if (!strcmp(argv[arg], "-8")) { + io = &io_ops[0]; + write_step = 1; + continue; + } if (!strcmp(argv[arg], "-v")) { do_verify = 1; continue; @@ -491,7 +596,7 @@ int main(int argc, char *argv[]) printf("flashkit id: %02x\n", id[0]); set_delay(fd, 1); - write_word(fd, 0, 0xf0); // flash reset + io->write_bus(fd, 0, 0xf0); // flash reset if (do_info || size_e) read_info(fd); @@ -520,24 +625,24 @@ int main(int argc, char *argv[]) uint8_t b[2]; set_delay(fd, 0); printf("writing %ld bytes:\n", size_w); - for (a = 0; a < size_w; a += 2) { + for (a = 0; a < size_w; a += write_step) { ssize_t r; b[1] = 0xff; - len = min(size_w - a, 2); + len = min(size_w - a, write_step); r = fread(b, 1, len, f_w); if (r != len) { perror("\nfread"); return 1; } - flash_seq_write(fd, address_in + a, b); + io->flash_seq_write(fd, address_in + a, b); - if (!(a & 0x3fe)) + if (!(a & 0x3ff)) print_progress(a, size_w); } print_progress(a, size_w); rv = ry_read(fd); - if (rv != ((b[0] << 8) | b[1])) + if (write_step == 2 && rv != ((b[0] << 8) | b[1])) fprintf(stderr, "warning: last bytes: %04x %02x%02x\n", rv, b[0], b[1]); rewind(f_w); @@ -561,9 +666,9 @@ int main(int argc, char *argv[]) printf("reading %ld bytes:\n", max(size_r, size_v)); print_progress(0, blks * sizeof(g_block)); - set_addr(fd, address_in); + io->set_addr(fd, address_in); for (done = 0; done < size_r || done < size_v; ) { - read_block(fd, g_block, sizeof(g_block)); + io->read_block(fd, g_block, sizeof(g_block)); if (f_r && done < size_r) { len = min(size_r - done, sizeof(g_block)); if (fwrite(g_block, 1, len, f_r) != len) { -- 2.39.2