* Change avrdude_message(MSG_XYZ, ...) to msg_xyz(...)
* Define and use pmsg_xyz(...) instead of msg_xyz("%s: ...", progname, ...)
* Review and change avrdude_message() levels
- Introduce new levels warning, error and ext_error
- Distribute info level to info, warning, error, ext_error
- Assign levels (more) consistently
- Unify grammar, punctuation and style of messages
* Use imsg_xyz() to print indented messages
* Show function name in errors and warnings on -v
* Reduce effective verbosity level by number of -q above one
* Fix writing of last word on DWORD TPI parts
* Add n_word_writes AVRMEM config option
* TPI word chunk mode in avr_write_mem
* Simplify addition of n_words_write mem component to grammar
Co-authored-by: Stefan Rueger <stefan.rueger@urclocks.com>
* Provide cached byte-wise read/write API
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_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
routines are available and if the device memory is EEPROM or flash,
otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
respectively. Byte-wise cached read always gets its data from the cache,
possibly after reading a page from the device memory. Byte-wise cached
write with an address in memory range only ever modifies the cache. Any
modifications are written to the device after calling avr_flush_cache() or
when attempting to read or write from a location outside the address range
of the device memory.
avr_flush_cache() synchronises pending writes to EEPROM and flash with the
device. With some programmer and part combinations, flash (and sometimes
EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
bits. When this is detected, either page erase is deployed (eg, with parts
that have PDI/UPDI interfaces), or if that is not available, both EEPROM
and flash caches are fully read in, a pgm->chip_erase() command is issued
and both EEPROM and flash are written back to the device. Hence, it can
take minutes to ensure that a single previously cleared bit is set and,
therefore, this routine should be called sparingly.
avr_chip_erase_cached() erases the chip and discards pending writes() to
flash or EEPROM. It presets the flash cache to all 0xff alleviating the
need to read from the device flash. However, if the programmer serves
bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
instead, necessitating flash memory be fetched from the device on first
read; the reason for this is that bootloaders emulate chip erase and they
won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
erase commands altogether) making it truly unknowable what the flash
contents on device is after a chip erase.
For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
previously cached EEPROM page that contained cleared bits now no longer
has these clear bits on the device. Only with this evidence is the EEPROM
cache preset to all 0xff otherwise the cache discards all pending writes
to EEPROM and is left unchanged otherwise.
Finally, avr_reset_cache() resets the cache without synchronising pending
writes() to the device.
Now variants of chips that the JTAG ICE supports will not cause a warning when used with the original JTAG ICE mkI.
Also, The ATmega165 isn't officially supported by the ICE mkI, so this should be properly tested with the ICE mkI first.
This makes it possible for the application to start immedeatly after the program has been loaded.
Simply use '-E reset' or '-E noreset'. Default is no reset.
Closes#733
Two parts are considered variants here if one part name starts with the name
of the other, flash memory sizes are the same, flash page sizes are the same
and the number of interrupts are the same.
These assignments have been removed as they are redundant and only
imitate the single prog_modes = PM_... | PM_....; assignment. They
are still allowed in the grammar, and would still work.
flags now just hold parameters of the JTAG interface and some secondary
serial, parallel, pseudo parallel info. This separation brings clarity. It
used to be hard to augur whether a part has an ISP interface:
(part->flags & (AVRPART_HAS_PDI | AVRPART_AVR32 | AVRPART_HAS_TPI
| AVRPART_HAS_UPDI)) == 0 && (part->flags & AVRPART_SERIALOK) != 0
or had HVSP or HVPP capability, for that matter. Now it is just, eg,
part->prog_modes & PM_ISP
part->prog_modes & PM_HVPP
- Add prog_modes to part and programmer definitions; prog_mode is a bitwise
or of programming modes
+ PM_SPM: Bootloaders, self-programming with SPM/NVM Controllers
+ PM_TPI: t4, t5, t9, t10, t20, t40, t102, t104
+ PM_ISP: SPI programming for In-System Programming (typ classic parts)
+ PM_PDI: Program and Debug Interface (xmega parts)
+ PM_UPDI: Unified Program and Debug Interface
+ PM_HVSP: High Voltage Serial Programming (some classic parts)
+ PM_HVPP: High Voltage Parallel Programming (most non-HVSP classic parts)
+ PM_debugWIRE: Simpler alternative to JTAG (a subset of HVPP/HVSP parts)
+ PM_JTAG: some classic parts, some xmega
+ PM_aWire: AVR32 parts
- Add mcuid, a unique id in 0..2039, to part definition for urclock programmer
- Add n_interrupts, the number of interrupts, to part definition
- Add n_page_erase to part definition (# of pages erased during NVM erase)
- Implement a simple calculator in config_gram.y so numeric values can be
expressed as simple expressions such as PM_SPM | PM_UPDI
- Introduce a new method of assigning simple components to the grammar without
touching config_gram.y via an eligible-component list in config.c; numeric
expressions on the rhs of an assignment resolve to integer values
- Update documentation in avrdude.conf.in and avrdude.texi
Done by adding code in developer_opts.c that allows to inject part
or memory parameters into a semi-automated rewrite of avrdude.conf
This is a generic method, whereby an external program can, eg.,
scrape atdf files for the right parameters and put them into a
source table into developer_opts.c
- Then write parts description with -p*/i
- Use the output in a new avrdude.conf
- Output again with -p* (no /i) and use that for final avrdude.conf
- Remove table entries
Some manual editing is still necessary to cater for the
@HAVE_PARPORT_BEGIN@ etc sections. This commit also fixes
superfluous whitesapce at the end of avrdude.conf.in lines
Although the avrdude.conf file has changed much, the internal
representation in avrdude has not. This can be verified by
exporting the raw internal data through
avrdude -c*/r -p*/r >/tmp/avrdude.raw
before the change and by comparing again after the change:
avrdude -c*/r -p*/r | diff - /tmp/avrdude.raw
Change (int) poll_index >= (int) addr to poll_index+1 > addr as the former
might turn out to be implementation-defined. The latter is always defined
and what we want here (poll_index+1 won't overflow). Originally, the
condition was poll_index > addr-1, which was always false for addr=0 owing to
2^n modulo arithmetic of unsigned.
Also changed a few comparisons so they no longer are between signed
and unsigned integers reducing compiler warnings.
In order to get meaningful const properties for the PROGRAMMER, AVRPART and
AVRMEM arguments, some code needed to be moved around, otherwise a network of
"tainted" assignments risked rendering nothing const:
- Change void (*enable)(PROGRAMMER *pgm) to void (*enable)(PROGRAMMER *pgm,
const AVRPART *p); this allows changes in the PROGRAMMER structure after
the part is known. For example, use TPI, UPDI, PDI functions in that
programmer appropriate to the part. This used to be done later in the
process, eg, in the initialize() function, which "taints" all other
programmer functions wrt const and sometimes requires other finessing with
flags etc. Much clearer with the modified enable() interface.
- Move TPI initpgm-type code from initialize() to enable() --- note that
initpgm() does not have the info at the time when it is called whether or
not TPI is required
- buspirate.c: move pgm->flag to PDATA(pgm)->flag (so legitimate
modification of the flag does not change PROGRAMMER structure)
- Move AVRPART_INIT_SMC and AVRPART_WRITE bits from the flags field in
AVRPART to jtagmkII.c's private data flags32 fiels as FLAGS32_INIT_SMC and
FLAGS32_WRITE bits
- Move the xbeeResetPin component to private data in stk500.c as this is
needed by xbee when it saddles on the stk500 code (previously, the flags
component of the part was re-dedicated to this)
- Change the way the "chained" private data are used in jtag3.c whilst
keeping the PROGRAMMER structure read-only otherwise
- In stk500v2.c move the STK600 pgm update from stk500v2_initialize() to
stk500v2_enable() so the former keeps the PROGRAMMER structure read-only
(for const assertion).
- In usbasp change the code from changing PROGRAMMER functions late to
dispatching to TPI or regular SPI protocol functions at runtime; reason
being the decision whether to use TPI protocol is done at run-time
depending on the capability of the attached programmer
Also fixes Issue #1071, the treatment of default eecr value.
`avrdude.1` is installed into `man` dir instead of its proper section
location.
This is due to the definition of `TYPE MAN` which points to
`<DATAROOT>/man` according to cmake docs.
Use `DESTINATION` and add proper section subdir.
This allows for `man -M <YOUR INSTALL dir>/share/man -w 1 avrdude` to succeed
instead of throwing `No manual entry for avrdude in section 1`
Signed-off-by: brutzzl3r <s3b.gr0ss@gmail.com>
man synopsis states [-n -logfile] option. Later on in avrdude.1 as well as in
main.c -l is used.
Also '-logfile' is no option alternative but a parameter.
This is a minor issue but still confusing when one uses / to search
through man pages.
-- Always leave the code cleaner than you found it --
Signed-off-by: brutzzl3r <s3b.gr0ss@gmail.com>
This commit replaces fixed-string buffers in PROGRAMMER, AVRPART and AVRMEM
that are dealt with by the parser and grammar. Now, string assignments are
always to const char *, ie, these are read-only strings with arbitrary
length.
config_gram.y now only needs to consider one type of string assignment.
This commit also
- Replaces the simple linear-search cache_string() function with faster
hashed cache_string(). Either way, the returned value is likely to be
shared, so should never be free()'d.
- Duplicates hvupdi_support list in pgm_dup() and frees it in pgm_free()
- Adds const qualifier to some function args in avrpart.c and pgm.c
- Hardens some functions against being called with NULL pointers
- Ensures _new() and _dup() functions for parts, programmers and memory
return a suitable memory. Out of memory triggers exit in one of three
functions, cfg_malloc(), cfg_realloc() and cfg_strdup(); there is
rarely anything useful that AVRDUDE or, for that matter, any
application compiled against libavrdude can do once you run out of
memory as AVRDUDE/libavrdude rely heavily on allocation of memory.
This commit deals with default_programmer, default_serial, default_parallel
and default_spi. The long term objective is to remove all fixed-size buffers
from the structures that lexer.l and config_gram.y deal with.
- Replace strdup(s) with cfg_strdup(funname, s) that exits on out of mem
- Replace malloc(n) with cfg_malloc(funname, n) that exits on out of mem
- Change multiline string scanning in lexer.l to avoid core dump
- Remove global variables string_buf and string_bug_ptr
- Ensure reading strings unescapes strings C-Style
- Ensure writing strings escapes strings C-Style again
Commit looks longer than needed as unescape() and auxiliary functions needed
to be moved from term.c (not in libavrdude) to config.c (in libavrdude).
Also changed usbdev, usbsn, usbvendor and usbproduct components from
PROGRAMMER structure to be cached string pointers rather than fixed-size
arrays. These will be initialised by pgm_new() with a pointer to nul;
Introduced -p <part>/A, which prints what -p <part>/S used to print, ie, all
components of the part structures including the default ones. Now -p <part>/S
prints the expanded part structure without use of parent and without printing
default values. This functionality is new and predominantly needed for
checking specific avrdude.conf entries, eg, avrdude -p*/St | grep pollindex
The option -p <part>/s continues to print a short entry of `avrdude.conf`
using its parent if so defined:
$ avrdude -p m328p/s
part parent "m328"
desc = "ATmega328P";
id = "m328p";
signature = 0x1e 0x95 0x0f;
;
This commit checks -U update requests for
- Typos in memory names
- Whether the files can be written or read
- Automatic format detection if necessary
before opening the programmer. This to reduce the chances of the
programming failing midway through.
Minor additional changes:
- Give strerror() system info when files are not read/writeable
- Lift the auto detection message from MSG_INFO to MSG_NOTICE
- Provide fileio_fmt_autodetect() in the AVRDUDE library
- Rename fmtstr() in the AVRDUDE library to fileio_fmtstr() to
avoid name clashes when an application links with it
Example:
$ avrdude -U - -U typo:r:.:h -U eeprom:w:testin:r -p ... -c ...
avrdude: can't auto detect file format for stdin/out, specify explicitly
avrdude: unknown memory type typo
avrdude: file . is not writeable (not a regular or character file?)
avrdude: file testin is not readable. No such file or directory
The check for typos in -U memory names against a list of known memory names
now happens after the config files have been read, so newly declared memory
names can be considered. This commit also weakens the check against existence
of a known memory: it is now sufficent for a name to pass when it could be
the initial string of any known memory of any part. Any -U memory that cannot
possibly be matched up with a known memory is considered a typo and leads to
an exit before the programmer is opened.
This to protect users from typos that leave a device partially programmed.
When every -U memory name might be matching one of the known memories, the
programming is attempted. If the part to be programmed turns out not to have
a particular -U memory, AVRDUDE warns the user and skips this -U update.
This to support unifying interfaces that call AVRDUDE with potentially more
memories than the actual part has (eg, efuse on ATmega8).
$ avrdude -qp m8 -c ... -U efuse:w:0xff:m && echo OK
avrdude: AVR device initialized and ready to accept instructions
avrdude: skipping -U efuse:... as memory not defined for part ATmega8
avrdude done. Thank you.
OK
Counting the number of bytes written to a memory and/or verified is not
trivial owing to potential holes in the input file and to potential trailing
0xff bytes in flash memory that are not written per default (but see -A). The
new function memstats(), which is best called just after an input file has
been read into mem->buf/mem->tags, computes the right number of bytes written
and allows easy computation of the number of bytes verified.
This commit also changes the strategy for the default verification after
writing to a chip memory, so that the input file only needs reading once thus
enabling successful verification of stdin input files.
Other, minor changes:
- Improving the grammar of AVRDUDE output, eg, 1 byte written instead of
1 bytes written
- Better description of the input file structure in terms of its sections,
the interval it spans, the number of pages, the number of padding bytes
in pages, and the number of actually cut off trailing 0xff bytes for flash
- Printing <stdin> or <stdout> instead of - in the -U routines
- Option -V no longer needs to be specified before option -U in order to work
As an aside this commit also provides useful helper functions for printing
plural(), inname(), outname() and interval() all of which return strings fit
for printing.
$ avrdude -qp ATmega2560 -c usbtiny -U blink-mega2560+lext-test.hex
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e9801 (probably m2560)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: input file blink-mega2560+lext-test.hex auto detected as Intel Hex
avrdude: reading input file blink-mega2560+lext-test.hex for flash
with 1346 bytes in 4 sections within [0, 0x3106d]
using 7 pages and 446 pad bytes
avrdude: writing 1346 bytes flash ...
avrdude: 1346 bytes of flash written
avrdude: verifying flash memory against blink-mega2560+lext-test.hex
avrdude: 1346 bytes of flash verified
avrdude done. Thank you.
$ avrdude -qp ATmega328P -c usb-bub-ii -U sketch-ending-in-ff.hex
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: input file sketch-ending-in-ff.hex auto detected as Intel Hex
avrdude: reading input file sketch-ending-in-ff.hex for flash
with 2160 bytes in 1 section within [0, 0x888]
using 17 pages and 16 pad bytes, cutting off 25 trailing 0xff bytes
avrdude: writing 2160 bytes flash ...
avrdude: 2160 bytes of flash written
avrdude: verifying flash memory against sketch-ending-in-ff.hex
avrdude: 2185 bytes of flash verified
avrdude done. Thank you.
$ echo "Hello, world..." | avrdude -qp ATmega328P -c ... -U eeprom:w:-:r
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file <stdin> for eeprom
avrdude: writing 16 bytes eeprom ...
avrdude: 16 bytes of eeprom written
avrdude: verifying eeprom memory against <stdin>
avrdude: 16 bytes of eeprom verified
avrdude done. Thank you.
For paged read/write early AVRDUDE implementations of the STK500 v1 protocol
communicated a word address (below a_div=2) or byte address (a_div=1) based
on the following code irrespective of which memories were used:
if(m->op[AVR_OP_LOADPAGE_LO] || m->op[AVR_OP_READ_LO])
a_div = 2;
else
a_div = 1;
This turned out to be a bug: it really should have been a_div=2 for flash and
a_div=1 for eeprom. At the time presumably no one noted because Atmel was at
the cusp of replacing their FW 1.x with FW 2 (and the STK500 v2 protocol).
It seems that the world (optiboot, Arduino as ISP, ...) has compensated for
the bug by assuming AVRDUDE sends *all* eeprom addresses as word addresses.
Actually these programmers overcompensated for the bug because for six out of
the 146 known SPI programmable parts with eeprom and page size > 1, AVRDUDE
would still send the eeprom addresses as byte addresses (ATmega8 ATmega8A
ATmega64 ATmega64A ATmega128 ATmega128A) owing to above code.
It makes no sense to correct the bug now seeing that virtually no one uses
the old 2005 STK 500 v1 firmware. This commit now follows optiboot, Arduino
as ISP and other projects, and simply sends all addresses for paged read or
write as word addresses. There are no longer (little known) exceptions for
ATmega8 et al that surprised some optiboot etc users.
The checks used to be in update.c, but as they are related to
the intended file operation, they are better placed in fileio.c.
The checks affected are to refuse 'm' on output (file write),
and 'd', 'h', 'o', and 'b' formats on input (file read).
The file format specifiers 'h', 'd', 'o', and 'b' are only valid for
outputting data. Reject them with a proper error message when
attempting to use them for input.
The function avr_set_addr_mem(AVRMEM *mem, int opnum, unsigned char *cmd,
unsigned long addr) is meant to replace avr_set_addr(OPCODE *op, unsigned
char *cmd, unsigned long addr) in future.
avr_set_addr_mem() has more information about the context of the task in that
it knows the memory size, memory page size, whether or not the memory is a
flash memory (which gets words addressees supplied) and, crucially, knows
which SPI operation it is meant to compute the address bits for.
avr_set_addr_mem() first computes the interval of bit numbers that must be
supplied for the SPI command to stand a chance to work. The function only
sets those address bits that are needed. Once all avr_set_addr() function
calls have been replaced by avr_set_addr_mem(), the SPI commands that need an
address can afford to declare in avrdude.conf all 16 address bits in the
middle two bytes of the SPI command. This over-declaration will be corrected
during runtime by avr_set_addr_mem(). One consequence of this is that parts
can inherit smaller or larger memories from parents without the need to use
different SPI codes in avrdude.conf. Another consequence is that
avr_set_addr_mem() can, and does, tell the caller whether vital address bits
were not declared in the SPI opcode. During parsing of avrdude.conf this
might be utilised to generate a corresponding warning. This will uncover
problematic SPI codes in avrdude.conf that in the past went undetected.
As the address bit numbers in the SPI opcodes are highly systematic, they
don't really need to be specified. Each bit can therefore be described as one
of the characters 0 (always 0), 1 (always 1), x (don't care, but will be set
as 0), a (a copy of the correct bit of the byte or word address of read,
write, load, pagewrite or load extended address command of memories with more
than one byte), i (input bit for a load/write) or o (output bit from a read).
The bits therefore do not need to be individually separated.
If a string in the list of strings that describe an SPI opcode does *not*
contain a space *and* is longer than 7 characters, it is interpreted as a
compact bit-pattern representation. The characters 0, 1, x, a, i and o will
be recognised as the corresponding bit, whilst any of the characters ., -, _
or / can act as arbitrary visual separators, which are ignored. Examples:
loadpage_lo = "0100.0000--000x.xxxx--xxaa.aaaa--iiii.iiii";
loadpage_lo = "0100.0000", "000x.xxxx", "xxaa.aaaa", "iiii.iiii";
loadpage_lo = "0100.0000", "000x.xxxx.xxaa.aaaa", "iiii.iiii";
loadpage_lo = "0100.0000-000x.xxxx--xxaa.aaaa-iiii.iiii";
loadpage_lo = "0100.0000/000x.xxxx/xxaa.aaaa/iiii.iiii";
The compact format is an extension of the current format, which remains
valid. Both, the compact and the traditional specification can be mixed in
different strings, albeit not in the same string:
load_ext_addr = "0100.1101", "0000.0000.0000", "0 0 0 a16", "0000.0000";
This commit changes the philosophy whenever avrdude.conf encounters the
same memory of a part for the second time or whenever a memory is
described that, through inheritance, already existed: AVRDUDE no longer
zaps the memory, it rather extends it.
Therefore, avrdude.conf.in's entry for ATmega128RFA1, which inherits from
the ATmega2561, needs a line `load_ext_addr = NULL;` in its flash memory
description to zap the inherited load_ext_addr SPI command.
Other than this, avrdude.conf.in needs no other change in order to effect
the same internal representation proving earlier updates to the .conf.in
file correct that manually ensured inheritance of memory contents.
When an SPI command has a lone 'a' the initialisation now is as would be
expected by all commands that take an address. Atmel's opcodes for SPI
programming are consistent in this respect. This commit makes specifying
the bit number in avrdude.conf optional. Instead of
read_lo = "0 0 1 0 0 0 0 0 0 0 a13 a12 a11 a10 a9 a8 a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
one can now use
read_lo = "0 0 1 0 0 0 0 0 0 0 a a a a a a a a a a a a a a o o o o o o o o";
Some 90% of the space of AVRPART and some 50% of PROGRAMMER is occupied by a
4 kB array config_file[] that contains the configuration file name. In
preparation of developer options that output a raw dump of the part
descriptions, this commit changes the config_file components from a large
array, which is duplicated in each part and programmer description, to a
cached string for each config file allowing for smaller raw dumps.
This commit also changes the config file name to its realpath(), eg, shortens
unwarranted `/bin/../etc/` file name components. It also changes the global
variable names `infile` and `fileno` to cfg_infile and cfg_fileno for an ever
so slight improvement of code clarity.
The new file type I is essentially Intel HEX that, on download, inserts
comments next to data records with the resolved effective address and an
ASCII dump of that same record. On upload the `I` format is permissive
with respect to check sum errors, eg, after manipulated an Intel HEX file
for debugging.
Usbtiny has a protocol or firmware problem that prevents it from reading
flash above 64 kB in page mode (used by -U flash:r:... and -U flash✌️...).
This commit fixes that problem by falling back on byte access for flash paged
reads above 64k. It also issues the correct load extended address command for
parts with more than 128 kB flash thus extending support to ATmega2560 et al.
Some C libraries assign true to isalpha(0xff), isdigit(0xff) or
ispunct(0xff), which means that the Operating System terminal sees a
character 0xff which it may not have a useful display character for.
This commit only outputs printable ASCII characters for an AVRDUDE
terminal dump reducing the risk of the OS terminal not being able
to print the character properly.
Error messages are written to stderr whilst normal terminal output is stdout.
When redirecting output to pipelines or files these two streams can get
separated as they are buffered separately. To avoid this, term.c now provides
a function terminal_message() that works just like avrdude_message() but
flushes stderr and stdout before printing on stderr, and it flushes stderr
afterwards.
This commit replaces all avrdude_message() calls except for progress report
with terminal_message() to ensure stdout and stderr streams keep together.
This enables the new quell terminal command to switch on and off progress
reports to the terminal. The code for this was moved from main.c to term.c.
It can be used as library call for other frontends than main.c
Sets the quell_progress global variable that can be, and is, consulted by
programmers.
Setting quell_progress to a positive number also switches off progress
bars. It is currently not possible to switch on progress bars again: that
is enabled in main.c once at the start of AVRDUDE.
That code in main should move to avr.c to enable report_update() to consult
quell_progress directly. Will do at another time when touching main.c and
avr.c. smr
The code no longer accepts valid mantissa-only doubles that are integer
rejects, eg, 078 or ULL overflows. These are most likely input errors by
the user: 8 is not an octal digit, they might have typed 17 hex digits,
not 16. It's just too hard to explain that 0xffffFFFFffffFFFFf writes
0x4430000000000000, which is the correct double representation of the
valid 17-digit hex mantissa that strtod() is perfectly happy to accept.
Integers can be hexadecimal, decimal or octal. An optional case-insensitive
suffix specifies their size: HH: 8 bit, H/S: 16 bit, L: 32 bit, LL: 64 bit
An optional U suffix makes a number unsigned. Ordinary 0x hex numbers are
always treated as unsigned. +0x or -0x hex numbers are treated as signed
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
smaller range when a suffix specifies a smaller type. Out of range signed
numbers trigger a warning.
Ordinary 0x hex numbers with n hex digits (counting leading zeros) use
the smallest size of 1, 2, 4 and 8 bytes that can accommodate any n-digit hex
number. If a suffix specifies a size explicitly the corresponding number of
least significant bytes are written. Otherwise, signed and unsigned integers
alike occupy the smallest of 1, 2, 4, or 8 bytes needed to accommodate them
in their respective representation.
Using strtoll() can only return numbers in the range [-2^63, 2^63-1]. This
means that 0xffffFFFFffffFFFF (2^64-1) will be out of range and is written as
max LL. Actually, every 64-bit number with high-bit set will wrongly be
written as max LL.
This commit uses strtoull() instead to fix this, and checks for unsiged out-
of-range error. strtoull() also has the neat benefit that input with a minus
sign is treated like C unsigned numbers, ie, -u is also a valid unsigned
number if only u is one. In case the input is meant to be treated as signed,
it is therefore still OK to use strtoull() in the first instance only that in
this case a second check against the range of the signed domain is necessary.
The paged read in pickit2.c has two errors:
- It drops load extended address commands unless a paged read happens at a
64k byte boundary; this is invalid when reading files with holes
- It wrongly assumed that flash memory is byte addressed
The fix is to carry out a load extended address command, if needed, at the
beginning of each paged flash read with the correct word address. Although the
pickit2_paged_load() has independent parameters page_size, addr and n_bytes,
AVRDUDE only ever calls paged read/write functions with page_size and n_bytes
both set to mem->page_size and addr aligned with a page boundary. Therefore, it
is sufficient to set the load extended address at the beginning of each page
read.