static int cmd_sig(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { int i; int rc; AVRMEM * m; rc = avr_signature(pgm, p); if (rc != 0) { fprintf(stderr, "error reading signature data, rc=%d\n", rc); } m = avr_locate_mem(p, "signature"); if (m == NULL) { fprintf(stderr, "signature data not defined for device \"%s\"\n", p->desc); } else { fprintf(stdout, "Device signature = 0x"); for (i=0; i<m->size; i++) fprintf(stdout, "%02x", m->buf[i]); fprintf(stdout, "\n\n"); } return 0; }
/* TPI chip erase sequence */ int avr_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p) { int err; AVRMEM *mem; if (p->flags & AVRPART_HAS_TPI) { pgm->pgm_led(pgm, ON); /* Set Pointer Register */ mem = avr_locate_mem(p, "flash"); if (mem == NULL) { fprintf(stderr, "No flash memory to erase for part %s\n", p->desc); return -1; } unsigned char cmd[] = { /* write pointer register high byte */ (TPI_CMD_SSTPR | 0), ((mem->offset & 0xFF) | 1), /* and low byte */ (TPI_CMD_SSTPR | 1), ((mem->offset >> 8) & 0xFF), /* write CHIP_ERASE command to NVMCMD register */ (TPI_CMD_SOUT | TPI_SIO_ADDR(TPI_IOREG_NVMCMD)), TPI_NVMCMD_CHIP_ERASE, /* write dummy value to start erase */ TPI_CMD_SST, 0xFF }; while (avr_tpi_poll_nvmbsy(pgm)); err = pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0); if(err) return err; while (avr_tpi_poll_nvmbsy(pgm)); pgm->pgm_led(pgm, OFF); return 0; } else {
/* * Writes the specified fuse in fusename (can be "lfuse", "hfuse", or * "efuse") and verifies it. Will try up to tries amount of times * before giving up */ int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries, int verbose) { AVRMEM * m; unsigned char fuseread; int returnvalue = -1; m = avr_locate_mem(p, fusename); if (m == NULL) { return -1; } /* Keep trying to write then read back the fuse values */ while (tries > 0) { if (avr_write_byte(pgm, p, m, 0, fuse) != 0) { continue; } if (pgm->read_byte(pgm, p, m, 0, &fuseread) != 0) { continue; } /* Report information to user if needed */ if (verbose > 0) { fprintf(stderr, "%s: safemode: Wrote %s to %x, read as %x. %d attempts left\n", progname, fusename, fuse, fuseread, tries-1); } /* If fuse wrote OK, no need to keep going */ if (fuse == fuseread) { tries = 0; returnvalue = 0; } tries--; } return returnvalue; }
static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { char * e; int len, maxsize; char * memtype; unsigned long addr, i; unsigned char * buf; unsigned char b; int rc; int werror; AVRMEM * mem; if (argc < 4) { fprintf(stderr, "Usage: write <memtype> <addr> <byte1> " "<byte2> ... byteN>\n"); return -1; } memtype = argv[1]; mem = avr_locate_mem(p, memtype); if (mem == NULL) { fprintf(stderr, "\"%s\" memory type not defined for part \"%s\"\n", memtype, p->desc); return -1; } maxsize = mem->size; addr = strtoul(argv[2], &e, 0); if (*e || (e == argv[2])) { fprintf(stderr, "%s (write): can't parse address \"%s\"\n", progname, argv[2]); return -1; } if (addr > maxsize) { fprintf(stderr, "%s (write): address 0x%05lx is out of range for %s memory\n", progname, addr, memtype); return -1; } /* number of bytes to write at the specified address */ len = argc - 3; if ((addr + len) > maxsize) { fprintf(stderr, "%s (write): selected address and # bytes exceed " "range for %s memory\n", progname, memtype); return -1; } buf = malloc(len); if (buf == NULL) { fprintf(stderr, "%s (write): out of memory\n", progname); return -1; } for (i=3; i<argc; i++) { buf[i-3] = strtoul(argv[i], &e, 0); if (*e || (e == argv[i])) { fprintf(stderr, "%s (write): can't parse byte \"%s\"\n", progname, argv[i]); free(buf); return -1; } } pgm->err_led(pgm, OFF); for (werror=0, i=0; i<len; i++) { rc = avr_write_byte(pgm, p, mem, addr+i, buf[i]); if (rc) { fprintf(stderr, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n", progname, buf[i], addr+i, rc); if (rc == -1) fprintf(stderr, "write operation not supported on memory type \"%s\"\n", mem->desc); werror = 1; } rc = pgm->read_byte(pgm, p, mem, addr+i, &b); if (b != buf[i]) { fprintf(stderr, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n", progname, buf[i], addr+i, b); werror = 1; } if (werror) { pgm->err_led(pgm, ON); } } free(buf); fprintf(stdout, "\n"); return 0; }
static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { static char prevmem[128] = {0}; char * e; unsigned char * buf; int maxsize; unsigned long i; static unsigned long addr=0; static int len=64; AVRMEM * mem; char * memtype = NULL; int rc; if (!((argc == 2) || (argc == 4))) { fprintf(stderr, "Usage: dump <memtype> [<addr> <len>]\n"); return -1; } memtype = argv[1]; if (strncmp(prevmem, memtype, strlen(memtype)) != 0) { addr = 0; len = 64; strncpy(prevmem, memtype, sizeof(prevmem)-1); prevmem[sizeof(prevmem)-1] = 0; } mem = avr_locate_mem(p, memtype); if (mem == NULL) { fprintf(stderr, "\"%s\" memory type not defined for part \"%s\"\n", memtype, p->desc); return -1; } if (argc == 4) { addr = strtoul(argv[2], &e, 0); if (*e || (e == argv[2])) { fprintf(stderr, "%s (dump): can't parse address \"%s\"\n", progname, argv[2]); return -1; } len = strtol(argv[3], &e, 0); if (*e || (e == argv[3])) { fprintf(stderr, "%s (dump): can't parse length \"%s\"\n", progname, argv[3]); return -1; } } maxsize = mem->size; if (addr >= maxsize) { if (argc == 2) { /* wrap around */ addr = 0; } else { fprintf(stderr, "%s (dump): address 0x%05lx is out of range for %s memory\n", progname, addr, mem->desc); return -1; } } /* trim len if nessary to not read past the end of memory */ if ((addr + len) > maxsize) len = maxsize - addr; buf = malloc(len); if (buf == NULL) { fprintf(stderr, "%s (dump): out of memory\n", progname); return -1; } for (i=0; i<len; i++) { rc = pgm->read_byte(pgm, p, mem, addr+i, &buf[i]); if (rc != 0) { fprintf(stderr, "error reading %s address 0x%05lx of part %s\n", mem->desc, addr+i, p->desc); if (rc == -1) fprintf(stderr, "read operation not supported on memory type \"%s\"\n", mem->desc); return -1; } } hexdump_buf(stdout, addr, buf, len); fprintf(stdout, "\n"); free(buf); addr = addr + len; return 0; }
int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags flags) { struct avrpart * v; AVRMEM * mem; int size, vsize; int rc; mem = avr_locate_mem(p, upd->memtype); if (mem == NULL) { fprintf(stderr, "\"%s\" memory type not defined for part \"%s\"\n", upd->memtype, p->desc); return -1; } if (upd->op == DEVICE_READ) { /* * read out the specified device memory and write it to a file */ if (quell_progress < 2) { fprintf(stderr, "%s: reading %s memory:\n", progname, mem->desc); } report_progress(0,1,"Reading"); rc = avr_read(pgm, p, upd->memtype, 0); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", progname, mem->desc, rc); return -1; } report_progress(1,1,NULL); size = rc; if (quell_progress < 2) { fprintf(stderr, "%s: writing output file \"%s\"\n", progname, strcmp(upd->filename, "-")==0 ? "<stdout>" : upd->filename); } rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size); if (rc < 0) { fprintf(stderr, "%s: write to file '%s' failed\n", progname, upd->filename); return -1; } } else if (upd->op == DEVICE_WRITE) { /* * write the selected device memory using data from a file; first * read the data from the specified file */ if (quell_progress < 2) { fprintf(stderr, "%s: reading input file \"%s\"\n", progname, strcmp(upd->filename, "-")==0 ? "<stdin>" : upd->filename); } rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); if (rc < 0) { fprintf(stderr, "%s: read from file '%s' failed\n", progname, upd->filename); return -1; } size = rc; /* * write the buffer contents to the selected memory type */ if (quell_progress < 2) { fprintf(stderr, "%s: writing %s (%d bytes):\n", progname, mem->desc, size); } if (!(flags & UF_NOWRITE)) { report_progress(0,1,"Writing"); rc = avr_write(pgm, p, upd->memtype, size, (flags & UF_AUTO_ERASE) != 0); report_progress(1,1,NULL); } else { /* * test mode, don't actually write to the chip, output the buffer * to stdout in intel hex instead */ rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size); } if (rc < 0) { fprintf(stderr, "%s: failed to write %s memory, rc=%d\n", progname, mem->desc, rc); return -1; } vsize = rc; if (quell_progress < 2) { fprintf(stderr, "%s: %d bytes of %s written\n", progname, vsize, mem->desc); } } else if (upd->op == DEVICE_VERIFY) { /* * verify that the in memory file (p->mem[AVR_M_FLASH|AVR_M_EEPROM]) * is the same as what is on the chip */ pgm->vfy_led(pgm, ON); if (quell_progress < 2) { fprintf(stderr, "%s: verifying %s memory against %s:\n", progname, mem->desc, upd->filename); fprintf(stderr, "%s: load data %s data from input file %s:\n", progname, mem->desc, upd->filename); } rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); if (rc < 0) { fprintf(stderr, "%s: read from file '%s' failed\n", progname, upd->filename); return -1; } v = avr_dup_part(p); size = rc; if (quell_progress < 2) { fprintf(stderr, "%s: input file %s contains %d bytes\n", progname, upd->filename, size); fprintf(stderr, "%s: reading on-chip %s data:\n", progname, mem->desc); } report_progress (0,1,"Reading"); rc = avr_read(pgm, p, upd->memtype, v); if (rc < 0) { fprintf(stderr, "%s: failed to read all of %s memory, rc=%d\n", progname, mem->desc, rc); pgm->err_led(pgm, ON); return -1; } report_progress (1,1,NULL); if (quell_progress < 2) { fprintf(stderr, "%s: verifying ...\n", progname); } rc = avr_verify(p, v, upd->memtype, size); if (rc < 0) { fprintf(stderr, "%s: verification error; content mismatch\n", progname); pgm->err_led(pgm, ON); return -1; } if (quell_progress < 2) { fprintf(stderr, "%s: %d bytes of %s verified\n", progname, rc, mem->desc); } pgm->vfy_led(pgm, OFF); } else { fprintf(stderr, "%s: invalid update operation (%d) requested\n", progname, upd->op); return -1; } return 0; }
/* * Reads the fuses three times, checking that all readings are the * same. This will ensure that the before values aren't in error! */ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse, PROGRAMMER * pgm, AVRPART * p) { unsigned char value; unsigned char fusegood = 0; unsigned char allowfuseread = 1; unsigned char safemode_lfuse; unsigned char safemode_hfuse; unsigned char safemode_efuse; unsigned char safemode_fuse; AVRMEM * m; safemode_lfuse = *lfuse; safemode_hfuse = *hfuse; safemode_efuse = *efuse; safemode_fuse = *fuse; /* Read fuse three times */ fusegood = 2; /* If AVR device doesn't support this fuse, don't want to generate a verify error */ m = avr_locate_mem(p, "fuse"); if (m != NULL) { fusegood = 0; /* By default fuse is a failure */ if(pgm->read_byte(pgm, p, m, 0, &safemode_fuse) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 1, fuse value: %x\n",progname, safemode_fuse); if(pgm->read_byte(pgm, p, m, 0, &value) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 2, fuse value: %x\n",progname, value); if (value == safemode_fuse) { if (pgm->read_byte(pgm, p, m, 0, &value) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 3, fuse value: %x\n",progname, value); if (value == safemode_fuse) { fusegood = 1; /* Fuse read OK three times */ } } } //Programmer does not allow fuse reading.... no point trying anymore if (allowfuseread == 0) { return -5; } if (fusegood == 0) { avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read fuse properly. " "Programmer may not be reliable.\n", progname); return -1; } else if (fusegood == 1) { avrdude_message(MSG_NOTICE, "%s: safemode: fuse reads as %X\n", progname, safemode_fuse); } /* Read lfuse three times */ fusegood = 2; /* If AVR device doesn't support this fuse, don't want to generate a verify error */ m = avr_locate_mem(p, "lfuse"); if (m != NULL) { fusegood = 0; /* By default fuse is a failure */ if (pgm->read_byte(pgm, p, m, 0, &safemode_lfuse) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 1, lfuse value: %x\n",progname, safemode_lfuse); if (pgm->read_byte(pgm, p, m, 0, &value) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 2, lfuse value: %x\n",progname, value); if (value == safemode_lfuse) { if (pgm->read_byte(pgm, p, m, 0, &value) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 3, lfuse value: %x\n",progname, value); if (value == safemode_lfuse){ fusegood = 1; /* Fuse read OK three times */ } } } //Programmer does not allow fuse reading.... no point trying anymore if (allowfuseread == 0) { return -5; } if (fusegood == 0) { avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read lfuse properly. " "Programmer may not be reliable.\n", progname); return -1; } else if (fusegood == 1) { avrdude_message(MSG_DEBUG, "%s: safemode: lfuse reads as %X\n", progname, safemode_lfuse); } /* Read hfuse three times */ fusegood = 2; /* If AVR device doesn't support this fuse, don't want to generate a verify error */ m = avr_locate_mem(p, "hfuse"); if (m != NULL) { fusegood = 0; /* By default fuse is a failure */ if (pgm->read_byte(pgm, p, m, 0, &safemode_hfuse) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 1, hfuse value: %x\n",progname, safemode_hfuse); if (pgm->read_byte(pgm, p, m, 0, &value) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 2, hfuse value: %x\n",progname, value); if (value == safemode_hfuse) { if (pgm->read_byte(pgm, p, m, 0, &value) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 3, hfuse value: %x\n",progname, value); if (value == safemode_hfuse){ fusegood = 1; /* Fuse read OK three times */ } } } //Programmer does not allow fuse reading.... no point trying anymore if (allowfuseread == 0) { return -5; } if (fusegood == 0) { avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read hfuse properly. " "Programmer may not be reliable.\n", progname); return -2; } else if (fusegood == 1){ avrdude_message(MSG_NOTICE, "%s: safemode: hfuse reads as %X\n", progname, safemode_hfuse); } /* Read efuse three times */ fusegood = 2; /* If AVR device doesn't support this fuse, don't want to generate a verify error */ m = avr_locate_mem(p, "efuse"); if (m != NULL) { fusegood = 0; /* By default fuse is a failure */ if (pgm->read_byte(pgm, p, m, 0, &safemode_efuse) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 1, efuse value: %x\n",progname, safemode_efuse); if (pgm->read_byte(pgm, p, m, 0, &value) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 2, efuse value: %x\n",progname, value); if (value == safemode_efuse) { if (pgm->read_byte(pgm, p, m, 0, &value) != 0) { allowfuseread = 0; } avrdude_message(MSG_DEBUG, "%s: safemode read 3, efuse value: %x\n",progname, value); if (value == safemode_efuse){ fusegood = 1; /* Fuse read OK three times */ } } } //Programmer does not allow fuse reading.... no point trying anymore if (allowfuseread == 0) { return -5; } if (fusegood == 0) { avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read efuse properly. " "Programmer may not be reliable.\n", progname); return -3; } else if (fusegood == 1) { avrdude_message(MSG_NOTICE, "%s: safemode: efuse reads as %X\n", progname, safemode_efuse); } *lfuse = safemode_lfuse; *hfuse = safemode_hfuse; *efuse = safemode_efuse; *fuse = safemode_fuse; return 0; }