diff --git a/f32x/f32x.c b/f32x/f32x.c index f447d05..498b1ca 100644 --- a/f32x/f32x.c +++ b/f32x/f32x.c @@ -23,12 +23,42 @@ #include "boundary.h" -#define LOCK_BYTE 0x3dff +struct chip { + const char *name; /* NULL for end of list */ + uint8_t dev_id; + int max_flash_kb; /* maximum flash size, in kB */ + +}; + +struct mem_layout { + int flash_kb; /* real flash size, in kB. 0 for end of list */ + uint16_t lock_byte; /* location of lock byte */ +}; + +static struct chip chips[] = { + { "C8051F320/1", 0x09, 16 }, + { "C8051F326/7", 0x0d, 16 }, + { "C8051F34x", 0x0f, 64 }, + { NULL, } +}; + +static struct mem_layout mem_layouts[] = { + { 16, 0x3dff }, + { 32, 0x7fff }, + { 64, 0xfbff }, + { 0, } +}; + +static const struct chip *chip = NULL; +static const struct mem_layout *layout = NULL; static size_t file_size; +/* ----- flash ------------------------------------------------------------- */ + + static void dump(const char *title, void *data, size_t size) { int i, j; @@ -80,6 +110,39 @@ static void flash_device(void *data, size_t size) } +static void do_flash(const char *name) +{ + FILE *file; + uint8_t code[16384]; + + file = fopen(name, "r"); + if (!file) { + perror(name); + exit(1); + } + file_size = fread(code, 1, sizeof(code), file); + (void) fclose(file); + flash_device(code, file_size); +} + + +/* ----- protect ----------------------------------------------------------- */ + + +static void protect(void) +{ + uint8_t pages, lock_byte; + + pages = (file_size+511) >> 9; + printf("Protecting %d page%s\n", pages, pages == 1 ? "" : "s"); + lock_byte = ~pages; + flash_block_write(layout->lock_byte, &lock_byte, 1); +} + + +/* ----- erase ------------------------------------------------------------- */ + + static void erase_flash(void) { flash_init(); @@ -87,6 +150,9 @@ static void erase_flash(void) } +/* ----- dump -------------------------------------------------------------- */ + + static void dump_flash(size_t size) { int i, j; @@ -119,54 +185,86 @@ static void dump_flash(size_t size) } +/* ----- identify ---------------------------------------------------------- */ + + +static void identify_chip(uint8_t dev) +{ + const struct chip *p; + + for (p = chips; p->name; p++) + if (p->dev_id == dev) { + chip = p; + return; + } +} + + static void identify(void) { - int i; + int i, same = 1; + uint8_t dev, same_dev; c2_addr_write(0); - printf("Dev"); - for (i = 0; i != 10; i++) - printf(" 0x%02x", c2_data_read(1)); - c2_addr_write(1); - printf("\nRev"); - for (i = 0; i != 10; i++) - printf(" 0x%02x", c2_data_read(1)); - printf("\n"); -} - - -static void do_flash(const char *name) -{ - FILE *file; - uint8_t code[16384]; - - file = fopen(name, "r"); - if (!file) { - perror(name); + fprintf(stderr, "Dev"); + for (i = 0; i != 10; i++) { + dev = c2_data_read(1); + fprintf(stderr, " 0x%02x", dev); + if (!i) + same_dev = dev; + else { + if (same_dev != dev) + same = 0; + } + } + if (!same) { + fprintf(stderr, "\ncommunication error\n"); exit(1); } - file_size = fread(code, 1, sizeof(code), file); - (void) fclose(file); - flash_device(code, file_size); + identify_chip(same_dev); + + c2_addr_write(1); + fprintf(stderr, "\nRev"); + for (i = 0; i != 10; i++) + fprintf(stderr, " 0x%02x", c2_data_read(1)); + fprintf(stderr, "\n"); } -static void protect(void) +static void determine_layout(int kb) { - uint8_t pages, lock_byte; + if (kb) { + if (chip && kb > chip->max_flash_kb) { + fprintf(stderr, + "chip has only %d kB of flash\n", + chip->max_flash_kb); + exit(1); + } + } else { + if (chip) + kb = chip->max_flash_kb; + } - pages = (file_size+511) >> 9; - printf("Protecting %d page%s\n", pages, pages == 1 ? "" : "s"); - lock_byte = ~pages; - flash_block_write(LOCK_BYTE, &lock_byte, 1); + if (!kb) + return; + for (layout = mem_layouts; layout->flash_kb; layout++) + if (layout->flash_kb == kb) + break; + if (!layout->flash_kb) { + fprintf(stderr, "no memory layout found for %d kB\n", kb); + exit(1); + } } +/* ----- main -------------------------------------------------------------- */ + + static void usage(const char *name) { fprintf(stderr, -"usage: %s [-n] [-p] file\n" -" %s [-n] -d\n" +"usage: %s [-n] [-p] [-k flash_kb] file\n" +" %s [-n] [-k flash_kb] -d\n" " %s [-n] -e\n" " %s [-n] -b pin_setup\n" " %s [-n]\n\n" @@ -176,16 +274,26 @@ static void usage(const char *name) " Pins can be set to 0, 1, or R (pull-up). Dots can be used to structure\n" " the bit string. Prints what the pins read back (0 or 1) in the same\n" " order, with a dot between P0 and P2.\n" -" -d dump Flash content\n" -" -e erase whole Flash\n" -" -n do not provide power to the target (default: do provide power)\n" -" -p protect the data after writing\n" +" -d dump Flash content\n" +" -e erase whole Flash\n" +" -k flash_kb set flash size (16/32/64; default: auto-select)\n" +" -n do not provide power to the target (default: do provide power)\n" +" -p protect the data after writing\n" "Invocation without argument resets the F32x.\n" , name, name, name, name, name); exit(1); } +static void need_layout(void) +{ + if (layout) + return; + fprintf(stderr, "please specify flash size with -k flash_kB\n"); + exit(1); +} + + int main(int argc, char **argv) { enum { @@ -195,10 +303,10 @@ int main(int argc, char **argv) mode_erase, mode_scan, } mode = mode_default; - int do_protect = 0, power = 1; + int do_protect = 0, power = 1, kb = 0; int c; - while ((c = getopt(argc, argv, "bdenp")) != EOF) + while ((c = getopt(argc, argv, "bdek:np")) != EOF) switch (c) { case 'd': if (mode) @@ -215,6 +323,9 @@ int main(int argc, char **argv) usage(*argv); mode = mode_scan;; break; + case 'k': + kb = atoi(optarg); + break; case 'n': power = 0; break; @@ -246,21 +357,36 @@ int main(int argc, char **argv) usage(*argv); break; } + if (do_protect && mode != mode_flash) + usage(*argv); c2_init(power); identify(); + determine_layout(kb); + + if (chip) + fprintf(stderr, "%s, ", chip->name); + else + fprintf(stderr, "unknown chip, "); + if (layout) + fprintf(stderr, "flash size: %d kB\n", layout->flash_kb); + else + fprintf(stderr, "flash size unknown\n"); switch (mode) { case mode_default: /* just reset */ break; case mode_dump: - dump_flash(0x4000); + need_layout(); + dump_flash(layout->lock_byte+2); break; case mode_erase: erase_flash(); break; case mode_flash: + if (do_protect) + need_layout(); do_flash(argv[optind]); if (do_protect) protect();