Merge branch 'main' into pr-pointer-truncation
This commit is contained in:
commit
22362e9f08
134
src/avrcache.c
134
src/avrcache.c
|
@ -44,6 +44,9 @@
|
|||
*
|
||||
* int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
|
||||
*
|
||||
* int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const
|
||||
* AVRMEM *mem, unsigned int baseaddr);
|
||||
*
|
||||
* int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
|
||||
*
|
||||
* avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
|
||||
|
@ -82,6 +85,9 @@
|
|||
* cache preset to all 0xff otherwise the cache discards all pending writes
|
||||
* to EEPROM and is left unchanged otherwise.
|
||||
*
|
||||
* The avr_page_erase_cached() function erases a page and synchronises it
|
||||
* with the cache.
|
||||
*
|
||||
* Finally, avr_reset_cache() resets the cache without synchronising pending
|
||||
* writes() to the device.
|
||||
*
|
||||
|
@ -188,21 +194,18 @@ static int initCache(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
}
|
||||
|
||||
|
||||
static int cacheAddress(int addr, const AVR_Cache *cp, const AVRMEM *mem, int level) {
|
||||
static int cacheAddress(int addr, const AVR_Cache *cp, const AVRMEM *mem) {
|
||||
int cacheaddr = addr + (int) (mem->offset - cp->offset);
|
||||
|
||||
if(cacheaddr < 0 || cacheaddr >= cp->size) { // Should never happen (unless offsets wrong in avrdude.conf)
|
||||
if(level != MSG_INFO)
|
||||
avrdude_message(level, "%s: ", progname);
|
||||
avrdude_message(level, "cacheAddress() %s cache address 0x%04x out of range [0, 0x%04x]\n", mem->desc, cacheaddr, cp->size);
|
||||
avrdude_message(MSG_INFO, "%s: cacheAddress() %s cache address 0x%04x out of range [0, 0x%04x]\n",
|
||||
progname, mem->desc, cacheaddr, cp->size);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
if(mem->page_size != cp->page_size) { // Should never happen (unless incompatible page sizes in avrdude.conf)
|
||||
if(level != MSG_INFO)
|
||||
avrdude_message(level, "%s: ", progname);
|
||||
avrdude_message(level, "cacheAddress() %s page size %d incompatible with cache page size %d\n",
|
||||
mem->desc, mem->page_size, cp->page_size);
|
||||
avrdude_message(MSG_INFO, "%s: cacheAddress() %s page size %d incompatible with cache page size %d\n",
|
||||
progname, mem->desc, mem->page_size, cp->page_size);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -210,7 +213,7 @@ static int cacheAddress(int addr, const AVR_Cache *cp, const AVRMEM *mem, int le
|
|||
}
|
||||
|
||||
|
||||
static int loadCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, int cacheaddr, int level) {
|
||||
static int loadCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, int cacheaddr, int nlOnErr) {
|
||||
int pgno = cacheaddr/cp->page_size;
|
||||
|
||||
if(!cp->iscached[pgno]) {
|
||||
|
@ -218,9 +221,9 @@ static int loadCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p,
|
|||
int cachebase = cacheaddr & ~(cp->page_size-1);
|
||||
if(avr_read_page_default(pgm, p, mem, addr & ~(cp->page_size-1), cp->cont + cachebase) < 0) {
|
||||
report_progress(1, -1, NULL);
|
||||
if(level != MSG_INFO || !quell_progress)
|
||||
avrdude_message(level, "%s: ", progname);
|
||||
avrdude_message(level, "loadCachePage() %s read failed at addr 0x%04x\n", mem->desc, addr);
|
||||
if(nlOnErr && quell_progress)
|
||||
avrdude_message(MSG_INFO, "\n");
|
||||
avrdude_message(MSG_INFO, "%s: loadCachePage() %s read error at addr 0x%04x\n", progname, mem->desc, addr);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -233,21 +236,21 @@ static int loadCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p,
|
|||
}
|
||||
|
||||
|
||||
static int writeCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int base, int level) {
|
||||
static int writeCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int base, int nlOnErr) {
|
||||
// Write modified page cont to device
|
||||
if(avr_write_page_default(pgm, p, mem, base, cp->cont + base) < 0) {
|
||||
report_progress(1, -1, NULL);
|
||||
if(level != MSG_INFO || !quell_progress)
|
||||
avrdude_message(level, "%s: ", progname);
|
||||
avrdude_message(level, "writeCachePage() %s write error at addr 0x%04x\n", mem->desc, base);
|
||||
if(nlOnErr && quell_progress)
|
||||
avrdude_message(MSG_INFO, "\n");
|
||||
avrdude_message(MSG_INFO, "%s: writeCachePage() %s write error at addr 0x%04x\n", progname, mem->desc, base);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
// Read page back from device and update copy to what is on device
|
||||
if(avr_read_page_default(pgm, p, mem, base, cp->copy + base) < 0) {
|
||||
report_progress(1, -1, NULL);
|
||||
if(level != MSG_INFO || !quell_progress)
|
||||
avrdude_message(level, "%s: ", progname);
|
||||
avrdude_message(level, "writeCachePage() %s read error at addr 0x%04x\n", mem->desc, base);
|
||||
if(nlOnErr && quell_progress)
|
||||
avrdude_message(MSG_INFO, "\n");
|
||||
avrdude_message(MSG_INFO, "%s: writeCachePage() %s read error at addr 0x%04x\n", progname, mem->desc, base);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -326,15 +329,17 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
AVR_Cache *cp = mems[i].cp;
|
||||
|
||||
if(!cp->cont) // Ensure cache is initialised from now on
|
||||
if(initCache(cp, pgm, p) < 0)
|
||||
if(initCache(cp, pgm, p) < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: initialising the cache failed\n", progname);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
if(chiperase || !mem || mems[i].zopaddr < 0)
|
||||
continue;
|
||||
|
||||
int n=mems[i].zopaddr;
|
||||
|
||||
if(writeCachePage(cp, pgm, p, mem, n, MSG_INFO) < 0)
|
||||
if(writeCachePage(cp, pgm, p, mem, n, 1) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
// Same? OK, can set cleared bit to one, "normal" memory
|
||||
if(!memcmp(cp->copy + n, cp->cont + n, cp->page_size)) {
|
||||
|
@ -344,7 +349,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
|
||||
// Probably NOR memory, check out page erase
|
||||
if(pgm->page_erase && pgm->page_erase(pgm, p, mem, n) >= 0) {
|
||||
if(writeCachePage(cp, pgm, p, mem, n, MSG_INFO) < 0)
|
||||
if(writeCachePage(cp, pgm, p, mem, n, 1) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
// Worked OK? Can use page erase on this memory
|
||||
if(!memcmp(cp->copy + n, cp->cont + n, cp->page_size)) {
|
||||
|
@ -357,8 +362,10 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
chiperase = 1;
|
||||
}
|
||||
|
||||
if(!chpages)
|
||||
if(!chpages) {
|
||||
avrdude_message(MSG_INFO, "done\n");
|
||||
return LIBAVRDUDE_SUCCESS;
|
||||
}
|
||||
|
||||
if(chiperase) {
|
||||
if(quell_progress) {
|
||||
|
@ -379,8 +386,8 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
nrd++;
|
||||
}
|
||||
|
||||
report_progress(0, 1, "Reading");
|
||||
if(nrd) {
|
||||
report_progress(0, 1, "Reading");
|
||||
// Read full flash and EEPROM
|
||||
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||
AVRMEM *mem = mems[i].mem;
|
||||
|
@ -391,20 +398,20 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
for(int ird = 0, pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) {
|
||||
if(!cp->iscached[pgno]) {
|
||||
report_progress(ird++, nrd, NULL);
|
||||
if(loadCachePage(cp, pgm, p, mem, n, n, MSG_INFO) < 0)
|
||||
if(loadCachePage(cp, pgm, p, mem, n, n, 1) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
report_progress(1, 0, NULL);
|
||||
}
|
||||
report_progress(1, 0, NULL);
|
||||
|
||||
report_progress(0, 1, "Erasing");
|
||||
if(avr_chip_erase(pgm, p) < 0) {
|
||||
report_progress(1, -1, NULL);
|
||||
if(!quell_progress)
|
||||
avrdude_message(MSG_INFO, "%s: ", progname);
|
||||
avrdude_message(MSG_INFO, "avr_flush_cache() chip erase failed\n");
|
||||
if(quell_progress)
|
||||
avrdude_message(MSG_INFO, "\n");
|
||||
avrdude_message(MSG_INFO, "%s: avr_flush_cache() chip erase failed\n", progname);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -426,9 +433,9 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
report_progress(1+ibo++, nbo+2, NULL);
|
||||
if(avr_read_page_default(pgm, p, mem, n, cp->copy + n) < 0) {
|
||||
report_progress(1, -1, NULL);
|
||||
if(!quell_progress)
|
||||
avrdude_message(MSG_INFO, "%s: ", progname);
|
||||
avrdude_message(MSG_INFO, "flash read failed at addr 0x%04x\n", n);
|
||||
if(quell_progress)
|
||||
avrdude_message(MSG_INFO, "\n");
|
||||
avrdude_message(MSG_INFO, "%s: flash read failed at addr 0x%04x\n", progname, n);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@ -439,9 +446,9 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
if(!_is_all_0xff(cp->copy + n, cp->page_size)) { // First page that had EEPROM data
|
||||
if(avr_read_page_default(pgm, p, mem, n, cp->copy + n) < 0) {
|
||||
report_progress(1, -1, NULL);
|
||||
if(!quell_progress)
|
||||
avrdude_message(MSG_INFO, "%s: ", progname);
|
||||
avrdude_message(MSG_INFO, "EEPROM read failed at addr 0x%04x\n", n);
|
||||
if(quell_progress)
|
||||
avrdude_message(MSG_INFO, "\n");
|
||||
avrdude_message(MSG_INFO, "%s: EEPROM read failed at addr 0x%04x\n", progname, n);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
// EEPROM zapped by chip erase? Set all copy to 0xff
|
||||
|
@ -468,8 +475,8 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
nwr++;
|
||||
}
|
||||
|
||||
report_progress(0, 1, "Writing");
|
||||
if(nwr) {
|
||||
report_progress(0, 1, "Writing");
|
||||
// Write all modified pages to the device
|
||||
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||
AVRMEM *mem = mems[i].mem;
|
||||
|
@ -481,24 +488,23 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
if(cp->iscached[pgno] && memcmp(cp->copy + n, cp->cont + n, cp->page_size)) {
|
||||
if(!chiperase && mems[i].pgerase)
|
||||
pgm->page_erase(pgm, p, mem, n);
|
||||
if(writeCachePage(cp, pgm, p, mem, n, MSG_INFO) < 0)
|
||||
if(writeCachePage(cp, pgm, p, mem, n, 1) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
if(memcmp(cp->copy + n, cp->cont + n, cp->page_size)) {
|
||||
report_progress(1, -1, NULL);
|
||||
if(!quell_progress)
|
||||
avrdude_message(MSG_INFO, "%s: ", progname);
|
||||
avrdude_message(MSG_INFO, "%s verification error at addr 0x%04x\n", mem->desc, n);
|
||||
if(quell_progress)
|
||||
avrdude_message(MSG_INFO, "\n");
|
||||
avrdude_message(MSG_INFO, "%s: %s verification error at addr 0x%04x\n", progname, mem->desc, n);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
report_progress(iwr++, nwr, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
report_progress(1, 0, NULL);
|
||||
}
|
||||
report_progress(1, 0, NULL);
|
||||
|
||||
avrdude_message(MSG_INFO, quell_progress? "done\n": "\n");
|
||||
|
||||
return LIBAVRDUDE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -531,12 +537,12 @@ int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *
|
|||
if(initCache(cp, pgm, p) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
int cacheaddr = cacheAddress((int) addr, cp, mem, MSG_NOTICE);
|
||||
int cacheaddr = cacheAddress((int) addr, cp, mem);
|
||||
if(cacheaddr < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
// Ensure cache page is there
|
||||
if(loadCachePage(cp, pgm, p, mem, addr, cacheaddr, MSG_NOTICE) < 0)
|
||||
if(loadCachePage(cp, pgm, p, mem, addr, cacheaddr, 0) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
*value = cp->cont[cacheaddr];
|
||||
|
@ -569,12 +575,12 @@ int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
|||
if(initCache(cp, pgm, p) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
int cacheaddr = cacheAddress((int) addr, cp, mem, MSG_NOTICE);
|
||||
int cacheaddr = cacheAddress((int) addr, cp, mem);
|
||||
if(cacheaddr < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
// Ensure cache page is there
|
||||
if(loadCachePage(cp, pgm, p, mem, addr, cacheaddr, MSG_NOTICE) < 0)
|
||||
if(loadCachePage(cp, pgm, p, mem, addr, cacheaddr, 0) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
cp->cont[cacheaddr] = data;
|
||||
|
@ -640,6 +646,42 @@ int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p) {
|
|||
}
|
||||
|
||||
|
||||
// Erase a page and synchronise it with the cache
|
||||
int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||
unsigned int uaddr) {
|
||||
|
||||
int addr = uaddr;
|
||||
|
||||
if(!pgm->page_erase || !avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
if(pgm->page_erase(pgm, p, mem, uaddr) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
AVR_Cache *cp = avr_mem_is_eeprom_type(mem)? pgm->cp_eeprom: pgm->cp_flash;
|
||||
|
||||
if(!cp->cont) // Init cache if needed
|
||||
if(initCache(cp, pgm, p) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
int cacheaddr = cacheAddress(addr, cp, mem);
|
||||
if(cacheaddr < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
// Invalidate this cache page and read back, ie, we don't trust the page_erase() routine
|
||||
cp->iscached[cacheaddr/cp->page_size] = 0;
|
||||
|
||||
// Reload cache page
|
||||
if(loadCachePage(cp, pgm, p, mem, (int) addr, cacheaddr, 0) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
if(!_is_all_0xff(cp->cont + (cacheaddr & ~(cp->page_size-1)), cp->page_size))
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
return LIBAVRDUDE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// Free cache(s) discarding any pending writes
|
||||
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
AVR_Cache *mems[2] = { pgm->cp_flash, pgm->cp_eeprom, };
|
||||
|
|
|
@ -639,7 +639,7 @@ Note: The ability to handle IPv6 hostnames and addresses is limited to
|
|||
Posix systems (by now).
|
||||
.It Fl q
|
||||
Disable (or quell) output of the progress bar while reading or writing
|
||||
to the device. Specify it a second time for even quieter operation.
|
||||
to the device. Specify it more often for even quieter operations.
|
||||
.It Fl s, u
|
||||
These options used to control the obsolete "safemode" feature which
|
||||
is no longer present. They are silently ignored for backwards compatibility.
|
||||
|
@ -812,7 +812,7 @@ abbreviated to the shortest unambiguous form. Terminal mode provides
|
|||
a command history using
|
||||
.Xr readline 3 ,
|
||||
so previously entered command lines can be recalled and edited. The
|
||||
following commands are currently implemented:
|
||||
following commands are currently implemented for all programmers:
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar dump memory addr len
|
||||
Read
|
||||
|
@ -827,12 +827,14 @@ and display them.
|
|||
Read 256 bytes from the specified memory area, and display them.
|
||||
.It Ar dump memory ...
|
||||
Read all bytes from the specified memory, and display them.
|
||||
.It Ar dump
|
||||
.It Ar dump memory
|
||||
Continue dumping the memory contents for another
|
||||
.Ar 256
|
||||
bytes where the previous
|
||||
.Ar dump
|
||||
command left off.
|
||||
.It Ar read
|
||||
can be used as an alias for dump
|
||||
.It Ar write memory addr data[,] {data[,]}
|
||||
Manually program the respective memory cells, starting at address
|
||||
.Ar addr ,
|
||||
|
@ -895,6 +897,39 @@ or after EOF on input is encountered. The abort command resets
|
|||
the cache discarding all previous writes to the flash and EEPROM cache.
|
||||
.It Ar erase
|
||||
Perform a chip erase and discard all pending writes to EEPROM and flash.
|
||||
.It Ar sig
|
||||
Display the device signature bytes.
|
||||
.It Ar part
|
||||
Display the current part settings and parameters. Includes chip
|
||||
specific information including all memory types supported by the
|
||||
device, read/write timing, etc.
|
||||
.It Ar verbose Op Ar level
|
||||
Change (when
|
||||
.Ar level
|
||||
is provided), or display the verbosity level.
|
||||
The initial verbosity level is controlled by the number of
|
||||
.Fl v
|
||||
options given on the commandline.
|
||||
.It Ar quell Op Ar level
|
||||
Change (when
|
||||
.Ar level
|
||||
is provided), or display the quell level. 1 is used to suppress progress reports.
|
||||
2 or higher yields in progressively quieter operations.
|
||||
The initial quell level is controlled by the number of
|
||||
.Fl q
|
||||
options given on the commandline.
|
||||
.It Ar \&?
|
||||
.It Ar help
|
||||
Give a short on-line summary of the available commands.
|
||||
.It Ar quit
|
||||
Leave terminal mode and thus
|
||||
.Nm avrdude .
|
||||
.El
|
||||
.Pp
|
||||
The terminal commands below may only be implemented on some specific programmers, and may therefore not be available in the help menu.
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It pgerase memory addr
|
||||
Erase one page of the memory specified.
|
||||
.It Ar send b1 b2 b3 b4
|
||||
Send raw instruction codes to the AVR device. If you need access to a
|
||||
feature of an AVR part that is not directly supported by
|
||||
|
@ -903,24 +938,18 @@ this command allows you to use it, even though
|
|||
.Nm
|
||||
does not implement the command. When using direct SPI mode, up to 3 bytes
|
||||
can be omitted.
|
||||
.It Ar sig
|
||||
Display the device signature bytes.
|
||||
.It Ar spi
|
||||
Enter direct SPI mode. The
|
||||
.Em pgmled
|
||||
pin acts as slave select.
|
||||
.Em Only supported on parallel bitbang programmers, and partially by USBtiny.
|
||||
.It Ar part
|
||||
Display the current part settings and parameters. Includes chip
|
||||
specific information including all memory types supported by the
|
||||
device, read/write timing, etc.
|
||||
.Em Supported on parallel bitbang programmers, and partially by USBtiny.
|
||||
.It Ar pgm
|
||||
Return to programming mode (from direct SPI mode).
|
||||
.It Ar vtarg voltage
|
||||
Set the target's supply voltage to
|
||||
.Ar voltage
|
||||
Volts.
|
||||
.Em Only supported on the STK500 and STK600 programmer.
|
||||
.Em Supported on the STK500 and STK600 programmer.
|
||||
.It Ar varef Oo Ar channel Oc Ar voltage
|
||||
Set the adjustable voltage source to
|
||||
.Ar voltage
|
||||
|
@ -932,7 +961,7 @@ On the Atmel STK600, two reference voltages are available, which
|
|||
can be selected by the optional
|
||||
.Ar channel
|
||||
argument (either 0 or 1).
|
||||
.Em Only supported on the STK500 and STK600 programmer.
|
||||
.Em Supported on the STK500 and STK600 programmer.
|
||||
.It Ar fosc freq Ns Op M Ns \&| Ns k
|
||||
Set the master oscillator to
|
||||
.Ar freq
|
||||
|
@ -942,17 +971,16 @@ An optional trailing letter
|
|||
multiplies by 1E6, a trailing letter
|
||||
.Ar \&k
|
||||
by 1E3.
|
||||
.Em Only supported on the STK500 and STK600 programmer.
|
||||
.Em Supported on the STK500 and STK600 programmer.
|
||||
.It Ar fosc off
|
||||
Turn the master oscillator off.
|
||||
.Em Only supported on the STK500 and STK600 programmer.
|
||||
.Em Supported on the STK500 and STK600 programmer.
|
||||
.It Ar sck period
|
||||
.Em STK500 and STK600 programmer only:
|
||||
.Em STK500 and STK600 programmer:
|
||||
Set the SCK clock period to
|
||||
.Ar period
|
||||
microseconds.
|
||||
.Pp
|
||||
.Em JTAG ICE only:
|
||||
.Em JTAG ICE:
|
||||
Set the JTAG ICE bit clock period to
|
||||
.Ar period
|
||||
microseconds.
|
||||
|
@ -962,24 +990,12 @@ software signs off from the JTAG ICE.
|
|||
This parameter can also be used on the JTAG ICE mkII, JTAGICE3, and Atmel-ICE to specify the
|
||||
ISP clock period when operating the ICE in ISP mode.
|
||||
.It Ar parms
|
||||
.Em STK500 and STK600 programmer only:
|
||||
.Em STK500 and STK600 programmer:
|
||||
Display the current voltage and master oscillator parameters.
|
||||
.Pp
|
||||
.Em JTAG ICE only:
|
||||
.Em JTAG ICE:
|
||||
Display the current target supply voltage and JTAG bit clock rate/period.
|
||||
.It Ar verbose Op Ar level
|
||||
Change (when
|
||||
.Ar level
|
||||
is provided), or display the verbosity level.
|
||||
The initial verbosity level is controlled by the number of
|
||||
.Fl v
|
||||
options given on the commandline.
|
||||
.It Ar \&?
|
||||
.It Ar help
|
||||
Give a short on-line summary of the available commands.
|
||||
.It Ar quit
|
||||
Leave terminal mode and thus
|
||||
.Nm avrdude .
|
||||
.Em Other programmers:
|
||||
Display the programmer specific parameters.
|
||||
.El
|
||||
.Ss Default Parallel port pin connections
|
||||
(these can be changed, see the
|
||||
|
|
|
@ -1329,7 +1329,7 @@ commands can be recalled and edited.
|
|||
@section Terminal Mode Commands
|
||||
|
||||
@noindent
|
||||
The following commands are implemented:
|
||||
The following commands are implemented for all programmers:
|
||||
|
||||
@table @code
|
||||
|
||||
|
@ -1350,6 +1350,9 @@ Read all bytes from the specified memory, and display them.
|
|||
Continue dumping the memory contents for another @var{nbytes} where the
|
||||
previous dump command left off.
|
||||
|
||||
@item read
|
||||
Can be used as an alias for dump.
|
||||
|
||||
@item write @var{memtype} @var{addr} @var{data[,]} @{@var{data[,]}@}
|
||||
Manually program the respective memory cells, starting at address
|
||||
@var{addr}, using the data items provided. The terminal implements
|
||||
|
@ -1461,36 +1464,26 @@ cache discarding all previous writes to the flash and EEPROM cache.
|
|||
@item erase
|
||||
Perform a chip erase and discard all pending writes to EEPROM and flash.
|
||||
|
||||
@item send @var{b1} @var{b2} @var{b3} @var{b4}
|
||||
Send raw instruction codes to the AVR device. If you need access to a
|
||||
feature of an AVR part that is not directly supported by AVRDUDE, this
|
||||
command allows you to use it, even though AVRDUDE does not implement the
|
||||
command. When using direct SPI mode, up to 3 bytes
|
||||
can be omitted.
|
||||
|
||||
@item sig
|
||||
Display the device signature bytes.
|
||||
|
||||
@item spi
|
||||
Enter direct SPI mode. The @emph{pgmled} pin acts as slave select.
|
||||
@emph{Only supported on parallel bitbang programmers, and partially by USBtiny.}
|
||||
Slave Select must be externally held low for direct SPI when
|
||||
using USBtinyISP, and send must be a multiple of four bytes.
|
||||
|
||||
@item part
|
||||
Display the current part settings and parameters. Includes chip
|
||||
specific information including all memory types supported by the
|
||||
device, read/write timing, etc.
|
||||
|
||||
@item pgm
|
||||
Return to programming mode (from direct SPI mode).
|
||||
|
||||
@item verbose [@var{level}]
|
||||
Change (when @var{level} is provided), or display the verbosity
|
||||
level.
|
||||
The initial verbosity level is controlled by the number of @code{-v} options
|
||||
given on the command line.
|
||||
|
||||
@item quell [@var{level}]
|
||||
Change (when @var{level} is provided), or display the quell
|
||||
level. 1 is used to suppress progress reports. 2 or higher yields
|
||||
progressively quieter operations. The initial quell level is controlled
|
||||
by the number of @code{-q} options given on the command line.
|
||||
|
||||
@item ?
|
||||
@itemx help
|
||||
Give a short on-line summary of the available commands.
|
||||
|
@ -1501,11 +1494,29 @@ Leave terminal mode and thus AVRDUDE.
|
|||
@end table
|
||||
|
||||
@noindent
|
||||
In addition, the following commands are supported on the STK500
|
||||
and STK600 programmer:
|
||||
In addition, the following commands are supported on some programmers:
|
||||
|
||||
@table @code
|
||||
|
||||
@item pgerase @var{memory} @var{addr}
|
||||
Erase one page of the memory specified.
|
||||
|
||||
@item send @var{b1} @var{b2} @var{b3} @var{b4}
|
||||
Send raw instruction codes to the AVR device. If you need access to a
|
||||
feature of an AVR part that is not directly supported by AVRDUDE, this
|
||||
command allows you to use it, even though AVRDUDE does not implement the
|
||||
command. When using direct SPI mode, up to 3 bytes
|
||||
can be omitted.
|
||||
|
||||
@item spi
|
||||
Enter direct SPI mode. The @emph{pgmled} pin acts as slave select.
|
||||
@emph{Only supported on parallel bitbang programmers, and partially by USBtiny.}
|
||||
Slave Select must be externally held low for direct SPI when
|
||||
using USBtinyISP, and send must be a multiple of four bytes.
|
||||
|
||||
@item pgm
|
||||
Return to programming mode (from direct SPI mode).
|
||||
|
||||
@item vtarg @var{voltage}
|
||||
Set the target's supply voltage to @var{voltage} Volts.
|
||||
|
||||
|
@ -1528,7 +1539,6 @@ Turn the master oscillator off.
|
|||
@item sck @var{period}
|
||||
@emph{STK500 and STK600 only:}
|
||||
Set the SCK clock period to @var{period} microseconds.
|
||||
|
||||
@emph{JTAG ICE only:}
|
||||
Set the JTAG ICE bit clock period to @var{period} microseconds.
|
||||
Note that unlike STK500 settings, this setting will be reverted to
|
||||
|
@ -1540,7 +1550,6 @@ ISP clock period when operating the ICE in ISP mode.
|
|||
@item parms
|
||||
@emph{STK500 and STK600 only:}
|
||||
Display the current voltage and master oscillator parameters.
|
||||
|
||||
@emph{JTAG ICE only:}
|
||||
Display the current target supply voltage and JTAG bit clock rate/period.
|
||||
|
||||
|
|
|
@ -802,6 +802,8 @@ typedef struct programmer_t {
|
|||
int (*read_byte_cached)(const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
unsigned long addr, unsigned char *value);
|
||||
int (*chip_erase_cached)(const struct programmer_t *pgm, const AVRPART *p);
|
||||
int (*page_erase_cached)(const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
unsigned int baseaddr);
|
||||
int (*flush_cache) (const struct programmer_t *pgm, const AVRPART *p);
|
||||
int (*reset_cache) (const struct programmer_t *pgm, const AVRPART *p);
|
||||
AVR_Cache *cp_flash, *cp_eeprom;
|
||||
|
@ -918,6 +920,7 @@ int avr_is_and(const unsigned char *s1, const unsigned char *s2, const unsigned
|
|||
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char *value);
|
||||
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data);
|
||||
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
|
||||
int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned int baseaddr);
|
||||
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
|
||||
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
|
||||
|
||||
|
|
|
@ -122,6 +122,7 @@ PROGRAMMER *pgm_new(void) {
|
|||
pgm->read_byte_cached = avr_read_byte_cached;
|
||||
pgm->write_byte_cached = avr_write_byte_cached;
|
||||
pgm->chip_erase_cached = avr_chip_erase_cached;
|
||||
pgm->page_erase_cached = avr_page_erase_cached;
|
||||
pgm->flush_cache = avr_flush_cache;
|
||||
pgm->reset_cache = avr_reset_cache;
|
||||
|
||||
|
|
406
src/term.c
406
src/term.c
|
@ -26,6 +26,7 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
|
@ -40,91 +41,60 @@
|
|||
#include "term.h"
|
||||
|
||||
struct command {
|
||||
char * name;
|
||||
int (*func)(PROGRAMMER * pgm, struct avrpart * p, int argc, char *argv[]);
|
||||
char * desc;
|
||||
char *name;
|
||||
int (*func)(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
size_t fnoff;
|
||||
char *desc;
|
||||
};
|
||||
|
||||
|
||||
static int cmd_dump (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
static int cmd_dump (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_write (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_flush (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_abort (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_erase (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_sig (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_part (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_help (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_quit (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_send (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_parms (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_vtarg (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_varef (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_fosc (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_sck (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_spi (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_pgm (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
static int cmd_quell (PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]);
|
||||
|
||||
static int cmd_write (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_flush (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_abort (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_erase (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_sig (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_part (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_help (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_quit (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_send (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_parms (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_vtarg (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_varef (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_fosc (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_sck (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_spi (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_pgm (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_verbose (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
|
||||
static int cmd_quell (PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char *argv[]);
|
||||
#define _fo(x) offsetof(PROGRAMMER, x)
|
||||
|
||||
struct command cmd[] = {
|
||||
{ "dump", cmd_dump, "%s <memory> [<addr> <len> | <addr> ... | <addr> | ...]" },
|
||||
{ "read", cmd_dump, "alias for dump" },
|
||||
{ "write", cmd_write, "%s <memory> <addr> [<data>[,] {<data>[,]} | <len> <data>[,] {<data>[,]} ...]" },
|
||||
{ "flush", cmd_flush, "synchronise flash & EEPROM writes with the device" },
|
||||
{ "abort", cmd_abort, "abort flash & EEPROM writes (reset the r/w cache)" },
|
||||
{ "erase", cmd_erase, "perform a chip erase" },
|
||||
{ "sig", cmd_sig, "display device signature bytes" },
|
||||
{ "part", cmd_part, "display the current part information" },
|
||||
{ "send", cmd_send, "send a raw command: %s <b1> <b2> <b3> <b4>" },
|
||||
{ "parms", cmd_parms, "display adjustable parameters (STK500 and Curiosity Nano only)" },
|
||||
{ "vtarg", cmd_vtarg, "set <V[target]> (STK500 and Curiosity Nano only)" },
|
||||
{ "varef", cmd_varef, "set <V[aref]> (STK500 only)" },
|
||||
{ "fosc", cmd_fosc, "set <oscillator frequency> (STK500 only)" },
|
||||
{ "sck", cmd_sck, "set <SCK period> (STK500 only)" },
|
||||
{ "spi", cmd_spi, "enter direct SPI mode" },
|
||||
{ "pgm", cmd_pgm, "return to programming mode" },
|
||||
{ "verbose", cmd_verbose, "change verbosity" },
|
||||
{ "quell", cmd_quell, "set quell level for progress bars" },
|
||||
{ "help", cmd_help, "help" },
|
||||
{ "?", cmd_help, "help" },
|
||||
{ "quit", cmd_quit, "quit after writing out cache for flash & EEPROM" }
|
||||
{ "dump", cmd_dump, _fo(read_byte_cached), "%s <memory> [<addr> <len> | <addr> ... | <addr> | ...]" },
|
||||
{ "read", cmd_dump, _fo(read_byte_cached), "alias for dump" },
|
||||
{ "write", cmd_write, _fo(write_byte_cached), "write <memory> <addr> <data>[,] {<data>[,]}" },
|
||||
{ "", cmd_write, _fo(write_byte_cached), "write <memory> <addr> <len> <data>[,] {<data>[,]} ..." },
|
||||
{ "flush", cmd_flush, _fo(flush_cache), "synchronise flash & EEPROM writes with the device" },
|
||||
{ "abort", cmd_abort, _fo(reset_cache), "abort flash & EEPROM writes (reset the r/w cache)" },
|
||||
{ "erase", cmd_erase, _fo(chip_erase_cached), "perform a chip erase" },
|
||||
{ "pgerase", cmd_pgerase, _fo(page_erase), "pgerase <memory> <addr>" },
|
||||
{ "sig", cmd_sig, _fo(open), "display device signature bytes" },
|
||||
{ "part", cmd_part, _fo(open), "display the current part information" },
|
||||
{ "send", cmd_send, _fo(cmd), "send a raw command: %s <b1> <b2> <b3> <b4>" },
|
||||
{ "parms", cmd_parms, _fo(print_parms), "display adjustable parameters" },
|
||||
{ "vtarg", cmd_vtarg, _fo(set_vtarget), "set <V[target]>" },
|
||||
{ "varef", cmd_varef, _fo(set_varef), "set <V[aref]>" },
|
||||
{ "fosc", cmd_fosc, _fo(set_fosc), "set <oscillator frequency>" },
|
||||
{ "sck", cmd_sck, _fo(set_sck_period), "set <SCK period>" },
|
||||
{ "spi", cmd_spi, _fo(setpin), "enter direct SPI mode" },
|
||||
{ "pgm", cmd_pgm, _fo(setpin), "return to programming mode" },
|
||||
{ "verbose", cmd_verbose, _fo(open), "change verbosity" },
|
||||
{ "quell", cmd_quell, _fo(open), "set quell level for progress bars" },
|
||||
{ "help", cmd_help, _fo(open), "show help message" },
|
||||
{ "?", cmd_help, _fo(open), "same as help" },
|
||||
{ "quit", cmd_quit, _fo(open), "quit after writing out cache for flash & EEPROM" }
|
||||
};
|
||||
|
||||
#define NCMDS ((int)(sizeof(cmd)/sizeof(struct command)))
|
||||
|
@ -133,8 +103,7 @@ struct command cmd[] = {
|
|||
|
||||
static int spi_mode = 0;
|
||||
|
||||
static int nexttok(char * buf, char ** tok, char ** next)
|
||||
{
|
||||
static int nexttok(char *buf, char **tok, char **next) {
|
||||
unsigned char *q, *n;
|
||||
|
||||
q = (unsigned char *) buf;
|
||||
|
@ -171,10 +140,9 @@ static int nexttok(char * buf, char ** tok, char ** next)
|
|||
}
|
||||
|
||||
|
||||
static int hexdump_line(char * buffer, unsigned char * p, int n, int pad)
|
||||
{
|
||||
char * hexdata = "0123456789abcdef";
|
||||
char * b = buffer;
|
||||
static int hexdump_line(char *buffer, unsigned char *p, int n, int pad) {
|
||||
char *hexdata = "0123456789abcdef";
|
||||
char *b = buffer;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
|
@ -201,8 +169,7 @@ static int hexdump_line(char * buffer, unsigned char * p, int n, int pad)
|
|||
}
|
||||
|
||||
|
||||
static int chardump_line(char * buffer, unsigned char * p, int n, int pad)
|
||||
{
|
||||
static int chardump_line(char *buffer, unsigned char *p, int n, int pad) {
|
||||
int i;
|
||||
unsigned char b[128];
|
||||
|
||||
|
@ -223,13 +190,12 @@ static int chardump_line(char * buffer, unsigned char * p, int n, int pad)
|
|||
}
|
||||
|
||||
|
||||
static int hexdump_buf(FILE * f, int startaddr, unsigned char * buf, int len)
|
||||
{
|
||||
static int hexdump_buf(FILE *f, int startaddr, unsigned char *buf, int len) {
|
||||
char dst1[80];
|
||||
char dst2[80];
|
||||
|
||||
int addr = startaddr;
|
||||
unsigned char * p = (unsigned char *)buf;
|
||||
unsigned char *p = (unsigned char *)buf;
|
||||
while (len) {
|
||||
int n = 16;
|
||||
if (n > len)
|
||||
|
@ -246,9 +212,7 @@ static int hexdump_buf(FILE * f, int startaddr, unsigned char * buf, int len)
|
|||
}
|
||||
|
||||
|
||||
static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_dump(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
if (argc < 2 || argc > 4) {
|
||||
terminal_message(MSG_INFO,
|
||||
"Usage: %s <memory> <addr> <len>\n"
|
||||
|
@ -262,8 +226,8 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
|
|||
|
||||
enum { read_size = 256 };
|
||||
static const char *prevmem = "";
|
||||
char * memtype = argv[1];
|
||||
AVRMEM * mem = avr_locate_mem(p, memtype);
|
||||
char *memtype = argv[1];
|
||||
AVRMEM *mem = avr_locate_mem(p, memtype);
|
||||
if (mem == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (dump): %s memory type not defined for part %s\n",
|
||||
progname, memtype, p->desc);
|
||||
|
@ -272,7 +236,7 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
|
|||
int maxsize = mem->size;
|
||||
|
||||
// Get start address if present
|
||||
char * end_ptr;
|
||||
char *end_ptr;
|
||||
static int addr = 0;
|
||||
|
||||
if (argc >= 3 && strcmp(argv[2], "...") != 0) {
|
||||
|
@ -281,9 +245,9 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
|
|||
terminal_message(MSG_INFO, "%s (dump): can't parse address %s\n",
|
||||
progname, argv[2]);
|
||||
return -1;
|
||||
} else if (addr >= maxsize) {
|
||||
terminal_message(MSG_INFO, "%s (dump): address 0x%05lx is out of range for %s memory\n",
|
||||
progname, (long) addr, mem->desc);
|
||||
} else if (addr < 0 || addr >= maxsize) {
|
||||
terminal_message(MSG_INFO, "%s (dump): %s address 0x%05x is out of range [0, 0x%05x]\n",
|
||||
progname, mem->desc, addr, maxsize-1);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +286,7 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
|
|||
if ((addr + len) > maxsize)
|
||||
len = maxsize - addr;
|
||||
|
||||
uint8_t * buf = malloc(len);
|
||||
uint8_t *buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (dump): out of memory\n", progname);
|
||||
return -1;
|
||||
|
@ -399,12 +363,10 @@ static int is_mantissa_only(char *p) {
|
|||
}
|
||||
|
||||
|
||||
static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_write(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
if (argc < 4) {
|
||||
terminal_message(MSG_INFO,
|
||||
"Usage: write <memory> <addr> <data>[,] {<data>[,]} \n"
|
||||
"Usage: write <memory> <addr> <data>[,] {<data>[,]}\n"
|
||||
" write <memory> <addr> <len> <data>[,] {<data>[,]} ...\n"
|
||||
"\n"
|
||||
"Ellipsis ... writes <len> bytes padded by repeating the last <data> item.\n"
|
||||
|
@ -440,8 +402,8 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
|||
uint8_t write_mode; // Operation mode, "standard" or "fill"
|
||||
uint8_t start_offset; // Which argc argument
|
||||
int len; // Number of bytes to write to memory
|
||||
char * memtype = argv[1]; // Memory name string
|
||||
AVRMEM * mem = avr_locate_mem(p, memtype);
|
||||
char *memtype = argv[1]; // Memory name string
|
||||
AVRMEM *mem = avr_locate_mem(p, memtype);
|
||||
if (mem == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (write): %s memory type not defined for part %s\n",
|
||||
progname, memtype, p->desc);
|
||||
|
@ -449,7 +411,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
int maxsize = mem->size;
|
||||
|
||||
char * end_ptr;
|
||||
char *end_ptr;
|
||||
int addr = strtoul(argv[2], &end_ptr, 0);
|
||||
if (*end_ptr || (end_ptr == argv[2])) {
|
||||
terminal_message(MSG_INFO, "%s (write): can't parse address %s\n",
|
||||
|
@ -457,14 +419,14 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (addr > maxsize) {
|
||||
terminal_message(MSG_INFO, "%s (write): address 0x%05lx is out of range for %s memory\n",
|
||||
progname, (long) addr, memtype);
|
||||
if (addr < 0 || addr >= maxsize) {
|
||||
terminal_message(MSG_INFO, "%s (write): %s address 0x%05x is out of range [0, 0x%05x]\n",
|
||||
progname, mem->desc, addr, maxsize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Allocate a buffer guaranteed to be large enough
|
||||
uint8_t * buf = calloc(mem->size + 8 + maxstrlen(argc-3, argv+3)+1, sizeof(uint8_t));
|
||||
uint8_t *buf = calloc(mem->size + 8 + maxstrlen(argc-3, argv+3)+1, sizeof(uint8_t));
|
||||
if (buf == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (write): out of memory\n", progname);
|
||||
return -1;
|
||||
|
@ -732,32 +694,24 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_flush(PROGRAMMER *pgm, struct avrpart *p, int ac, char *av[]) {
|
||||
static int cmd_flush(PROGRAMMER *pgm, AVRPART *p, int ac, char *av[]) {
|
||||
pgm->flush_cache(pgm, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cmd_abort(PROGRAMMER *pgm, struct avrpart *p, int ac, char *av[]) {
|
||||
static int cmd_abort(PROGRAMMER *pgm, AVRPART *p, int ac, char *av[]) {
|
||||
pgm->reset_cache(pgm, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cmd_send(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_send(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
unsigned char cmd[4], res[4];
|
||||
char * e;
|
||||
char *e;
|
||||
int i;
|
||||
int len;
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (send): the %s programmer does not support direct ISP commands\n",
|
||||
progname, pgm->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (spi_mode && (pgm->spi == NULL)) {
|
||||
terminal_message(MSG_INFO, "%s (send): the %s programmer does not support direct SPI transfers\n",
|
||||
progname, pgm->type);
|
||||
|
@ -806,9 +760,7 @@ static int cmd_send(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_erase(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_erase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
terminal_message(MSG_INFO, "%s: erasing chip\n", progname);
|
||||
// Erase chip and clear cache
|
||||
pgm->chip_erase_cached(pgm, p);
|
||||
|
@ -817,9 +769,53 @@ static int cmd_erase(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_part(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_pgerase(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
if(argc < 3) {
|
||||
terminal_message(MSG_INFO, "Usage: pgerase <memory> <addr>\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *memtype = argv[1];
|
||||
AVRMEM *mem = avr_locate_mem(p, memtype);
|
||||
if(!mem) {
|
||||
terminal_message(MSG_INFO, "%s (pgerase): %s memory type not defined for part %s\n",
|
||||
progname, memtype, p->desc);
|
||||
return -1;
|
||||
}
|
||||
if(!avr_has_paged_access(pgm, mem)) {
|
||||
terminal_message(MSG_INFO, "%s (pgerase): %s memory cannot be paged addressed by %s\n",
|
||||
progname, memtype, ldata(lfirst(pgm->id)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int maxsize = mem->size;
|
||||
|
||||
char *end_ptr;
|
||||
int addr = strtoul(argv[2], &end_ptr, 0);
|
||||
if(*end_ptr || (end_ptr == argv[2])) {
|
||||
terminal_message(MSG_INFO, "%s (pgerase): can't parse address %s\n",
|
||||
progname, argv[2]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr < 0 || addr >= maxsize) {
|
||||
terminal_message(MSG_INFO, "%s (pgerase): %s address 0x%05x is out of range [0, 0x%05x]\n",
|
||||
progname, mem->desc, addr, maxsize-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// terminal_message(MSG_INFO, "%s: %s page erase 0x%05x\n", progname, mem->desc, addr & ~(mem->page_size-1));
|
||||
if(pgm->page_erase_cached(pgm, p, mem, (unsigned int) addr) < 0) {
|
||||
terminal_message(MSG_INFO, "%s (pgerase): %s page at 0x%05x could not be erased\n",
|
||||
progname, mem->desc, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cmd_part(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
fprintf(stdout, "\n");
|
||||
avr_display(stdout, p, "", 0);
|
||||
fprintf(stdout, "\n");
|
||||
|
@ -828,12 +824,10 @@ static int cmd_part(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_sig(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_sig(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
int i;
|
||||
int rc;
|
||||
AVRMEM * m;
|
||||
AVRMEM *m;
|
||||
|
||||
rc = avr_signature(pgm, p);
|
||||
if (rc != 0) {
|
||||
|
@ -857,9 +851,7 @@ static int cmd_sig(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_quit(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_quit(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
/* FUSE bit verify will fail if left in SPI mode */
|
||||
if (spi_mode) {
|
||||
cmd_pgm(pgm, p, 0, NULL);
|
||||
|
@ -868,23 +860,14 @@ static int cmd_quit(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_parms(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
if (pgm->print_parms == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (parms): the %s programmer does not support "
|
||||
"adjustable parameters\n", progname, pgm->type);
|
||||
return -1;
|
||||
}
|
||||
static int cmd_parms(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
pgm->print_parms(pgm);
|
||||
terminal_message(MSG_INFO, "\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cmd_vtarg(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_vtarg(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
int rc;
|
||||
double v;
|
||||
char *endp;
|
||||
|
@ -899,11 +882,6 @@ static int cmd_vtarg(PROGRAMMER * pgm, struct avrpart * p,
|
|||
progname, argv[1]);
|
||||
return -1;
|
||||
}
|
||||
if (pgm->set_vtarget == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (vtarg): the %s programmer cannot set V[target]\n",
|
||||
progname, pgm->type);
|
||||
return -2;
|
||||
}
|
||||
if ((rc = pgm->set_vtarget(pgm, v)) != 0) {
|
||||
terminal_message(MSG_INFO, "%s (vtarg): failed to set V[target] (rc = %d)\n",
|
||||
progname, rc);
|
||||
|
@ -913,9 +891,7 @@ static int cmd_vtarg(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_fosc(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_fosc(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
int rc;
|
||||
double v;
|
||||
char *endp;
|
||||
|
@ -938,11 +914,6 @@ static int cmd_fosc(PROGRAMMER * pgm, struct avrpart * p,
|
|||
v *= 1e6;
|
||||
else if (*endp == 'k' || *endp == 'K')
|
||||
v *= 1e3;
|
||||
if (pgm->set_fosc == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (fosc): the %s programmer cannot set oscillator frequency\n",
|
||||
progname, pgm->type);
|
||||
return -2;
|
||||
}
|
||||
if ((rc = pgm->set_fosc(pgm, v)) != 0) {
|
||||
terminal_message(MSG_INFO, "%s (fosc): failed to set oscillator frequency (rc = %d)\n",
|
||||
progname, rc);
|
||||
|
@ -952,9 +923,7 @@ static int cmd_fosc(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_sck(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_sck(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
int rc;
|
||||
double v;
|
||||
char *endp;
|
||||
|
@ -970,11 +939,6 @@ static int cmd_sck(PROGRAMMER * pgm, struct avrpart * p,
|
|||
return -1;
|
||||
}
|
||||
v *= 1e-6; /* Convert from microseconds to seconds. */
|
||||
if (pgm->set_sck_period == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (sck): the %s programmer cannot set SCK period\n",
|
||||
progname, pgm->type);
|
||||
return -2;
|
||||
}
|
||||
if ((rc = pgm->set_sck_period(pgm, v)) != 0) {
|
||||
terminal_message(MSG_INFO, "%s (sck): failed to set SCK period (rc = %d)\n",
|
||||
progname, rc);
|
||||
|
@ -984,9 +948,7 @@ static int cmd_sck(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_varef(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_varef(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
int rc;
|
||||
unsigned int chan;
|
||||
double v;
|
||||
|
@ -1018,11 +980,6 @@ static int cmd_varef(PROGRAMMER * pgm, struct avrpart * p,
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
if (pgm->set_varef == NULL) {
|
||||
terminal_message(MSG_INFO, "%s (varef): the %s programmer cannot set V[aref]\n",
|
||||
progname, pgm->type);
|
||||
return -2;
|
||||
}
|
||||
if ((rc = pgm->set_varef(pgm, chan, v)) != 0) {
|
||||
terminal_message(MSG_INFO, "%s (varef): failed to set V[aref] (rc = %d)\n",
|
||||
progname, rc);
|
||||
|
@ -1032,56 +989,39 @@ static int cmd_varef(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
static int cmd_help(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_help(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
int i;
|
||||
|
||||
fprintf(stdout, "Valid commands:\n");
|
||||
for (i=0; i<NCMDS; i++) {
|
||||
if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
|
||||
continue;
|
||||
fprintf(stdout, " %-7s : ", cmd[i].name);
|
||||
fprintf(stdout, cmd[i].desc, cmd[i].name);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
fprintf(stdout, "\n"
|
||||
"Note that flash and EEPROM type memories are normally read and written\n"
|
||||
"using a cache and paged r/w access; the cache is synchronised on quit.\n"
|
||||
"Use the 'part' command to display valid memory types for use with the\n"
|
||||
"'dump' and 'write' commands.\n\n");
|
||||
|
||||
"Note that not all programmer derivatives support all commands. Flash and\n"
|
||||
"EEPROM type memories are normally read and written using a cache via paged\n"
|
||||
"read and write access; the cache is synchronised on quit. Use the part\n"
|
||||
"command to display valid memory types for use with dump and write.\n\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_spi(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
if (pgm->setpin != NULL) {
|
||||
pgm->setpin(pgm, PIN_AVR_RESET, 1);
|
||||
spi_mode = 1;
|
||||
return 0;
|
||||
}
|
||||
terminal_message(MSG_INFO, "%s: spi command unavailable for this programmer type\n",
|
||||
progname);
|
||||
return -1;
|
||||
static int cmd_spi(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
pgm->setpin(pgm, PIN_AVR_RESET, 1);
|
||||
spi_mode = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_pgm(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
if (pgm->setpin != NULL) {
|
||||
pgm->setpin(pgm, PIN_AVR_RESET, 0);
|
||||
spi_mode = 0;
|
||||
pgm->initialize(pgm, p);
|
||||
return 0;
|
||||
}
|
||||
terminal_message(MSG_INFO, "%s: pgm command unavailable for this programmer type\n",
|
||||
progname);
|
||||
return -1;
|
||||
static int cmd_pgm(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
pgm->setpin(pgm, PIN_AVR_RESET, 0);
|
||||
spi_mode = 0;
|
||||
pgm->initialize(pgm, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_verbose(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_verbose(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
int nverb;
|
||||
char *endp;
|
||||
|
||||
|
@ -1110,9 +1050,7 @@ static int cmd_verbose(PROGRAMMER * pgm, struct avrpart * p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cmd_quell(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int cmd_quell(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
int nquell;
|
||||
char *endp;
|
||||
|
||||
|
@ -1146,17 +1084,16 @@ static int cmd_quell(PROGRAMMER * pgm, struct avrpart * p,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int tokenize(char * s, char *** argv)
|
||||
{
|
||||
static int tokenize(char * s, char ***argv) {
|
||||
int i, n, l, nargs;
|
||||
int len, slen;
|
||||
char * buf;
|
||||
char *buf;
|
||||
int bufsize;
|
||||
char ** bufv;
|
||||
char * bufp;
|
||||
char * q, * r;
|
||||
char * nbuf;
|
||||
char ** av;
|
||||
char **bufv;
|
||||
char *bufp;
|
||||
char *q, *r;
|
||||
char *nbuf;
|
||||
char **av;
|
||||
|
||||
slen = strlen(s);
|
||||
|
||||
|
@ -1244,9 +1181,7 @@ static int tokenize(char * s, char *** argv)
|
|||
}
|
||||
|
||||
|
||||
static int do_cmd(PROGRAMMER * pgm, struct avrpart * p,
|
||||
int argc, char * argv[])
|
||||
{
|
||||
static int do_cmd(PROGRAMMER *pgm, AVRPART *p, int argc, char *argv[]) {
|
||||
int i;
|
||||
int hold;
|
||||
int len;
|
||||
|
@ -1254,10 +1189,11 @@ static int do_cmd(PROGRAMMER * pgm, struct avrpart * p,
|
|||
len = strlen(argv[0]);
|
||||
hold = -1;
|
||||
for (i=0; i<NCMDS; i++) {
|
||||
if (strcasecmp(argv[0], cmd[i].name) == 0) {
|
||||
if(!*(void (**)(void)) ((char *) pgm + cmd[i].fnoff))
|
||||
continue;
|
||||
if (len && strcasecmp(argv[0], cmd[i].name) == 0)
|
||||
return cmd[i].func(pgm, p, argc, argv);
|
||||
}
|
||||
else if (strncasecmp(argv[0], cmd[i].name, len)==0) {
|
||||
if (len && strncasecmp(argv[0], cmd[i].name, len)==0) {
|
||||
if (hold != -1) {
|
||||
terminal_message(MSG_INFO, "%s (cmd): command %s is ambiguous\n",
|
||||
progname, argv[0]);
|
||||
|
@ -1277,8 +1213,7 @@ static int do_cmd(PROGRAMMER * pgm, struct avrpart * p,
|
|||
}
|
||||
|
||||
|
||||
char * terminal_get_input(const char *prompt)
|
||||
{
|
||||
char *terminal_get_input(const char *prompt) {
|
||||
#if defined(HAVE_LIBREADLINE) && !defined(WIN32)
|
||||
char *input;
|
||||
input = readline(prompt);
|
||||
|
@ -1300,13 +1235,12 @@ char * terminal_get_input(const char *prompt)
|
|||
}
|
||||
|
||||
|
||||
int terminal_mode(PROGRAMMER * pgm, struct avrpart * p)
|
||||
{
|
||||
char * cmdbuf;
|
||||
char * q;
|
||||
int rc;
|
||||
int argc;
|
||||
char ** argv;
|
||||
int terminal_mode(PROGRAMMER *pgm, AVRPART *p) {
|
||||
char *cmdbuf;
|
||||
char *q;
|
||||
int rc;
|
||||
int argc;
|
||||
char **argv;
|
||||
|
||||
rc = 0;
|
||||
while ((cmdbuf = terminal_get_input("avrdude> ")) != NULL) {
|
||||
|
|
Loading…
Reference in New Issue