mirror of
https://github.com/avrdudes/avrdude.git
synced 2026-06-02 09:46:34 +03:00
Merge remote-tracking branch 'upstream/main' into swig_libavrdude
This commit is contained in:
1
.github/workflows/build.yml
vendored
1
.github/workflows/build.yml
vendored
@@ -213,6 +213,7 @@ jobs:
|
||||
bison
|
||||
libelf
|
||||
libusb
|
||||
libusb-compat
|
||||
hidapi
|
||||
libftdi
|
||||
readline
|
||||
|
||||
25
AUTHORS
25
AUTHORS
@@ -13,32 +13,48 @@ AVRDUDE is currently maintained by:
|
||||
Contributors:
|
||||
|
||||
Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
Eric Weddington <ericw@evcohs.com>
|
||||
Eric B. Weddington <ericw@evcohs.com>
|
||||
Martin J. Thomas <mthomas@rhrk.uni-kl.de>
|
||||
Theodore A. Roth <troth@openavr.org>
|
||||
Erik Walthinsen
|
||||
Jan-Hinnerk Reichert <hinni@despammed.com>
|
||||
Alex Shepherd <maillists@ajsystems.co.nz>
|
||||
Martin Thomas <mthomas@rhrk.uni-kl.de>
|
||||
Theodore A. Roth <troth@openavr.org>
|
||||
Juliane Holzt <avrdude@juliane.holzt.de>
|
||||
Colin O'Flynn <coflynn@newae.com>
|
||||
Thomas Fischl <tfischl@gmx.de>
|
||||
David Hoerl <dhoerl@mac.com>
|
||||
Christian Starkjohann
|
||||
David Moore
|
||||
David Brownell
|
||||
Dick Streefland
|
||||
Limor Fried
|
||||
Klaus Leidinger <klaus@mikrocontroller-projekte.de>
|
||||
Lars Immisch
|
||||
Michal Ludvig <mludvig@logix.net.nz>
|
||||
Roger E. Wolff <R.E.Wolff@BitWizard.nl>
|
||||
Darell Tan <darell.tan@gmail.com>
|
||||
Brett Hagman <bhagman@roguerobotics.com>
|
||||
Wolfgang Moser
|
||||
Ville Voipio
|
||||
Hannes Weisbach
|
||||
Doug Springer
|
||||
Brett Hagman <bhagman@roguerobotics.com>
|
||||
Rene Liebscher <r.liebscher@gmx.de>
|
||||
Jim Paris <jim@jtan.com>
|
||||
Jan Egil Ruud <janegil.ruud@microchip.com>
|
||||
David Mosberger <davidm@egauge.net>
|
||||
Kirill Levchenko
|
||||
Kevin Cuzner <kevin@kevincuzner.com>
|
||||
David Sainty
|
||||
Alexey Sadkov
|
||||
Marius Greuel <greuelm@mgtek.com>
|
||||
Ralf Ramsauer <ralf@vmexit.de>
|
||||
Dawid Buchwald <dawid.buchwald@hotmail.com>
|
||||
Hans Eirik Bull
|
||||
Stefan Rueger
|
||||
Xiaofan Chen
|
||||
Jeff Kent
|
||||
Sebastian Kuzminsky <seb@highlab.com>
|
||||
Sydney Louisa Wilke <git@funkeleinhorn.com>
|
||||
|
||||
Contributors to code no longer present:
|
||||
|
||||
@@ -47,4 +63,3 @@ Contributors to code no longer present:
|
||||
Chris Liechti for loaddrv modifications
|
||||
|
||||
For minor contributions, please see the ChangeLog files / Git log.
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ endif()
|
||||
find_library(HAVE_LIBREADLINE NAMES ${PREFERRED_LIBREADLINE})
|
||||
if(HAVE_LIBREADLINE)
|
||||
set(LIB_LIBREADLINE ${HAVE_LIBREADLINE})
|
||||
find_library(LIB_NCURSES NAMES ncurses)
|
||||
find_library(LIB_NCURSES NAMES ncurses pdcurses)
|
||||
elseif(MSVC)
|
||||
set(HAVE_LIBREADLINE 1)
|
||||
endif()
|
||||
|
||||
74
NEWS
74
NEWS
@@ -1,5 +1,3 @@
|
||||
$Id$
|
||||
|
||||
Approximate change log for AVRDUDE by version.
|
||||
|
||||
(For detailed changes, see the version control system logs.)
|
||||
@@ -9,26 +7,57 @@ Changes since version 7.3:
|
||||
|
||||
* Major changes compared to the previous version:
|
||||
|
||||
- Support of multi-memory .hex/.srec files and memory lists #1828
|
||||
- New terminal disasm command #1842
|
||||
|
||||
* New devices supported:
|
||||
|
||||
- AVR16DU14, AVR16DU20, AVR16DU28, AVR16DU32
|
||||
- AVR32DU14, AVR32DU20, AVR32DU28, AVR32DU32
|
||||
|
||||
* New programmers supported:
|
||||
|
||||
- serprog
|
||||
|
||||
* New serial adapters supported:
|
||||
|
||||
- ch342, ch344, ch347, ch9103
|
||||
|
||||
* Issues fixed:
|
||||
|
||||
- Avrintel.h missing from installation #1683
|
||||
- Use of undeclared identifier 'AVRDUDE_FULL_VERSION' #1706
|
||||
- Wrong message level in jtag3_prmsg() #1726
|
||||
- Old avrdude_message() can go away #1719
|
||||
- avr_{read,write}_mem fail to initialize progress reporting #1718
|
||||
- avr*timestamp() oddities #1722
|
||||
- -F option not honored bug #1740
|
||||
- -F option not honoured #1740
|
||||
- "jtag2 is not a unique start of a programmer name" #1739
|
||||
- Regression: EEPROM issue with official STK500 V1 FW #1713
|
||||
- usbasp_write_byte in TPI mode not implemented #1755
|
||||
- Remove calls to exit() from libavrdude library #774
|
||||
- cmake enabling LINUXGPIO on ubuntu 20.04 fails #1782
|
||||
- macOS github action failed. #1793
|
||||
- Format mismatch warnings #1799
|
||||
- 0xff optimization when reading #1732
|
||||
- Add support for more AVR-DU parts #1742
|
||||
- Misleading error message: cannot find programmer id #1805
|
||||
- Custom programmer broken in v7.3 #1807
|
||||
- ATtiny11 does not have EEPROM #1812
|
||||
- AVRDUDE fails to return -1 on some write errors #1821
|
||||
- Multi-memory files #1817
|
||||
- Terminal erase command #1833
|
||||
- Bootrow r/w does not work for -c serialupdi #1832
|
||||
- Wrong error message when specifying wrong AVR-Ex part #1813
|
||||
- AVR109 auto reset functionality #1697
|
||||
- Unable to write LOCK bit byte to JTAG3_TPI #1858
|
||||
- Unexpected auto-erase consequences #1861
|
||||
- JTAGICE3 EDBG communication mode relies on hardcoded USBVID #1838
|
||||
- avrdude documentation typo(s) attemps #1852
|
||||
- Conflicting types for op16_is_mnemo: enum/integer #1851
|
||||
|
||||
* Pull requests:
|
||||
|
||||
- Remove 32bit MSYS2 mingw32 and clang32 build #1687
|
||||
- Make avrintel.h an internal header file for libavrdude #1686
|
||||
- Fix -Wcalloc-transposed-args warning #1680
|
||||
@@ -65,9 +94,48 @@ Changes since version 7.3:
|
||||
- Use magic memory tree interface throughout #1795
|
||||
- Silence MacOS compiler warning #1794
|
||||
- Add macOS autotools to github action #1798
|
||||
- Silence compiler warnings #1800
|
||||
- Fix 7 typos in 4 files #1802
|
||||
- Put static variables into context structure #1803
|
||||
- Add new AVRnnDUnn parts #1804
|
||||
- Differentiate cause when programmer isn't found #1806
|
||||
- Prepare for next urboot version #1808
|
||||
- Rename AVRDUDE symbol names ending in _t #1809
|
||||
- Warn when programmer failes to define prog_modes #1810
|
||||
- Add serprog programmer #1801
|
||||
- Remove EEPROM from ATtiny11 avrdude.conf entry #1814
|
||||
- Guard serial_number access in usbhid_open() to avoid segfault #1815
|
||||
- Allow selection of program modes for developer options #1816
|
||||
- Return -1 on write error #1822
|
||||
- Extend elf format for bootrow #1820
|
||||
- Update AUTHORS list #1819
|
||||
- Downgrade out-of-range file input errors on -F #1818
|
||||
- Multi-memory file handling #1828
|
||||
- Add developer options -p*/vcr to explore SW compatibility #1830
|
||||
- Improve chip erase emulation for dryboot/dryrun #1836
|
||||
- Use page erase for UPDI programming #1837
|
||||
- Add fuses, calibration, sernum and tempsense memories #1829
|
||||
- Fix bootrow access for -c serialupdi #1835
|
||||
- Improve signature check for UPDI parts #1840
|
||||
- Improve error handling for avrdude without libserialport #1843
|
||||
- Provide terminal disasm command #1842
|
||||
- Improve auto-reset handling and -x/-E parsing #1844
|
||||
- Remove obsolete SVN $Id$ tags from source files #1850
|
||||
- Update look and feel #1849
|
||||
- Update documentation for -E and -x #1853
|
||||
- Add more WCH USB to serial chips #1855
|
||||
- cmake: LIB_NCURSES also accept pdcurses #1856
|
||||
- Fix byte writes to TPI lockbits for jpag3.c #1859
|
||||
- Refine auto-erase strategy #1862
|
||||
- Provide -P usb:vid:pid for USB hid i/f and allow
|
||||
long -P usb:serno for usblib and hidapi #186
|
||||
|
||||
* Internals:
|
||||
|
||||
- Created a context structure pointed to by cx, which harbours global
|
||||
and static variables
|
||||
- Made programmers libavrdude ready: remove exit() calls and moved
|
||||
static variables into local struct pdata
|
||||
|
||||
Changes in version 7.3:
|
||||
|
||||
|
||||
@@ -175,6 +175,7 @@ set(SOURCES
|
||||
avrftdi_tpi.h
|
||||
avrintel.c
|
||||
libavrdude-avrintel.h
|
||||
avr_opcodes.c
|
||||
avrpart.c
|
||||
bitbang.c
|
||||
bitbang.h
|
||||
@@ -189,6 +190,7 @@ set(SOURCES
|
||||
confwin.c
|
||||
crc16.c
|
||||
crc16.h
|
||||
disasm.c
|
||||
dfu.c
|
||||
dfu.h
|
||||
dryrun.c
|
||||
@@ -240,6 +242,8 @@ set(SOURCES
|
||||
serialadapter.c
|
||||
serialupdi.c
|
||||
serialupdi.h
|
||||
serprog.c
|
||||
serprog.h
|
||||
solaris_ecpp.h
|
||||
stk500.c
|
||||
stk500.h
|
||||
@@ -384,6 +388,7 @@ endif()
|
||||
# =====================================
|
||||
|
||||
install(TARGETS avrdude DESTINATION bin)
|
||||
install(PROGRAMS "elf2tag" DESTINATION bin)
|
||||
install(TARGETS libavrdude
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
#
|
||||
# avrdude - A Downloader/Uploader for AVR device programmers
|
||||
# Copyright (C) 2003, 2004 Theodore A. Roth <troth@openavr.org>
|
||||
# Copyright (C) 2003, 2004 Theodore A. Roth <troth@openavr.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -26,10 +26,6 @@
|
||||
#
|
||||
# make V=1
|
||||
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
EXTRA_DIST = \
|
||||
avrdude.1 \
|
||||
avrdude.spec \
|
||||
@@ -105,6 +101,7 @@ libavrdude_a_SOURCES = \
|
||||
avrintel.c \
|
||||
libavrdude-avrintel.h \
|
||||
avrpart.c \
|
||||
avr_opcodes.c \
|
||||
bitbang.c \
|
||||
bitbang.h \
|
||||
buspirate.c \
|
||||
@@ -118,6 +115,7 @@ libavrdude_a_SOURCES = \
|
||||
confwin.c \
|
||||
crc16.c \
|
||||
crc16.h \
|
||||
disasm.c \
|
||||
dfu.c \
|
||||
dfu.h \
|
||||
dryrun.c \
|
||||
@@ -185,6 +183,8 @@ libavrdude_a_SOURCES = \
|
||||
usbasp.h \
|
||||
serialupdi.c \
|
||||
serialupdi.h \
|
||||
serprog.c \
|
||||
serprog.h \
|
||||
updi_constants.h \
|
||||
updi_link.c \
|
||||
updi_link.h \
|
||||
@@ -232,6 +232,8 @@ avrdude_SOURCES = \
|
||||
developer_opts.h \
|
||||
developer_opts_private.h
|
||||
|
||||
dist_bin_SCRIPTS = elf2tag
|
||||
|
||||
man_MANS = avrdude.1
|
||||
|
||||
sysconf_DATA = avrdude.conf
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* avrdude interface for Arduino programmer
|
||||
*
|
||||
@@ -37,6 +35,43 @@
|
||||
#include "stk500.h"
|
||||
#include "arduino.h"
|
||||
|
||||
static int arduino_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
int attempts;
|
||||
int rv = 0;
|
||||
bool help = 0;
|
||||
|
||||
for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
if (sscanf(extended_param, "attempts=%i", &attempts) == 1) {
|
||||
PDATA(pgm)->retry_attempts = attempts;
|
||||
pmsg_info("setting number of retry attempts to %d\n", attempts);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(str_eq(extended_param, "noautoreset")) {
|
||||
PDATA(pgm)->autoreset = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_eq(extended_param, "help")) {
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
if (!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x attempts=<n> Specify the number <n> of connection retry attempts\n");
|
||||
msg_error(" -x noautoreset Don't toggle RTS/DTR lines on port open to prevent a hardware reset\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* read signature bytes - arduino version */
|
||||
static int arduino_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m) {
|
||||
unsigned char buf[32];
|
||||
@@ -85,28 +120,28 @@ static int arduino_open(PROGRAMMER *pgm, const char *port) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// This code assumes a negative-logic USB to TTL serial adapter
|
||||
// Set RTS/DTR high to discharge the series-capacitor, if present
|
||||
serial_set_dtr_rts(&pgm->fd, 0);
|
||||
/*
|
||||
* Long wait needed for optiboot: otherwise the second of two bootloader
|
||||
* calls in quick succession fails:
|
||||
*
|
||||
* avrdude -c arduino -qqp m328p -U x.hex; avrdude -c arduino -qqp m328p -U x.hex
|
||||
*/
|
||||
usleep(250 * 1000);
|
||||
// Pull the RTS/DTR line low to reset AVR
|
||||
serial_set_dtr_rts(&pgm->fd, 1);
|
||||
// Max 100 us: charging a cap longer creates a high reset spike above Vcc
|
||||
usleep(100);
|
||||
// Set the RTS/DTR line back to high, so direct connection to reset works
|
||||
serial_set_dtr_rts(&pgm->fd, 0);
|
||||
if(PDATA(pgm)->autoreset) {
|
||||
// This code assumes a negative-logic USB to TTL serial adapter
|
||||
// Set RTS/DTR high to discharge the series-capacitor, if present
|
||||
serial_set_dtr_rts(&pgm->fd, 0);
|
||||
/*
|
||||
* Long wait needed for optiboot: otherwise the second of two bootloader
|
||||
* calls in quick succession fails:
|
||||
*
|
||||
* avrdude -c arduino -qqp m328p -U x.hex; avrdude -c arduino -qqp m328p -U x.hex
|
||||
*/
|
||||
usleep(250 * 1000);
|
||||
// Pull the RTS/DTR line low to reset AVR
|
||||
serial_set_dtr_rts(&pgm->fd, 1);
|
||||
// Max 100 us: charging a cap longer creates a high reset spike above Vcc
|
||||
usleep(100);
|
||||
// Set the RTS/DTR line back to high, so direct connection to reset works
|
||||
serial_set_dtr_rts(&pgm->fd, 0);
|
||||
|
||||
usleep(100 * 1000);
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
// Drain any extraneous input
|
||||
stk500_drain(pgm, 0);
|
||||
|
||||
if (stk500_getsync(pgm) < 0)
|
||||
@@ -115,8 +150,7 @@ static int arduino_open(PROGRAMMER *pgm, const char *port) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void arduino_close(PROGRAMMER * pgm)
|
||||
{
|
||||
static void arduino_close(PROGRAMMER *pgm) {
|
||||
serial_close(&pgm->fd);
|
||||
pgm->fd.ifd = -1;
|
||||
}
|
||||
@@ -129,11 +163,11 @@ void arduino_initpgm(PROGRAMMER *pgm) {
|
||||
and the DTR signal is set when opening the serial port
|
||||
for the Auto-Reset feature */
|
||||
stk500_initpgm(pgm);
|
||||
|
||||
strcpy(pgm->type, "Arduino");
|
||||
pgm->read_sig_bytes = arduino_read_sig_bytes;
|
||||
pgm->open = arduino_open;
|
||||
pgm->close = arduino_close;
|
||||
pgm->parseextparams = arduino_parseextparms;
|
||||
|
||||
disable_trailing_ff_removal(); /* so that arduino bootloader can ignore chip erase */
|
||||
cx->avr_disableffopt = 1; // Disable trailing 0xff removal
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef arduino_h__
|
||||
#define arduino_h__
|
||||
|
||||
|
||||
281
src/avr.c
281
src/avr.c
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2011 Darell Tan <darell.tan@gmail.com>
|
||||
* Copyright (C) 2022- Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,8 +18,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -180,6 +179,38 @@ static int avr_tpi_setup_rw(const PROGRAMMER *pgm, const AVRMEM *mem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If mem is a sub-memory of sigrow return its offset within sigrow, 0 otherwise
|
||||
int avr_sigrow_offset(const AVRPART *p, const AVRMEM *mem, int addr) {
|
||||
int offset = 0;
|
||||
|
||||
if(mem_is_in_sigrow(mem)) {
|
||||
AVRMEM *m = avr_locate_sigrow(p);
|
||||
if(m) {
|
||||
int off = mem->offset - m->offset;
|
||||
if(off >= 0 && off + addr < m->size)
|
||||
offset = off;
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
// If mem is a sub-memory of flash return its offset within flash, 0 otherwise
|
||||
int avr_flash_offset(const AVRPART *p, const AVRMEM *mem, int addr) {
|
||||
int offset = 0;
|
||||
|
||||
if(mem_is_in_flash(mem)) {
|
||||
AVRMEM *m = avr_locate_flash(p);
|
||||
if(m) {
|
||||
int off = mem->offset - m->offset;
|
||||
if(off >= 0 && off + addr < m->size)
|
||||
offset = off;
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
int avr_read_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||
unsigned long addr, unsigned char * value)
|
||||
{
|
||||
@@ -190,8 +221,7 @@ int avr_read_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
OPCODE * readop, * lext;
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
pmsg_error("%s programmer uses avr_read_byte_default() but does not\n", pgm->type);
|
||||
imsg_error("provide a cmd() method\n");
|
||||
pmsg_error("%s programmer uses %s() without providing a cmd() method\n", pgm->type, __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -257,7 +287,7 @@ int avr_read_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
memset(cmd, 0, sizeof(cmd));
|
||||
|
||||
avr_set_bits(readop, cmd);
|
||||
avr_set_addr(readop, cmd, addr);
|
||||
avr_set_addr(readop, cmd, addr + avr_sigrow_offset(p, mem, addr));
|
||||
rc = pgm->cmd(pgm, cmd, res);
|
||||
if(rc < 0)
|
||||
goto rcerror;
|
||||
@@ -291,15 +321,14 @@ rcerror:
|
||||
int avr_mem_hiaddr(const AVRMEM * mem)
|
||||
{
|
||||
int i, n;
|
||||
static int disableffopt;
|
||||
|
||||
/* calling once with NULL disables any future trailing-0xff optimisation */
|
||||
// Deprecated: calling with NULL disables trailing 0xff optimisation (remove in v8.0)
|
||||
if(!mem) {
|
||||
disableffopt = 1;
|
||||
cx->avr_disableffopt = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(disableffopt)
|
||||
if(cx->avr_disableffopt)
|
||||
return mem->size;
|
||||
|
||||
/* if the memory is not a flash-type memory do not remove trailing 0xff */
|
||||
@@ -323,10 +352,9 @@ int avr_mem_hiaddr(const AVRMEM * mem)
|
||||
|
||||
|
||||
/*
|
||||
* Read the entirety of the specified memory into the corresponding
|
||||
* buffer of the avrpart pointed to by p. If v is non-NULL, verify against
|
||||
* v's memory area, only those cells that are tagged TAG_ALLOCATED are
|
||||
* verified.
|
||||
* Read the entirety of the specified memory into the corresponding buffer of
|
||||
* the avrpart pointed to by p. If v is non-NULL, verify against v's memory
|
||||
* area, only those cells that are tagged TAG_ALLOCATED are verified.
|
||||
*
|
||||
* Return the number of bytes read, or < 0 if an error occurs.
|
||||
*/
|
||||
@@ -340,14 +368,6 @@ int avr_read(const PROGRAMMER *pgm, const AVRPART *p, const char *memstr, const
|
||||
return avr_read_mem(pgm, p, mem, v);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read the entirety of the specified memory into the corresponding buffer of
|
||||
* the avrpart pointed to by p. If v is non-NULL, verify against v's memory
|
||||
* area, only those cells that are tagged TAG_ALLOCATED are verified.
|
||||
*
|
||||
* Return the number of bytes read, or < 0 if an error occurs.
|
||||
*/
|
||||
int avr_read_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, const AVRPART *v) {
|
||||
unsigned long i, lastaddr;
|
||||
unsigned char cmd[4];
|
||||
@@ -458,7 +478,7 @@ int avr_read_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, con
|
||||
nread++;
|
||||
report_progress(nread, npages, NULL);
|
||||
} else {
|
||||
pmsg_debug("avr_read_mem(): skipping page %u: no interesting data\n", pageaddr / mem->page_size);
|
||||
pmsg_debug("%s(): skipping page %u: no interesting data\n", __func__, pageaddr / mem->page_size);
|
||||
}
|
||||
}
|
||||
if (!failure) {
|
||||
@@ -519,8 +539,7 @@ int avr_write_page(const PROGRAMMER *pgm, const AVRPART *p_unused, const AVRMEM
|
||||
led_set(pgm, LED_PGM);
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
pmsg_error("%s programmer uses avr_write_page() but does not\n", pgm->type);
|
||||
imsg_error("provide a cmd() method\n");
|
||||
pmsg_error("%s programmer uses %s() without providing a cmd() method\n", pgm->type, __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -578,16 +597,14 @@ uint64_t avr_ustimestamp() {
|
||||
|
||||
memset(&tv, 0, sizeof tv);
|
||||
if(gettimeofday(&tv, NULL) == 0) {
|
||||
static uint64_t epoch;
|
||||
static int init;
|
||||
uint64_t now;
|
||||
|
||||
now = tv.tv_sec*1000000ULL + tv.tv_usec;
|
||||
if(!init) {
|
||||
epoch = now;
|
||||
init = 1;
|
||||
if(!cx->avr_epoch_init) {
|
||||
cx->avr_epoch = now;
|
||||
cx->avr_epoch_init = 1;
|
||||
}
|
||||
return now - epoch;
|
||||
return now - cx->avr_epoch;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -651,8 +668,7 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
led_set(pgm, LED_PGM);
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
pmsg_error("%s programmer uses avr_write_byte_default() but does not\n", pgm->type);
|
||||
imsg_error("provide a cmd() method\n");
|
||||
pmsg_error("%s programmer uses %s() without providing a cmd() method\n", pgm->type, __func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -856,9 +872,9 @@ int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
usleep(250000);
|
||||
rc = pgm->initialize(pgm, p);
|
||||
if (rc < 0) {
|
||||
pmsg_error("initialization failed, rc=%d\n", rc);
|
||||
imsg_error("cannot re-initialize device after programming the %s bits\n", mem->desc);
|
||||
imsg_error("you must manually power-down the device and restart %s to continue\n", progname);
|
||||
pmsg_error("initialization failed (rc = %d):\n", rc);
|
||||
imsg_error("cannot re-initialize device after programming the %s bits; you\n", mem->desc);
|
||||
imsg_error("must manually power-down the device and restart %s to continue\n", progname);
|
||||
rc = -3;
|
||||
goto rcerror;
|
||||
}
|
||||
@@ -936,14 +952,6 @@ int avr_write(const PROGRAMMER *pgm, const AVRPART *p, const char *memstr, int s
|
||||
return avr_write_mem(pgm, p, m, size, auto_erase);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the whole memory region of the specified memory from its buffer of
|
||||
* the avrpart pointed to by p to the device. Write up to size bytes from
|
||||
* the buffer. Data is only written if the corresponding tags byte is set.
|
||||
* Data beyond size bytes are not affected.
|
||||
*
|
||||
* Return the number of bytes written, or LIBAVRDUDE_GENERAL_FAILURE on error.
|
||||
*/
|
||||
int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int size, int auto_erase) {
|
||||
int wsize;
|
||||
unsigned int i, lastaddr;
|
||||
@@ -957,8 +965,8 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
|
||||
if (size < wsize) {
|
||||
wsize = size;
|
||||
} else if (size > wsize) {
|
||||
pmsg_warning("%d bytes requested, but memory region is only %d bytes\n", size, wsize);
|
||||
imsg_warning("Only %d bytes will actually be written\n", wsize);
|
||||
pmsg_warning("%d bytes requested, but memory region is only %d bytes;\n", size, wsize);
|
||||
imsg_warning("only %d bytes will actually be written\n", wsize);
|
||||
}
|
||||
|
||||
if(wsize <= 0) {
|
||||
@@ -1107,14 +1115,14 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
|
||||
|
||||
// Read flash contents to separate memory spc and fill in holes
|
||||
if(avr_read_page_default(pgm, p, cm, beg, spc) >= 0) {
|
||||
pmsg_notice2("padding %s [0x%04x, 0x%04x]\n", cm->desc, beg, end-1);
|
||||
pmsg_debug("padding %s [0x%04x, 0x%04x]\n", cm->desc, beg, end-1);
|
||||
for(i = beg; i < end; i++)
|
||||
if(!(cm->tags[i] & TAG_ALLOCATED)) {
|
||||
cm->tags[i] |= TAG_ALLOCATED;
|
||||
cm->buf[i] = spc[i-beg];
|
||||
}
|
||||
} else {
|
||||
pmsg_notice2("cannot read %s [0x%04x, 0x%04x] to pad page\n",
|
||||
pmsg_debug("cannot read %s [0x%04x, 0x%04x] to pad page\n",
|
||||
cm->desc, beg, end-1);
|
||||
}
|
||||
}
|
||||
@@ -1206,8 +1214,9 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
|
||||
|
||||
if (do_write) {
|
||||
if(avr_write_byte(pgm, p, m, i, data)) {
|
||||
msg_error(" ***failed;\n");
|
||||
msg_error(" *** failed\n");
|
||||
led_set(pgm, LED_ERR);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1215,15 +1224,20 @@ int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, int
|
||||
flush_page = 0;
|
||||
|
||||
if(avr_write_page(pgm, p, m, i)) {
|
||||
msg_error(" *** page %d (addresses 0x%04x - 0x%04x) failed to write\n\n",
|
||||
msg_error(" *** failed to write page %d [0x%04x, 0x%04x]\n",
|
||||
i / m->page_size, i - m->page_size + 1, i);
|
||||
led_set(pgm, LED_ERR);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
led_clr(pgm, LED_PGM);
|
||||
return i;
|
||||
|
||||
error:
|
||||
led_clr(pgm, LED_PGM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1237,7 +1251,7 @@ int avr_signature(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
report_progress(0, 1, "Reading");
|
||||
rc = avr_read(pgm, p, "signature", 0);
|
||||
if (rc < LIBAVRDUDE_SUCCESS && rc != LIBAVRDUDE_EXIT) {
|
||||
pmsg_error("unable to read signature data for part %s, rc=%d\n", p->desc, rc);
|
||||
pmsg_error("unable to read signature data for part %s (rc = %d)\n", p->desc, rc);
|
||||
return rc;
|
||||
}
|
||||
report_progress(1, 1, NULL);
|
||||
@@ -1268,7 +1282,7 @@ int avr_mem_bitmask(const AVRPART *p, const AVRMEM *mem, int addr) {
|
||||
}
|
||||
|
||||
// Bitmask for ISP programming (classic parts only)
|
||||
static uint8_t get_fuse_bitmask(AVRMEM * m) {
|
||||
static uint8_t get_fuse_bitmask(const AVRMEM *m) {
|
||||
uint8_t bitmask_r = 0;
|
||||
uint8_t bitmask_w = 0;
|
||||
int i;
|
||||
@@ -1300,27 +1314,29 @@ int compare_memory_masked(AVRMEM * m, uint8_t b1, uint8_t b2) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify the memory buffer of p with that of v. The byte range of v
|
||||
* may be a subset of p. The byte range of p should cover the whole
|
||||
* chip's memory size.
|
||||
* Verify the memory buffer of p with that of v. The byte range of v may be a
|
||||
* subset of p. The byte range of p should cover the whole chip's memory size.
|
||||
*
|
||||
* Return the number of bytes verified, or -1 if they don't match.
|
||||
*/
|
||||
int avr_verify(const PROGRAMMER *pgm, const AVRPART *p, const AVRPART *v, const char *memstr, int size) {
|
||||
int i;
|
||||
unsigned char * buf1, * buf2;
|
||||
int vsize;
|
||||
AVRMEM * a, * b;
|
||||
const AVRMEM *a = avr_locate_mem(p, memstr);
|
||||
|
||||
a = avr_locate_mem(p, memstr);
|
||||
if (a == NULL) {
|
||||
if(!a) {
|
||||
pmsg_error("memory %s not defined for part %s\n", memstr, p->desc);
|
||||
return -1;
|
||||
}
|
||||
return avr_verify_mem(pgm, p, v, a, size);
|
||||
}
|
||||
|
||||
b = avr_locate_mem(v, memstr);
|
||||
if (b == NULL) {
|
||||
pmsg_error("memory %s not defined for part %s\n", memstr, v->desc);
|
||||
int avr_verify_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRPART *v, const AVRMEM *a, int size) {
|
||||
int i;
|
||||
unsigned char *buf1, *buf2;
|
||||
int vsize;
|
||||
AVRMEM *b;
|
||||
|
||||
if(!(b = avr_locate_mem(v, a->desc))) {
|
||||
pmsg_error("memory %s not defined for part %s\n", a->desc, v->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1329,50 +1345,51 @@ int avr_verify(const PROGRAMMER *pgm, const AVRPART *p, const AVRPART *v, const
|
||||
vsize = a->size;
|
||||
|
||||
if (vsize < size) {
|
||||
pmsg_warning("requested verification for %d bytes\n", size);
|
||||
imsg_warning("%s memory region only contains %d bytes\n", memstr, vsize);
|
||||
pmsg_warning("requested verification for %d bytes but\n", size);
|
||||
imsg_warning("%s memory region only contains %d bytes;\n", a->desc, vsize);
|
||||
imsg_warning("only %d bytes will be verified\n", vsize);
|
||||
size = vsize;
|
||||
}
|
||||
|
||||
int verror = 0, vroerror = 0, maxerrs = verbose >= MSG_DEBUG? size+1: 10;
|
||||
int ro = mem_is_readonly(a); // Other memories can have known protected zones such as bootloaders
|
||||
for (i=0; i<size; i++) {
|
||||
if ((b->tags[i] & TAG_ALLOCATED) != 0 && buf1[i] != buf2[i]) {
|
||||
uint8_t bitmask = p->prog_modes & PM_ISP? get_fuse_bitmask(a): avr_mem_bitmask(p, a, i);
|
||||
if(pgm->readonly && pgm->readonly(pgm, p, a, i)) {
|
||||
if(ro || (pgm->readonly && pgm->readonly(pgm, p, a, i))) {
|
||||
if(quell_progress < 2) {
|
||||
if(vroerror < 10) {
|
||||
if(!(verror + vroerror))
|
||||
pmsg_warning("verification mismatch%s\n",
|
||||
pmsg_warning("%s verification mismatch%s\n", a->desc,
|
||||
mem_is_in_flash(a)? " in r/o areas, expected for vectors and/or bootloader": "");
|
||||
imsg_warning("device 0x%02x != input 0x%02x at addr 0x%04x (read only location)\n",
|
||||
imsg_warning(" device 0x%02x != input 0x%02x at addr 0x%04x (read only location: ignored)\n",
|
||||
buf1[i], buf2[i], i);
|
||||
} else if(vroerror == 10)
|
||||
imsg_warning("suppressing further mismatches in read-only areas\n");
|
||||
imsg_warning(" suppressing further mismatches in read-only areas\n");
|
||||
}
|
||||
vroerror++;
|
||||
} else if((buf1[i] & bitmask) != (buf2[i] & bitmask)) {
|
||||
// Mismatch is not just in unused bits
|
||||
if(verror < maxerrs) {
|
||||
if(!(verror + vroerror))
|
||||
pmsg_warning("verification mismatch\n");
|
||||
imsg_error("device 0x%02x != input 0x%02x at addr 0x%04x (error)\n", buf1[i], buf2[i], i);
|
||||
pmsg_warning("%s verification mismatch\n", a->desc);
|
||||
imsg_error(" device 0x%02x != input 0x%02x at addr 0x%04x (error)\n", buf1[i], buf2[i], i);
|
||||
} else if(verror == maxerrs) {
|
||||
imsg_warning("suppressing further verification errors\n");
|
||||
imsg_warning(" suppressing further verification errors\n");
|
||||
}
|
||||
verror++;
|
||||
if(verbose < 1)
|
||||
if(verbose < MSG_NOTICE)
|
||||
return -1;
|
||||
} else {
|
||||
// Mismatch is only in unused bits
|
||||
if ((buf1[i] | bitmask) != 0xff) {
|
||||
// Programmer returned unused bits as 0, must be the part/programmer
|
||||
pmsg_warning("ignoring mismatch in unused bits of %s\n", memstr);
|
||||
pmsg_warning("ignoring mismatch in unused bits of %s\n", a->desc);
|
||||
imsg_warning("(device 0x%02x != input 0x%02x); to prevent this warning fix\n", buf1[i], buf2[i]);
|
||||
imsg_warning("the part or programmer definition in the config file\n");
|
||||
} else {
|
||||
// Programmer returned unused bits as 1, must be the user
|
||||
pmsg_warning("ignoring mismatch in unused bits of %s\n", memstr);
|
||||
pmsg_warning("ignoring mismatch in unused bits of %s\n", a->desc);
|
||||
imsg_warning("(device 0x%02x != input 0x%02x); to prevent this warning set\n", buf1[i], buf2[i]);
|
||||
imsg_warning("unused bits to 1 when writing (double check with datasheet)\n");
|
||||
}
|
||||
@@ -1398,7 +1415,7 @@ int avr_get_cycle_count(const PROGRAMMER *pgm, const AVRPART *p, int *cycles) {
|
||||
for (i=4; i>0; i--) {
|
||||
rc = pgm->read_byte(pgm, p, a, a->size-i, &v1);
|
||||
if (rc < 0) {
|
||||
pmsg_warning("cannot read memory for cycle count, rc=%d\n", rc);
|
||||
pmsg_warning("cannot read memory for cycle count (rc = %d)\n", rc);
|
||||
return -1;
|
||||
}
|
||||
cycle_count = (cycle_count << 8) | v1;
|
||||
@@ -1436,7 +1453,7 @@ int avr_put_cycle_count(const PROGRAMMER *pgm, const AVRPART *p, int cycles) {
|
||||
|
||||
rc = avr_write_byte(pgm, p, a, a->size-i, v1);
|
||||
if (rc < 0) {
|
||||
pmsg_warning("cannot write memory for cycle count, rc=%d\n", rc);
|
||||
pmsg_warning("cannot write memory for cycle count (rc = %d)\n", rc);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1445,44 +1462,93 @@ int avr_put_cycle_count(const PROGRAMMER *pgm, const AVRPART *p, int cycles) {
|
||||
}
|
||||
|
||||
|
||||
// Returns a pointer to static memory of list of programming modes
|
||||
char *avr_prog_modes(int pm) {
|
||||
static char type[1024];
|
||||
// Return temporary string buffer with n bytes from a closed-circuit space
|
||||
char *avr_cc_buffer(size_t n) {
|
||||
size_t avail = sizeof cx->avr_space - AVR_SAFETY_MARGIN;
|
||||
if(!is_memset(cx->avr_space + avail, 0, AVR_SAFETY_MARGIN)) {
|
||||
pmsg_warning("avr_cc_buffer(n) overran; n chosen too small in previous calls? Change and recompile\n");
|
||||
memset(cx->avr_space + avail, 0, AVR_SAFETY_MARGIN);
|
||||
}
|
||||
|
||||
strcpy(type, "?");
|
||||
if(n > avail) {
|
||||
pmsg_error("requested size %lu too big for cx->avr_space[%lu+AVR_SAFETY_MARGIN] (change source)\n",
|
||||
(unsigned long) n, (unsigned long) avail);
|
||||
cx->avr_s = cx->avr_space;
|
||||
n = avail;
|
||||
} else if(!cx->avr_s)
|
||||
cx->avr_s = cx->avr_space;
|
||||
|
||||
cx->avr_s += strlen(cx->avr_s) + 1; // Move behind string from last call
|
||||
|
||||
// Rewind if too little space left
|
||||
if((size_t) (cx->avr_s - cx->avr_space) > avail - n)
|
||||
cx->avr_s = cx->avr_space;
|
||||
|
||||
memset(cx->avr_s, 0, n);
|
||||
return cx->avr_s;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string in closed-circuit space with a list of programming
|
||||
* modes encoded in pm; variant creates the list in subtly different ways:
|
||||
* - variants == 0: PM_SPM prints bootloader
|
||||
* - variants == 1: PM_SPM prints SPM
|
||||
* - variants == 2: rather than a comma-separated list it's | PM_... separated
|
||||
* If pm is 0 (no programming modes) returns "0"
|
||||
*/
|
||||
static char *prog_modes_string(int pm, int variant) {
|
||||
char *type = avr_cc_buffer(256); // Longest returned string has 142 chars
|
||||
|
||||
const char *spm = variant? "SPM": "bootloader";
|
||||
const char *sep = variant == 2? " | PM_": ", ";
|
||||
int skip = 3 + (variant == 2);
|
||||
|
||||
strcpy(type, "0");
|
||||
if(pm & PM_SPM)
|
||||
strcat(type, ", bootloader");
|
||||
strcat(strcat(type, sep), spm);
|
||||
if(pm & PM_TPI)
|
||||
strcat(type, ", TPI");
|
||||
strcat(strcat(type, sep), "TPI");
|
||||
if(pm & PM_ISP)
|
||||
strcat(type, ", ISP");
|
||||
strcat(strcat(type, sep), "ISP");
|
||||
if(pm & PM_PDI)
|
||||
strcat(type, ", PDI");
|
||||
strcat(strcat(type, sep), "PDI");
|
||||
if(pm & PM_UPDI)
|
||||
strcat(type, ", UPDI");
|
||||
strcat(strcat(type, sep), "UPDI");
|
||||
if(pm & PM_HVSP)
|
||||
strcat(type, ", HVSP");
|
||||
strcat(strcat(type, sep), "HVSP");
|
||||
if(pm & PM_HVPP)
|
||||
strcat(type, ", HVPP");
|
||||
strcat(strcat(type, sep), "HVPP");
|
||||
if(pm & PM_debugWIRE)
|
||||
strcat(type, ", debugWIRE");
|
||||
strcat(strcat(type, sep), "debugWIRE");
|
||||
if(pm & PM_JTAG)
|
||||
strcat(type, ", JTAG");
|
||||
strcat(strcat(type, sep), "JTAG");
|
||||
if(pm & PM_JTAGmkI)
|
||||
strcat(type, ", JTAGmkI");
|
||||
strcat(strcat(type, sep), "JTAGmkI");
|
||||
if(pm & PM_XMEGAJTAG)
|
||||
strcat(type, ", XMEGAJTAG");
|
||||
strcat(strcat(type, sep), "XMEGAJTAG");
|
||||
if(pm & PM_AVR32JTAG)
|
||||
strcat(type, ", AVR32JTAG");
|
||||
strcat(strcat(type, sep), "AVR32JTAG");
|
||||
if(pm & PM_aWire)
|
||||
strcat(type, ", aWire");
|
||||
strcat(strcat(type, sep), "aWire");
|
||||
|
||||
return type + (type[1] == 0? 0: 3);
|
||||
return type + (type[1] == 0? 0: skip);
|
||||
}
|
||||
|
||||
char *avr_prog_modes(int pm) { // PM_SPM prints bootloader
|
||||
return prog_modes_string(pm, 0);
|
||||
}
|
||||
|
||||
char *str_prog_modes(int pm) { // PM_SPM prints SPM
|
||||
return prog_modes_string(pm, 1);
|
||||
}
|
||||
|
||||
char *dev_prog_modes(int pm) { // Symbolic C code of prog_modes
|
||||
return prog_modes_string(pm, 2);
|
||||
}
|
||||
|
||||
|
||||
// Typical order in which memories show in avrdude.conf, runtime adds unknown ones (if any)
|
||||
memtable_t avr_mem_order[100] = {
|
||||
Memtable avr_mem_order[100] = {
|
||||
{"eeprom", MEM_EEPROM},
|
||||
{"flash", MEM_FLASH | MEM_IN_FLASH},
|
||||
{"application", MEM_APPLICATION | MEM_IN_FLASH},
|
||||
@@ -1517,8 +1583,8 @@ memtable_t avr_mem_order[100] = {
|
||||
{"lockbits", MEM_LOCK},
|
||||
{"prodsig", MEM_SIGROW | MEM_IN_SIGROW | MEM_READONLY},
|
||||
{"sigrow", MEM_SIGROW | MEM_IN_SIGROW | MEM_READONLY},
|
||||
{"signature", MEM_SIGNATURE | MEM_IN_SIGROW | MEM_READONLY},
|
||||
{"calibration", MEM_CALIBRATION | MEM_IN_SIGROW | MEM_READONLY},
|
||||
{"signature", MEM_SIGNATURE | MEM_IN_SIGROW | MEM_READONLY}, // Not in SIGROW in Classic/XMEGA parts
|
||||
{"calibration", MEM_CALIBRATION | MEM_IN_SIGROW | MEM_READONLY}, // Not in SIGROW in Classic parts
|
||||
{"tempsense", MEM_TEMPSENSE | MEM_IN_SIGROW | MEM_READONLY},
|
||||
{"sernum", MEM_SERNUM | MEM_IN_SIGROW | MEM_READONLY},
|
||||
{"osccal16", MEM_OSCCAL16 | MEM_IN_SIGROW | MEM_READONLY},
|
||||
@@ -1582,6 +1648,11 @@ int avr_mem_cmp(void *mem1, void *mem2) {
|
||||
return diff;
|
||||
if(!m1) // Sanity, if called with NULL pointers
|
||||
return 0;
|
||||
if(mem_is_in_fuses(m1)) { // Sort by fuse offset if fuses or a fuse
|
||||
diff = mem_fuse_offset(m1) - mem_fuse_offset(m2);
|
||||
if(diff)
|
||||
return diff;
|
||||
}
|
||||
diff = m1->offset - m2->offset; // Sort by offset within each group
|
||||
if(diff)
|
||||
return diff;
|
||||
@@ -1710,8 +1781,6 @@ int avr_unlock(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
*/
|
||||
|
||||
void report_progress(int completed, int total, const char *hdr) {
|
||||
static int last;
|
||||
static double start_time;
|
||||
int percent;
|
||||
double t;
|
||||
|
||||
@@ -1725,12 +1794,12 @@ void report_progress(int completed, int total, const char *hdr) {
|
||||
|
||||
t = avr_timestamp();
|
||||
|
||||
if(hdr || !start_time)
|
||||
start_time = t;
|
||||
if(hdr || !cx->avr_start_time)
|
||||
cx->avr_start_time = t;
|
||||
|
||||
if(hdr || percent > last) {
|
||||
last = percent;
|
||||
update_progress(percent, t - start_time, hdr, total < 0? -1: !!total);
|
||||
if(hdr || percent > cx->avr_last_percent) {
|
||||
cx->avr_last_percent = percent;
|
||||
update_progress(percent, t - cx->avr_start_time, hdr, total < 0? -1: !!total);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
39
src/avr910.c
39
src/avr910.c
@@ -1,8 +1,8 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright 2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright 2008 Klaus Leidinger <klaus@mikrocontroller-projekte.de>
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2008 Klaus Leidinger <klaus@mikrocontroller-projekte.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,8 +18,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* avrdude interface for Atmel Low Cost Serial programmers which adher to the
|
||||
* protocol described in application note avr910.
|
||||
@@ -308,22 +306,21 @@ static int avr910_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||
|
||||
|
||||
static int avr910_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
if (str_starts(extended_param, "devcode=")) {
|
||||
int devcode;
|
||||
if (sscanf(extended_param, "devcode=%i", &devcode) != 1 ||
|
||||
devcode <= 0 || devcode > 255) {
|
||||
pmsg_error("invalid devcode '%s'\n", extended_param);
|
||||
pmsg_error("invalid device code in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
pmsg_notice2("avr910_parseextparms(): devcode overwritten as 0x%02x\n", devcode);
|
||||
pmsg_notice2("%s(): devcode overwritten as 0x%02x\n", __func__, devcode);
|
||||
PDATA(pgm)->devcode = devcode;
|
||||
|
||||
continue;
|
||||
@@ -335,15 +332,19 @@ static int avr910_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
continue;
|
||||
}
|
||||
if (str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -xdevcode=<arg> Override device code\n");
|
||||
msg_error(" -xno_blockmode Disable default checking for block transfer capability\n");
|
||||
msg_error(" -xhelp Show this help menu and exit\n");
|
||||
return LIBAVRDUDE_EXIT;
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
pmsg_error("invalid extended parameter '%s'\n", extended_param);
|
||||
rv = -1;
|
||||
if (!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x devcode=<n> Set device code to <n> (0x.. hex, 0... oct or dec)\n");
|
||||
msg_error(" -x no_blockmode Disable default checking for block transfer capability\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef avr910_h
|
||||
#define avr910_h
|
||||
|
||||
|
||||
739
src/avr_opcodes.c
Normal file
739
src/avr_opcodes.c
Normal file
@@ -0,0 +1,739 @@
|
||||
/*
|
||||
* AVRDUDE - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2024 Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "libavrdude.h"
|
||||
|
||||
/*
|
||||
* AVR opcode table
|
||||
*
|
||||
* - Order of enums MNEMO_... in libavedude.h must align with table
|
||||
*
|
||||
* - Order makes the first match of a 16-bit opcode a "good" one
|
||||
* + Undocumented opcodes come last
|
||||
* + Specific reduced-core sts/lds opcodes are penultimate
|
||||
* + More specific opcodes before less specific ones (clr before eor)
|
||||
* + Opcodes labelled alias come behind those not labelled so
|
||||
*
|
||||
* - The operand field has a very specific syntax as follows
|
||||
*
|
||||
* A 5-bit I/O address (sbic, sbis, sbi, cbi)
|
||||
* 6-bit I/O address (in, out)
|
||||
*
|
||||
* a 7-bit encoded address 0x40..0xbf for reduced-core (lds, sts)
|
||||
*
|
||||
* b bit number 0..7 (sbrc, sbrs, sbic, sbis, sbi, cbi, bst, bld, u/bld,
|
||||
* u/bst, u/sbrc, u/sbrs)
|
||||
*
|
||||
* k signed 7-bit for 2*k byte PC additional offset in [.-128, .+126]
|
||||
* (brcs, brlo, breq, brmi, brvs, brlt, brhs, brts, brie, brcc, brsh,
|
||||
* brne, brpl, brvc, brge, brhc, brtc, brid, brbs, brbc)
|
||||
* signed 12-bit for 2*k bytes PC additional offset in [.-4096, .+4094]
|
||||
* (rjmp, rcall)
|
||||
* 16-bit absolute byte address (lds, sts)
|
||||
* 22-bit absolute word address for the PC (jmp, call)
|
||||
*
|
||||
* K 4-bit encryption round index 0..15 (des)
|
||||
* 6-bit constant 0..63 (adiw, sbiw)
|
||||
* 8-bit constant 0..255 (subi, sbci, andi, ori, sbr, cbr, cpi, ldi)
|
||||
*
|
||||
* q 6-bit displacement 0..63 (ldd, ldd, std, std)
|
||||
*
|
||||
* Rd 2-bit destination register in r24, r26, r28, r30 (adiw, sbiw)
|
||||
* 3-bit dest register in r16, ..., r23 (mulsu, fmul, fmuls, fmulsu)
|
||||
* 4-bit destination register in r16, ..., r31 (subi, sbci, andi, ori,
|
||||
* sbr, cbr, ser, muls, cpi, ldi, lds)
|
||||
* 4-bit destination register in r0, r2, ..., r30 (movw)
|
||||
* 5-bit destination register in r0, r1, ..., r31 (add, adc, sub, sbc,
|
||||
* and, or, eor, com, neg, inc, dec, clr, mul, cpse, cp, cpc, mov,
|
||||
* lds, ld, ldd, lpm, elpm, in, pop, xch, las, lac, lat, lsl, lsr,
|
||||
* rol, ror, asr, swap, bld, u/bld)
|
||||
*
|
||||
* Rr 3-bit source register in r16, ..., r23 (mulsu, fmul, fmuls, fmulsu)
|
||||
* 4-bit source register in r16, ..., r31 (muls, sts)
|
||||
* 4-bit source register in r0, r2, ..., r30 (movw)
|
||||
* 5-bit source register in r0, r1, ..., r31 (add, adc, sub, sbc, and,
|
||||
* or, eor, tst, mul, cpse, cp, cpc, sbrc, sbrs, mov, sts, st,
|
||||
* std, out, push, bst, u/bst, u/sbrc, u/sbrs)
|
||||
*
|
||||
* s SREG bit number 0..7 (brbs, brbc, bset, bclr)
|
||||
*
|
||||
* - Source: Table was curated from https://github.com/nlitsme/AVRInstructionSet
|
||||
*/
|
||||
|
||||
const AVR_opcode avr_opcodes[MNEMO_N] = {
|
||||
#define OP_ID(nam) MNEMO_##nam, #nam
|
||||
|
||||
// Arithmetic and Logic Instructions
|
||||
{OP_ID(lsl), 0xfc00, 0x0c00, 1, OP_AVR1, "0000 11d= dddd ====", OTY_ALBI|OTY_RALL|OTY_CONSTRAINT,
|
||||
"lsl", "Rd", "logical shift left", "C <-- Rd(7) <-- Rd(6) ... Rd(1) <-- Rd(0) <-- 0", "--H-VNZC",
|
||||
{"1", "1", "1", "1"}, "alias for add Rd, Rd"},
|
||||
{OP_ID(add), 0xfc00, 0x0c00, 1, OP_AVR1, "0000 11rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"add", "Rd, Rr", "add without carry", "Rd <-- Rd + Rr", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(rol), 0xfc00, 0x1c00, 1, OP_AVR1, "0001 11d= dddd ====", OTY_ALBI|OTY_RALL|OTY_CONSTRAINT,
|
||||
"rol", "Rd", "rotate left through carry", "C <-- Rd(7) <-- Rd(6) ... Rd(1) <-- Rd(0) <-- C", "--H-VNZC",
|
||||
{"1", "1", "1", "1"}, "alias for adc Rd, Rd"},
|
||||
{OP_ID(adc), 0xfc00, 0x1c00, 1, OP_AVR1, "0001 11rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"adc", "Rd, Rr", "add with carry", "Rd <-- Rd + Rr + C", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(ror), 0xfe0f, 0x9407, 1, OP_AVR1, "1001 010d dddd 0111", OTY_ALBI|OTY_RALL,
|
||||
"ror", "Rd", "rotate right through carry", "C --> Rd(7) --> Rd(6) ... Rd(1) --> Rd(0) --> C", "----VNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(asr), 0xfe0f, 0x9405, 1, OP_AVR1, "1001 010d dddd 0101", OTY_ALBI|OTY_RALL,
|
||||
"asr", "Rd", "arithmetic shift right", "Rd(7) --> Rd(7) --> Rd(6) ... Rd(1) --> Rd(0) --> C", "----VNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(adiw), 0xff00, 0x9600, 1, OP_AVR2nRC, "1001 0110 KKdd KKKK", OTY_ALBI|OTY_RW24,
|
||||
"adiw", "Rd, K", "add immediate to word", "Rd+1:Rd <-- Rd+1:Rd + K", "---SVNZC",
|
||||
{"2", "2", "2", "n/a"}, "d in {24, 26, 28, 30}"},
|
||||
{OP_ID(sub), 0xfc00, 0x1800, 1, OP_AVR1, "0001 10rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"sub", "Rd, Rr", "subtract without carry", "Rd <-- Rd - Rr", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(subi), 0xf000, 0x5000, 1, OP_AVR1, "0101 KKKK dddd KKKK", OTY_ALBI|OTY_RUPP,
|
||||
"subi", "Rd, K", "subtract immediate", "Rd <-- Rd - K", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, "d = 16..31"},
|
||||
{OP_ID(sbc), 0xfc00, 0x0800, 1, OP_AVR1, "0000 10rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"sbc", "Rd, Rr", "subtract with carry", "Rd <-- Rd - Rr - C", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(sbci), 0xf000, 0x4000, 1, OP_AVR1, "0100 KKKK dddd KKKK", OTY_ALBI|OTY_RUPP,
|
||||
"sbci", "Rd, K", "subtract immediate with carry", "Rd <-- Rd - K - C", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, "d = 16..31"},
|
||||
{OP_ID(sbiw), 0xff00, 0x9700, 1, OP_AVR2nRC, "1001 0111 KKdd KKKK", OTY_ALBI|OTY_RW24,
|
||||
"sbiw", "Rd, K", "subtract immediate from word", "Rd+1:Rd <-- Rd+1:Rd - K", "---SVNZC",
|
||||
{"2", "2", "2", "n/a"}, "d in {24, 26, 28, 30}"},
|
||||
{OP_ID(tst), 0xfc00, 0x2000, 1, OP_AVR1, "0010 00r= rrrr ====", OTY_ALBI|OTY_RALL|OTY_CONSTRAINT,
|
||||
"tst", "Rr", "test for zero or minus", "Rr <-- Rr & Rr", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, "alias for and Rd, Rd"},
|
||||
{OP_ID(and), 0xfc00, 0x2000, 1, OP_AVR1, "0010 00rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"and", "Rd, Rr", "logical and", "Rd <-- Rd & Rr", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(andi), 0xf000, 0x7000, 1, OP_AVR1, "0111 KKKK dddd KKKK", OTY_ALBI|OTY_RUPP,
|
||||
"andi", "Rd, K", "logical and with immediate", "Rd <-- Rd & K", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, "d = 16..31"},
|
||||
{OP_ID(cbr), 0xf000, 0x7000, 1, OP_AVR1, "0111 KKKK dddd KKKK", OTY_ALBI|OTY_RUPP|OTY_ALIAS,
|
||||
"cbr", "Rd, K", "clear bit(s) in register", "Rd <-- Rd & (0xff - K)", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, "alias for andi Rd, (0xff - K); d = 16..31"},
|
||||
{OP_ID(or), 0xfc00, 0x2800, 1, OP_AVR1, "0010 10rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"or", "Rd, Rr", "logical or", "Rd <-- Rd | Rr", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(ori), 0xf000, 0x6000, 1, OP_AVR1, "0110 KKKK dddd KKKK", OTY_ALBI|OTY_RUPP,
|
||||
"ori", "Rd, K", "logical or with immediate", "Rd <-- Rd | K", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, "d = 16..31"},
|
||||
{OP_ID(sbr), 0xf000, 0x6000, 1, OP_AVR1, "0110 KKKK dddd KKKK", OTY_ALBI|OTY_RUPP|OTY_ALIAS,
|
||||
"sbr", "Rd, K", "set bit(s) in register", "Rd <-- Rd | K", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, "alias for ori Rd, K; d = 16..31"},
|
||||
{OP_ID(clr), 0xfc00, 0x2400, 1, OP_AVR1, "0010 01d= dddd ====", OTY_ALBI|OTY_RALL|OTY_CONSTRAINT,
|
||||
"clr", "Rd", "clear register", "Rd <-- Rd ^ Rd", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, "alias for eor Rd, Rd"},
|
||||
{OP_ID(eor), 0xfc00, 0x2400, 1, OP_AVR1, "0010 01rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"eor", "Rd, Rr", "exclusive or", "Rd <-- Rd ^ Rr", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(com), 0xfe0f, 0x9400, 1, OP_AVR1, "1001 010d dddd 0000", OTY_ALBI|OTY_RALL,
|
||||
"com", "Rd", "one's complement", "Rd <-- 0xff - Rd", "---SVNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(neg), 0xfe0f, 0x9401, 1, OP_AVR1, "1001 010d dddd 0001", OTY_ALBI|OTY_RALL,
|
||||
"neg", "Rd", "two's complement", "Rd <-- 0x00 - Rd", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(inc), 0xfe0f, 0x9403, 1, OP_AVR1, "1001 010d dddd 0011", OTY_ALBI|OTY_RALL,
|
||||
"inc", "Rd", "increment", "Rd <-- Rd + 1", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(dec), 0xfe0f, 0x940a, 1, OP_AVR1, "1001 010d dddd 1010", OTY_ALBI|OTY_RALL,
|
||||
"dec", "Rd", "decrement", "Rd <-- Rd - 1", "---SVNZ-",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(mul), 0xfc00, 0x9c00, 1, OP_AVR4, "1001 11rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"mul", "Rd, Rr", "multiply unsigned", "R1:R0 <-- Rd x Rr (UU)", "------ZC",
|
||||
{"2", "2", "2", "n/a"}, ""},
|
||||
{OP_ID(muls), 0xff00, 0x0200, 1, OP_AVR4, "0000 0010 dddd rrrr", OTY_ALBI|OTY_RUPP,
|
||||
"muls", "Rd, Rr", "multiply signed", "R1:R0 <-- Rd x Rr (SS)", "------ZC",
|
||||
{"2", "2", "2", "n/a"}, "d, r = 16..31"},
|
||||
{OP_ID(mulsu), 0xff88, 0x0300, 1, OP_AVR4, "0000 0011 0ddd 0rrr", OTY_ALBI|OTY_RUPP,
|
||||
"mulsu", "Rd, Rr", "multiply signed with unsigned", "R1:R0 <-- Rd x Rr (SU)", "------ZC",
|
||||
{"2", "2", "2", "n/a"}, "d, r = 16..23"},
|
||||
{OP_ID(fmul), 0xff88, 0x0308, 1, OP_AVR4, "0000 0011 0ddd 1rrr", OTY_ALBI|OTY_RUPP,
|
||||
"fmul", "Rd, Rr", "fractional multiply unsigned", "R1:R0 <-- Rd x Rr << 1 (UU)", "------ZC",
|
||||
{"2", "2", "2", "n/a"}, "d, r = 16..23"},
|
||||
{OP_ID(fmuls), 0xff88, 0x0380, 1, OP_AVR4, "0000 0011 1ddd 0rrr", OTY_ALBI|OTY_RUPP,
|
||||
"fmuls", "Rd, Rr", "fractional multiply signed", "R1:R0 <-- Rd x Rr << 1 (SS)", "------ZC",
|
||||
{"2", "2", "2", "n/a"}, "d, r = 16..23"},
|
||||
{OP_ID(fmulsu), 0xff88, 0x0388, 1, OP_AVR4, "0000 0011 1ddd 1rrr", OTY_ALBI|OTY_RUPP,
|
||||
"fmulsu", "Rd, Rr", "fractional multiply signed with unsigned", "R1:R0 <-- Rd x Rr << 1 (SU)", "------ZC",
|
||||
{"2", "2", "2", "n/a"}, "d, r = 16..23"},
|
||||
{OP_ID(des), 0xff0f, 0x940b, 1, OP_AVR_XM, "1001 0100 KKKK 1011", OTY_ALBI,
|
||||
"des", "K", "data encryption round", "if (H = 0) then R15:R0 <-- Encrypt(R15:R0, K) if (H = 1) then R15:R0 <-- Decrypt(R15:R0, K)", "--------",
|
||||
{"n/a", "1/2", "n/a", "n/a"}, ""},
|
||||
|
||||
// Branch Instructions (and compare)
|
||||
{OP_ID(rjmp), 0xf000, 0xc000, 1, OP_AVR1, "1100 kkkk kkkk kkkk", OTY_RJMI,
|
||||
"rjmp", "k", "relative jump", "PC <-- PC + k + 1", "--------",
|
||||
{"2", "2", "2", "2"}, ""},
|
||||
{OP_ID(ijmp), 0xffff, 0x9409, 1, OP_AVR2, "1001 0100 0000 1001", OTY_JMPI|OTY_ZWORD,
|
||||
"ijmp", "", "indirect jump to (Z)", "PC(15:0) <-- Z, PC(21:16) <-- 0", "--------",
|
||||
{"2", "2", "2", "2"}, ""},
|
||||
{OP_ID(eijmp), 0xffff, 0x9419, 1, OP_AVR_XL, "1001 0100 0001 1001", OTY_JMPX|OTY_ZWORD,
|
||||
"eijmp", "", "extended indirect jump to (Z)", "PC(15:0) <-- Z, PC(21:16) <-- EIND", "--------",
|
||||
{"2", "2", "2", "n/a"}, ""},
|
||||
{OP_ID(jmp), 0xfe0e, 0x940c, 2, OP_AVR_M, "1001 010k kkkk 110k kkkk kkkk kkkk kkkk", OTY_JMPI,
|
||||
"jmp", "k", "jump", "PC <-- k", "--------",
|
||||
{"3", "3", "3", "n/a"}, ""},
|
||||
{OP_ID(rcall), 0xf000, 0xd000, 1, OP_AVR1, "1101 kkkk kkkk kkkk", OTY_RJMX,
|
||||
"rcall", "k", "relative call subroutine", "PC <-- PC + k + 1", "--------",
|
||||
{"3+", "2+", "2+", "3"}, ""},
|
||||
{OP_ID(icall), 0xffff, 0x9509, 1, OP_AVR2, "1001 0101 0000 1001", OTY_JMPX|OTY_ZWORD,
|
||||
"icall", "", "indirect call to (Z)", "PC(15:0) <-- Z, PC(21:16) <-- 0", "--------",
|
||||
{"3+", "2+", "2+", "3"}, ""},
|
||||
{OP_ID(eicall), 0xffff, 0x9519, 1, OP_AVR_XL, "1001 0101 0001 1001", OTY_JMPX|OTY_ZWORD,
|
||||
"eicall", "", "extended indirect call to (Z)", "PC(15:0) <-- Z, PC(21:16) <-- EIND", "--------",
|
||||
{"4", "3", "3", "n/a"}, ""},
|
||||
{OP_ID(call), 0xfe0e, 0x940e, 2, OP_AVR_M, "1001 010k kkkk 111k kkkk kkkk kkkk kkkk", OTY_JMPX,
|
||||
"call", "k", "call subroutine", "PC <-- k, STACK <-- PC, SP <-- SP - 2", "--------",
|
||||
{"4+", "3+", "3+", "n/a"}, ""},
|
||||
{OP_ID(ret), 0xffff, 0x9508, 1, OP_AVR1, "1001 0101 0000 1000", OTY_JMPX,
|
||||
"ret", "", "subroutine return", "SP <-- SP + 2, PC <-- STACK", "--------",
|
||||
{"4+", "4+", "4+", "6"}, ""},
|
||||
{OP_ID(reti), 0xffff, 0x9518, 1, OP_AVR1, "1001 0101 0001 1000", OTY_JMPX,
|
||||
"reti", "", "interrupt return", "SP <-- SP + 2, PC <-- STACK", "I-------",
|
||||
{"4+", "4+", "4+", "6"}, ""},
|
||||
{OP_ID(cpse), 0xfc00, 0x1000, 1, OP_AVR1, "0001 00rd dddd rrrr", OTY_SKPI|OTY_RALL,
|
||||
"cpse", "Rd, Rr", "compare and skip if equal", "if(Rd=Rr) PC <-- PC + 2/3", "--------",
|
||||
{"1-3", "1-3", "1-3", "1/2"}, ""},
|
||||
{OP_ID(cp), 0xfc00, 0x1400, 1, OP_AVR1, "0001 01rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"cp", "Rd, Rr", "compare", "Rd - Rr", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(cpc), 0xfc00, 0x0400, 1, OP_AVR1, "0000 01rd dddd rrrr", OTY_ALBI|OTY_RALL,
|
||||
"cpc", "Rd, Rr", "compare with carry", "Rd - Rr - C", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(cpi), 0xf000, 0x3000, 1, OP_AVR1, "0011 KKKK dddd KKKK", OTY_ALBI|OTY_RUPP,
|
||||
"cpi", "Rd, K", "compare with immediate", "Rd - K", "--HSVNZC",
|
||||
{"1", "1", "1", "1"}, "d = 16..31"},
|
||||
{OP_ID(sbrc), 0xfe08, 0xfc00, 1, OP_AVR1, "1111 110r rrrr 0bbb", OTY_SKPI|OTY_RALL,
|
||||
"sbrc", "Rr, b", "skip if bit in register cleared", "if(Rr(b)=0) PC <-- PC + 2/3", "--------",
|
||||
{"1-3", "1-3", "1-3", "1/2"}, ""},
|
||||
{OP_ID(sbrs), 0xfe08, 0xfe00, 1, OP_AVR1, "1111 111r rrrr 0bbb", OTY_SKPI|OTY_RALL,
|
||||
"sbrs", "Rr, b", "skip if bit in register set", "if(Rr(b)=1) PC <-- PC + 2/3", "--------",
|
||||
{"1-3", "1-3", "1-3", "1/2"}, ""},
|
||||
{OP_ID(sbic), 0xff00, 0x9900, 1, OP_AVR1, "1001 1001 AAAA Abbb", OTY_SKPX,
|
||||
"sbic", "A, b", "skip if bit in I/O register cleared", "if(I/O(A,b)=0) PC <-- PC + 2/3", "--------",
|
||||
{"1-3", "2-4", "1-3", "1/2"}, ""},
|
||||
{OP_ID(sbis), 0xff00, 0x9b00, 1, OP_AVR1, "1001 1011 AAAA Abbb", OTY_SKPX,
|
||||
"sbis", "A, b", "skip if bit in I/O register set", "If(I/O(A,b)=1) PC <-- PC + 2/3", "--------",
|
||||
{"1-3", "2-4", "1-3", "1/2"}, ""},
|
||||
{OP_ID(brcs), 0xfc07, 0xf000, 1, OP_AVR1, "1111 00kk kkkk k000", OTY_BRAI,
|
||||
"brcs", "k", "branch if carry set", "if(C=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbs 0, k (C Carry)"},
|
||||
{OP_ID(brlo), 0xfc07, 0xf000, 1, OP_AVR1, "1111 00kk kkkk k000", OTY_BRAI|OTY_ALIAS,
|
||||
"brlo", "k", "branch if lower", "if(C=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbs 0, k (C Carry)"},
|
||||
{OP_ID(breq), 0xfc07, 0xf001, 1, OP_AVR1, "1111 00kk kkkk k001", OTY_BRAI,
|
||||
"breq", "k", "branch if equal", "if(Z=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbs 1, k (Z Zero)"},
|
||||
{OP_ID(brmi), 0xfc07, 0xf002, 1, OP_AVR1, "1111 00kk kkkk k010", OTY_BRAI,
|
||||
"brmi", "k", "branch if minus", "if(N=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbs 2, k (N Negative)"},
|
||||
{OP_ID(brvs), 0xfc07, 0xf003, 1, OP_AVR1, "1111 00kk kkkk k011", OTY_BRAI,
|
||||
"brvs", "k", "branch if overflow flag is set", "if(V=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbs 3, k (V Overflow in two's complement)"},
|
||||
{OP_ID(brlt), 0xfc07, 0xf004, 1, OP_AVR1, "1111 00kk kkkk k100", OTY_BRAI,
|
||||
"brlt", "k", "branch if less than (signed)", "if(N^V=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbs 4, k (S Sign)"},
|
||||
{OP_ID(brhs), 0xfc07, 0xf005, 1, OP_AVR1, "1111 00kk kkkk k101", OTY_BRAI,
|
||||
"brhs", "k", "branch if half-carry flag set", "if(H=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbs 5, k (H Half carry)"},
|
||||
{OP_ID(brts), 0xfc07, 0xf006, 1, OP_AVR1, "1111 00kk kkkk k110", OTY_BRAI,
|
||||
"brts", "k", "branch if T flag set", "if(T=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbs 6, k (T Transfer bit)"},
|
||||
{OP_ID(brie), 0xfc07, 0xf007, 1, OP_AVR1, "1111 00kk kkkk k111", OTY_BRAI,
|
||||
"brie", "k", "branch if interrupt enabled", "if(I=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbs 7, k (I Interrupt enable)"},
|
||||
{OP_ID(brbs), 0xfc00, 0xf000, 1, OP_AVR1, "1111 00kk kkkk ksss", OTY_BRAI,
|
||||
"brbs", "s, k", "branch if status flag set", "if(SREG(s)=1) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, ""},
|
||||
{OP_ID(brcc), 0xfc07, 0xf400, 1, OP_AVR1, "1111 01kk kkkk k000", OTY_BRAI,
|
||||
"brcc", "k", "branch if carry cleared", "if(C=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbc 0, k (C Carry)"},
|
||||
{OP_ID(brsh), 0xfc07, 0xf400, 1, OP_AVR1, "1111 01kk kkkk k000", OTY_BRAI|OTY_ALIAS,
|
||||
"brsh", "k", "branch if same or higher", "if(C=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbc 0, k (C Carry)"},
|
||||
{OP_ID(brne), 0xfc07, 0xf401, 1, OP_AVR1, "1111 01kk kkkk k001", OTY_BRAI,
|
||||
"brne", "k", "branch if not equal", "if(Z=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbc 1, k (Z Zero)"},
|
||||
{OP_ID(brpl), 0xfc07, 0xf402, 1, OP_AVR1, "1111 01kk kkkk k010", OTY_BRAI,
|
||||
"brpl", "k", "branch if plus", "if(N=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbc 2, k (N Negative)"},
|
||||
{OP_ID(brvc), 0xfc07, 0xf403, 1, OP_AVR1, "1111 01kk kkkk k011", OTY_BRAI,
|
||||
"brvc", "k", "branch if overflow flag is cleared", "if(V=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbc 3, k (V Overflow in two's complement)"},
|
||||
{OP_ID(brge), 0xfc07, 0xf404, 1, OP_AVR1, "1111 01kk kkkk k100", OTY_BRAI,
|
||||
"brge", "k", "branch if greater or equal (signed)", "if(N^V=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbc 4, k (S Sign)"},
|
||||
{OP_ID(brhc), 0xfc07, 0xf405, 1, OP_AVR1, "1111 01kk kkkk k101", OTY_BRAI,
|
||||
"brhc", "k", "branch if half-carry flag cleared", "if(H=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbc 5, k (H Half carry)"},
|
||||
{OP_ID(brtc), 0xfc07, 0xf406, 1, OP_AVR1, "1111 01kk kkkk k110", OTY_BRAI,
|
||||
"brtc", "k", "branch if T flag cleared", "if(T=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbc 6, k (T Transfer bit)"},
|
||||
{OP_ID(brid), 0xfc07, 0xf407, 1, OP_AVR1, "1111 01kk kkkk k111", OTY_BRAI,
|
||||
"brid", "k", "branch if interrupt disabled", "if(I=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, "alias for brbc 7, k (I Interrupt enable)"},
|
||||
{OP_ID(brbc), 0xfc00, 0xf400, 1, OP_AVR1, "1111 01kk kkkk ksss", OTY_BRAI,
|
||||
"brbc", "s, k", "branch if status flag cleared", "if(SREG(s)=0) then PC <-- PC + k + 1", "--------",
|
||||
{"1/2", "1/2", "1/2", "1/2"}, ""},
|
||||
|
||||
// Data Transfer Instructions
|
||||
{OP_ID(mov), 0xfc00, 0x2c00, 1, OP_AVR1, "0010 11rd dddd rrrr", OTY_XFRI|OTY_RALL,
|
||||
"mov", "Rd, Rr", "copy register", "Rd <-- Rr", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(movw), 0xff00, 0x0100, 1, OP_AVR25, "0000 0001 dddd rrrr", OTY_XFRI|OTY_REVN,
|
||||
"movw", "Rd, Rr", "copy register pair", "Rd+1:Rd <-- Rr+1:Rr", "--------",
|
||||
{"1", "1", "1", "n/a"}, "d, r in {0, 2, ..., 30}"},
|
||||
{OP_ID(ser), 0xff0f, 0xef0f, 1, OP_AVR1, "1110 1111 dddd 1111", OTY_ALBI|OTY_RUPP,
|
||||
"ser", "Rd", "set register", "Rd <-- 0xff", "--------",
|
||||
{"1", "1", "1", "1"}, "alias for ldi Rd, 0xff; d = 16..31"},
|
||||
{OP_ID(ldi), 0xf000, 0xe000, 1, OP_AVR1, "1110 KKKK dddd KKKK", OTY_XFRI|OTY_RUPP,
|
||||
"ldi", "Rd, K", "load immediate", "Rd <-- K", "--------",
|
||||
{"1", "1", "1", "1"}, "d = 16..31"},
|
||||
{OP_ID(lds), 0xfe0f, 0x9000, 2, OP_AVR2nRC, "1001 000d dddd 0000 kkkk kkkk kkkk kkkk", OTY_XFRX|OTY_RALL,
|
||||
"lds", "Rd, k", "load direct from data space", "Rd <-- (k)", "--------",
|
||||
{"2", "3", "3", "2"}, ""},
|
||||
{OP_ID(ld_x), 0xfe0f, 0x900c, 1, OP_AVR2, "1001 000d dddd 1100", OTY_XFRX|OTY_RALL,
|
||||
"ld", "Rd, X", "load indirect", "Rd <-- (X)", "--------",
|
||||
{"2", "2", "2", "1/2"}, ""},
|
||||
{OP_ID(ld_xp), 0xfe0f, 0x900d, 1, OP_AVR2, "1001 000d dddd 1101", OTY_XFRX|OTY_RALL|OTY_XWRN,
|
||||
"ld", "Rd, X+", "load indirect and post-increment", "Rd <-- (X), X <-- X + 1", "--------",
|
||||
{"2", "2", "2", "2/3"}, ""},
|
||||
{OP_ID(ld_mx), 0xfe0f, 0x900e, 1, OP_AVR2, "1001 000d dddd 1110", OTY_XFRX|OTY_RALL|OTY_XWRN,
|
||||
"ld", "Rd, -X", "load indirect and pre-decrement", "X <-- X - 1, Rd <-- (X)", "--------",
|
||||
{"2", "3", "2", "2/3"}, ""},
|
||||
{OP_ID(ld_y), 0xfe0f, 0x8008, 1, OP_AVR2, "1000 000d dddd 1000", OTY_XFRX|OTY_RALL,
|
||||
"ld", "Rd, Y", "load indirect", "Rd <-- (Y) <-- (Y)", "--------",
|
||||
{"2", "2", "2", "1/2"}, "alias for ldd Rd, Y+0"},
|
||||
{OP_ID(ld_yp), 0xfe0f, 0x9009, 1, OP_AVR2, "1001 000d dddd 1001", OTY_XFRX|OTY_RALL|OTY_YWRN,
|
||||
"ld", "Rd, Y+", "load indirect and post-increment", "Rd <-- (Y), Y <-- Y + 1", "--------",
|
||||
{"2", "2", "2", "2/3"}, ""},
|
||||
{OP_ID(ld_my), 0xfe0f, 0x900a, 1, OP_AVR2, "1001 000d dddd 1010", OTY_XFRX|OTY_RALL|OTY_YWRN,
|
||||
"ld", "Rd, -Y", "load indirect and pre-decrement", "Y <-- Y - 1 Rd <-- (Y)", "--------",
|
||||
{"2", "3", "2", "2/3"}, ""},
|
||||
{OP_ID(ldd_y), 0xd208, 0x8008, 1, OP_AVR2nRC, "10q0 qq0d dddd 1qqq", OTY_XFRX|OTY_RALL,
|
||||
"ldd", "Rd, Y+q", "load indirect with displacement", "Rd <-- (Y+q)", "--------",
|
||||
{"2", "3", "2", "n/a"}, ""},
|
||||
{OP_ID(ld_z), 0xfe0f, 0x8000, 1, OP_AVR1, "1000 000d dddd 0000", OTY_XFRX|OTY_RALL,
|
||||
"ld", "Rd, Z", "load indirect", "Rd <-- (Z)", "--------",
|
||||
{"2", "2", "2", "1/2"}, "alias for ldd Rd, Z+0"},
|
||||
{OP_ID(ld_zp), 0xfe0f, 0x9001, 1, OP_AVR1, "1001 000d dddd 0001", OTY_XFRX|OTY_RALL|OTY_ZWRN,
|
||||
"ld", "Rd, Z+", "load indirect and post-increment", "Rd <-- (Z), Z <-- Z + 1", "--------",
|
||||
{"2", "2", "2", "2/3"}, ""},
|
||||
{OP_ID(ld_mz), 0xfe0f, 0x9002, 1, OP_AVR1, "1001 000d dddd 0010", OTY_XFRX|OTY_RALL|OTY_ZWRN,
|
||||
"ld", "Rd, -Z", "load indirect and pre-decrement", "Z <-- Z - 1, Rd <-- (Z)", "--------",
|
||||
{"2", "3", "2", "2/3"}, ""},
|
||||
{OP_ID(ldd_z), 0xd208, 0x8000, 1, OP_AVR2nRC, "10q0 qq0d dddd 0qqq", OTY_XFRX|OTY_RALL,
|
||||
"ldd", "Rd, Z+q", "load indirect with displacement", "Rd <-- (Z+q)", "--------",
|
||||
{"2", "3", "2", "n/a"}, ""},
|
||||
{OP_ID(sts), 0xfe0f, 0x9200, 2, OP_AVR2nRC, "1001 001r rrrr 0000 kkkk kkkk kkkk kkkk", OTY_XFRX|OTY_RALL,
|
||||
"sts", "k, Rr", "store direct to data space", "(k) <-- Rr", "--------",
|
||||
{"2", "2", "2", "1"}, ""},
|
||||
{OP_ID(st_x), 0xfe0f, 0x920c, 1, OP_AVR2, "1001 001r rrrr 1100", OTY_XFRX|OTY_RALL,
|
||||
"st", "X, Rr", "store indirect", "(X) <-- Rr", "--------",
|
||||
{"2", "1", "1", "1"}, ""},
|
||||
{OP_ID(st_xp), 0xfe0f, 0x920d, 1, OP_AVR2, "1001 001r rrrr 1101", OTY_XFRX|OTY_RALL|OTY_XWRN,
|
||||
"st", "X+, Rr", "store indirect and post-increment", "(X) <-- Rr, X <-- X + 1", "--------",
|
||||
{"2", "1", "1", "1"}, ""},
|
||||
{OP_ID(st_mx), 0xfe0f, 0x920e, 1, OP_AVR2, "1001 001r rrrr 1110", OTY_XFRX|OTY_RALL|OTY_XWRN,
|
||||
"st", "-X, Rr", "store indirect and pre-decrement", "X <-- X - 1, (X) <-- Rr", "--------",
|
||||
{"2", "2", "1", "1"}, ""},
|
||||
{OP_ID(st_y), 0xfe0f, 0x8208, 1, OP_AVR2, "1000 001r rrrr 1000", OTY_XFRX|OTY_RALL,
|
||||
"st", "Y, Rr", "store indirect", "(Y) <-- Rr", "--------",
|
||||
{"2", "1", "1", "1"}, "alias for std Y+0, Rr"},
|
||||
{OP_ID(st_yp), 0xfe0f, 0x9209, 1, OP_AVR2, "1001 001r rrrr 1001", OTY_XFRX|OTY_RALL|OTY_YWRN,
|
||||
"st", "Y+, Rr", "store indirect and post-increment", "(Y) <-- Rr, Y <-- Y + 1", "--------",
|
||||
{"2", "1", "1", "1"}, ""},
|
||||
{OP_ID(st_my), 0xfe0f, 0x920a, 1, OP_AVR2, "1001 001r rrrr 1010", OTY_XFRX|OTY_RALL|OTY_YWRN,
|
||||
"st", "-Y, Rr", "store indirect and pre-decrement", "Y <-- Y - 1, (Y) <-- Rr", "--------",
|
||||
{"2", "2", "1", "1"}, ""},
|
||||
{OP_ID(std_y), 0xd208, 0x8208, 1, OP_AVR2nRC, "10q0 qq1r rrrr 1qqq", OTY_XFRX|OTY_RALL,
|
||||
"std", "Y+q, Rr", "store indirect with displacement", "(Y+q) <-- Rr", "--------",
|
||||
{"2", "2", "1", "n/a"}, ""},
|
||||
{OP_ID(st_z), 0xfe0f, 0x8200, 1, OP_AVR1, "1000 001r rrrr 0000", OTY_XFRX|OTY_RALL,
|
||||
"st", "Z, Rr", "store indirect", "(Z) <-- Rr", "--------",
|
||||
{"2", "1", "1", "1"}, "alias for std Z+0, Rr"},
|
||||
{OP_ID(st_zp), 0xfe0f, 0x9201, 1, OP_AVR1, "1001 001r rrrr 0001", OTY_XFRX|OTY_RALL|OTY_ZWRN,
|
||||
"st", "Z+, Rr", "store indirect and post-increment", "(Z) <-- Rr, Z <-- Z + 1", "--------",
|
||||
{"2", "1", "1", "1"}, ""},
|
||||
{OP_ID(st_mz), 0xfe0f, 0x9202, 1, OP_AVR1, "1001 001r rrrr 0010", OTY_XFRX|OTY_RALL|OTY_ZWRN,
|
||||
"st", "-Z, Rr", "store indirect and pre-decrement", "Z <-- Z - 1, (Z) <-- Rr", "--------",
|
||||
{"2", "2", "1", "1"}, ""},
|
||||
{OP_ID(std_z), 0xd208, 0x8200, 1, OP_AVR2nRC, "10q0 qq1r rrrr 0qqq", OTY_XFRX|OTY_RALL,
|
||||
"std", "Z+q, Rr", "store indirect with displacement", "(Z+q) <-- Rr", "--------",
|
||||
{"2", "2", "1", "n/a"}, ""},
|
||||
{OP_ID(lpm_0), 0xffff, 0x95c8, 1, OP_AVR1nRC, "1001 0101 1100 1000", OTY_XFRX,
|
||||
"lpm", "", "load program memory", "R0 <-- (Z)", "--------",
|
||||
{"3", "3", "3", "n/a"}, ""},
|
||||
{OP_ID(lpm_z), 0xfe0f, 0x9004, 1, OP_AVR25, "1001 000d dddd 0100", OTY_XFRX|OTY_RALL,
|
||||
"lpm", "Rd, Z", "load program memory", "Rd <-- (Z)", "--------",
|
||||
{"3", "3", "3", "n/a"}, ""},
|
||||
{OP_ID(lpm_zp), 0xfe0f, 0x9005, 1, OP_AVR25, "1001 000d dddd 0101", OTY_XFRX|OTY_RALL|OTY_ZWRN,
|
||||
"lpm", "Rd, Z+", "load program memory and post-increment", "Rd <-- (Z), Z <-- Z + 1", "--------",
|
||||
{"3", "3", "3", "n/a"}, ""},
|
||||
{OP_ID(elpm_0), 0xffff, 0x95d8, 1, OP_AVR_L, "1001 0101 1101 1000", OTY_XFRX,
|
||||
"elpm", "", "extended load program memory", "R0 <-- (RAMPZ:Z)", "--------",
|
||||
{"3", "3", "3", "n/a"}, ""},
|
||||
{OP_ID(elpm_z), 0xfe0f, 0x9006, 1, OP_AVR_L, "1001 000d dddd 0110", OTY_XFRX|OTY_RALL,
|
||||
"elpm", "Rd, Z", "extended load program memory", "Rd <-- (RAMPZ:Z)", "--------",
|
||||
{"3", "3", "3", "n/a"}, ""},
|
||||
{OP_ID(elpm_zp), 0xfe0f, 0x9007, 1, OP_AVR_L, "1001 000d dddd 0111", OTY_XFRX|OTY_RALL|OTY_ZWRN,
|
||||
"elpm", "Rd, Z+", "extended load program memory and post-increment", "Rd <-- (RAMPZ:Z), Z <-- Z + 1", "--------",
|
||||
{"3", "3", "3", "n/a"}, ""},
|
||||
{OP_ID(spm), 0xffff, 0x95e8, 1, OP_AVR25, "1001 0101 1110 1000", OTY_XFRX,
|
||||
"spm", "", "store program memory", "(RAMPZ:Z) <-- R1:R0", "--------",
|
||||
{"-", "-", "-", "-"}, ""},
|
||||
{OP_ID(spm_zp), 0xffff, 0x95f8, 1, OP_AVR_XTM, "1001 0101 1111 1000", OTY_XFRX,
|
||||
"spm", "Z+", "store program memory and post-increment by 2", "(RAMPZ:Z) <-- R1:R0, Z <-- Z + 2", "--------",
|
||||
{"n/a", "-", "-", "n/a"}, ""},
|
||||
{OP_ID(in), 0xf800, 0xb000, 1, OP_AVR1, "1011 0AAd dddd AAAA", OTY_XFRX|OTY_RALL,
|
||||
"in", "Rd, A", "in from I/O location", "Rd <-- I/O(A)", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(out), 0xf800, 0xb800, 1, OP_AVR1, "1011 1AAr rrrr AAAA", OTY_XFRX|OTY_RALL,
|
||||
"out", "A, Rr", "out to I/O location", "I/O(A) <-- Rr", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(push), 0xfe0f, 0x920f, 1, OP_AVR2, "1001 001r rrrr 1111", OTY_XFRX|OTY_RALL,
|
||||
"push", "Rr", "push register on stack", "STACK <-- Rr, SP <-- SP - 2", "--------",
|
||||
{"2", "1", "1", "1"}, ""},
|
||||
{OP_ID(pop), 0xfe0f, 0x900f, 1, OP_AVR2, "1001 000d dddd 1111", OTY_XFRX|OTY_RALL,
|
||||
"pop", "Rd", "pop register from stack", "SP <-- SP + 2, Rd <-- STACK", "--------",
|
||||
{"2", "2", "2", "3"}, ""},
|
||||
{OP_ID(xch), 0xfe0f, 0x9204, 1, OP_AVR_XM, "1001 001d dddd 0100", OTY_XFRX|OTY_RALL,
|
||||
"xch", "Z, Rd", "exchange", "(Z) <-- Rd, Rd <-- (Z)", "--------",
|
||||
{"n/a", "1", "n/a", "n/a"}, ""},
|
||||
{OP_ID(las), 0xfe0f, 0x9205, 1, OP_AVR_XM, "1001 001d dddd 0101", OTY_ALBX|OTY_RALL,
|
||||
"las", "Z, Rd", "load and set", "(Z) <-- Rd | (Z), Rd <-- (Z)", "--------",
|
||||
{"n/a", "1", "n/a", "n/a"}, ""},
|
||||
{OP_ID(lac), 0xfe0f, 0x9206, 1, OP_AVR_XM, "1001 001d dddd 0110", OTY_ALBX|OTY_RALL,
|
||||
"lac", "Z, Rd", "load and clear", "(Z) <-- (0xff - Rd) & (Z), Rd <-- (Z)", "--------",
|
||||
{"n/a", "1", "n/a", "n/a"}, ""},
|
||||
{OP_ID(lat), 0xfe0f, 0x9207, 1, OP_AVR_XM, "1001 001d dddd 0111", OTY_ALBX|OTY_RALL,
|
||||
"lat", "Z, Rd", "load and toggle", "(Z) <-- Rd ^ (Z), Rd <-- (Z)", "--------",
|
||||
{"n/a", "1", "n/a", "n/a"}, ""},
|
||||
|
||||
// Bit and Bit-test Instructions
|
||||
{OP_ID(lsr), 0xfe0f, 0x9406, 1, OP_AVR1, "1001 010d dddd 0110", OTY_ALBI|OTY_RALL,
|
||||
"lsr", "Rd", "logical shift right", "0 --> Rd(7) --> Rd(6) ... Rd(1) --> Rd(0) --> C", "----VNZC",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(swap), 0xfe0f, 0x9402, 1, OP_AVR1, "1001 010d dddd 0010", OTY_ALBI|OTY_RALL,
|
||||
"swap", "Rd", "swap nibbles", "Rd(3..0) <--> Rd(7..4)", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(sbi), 0xff00, 0x9a00, 1, OP_AVR1, "1001 1010 AAAA Abbb", OTY_ALBX,
|
||||
"sbi", "A, b", "set bit in I/O register", "I/O(A,b) <-- 1", "--------",
|
||||
{"2", "1", "1", "1"}, ""},
|
||||
{OP_ID(cbi), 0xff00, 0x9800, 1, OP_AVR1, "1001 1000 AAAA Abbb", OTY_ALBX,
|
||||
"cbi", "A, b", "clear bit in I/O register", "I/O(A,b) <-- 0", "--------",
|
||||
{"2", "1", "1", "1"}, ""},
|
||||
{OP_ID(bst), 0xfe08, 0xfa00, 1, OP_AVR1, "1111 101r rrrr 0bbb", OTY_ALBI|OTY_RALL,
|
||||
"bst", "Rr, b", "bit store from register to T", "T <-- Rr(b)", "-T------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(bld), 0xfe08, 0xf800, 1, OP_AVR1, "1111 100d dddd 0bbb", OTY_ALBI|OTY_RALL,
|
||||
"bld", "Rd, b", "bit load from T to register", "Rd(b) <-- T", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(sec), 0xffff, 0x9408, 1, OP_AVR1, "1001 0100 0000 1000", OTY_ALBI,
|
||||
"sec", "", "set carry", "C <-- 1", "-------C",
|
||||
{"1", "1", "1", "1"}, "alias for bset 0"},
|
||||
{OP_ID(clc), 0xffff, 0x9488, 1, OP_AVR1, "1001 0100 1000 1000", OTY_ALBI,
|
||||
"clc", "", "clear carry", "C <-- 0", "-------C",
|
||||
{"1", "1", "1", "1"}, "alias for bclr 0"},
|
||||
{OP_ID(sen), 0xffff, 0x9428, 1, OP_AVR1, "1001 0100 0010 1000", OTY_ALBI,
|
||||
"sen", "", "set negative flag", "N <-- 1", "-----N--",
|
||||
{"1", "1", "1", "1"}, "alias for bset 2"},
|
||||
{OP_ID(cln), 0xffff, 0x94a8, 1, OP_AVR1, "1001 0100 1010 1000", OTY_ALBI,
|
||||
"cln", "", "clear negative flag", "N <-- 0", "-----N--",
|
||||
{"1", "1", "1", "1"}, "alias for bclr 2"},
|
||||
{OP_ID(sez), 0xffff, 0x9418, 1, OP_AVR1, "1001 0100 0001 1000", OTY_ALBI,
|
||||
"sez", "", "set zero flag", "Z <-- 1", "------Z-",
|
||||
{"1", "1", "1", "1"}, "alias for bset 1"},
|
||||
{OP_ID(clz), 0xffff, 0x9498, 1, OP_AVR1, "1001 0100 1001 1000", OTY_ALBI,
|
||||
"clz", "", "clear zero flag", "Z <-- 0", "------Z-",
|
||||
{"1", "1", "1", "1"}, "alias for bclr 1"},
|
||||
{OP_ID(sei), 0xffff, 0x9478, 1, OP_AVR1, "1001 0100 0111 1000", OTY_ALBX,
|
||||
"sei", "", "global interrupt enable", "I <-- 1", "I-------",
|
||||
{"1", "1", "1", "1"}, "alias for bset 7"},
|
||||
{OP_ID(cli), 0xffff, 0x94f8, 1, OP_AVR1, "1001 0100 1111 1000", OTY_ALBI,
|
||||
"cli", "", "global interrupt disable", "I <-- 0", "I-------",
|
||||
{"1", "1", "1", "1"}, "alias for bclr 7"},
|
||||
{OP_ID(ses), 0xffff, 0x9448, 1, OP_AVR1, "1001 0100 0100 1000", OTY_ALBI,
|
||||
"ses", "", "set signed test flag", "S <-- 1", "---S----",
|
||||
{"1", "1", "1", "1"}, "alias for bset 4"},
|
||||
{OP_ID(cls), 0xffff, 0x94c8, 1, OP_AVR1, "1001 0100 1100 1000", OTY_ALBI,
|
||||
"cls", "", "clear signed test flag", "S <-- 0", "---S----",
|
||||
{"1", "1", "1", "1"}, "alias for bclr 4"},
|
||||
{OP_ID(sev), 0xffff, 0x9438, 1, OP_AVR1, "1001 0100 0011 1000", OTY_ALBI,
|
||||
"sev", "", "set two's complement overflow", "V <-- 1", "----V---",
|
||||
{"1", "1", "1", "1"}, "alias for bset 3"},
|
||||
{OP_ID(clv), 0xffff, 0x94b8, 1, OP_AVR1, "1001 0100 1011 1000", OTY_ALBI,
|
||||
"clv", "", "clear two's complement overflow", "V <-- 0", "----V---",
|
||||
{"1", "1", "1", "1"}, "alias for bclr 3"},
|
||||
{OP_ID(set), 0xffff, 0x9468, 1, OP_AVR1, "1001 0100 0110 1000", OTY_ALBI,
|
||||
"set", "", "set T in sreg", "T <-- 1", "-T------",
|
||||
{"1", "1", "1", "1"}, "alias for bset 6"},
|
||||
{OP_ID(clt), 0xffff, 0x94e8, 1, OP_AVR1, "1001 0100 1110 1000", OTY_ALBI,
|
||||
"clt", "", "clear T in sreg", "T <-- 0", "-T------",
|
||||
{"1", "1", "1", "1"}, "alias for bclr 6"},
|
||||
{OP_ID(seh), 0xffff, 0x9458, 1, OP_AVR1, "1001 0100 0101 1000", OTY_ALBI,
|
||||
"seh", "", "set half-carry flag in sreg", "H <-- 1", "--H-----",
|
||||
{"1", "1", "1", "1"}, "alias for bset 5"},
|
||||
{OP_ID(clh), 0xffff, 0x94d8, 1, OP_AVR1, "1001 0100 1101 1000", OTY_ALBI,
|
||||
"clh", "", "clear half-carry flag in sreg", "H <-- 0", "--H-----",
|
||||
{"1", "1", "1", "1"}, "alias for bclr 5"},
|
||||
{OP_ID(bset), 0xff8f, 0x9408, 1, OP_AVR1, "1001 0100 0sss 1000", OTY_ALBX,
|
||||
"bset", "s", "flag set", "SREG(s) <-- 1", "SREG-bit",
|
||||
{"1", "1", "1", "1"}, "s = 0-7 = C,Z,N,V,S,H,T,I"},
|
||||
{OP_ID(bclr), 0xff8f, 0x9488, 1, OP_AVR1, "1001 0100 1sss 1000", OTY_ALBI,
|
||||
"bclr", "s", "flag clear", "SREG(s) <-- 0", "SREG-bit",
|
||||
{"1", "1", "1", "1"}, "s = 0-7 = C,Z,N,V,S,H,T,I"},
|
||||
|
||||
// MCU Control Instructions
|
||||
{OP_ID(break), 0xffff, 0x9598, 1, OP_AVR1, "1001 0101 1001 1000", OTY_MCUX,
|
||||
"break", "", "break", "on-chip debug system breakpoint", "--------",
|
||||
{"-", "-", "-", "-"}, "not available on all parts"},
|
||||
{OP_ID(nop), 0xffff, 0x0000, 1, OP_AVR1, "0000 0000 0000 0000", OTY_MCUI,
|
||||
"nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(sleep), 0xffff, 0x9588, 1, OP_AVR1, "1001 0101 1000 1000", OTY_MCUX,
|
||||
"sleep", "", "sleep", "sleep mode defined by the MCU control register", "--------",
|
||||
{"-", "-", "-", "-"}, ""},
|
||||
{OP_ID(wdr), 0xffff, 0x95a8, 1, OP_AVR1, "1001 0101 1010 1000", OTY_MCUI,
|
||||
"wdr", "", "watchdog reset", "reset the watchdog timer", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
|
||||
/*
|
||||
* Special 16-bit lds/sts opcodes for reduced-core ATtinys only; they conflict with
|
||||
* regular ldd Rd, Y+q; ldd Rd, Z+q; std Y+q, Rr; std Z+q, Rr opcodes
|
||||
*/
|
||||
{OP_ID(lds_rc), 0xf800, 0xa000, 1, OP_AVR_RC, "1010 0aaa dddd aaaa", OTY_XFRX|OTY_RUPP,
|
||||
"lds", "Rd, a", "load direct from data space", "Rd <-- (a)", "--------",
|
||||
{"n/a", "n/a", "n/a", "2"}, "AVRrc only (TPI parts); a = 0x40..0xbf"},
|
||||
{OP_ID(sts_rc), 0xf800, 0xa800, 1, OP_AVR_RC, "1010 1aaa rrrr aaaa", OTY_XFRX|OTY_RUPP,
|
||||
"sts", "a, Rr", "store direct to data space", "(a) <-- Rr", "--------",
|
||||
{"n/a", "n/a", "n/a", "1"}, "AVRrc only (TPI parts); a = 0x40..0xbf"},
|
||||
|
||||
// Undocumented opcodes: they are said(!) to do the following
|
||||
{OP_ID(u_nop_1), 0xff00, 0x0000, 1, OP_AVR_ILL, "0000 0000 xxxx xxxx", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, "xxxx xxxx != 0000 0000"},
|
||||
{OP_ID(u_nop_2), 0xfe0f, 0x9003, 1, OP_AVR_ILL, "1001 000x xxxx 0011", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_nop_3), 0xfe0f, 0x9008, 1, OP_AVR_ILL, "1001 000x xxxx 1000", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_nop_4), 0xfe0f, 0x900b, 1, OP_AVR_ILL, "1001 000x xxxx 1011", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_nop_5), 0xfe0f, 0x9203, 1, OP_AVR_ILL, "1001 001x xxxx 0011", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_nop_6), 0xfe0f, 0x9208, 1, OP_AVR_ILL, "1001 001x xxxx 1000", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_nop_7), 0xfe0f, 0x920b, 1, OP_AVR_ILL, "1001 001x xxxx 1011", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_icall), 0xff1f, 0x9509, 1, OP_AVR_ILL, "1001 0101 xxx0 1001", OTY_JMPX|OTY_ZWORD,
|
||||
"u/icall", "", "indirect call to (Z)", "PC(15:0) <-- Z, PC(21:16) <-- 0", "--------",
|
||||
{"3+", "2+", "2+", "3"}, "xxx != 000"},
|
||||
{OP_ID(u_eicall), 0xff1f, 0x9519, 1, OP_AVR_ILL, "1001 0101 xxx1 1001", OTY_JMPX|OTY_ZWORD,
|
||||
"u/eicall", "", "extended indirect call to (Z)", "PC(15:0) <-- Z, PC(21:16) <-- EIND", "--------",
|
||||
{"4", "3", "3", "n/a"}, "xxx != 000"},
|
||||
{OP_ID(u_ret), 0xff9f, 0x9508, 1, OP_AVR_ILL, "1001 0101 0xx0 1000", OTY_JMPX,
|
||||
"u/ret", "", "subroutine return", "SP --> SP + 2, PC <-- STACK", "--------",
|
||||
{"4+", "4+", "4+", "6"}, "xx != 00"},
|
||||
{OP_ID(u_reti), 0xff9f, 0x9518, 1, OP_AVR_ILL, "1001 0101 0xx1 1000", OTY_JMPX,
|
||||
"u/reti", "", "interrupt return", "SP -> SP + 2, PC <-- STACK", "I-------",
|
||||
{"4+", "4+", "4+", "6"}, "xx != 00"},
|
||||
{OP_ID(u_nop_8), 0xffff, 0x95b8, 1, OP_AVR_ILL, "1001 0101 1011 1000", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_nop_9), 0xfe0f, 0x9404, 1, OP_AVR_ILL, "1001 010x xxxx 0100", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_nop_a), 0xff0f, 0x950b, 1, OP_AVR_ILL, "1001 0101 xxxx 1011", OTY_MCUI,
|
||||
"u/nop", "", "no operation", "-", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_ijmp), 0xff1f, 0x9409, 1, OP_AVR_ILL, "1001 0100 xxx0 1001", OTY_JMPI|OTY_ZWORD,
|
||||
"u/ijmp", "", "indirect jump to (Z)", "PC(15:0) <-- Z, PC(21:16) <-- 0", "--------",
|
||||
{"2", "2", "2", "2"}, "xxx != 000"},
|
||||
{OP_ID(u_eijmp), 0xff1f, 0x9419, 1, OP_AVR_ILL, "1001 0100 xxx1 1001", OTY_JMPX|OTY_ZWORD,
|
||||
"u/eijmp", "", "extended indirect jump to (Z)", "PC(15:0) <-- Z, PC(21:16) <-- EIND", "--------",
|
||||
{"2", "2", "2", "n/a"}, "xxx != 000"},
|
||||
{OP_ID(u_bld), 0xfe08, 0xf808, 1, OP_AVR_ILL, "1111 100d dddd 1bbb", OTY_ALBI|OTY_RALL,
|
||||
"u/bld", "Rd, b", "bit load from T to register", "Rd(b) <-- T", "--------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_bst), 0xfe08, 0xfa08, 1, OP_AVR_ILL, "1111 101r rrrr 1bbb", OTY_ALBI|OTY_RALL,
|
||||
"u/bst", "Rr, b", "bit store from register to T", "T <-- Rr(b)", "-T------",
|
||||
{"1", "1", "1", "1"}, ""},
|
||||
{OP_ID(u_sbrc), 0xfe08, 0xfc08, 1, OP_AVR_ILL, "1111 110r rrrr 1bbb", OTY_SKPI|OTY_RALL,
|
||||
"u/sbrc", "Rr, b", "skip if bit in register cleared", "if(Rr(b)=0) PC <-- PC + 2/3", "--------",
|
||||
{"1-3", "1-3", "1-3", "1/2"}, ""},
|
||||
{OP_ID(u_sbrs), 0xfe08, 0xfe08, 1, OP_AVR_ILL, "1111 111r rrrr 1bbb", OTY_SKPI|OTY_RALL,
|
||||
"u/sbrs", "Rr, b", "skip if bit in register set", "if(Rr(b)=1) PC <-- PC + 2/3", "--------",
|
||||
{"1-3", "1-3", "1-3", "1/2"}, ""},
|
||||
};
|
||||
|
||||
// Return whether or not the given 16-bit opcode is the mnemonic
|
||||
int op16_is_mnemo(int op, AVR_mnemo mnemo) {
|
||||
return mnemo < 0 || mnemo >= MNEMO_N? 0:
|
||||
(op & avr_opcodes[mnemo].mask) != avr_opcodes[mnemo].value? 0:
|
||||
!(avr_opcodes[mnemo].type & OTY_CONSTRAINT)? 1:
|
||||
(op>>0 & 15) == (op>>4 & 15) && (op>>9 & 1) == (op>>8 & 1); // Constraint Rd == Rr
|
||||
}
|
||||
|
||||
// Return whether or not the given 16-bit opcode has a 16-bit address argument
|
||||
int is_opcode32(int op) {
|
||||
return
|
||||
op16_is_mnemo(op, MNEMO_call) || op16_is_mnemo(op, MNEMO_jmp) ||
|
||||
op16_is_mnemo(op, MNEMO_sts) || op16_is_mnemo(op, MNEMO_lds);
|
||||
}
|
||||
|
||||
// Return width of opcode in bytes (2 or 4)
|
||||
int op_width(int op16) {
|
||||
return is_opcode32(op16)? 4: 2;
|
||||
}
|
||||
|
||||
// Return the register number of the 16-bit ldi opcode and 0 if it's not ldi
|
||||
int ldi_Rd(int op) {
|
||||
return op16_is_mnemo(op, MNEMO_ldi)? 16 + ((op >> 4) & 15): 0;
|
||||
}
|
||||
|
||||
// Return the constant number in the 16-bit ldi opcode and -1 if it's not ldi
|
||||
int ldi_K(int op) {
|
||||
return op16_is_mnemo(op, MNEMO_ldi)? ((op & 0x0f00) >> 4) | (op & 0x0f): -1;
|
||||
}
|
||||
|
||||
// Returns bitmask of first character chr in bits
|
||||
static int bitmask_first_chr(const char *bits, int chr) {
|
||||
int ret = 0x8000;
|
||||
for(const char *c = bits; *c && *c != chr && ret; c++)
|
||||
if(*c != ' ')
|
||||
ret >>= 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Return first match of opcode that is compatible with avrlevel or MNEMO_NONE
|
||||
AVR_mnemo opcode_mnemo(int op, int avrlevel) {
|
||||
for(AVR_mnemo i = 0; i < MNEMO_N; i++)
|
||||
if(avr_opcodes[i].avrlevel & avrlevel)
|
||||
if(op16_is_mnemo(op, i)) {
|
||||
if(avrlevel == PART_AVR_RC && (avr_opcodes[i].type & OTY_REG_MASK) == OTY_RALL) {
|
||||
// Reduced-core ATtiny does not have registers r0, ..., r15
|
||||
int bmask; // Assert highest bit in 5-bit r/d is set
|
||||
if((bmask = bitmask_first_chr(avr_opcodes[i].bits, 'r')) && !(op & bmask))
|
||||
return MNEMO_NONE;
|
||||
if((bmask = bitmask_first_chr(avr_opcodes[i].bits, 'd')) && !(op & bmask))
|
||||
return MNEMO_NONE;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
return MNEMO_NONE;
|
||||
}
|
||||
|
||||
// Opcodes in avr_opcodes[] that a part ought to be able to run
|
||||
int avr_get_archlevel(const AVRPART *p) {
|
||||
int ret =
|
||||
p->prog_modes & PM_UPDI? PART_AVR_XT:
|
||||
p->prog_modes & PM_PDI? PART_AVR_XM:
|
||||
p->prog_modes & PM_TPI? PART_AVR_RC: 0;
|
||||
|
||||
if(!ret) { // Non-TPI classic part
|
||||
switch(p->archnum) {
|
||||
case 1:
|
||||
ret = PART_AVR1;
|
||||
break;
|
||||
default: // If AVRDUE doesn't know, it's probably rare & old
|
||||
case 2:
|
||||
ret = PART_AVR2;
|
||||
break;
|
||||
case 25:
|
||||
ret = PART_AVR25;
|
||||
break;
|
||||
case 3: case 31: case 35: // Sic
|
||||
ret = PART_AVR3;
|
||||
break;
|
||||
break;
|
||||
case 4:
|
||||
ret = PART_AVR4;
|
||||
break;
|
||||
case 5:
|
||||
ret = PART_AVR5;
|
||||
break;
|
||||
case 51:
|
||||
ret = PART_AVR51;
|
||||
break;
|
||||
case 6:
|
||||
ret = PART_AVR6;
|
||||
}
|
||||
}
|
||||
|
||||
AVRMEM *mem = avr_locate_flash(p);
|
||||
if(mem) { // Add opcodes needed for large parts in any case
|
||||
if(mem->size > 8192)
|
||||
ret |= OP_AVR_M; // JMP, CALL
|
||||
if(mem->size > 65536)
|
||||
ret |= OP_AVR_L; // ELPM
|
||||
if(mem->size > 128*1024)
|
||||
ret |= OP_AVR_XL; // EIJMP, EICALL
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Index in the avr_opcodes[].clock[] array for timings of an opcode
|
||||
AVR_cycle_index avr_get_cycle_index(const AVRPART *p) {
|
||||
return
|
||||
p->prog_modes & PM_UPDI? OP_AVRxt:
|
||||
p->prog_modes & PM_PDI? OP_AVRxm:
|
||||
p->prog_modes & PM_TPI? OP_AVRrc: OP_AVRe;
|
||||
}
|
||||
|
||||
// Return the mnemonic string of an opcode
|
||||
const char *mnemo_str(int op) {
|
||||
AVR_mnemo mnemo = opcode_mnemo(op, PART_ALL | OP_AVR_ILL);
|
||||
if(mnemo < 0 || mnemo >= MNEMO_N)
|
||||
return "illegal";
|
||||
return avr_opcodes[mnemo].opcode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return
|
||||
* 2 if opcode treats Z register as word address
|
||||
* 1 if opcode treats Z as byte address
|
||||
* 0 otherwise (Z not involved in opcode)
|
||||
*/
|
||||
int z_width(int op16, AVR_mnemo *mnemop) {
|
||||
AVR_mnemo mlist[] = {
|
||||
MNEMO_ijmp, MNEMO_eijmp, MNEMO_icall, MNEMO_eicall, MNEMO_u_icall, MNEMO_u_eicall,
|
||||
MNEMO_u_ijmp, MNEMO_u_eijmp, MNEMO_ld_z, MNEMO_ld_zp, MNEMO_ld_mz, MNEMO_ldd_z,
|
||||
MNEMO_st_z, MNEMO_st_zp, MNEMO_st_mz, MNEMO_std_z, MNEMO_lpm_0, MNEMO_lpm_z,
|
||||
MNEMO_lpm_zp, MNEMO_elpm_0, MNEMO_elpm_z, MNEMO_elpm_zp, MNEMO_spm, MNEMO_spm_zp,
|
||||
MNEMO_xch, MNEMO_las, MNEMO_lac, MNEMO_lat,
|
||||
};
|
||||
|
||||
for(AVR_mnemo m=0; m < (AVR_mnemo) (sizeof mlist/sizeof*mlist); m++)
|
||||
if(op16_is_mnemo(op16, mlist[m])) {
|
||||
if(mnemop)
|
||||
*mnemop = mlist[m];
|
||||
return avr_opcodes[mlist[m]].type & OTY_ZWORD? 2: 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2022 Stefan Rueger <stefan.rueger@urclocks.c>
|
||||
* Copyright (C) 2022 Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -66,8 +64,8 @@
|
||||
* flash (and sometimes EEPROM, too) looks like a NOR memory, ie, a write can
|
||||
* only clear bits, never set them. For NOR memories a page erase or, if not
|
||||
* available, a chip erase needs to be issued before writing arbitrary data.
|
||||
* Bootrow and usersig are generally unaffected by a chip erase, so will need
|
||||
* a page erase. When a memory looks like a NOR memory, either page erase is
|
||||
* Usersig is generally unaffected by a chip erase, so will always need a
|
||||
* page erase. When a memory looks like a NOR memory, 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
|
||||
@@ -90,7 +88,7 @@
|
||||
* 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. avr_chip_erase_cached() does not
|
||||
* affect the bootrow or usersig cache.
|
||||
* affect the usersig cache.
|
||||
*
|
||||
* The avr_page_erase_cached() function erases a page and synchronises it
|
||||
* with the cache.
|
||||
@@ -330,13 +328,6 @@ error:
|
||||
}
|
||||
|
||||
|
||||
// Does the memory region only haxe 0xff?
|
||||
static int _is_all_0xff(const void *p, size_t n) {
|
||||
const unsigned char *q = (const unsigned char *) p;
|
||||
return n <= 0 || (*q == 0xff && memcmp(q, q+1, n-1) == 0);
|
||||
}
|
||||
|
||||
|
||||
// A coarse guess where any bootloader might start (prob underestimates the start)
|
||||
static int guessBootStart(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
int bootstart = 0;
|
||||
@@ -370,12 +361,12 @@ typedef struct {
|
||||
AVRMEM *mem;
|
||||
AVR_Cache *cp;
|
||||
int isflash, iseeprom, zopaddr, pgerase;
|
||||
} CacheDesc_t;
|
||||
} Cache_desc;
|
||||
|
||||
|
||||
// Write flash, EEPROM, bootrow and usersig caches to device and free them
|
||||
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
CacheDesc_t mems[] = {
|
||||
Cache_desc mems[] = {
|
||||
{ avr_locate_flash(p), pgm->cp_flash, 1, 0, -1, 0 },
|
||||
{ avr_locate_eeprom(p), pgm->cp_eeprom, 0, 1, -1, 0 },
|
||||
{ avr_locate_bootrow(p), pgm->cp_bootrow, 0, 0, -1, 0 },
|
||||
@@ -539,7 +530,7 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
} else if(mems[i].iseeprom) {
|
||||
// Don't know whether chip erase has zapped EEPROM
|
||||
for(int n = 0; n < cp->size; n += cp->page_size) {
|
||||
if(!_is_all_0xff(cp->copy + n, cp->page_size)) { // First page that had EEPROM data
|
||||
if(!is_memset(cp->copy + n, 0xff, 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)
|
||||
@@ -547,8 +538,8 @@ int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
pmsg_error("EEPROM read failed at addr 0x%04x\n", n);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
}
|
||||
// EEPROM zapped by chip erase? Set all copy to 0xff
|
||||
if(_is_all_0xff(cp->copy + n, cp->page_size))
|
||||
// EEPROM zapped by chip erase? Set all of copy to 0xff
|
||||
if(is_memset(cp->copy + n, 0xff, cp->page_size))
|
||||
memset(cp->copy, 0xff, cp->size);
|
||||
break;
|
||||
}
|
||||
@@ -696,10 +687,11 @@ int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
|
||||
// Erase the chip and set the cache accordingly
|
||||
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
CacheDesc_t mems[3] = {
|
||||
Cache_desc mems[] = {
|
||||
{ avr_locate_flash(p), pgm->cp_flash, 1, 0, -1, 0 },
|
||||
{ avr_locate_eeprom(p), pgm->cp_eeprom, 0, 1, -1, 0 },
|
||||
// bootrow/usersig is unaffected by CE
|
||||
{ avr_locate_bootrow(p), pgm->cp_bootrow, 0, 0, -1, 0 },
|
||||
// usersig is unaffected by CE
|
||||
};
|
||||
int rc;
|
||||
|
||||
@@ -725,19 +717,19 @@ int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
memset(cp->cont, 0xff, cp->size);
|
||||
memset(cp->iscached, 1, cp->size/cp->page_size);
|
||||
}
|
||||
} else if(mems[i].iseeprom) { // Test whether cached EEPROM pages were zapped
|
||||
bool erasedee = 0;
|
||||
} else { // Test whether cached EEPROM/bootrow pages were zapped
|
||||
bool erased = 0;
|
||||
for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) {
|
||||
if(cp->iscached[pgno]) {
|
||||
if(!_is_all_0xff(cp->copy + n, cp->page_size)) { // Page has EEPROM data?
|
||||
if(!is_memset(cp->copy + n, 0xff, cp->page_size)) { // Page has data?
|
||||
if(avr_read_page_default(pgm, p, mem, n, cp->copy + n) < 0)
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
erasedee = _is_all_0xff(cp->copy + n, cp->page_size);
|
||||
erased = is_memset(cp->copy + n, 0xff, cp->page_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(erasedee) { // EEPROM was erased, set cache correspondingly
|
||||
if(erased) { // Memory was erased, set cache correspondingly
|
||||
memset(cp->copy, 0xff, cp->size);
|
||||
memset(cp->cont, 0xff, cp->size);
|
||||
memset(cp->iscached, 1, cp->size/cp->page_size);
|
||||
@@ -788,7 +780,7 @@ int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
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))
|
||||
if(!is_memset(cp->cont + (cacheaddr & ~(cp->page_size-1)), 0xff, cp->page_size))
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
|
||||
return LIBAVRDUDE_SUCCESS;
|
||||
|
||||
520
src/avrdude.1
520
src/avrdude.1
@@ -17,8 +17,6 @@
|
||||
.\" along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
.\"
|
||||
.\"
|
||||
.\" $Id$
|
||||
.\"
|
||||
.Dd January 15, 2023
|
||||
.Os
|
||||
.Dt AVRDUDE 1
|
||||
@@ -286,7 +284,7 @@ for Teensy specific options.
|
||||
.Pp
|
||||
Input files can be provided, and output files can be written in
|
||||
different file formats, such as raw binary files containing the data
|
||||
to download to the chip, Intel hex format, or Motorola S-record
|
||||
to download to the chip, Intel Hex format, or Motorola S-Record
|
||||
format. There are a number of tools available to produce those files,
|
||||
like
|
||||
.Xr asl 1
|
||||
@@ -470,106 +468,83 @@ is engaged by default when specifying
|
||||
. Fl c
|
||||
arduino.
|
||||
.It Fl D
|
||||
Disable auto erase for flash. When the
|
||||
Disable auto-erase for flash. When the
|
||||
.Fl U
|
||||
option with flash memory is specified,
|
||||
option for writing to any flash memory is specified,
|
||||
.Nm
|
||||
will perform a chip erase before starting any of the programming
|
||||
operations, since it generally is a mistake to program the flash
|
||||
without performing an erase first. This option disables that.
|
||||
Auto erase is not used for ATxmega devices as these devices can
|
||||
use page erase before writing each page so no explicit chip erase
|
||||
is required.
|
||||
Note however that any page not affected by the current operation
|
||||
will retain its previous contents.
|
||||
Setting
|
||||
operations, since it generally is a mistake to program the flash without
|
||||
performing an erase first. This option disables that. Auto-erase is not
|
||||
used for ATxmega parts nor for the UPDI (AVR8X family) parts as these can
|
||||
use page erase before writing each page so no explicit chip erase is
|
||||
required. Note, however, that any flash page not affected by the current
|
||||
operation will retain its previous contents. Setting
|
||||
.Fl D
|
||||
implies
|
||||
.Fl A.
|
||||
.It Fl e
|
||||
Causes a chip erase to be executed. This will reset the contents of the
|
||||
Causes a chip erase to be executed. This will reset the contents of the
|
||||
flash ROM and EEPROM to the value
|
||||
.Ql 0xff ,
|
||||
and clear all lock bits.
|
||||
Except for ATxmega devices which can use page erase,
|
||||
it is basically a prerequisite command before the flash ROM can be
|
||||
reprogrammed again. The only exception would be if the new
|
||||
Except for ATxmega and UPDI (AVR8X family) devices, all of which can use
|
||||
page erase, it is basically a prerequisite command before the flash ROM
|
||||
can be reprogrammed again. The only exception would be if the new
|
||||
contents would exclusively cause bits to be programmed from the value
|
||||
.Ql 1
|
||||
to
|
||||
.Ql 0 .
|
||||
Note that in order to reprogram EEPROM cells, no explicit prior chip
|
||||
This option carries out the chip erase at the beginning, before any of the
|
||||
.Fl U,
|
||||
.Fl T
|
||||
or
|
||||
.Fl t
|
||||
options are processed. If a chip erase is required in at a certain
|
||||
position within the sequence of
|
||||
.Fl U,
|
||||
.Fl T
|
||||
or
|
||||
.Fl t
|
||||
options it is recommended to use -T erase instead which is processed in
|
||||
the given command line order.
|
||||
.Pp
|
||||
In absence of an explicit
|
||||
.Fl e
|
||||
or
|
||||
.Fl D
|
||||
option
|
||||
.Nm
|
||||
tries to augur from the command line whether or not the chip should be
|
||||
auto-erased at the beginning. If
|
||||
.Nm
|
||||
detects a
|
||||
.Fl U
|
||||
command that writes to flash then auto-erase will be carried out before
|
||||
any other programming unless a -T erase commad has been detected
|
||||
beforehand and unless flash is read before writing to it. For the purpose
|
||||
of this analysis any terminal command is considered to possibly read
|
||||
flash.
|
||||
.Pp
|
||||
Note that for reprogramming EEPROM cells, no explicit prior chip
|
||||
erase is required since the MCU provides an auto-erase cycle in that
|
||||
case before programming the cell.
|
||||
.It Xo Fl E Ar exitspec Ns
|
||||
.Op \&, Ns Ar exitspec
|
||||
.Xc
|
||||
By default,
|
||||
.Nm
|
||||
leaves the parallel port in the same state at exit as it has been
|
||||
found at startup. This option modifies the state of the
|
||||
.Ql /RESET
|
||||
and
|
||||
.Ql Vcc
|
||||
lines the parallel port is left at, according to the
|
||||
Pass
|
||||
.Ar exitspec
|
||||
arguments provided, as follows:
|
||||
.Bl -tag -width noreset
|
||||
.It Ar reset
|
||||
The
|
||||
.Ql /RESET
|
||||
signal will be left activated at program exit, that is it will be held
|
||||
.Em low ,
|
||||
in order to keep the MCU in reset state afterwards. Note in particular
|
||||
that the programming algorithm for the AT90S1200 device mandates that
|
||||
the
|
||||
.Ql /RESET
|
||||
signal is active
|
||||
.Em before
|
||||
powering up the MCU, so in case an external power supply is used for this
|
||||
MCU type, a previous invocation of
|
||||
to the chosen programmer. The interpretation of the exitspec parameter
|
||||
depends on the programmer itself. See below for a list of programmers
|
||||
accepting exitspec parameter options or issue
|
||||
.Nm
|
||||
with this option specified is one of the possible ways to guarantee this
|
||||
condition.
|
||||
.Em reset
|
||||
is supported by the linuxspi and flip2 programmer options, as well as all
|
||||
parallel port based programmers.
|
||||
.It Ar noreset
|
||||
The
|
||||
.Ql /RESET
|
||||
line will be deactivated at program exit, thus allowing the MCU target
|
||||
program to run while the programming hardware remains connected.
|
||||
.Em noreset
|
||||
is supported by the linuxspi and flip2 programmer options, as well as all
|
||||
parallel port based programmers.
|
||||
.It Ar vcc
|
||||
This option will leave those parallel port pins active
|
||||
.Pq \&i. \&e. Em high
|
||||
that can be used to supply
|
||||
.Ql Vcc
|
||||
power to the MCU.
|
||||
.It Ar novcc
|
||||
This option will pull the
|
||||
.Ql Vcc
|
||||
pins of the parallel port down at program exit.
|
||||
.It Ar d_high
|
||||
This option will leave the 8 data pins on the parallel port active.
|
||||
.Pq \&i. \&e. Em high
|
||||
.It Ar d_low
|
||||
This option will leave the 8 data pins on the parallel port inactive.
|
||||
.Pq \&i. \&e. Em low
|
||||
.El
|
||||
.Pp
|
||||
Multiple
|
||||
.Ar exitspec
|
||||
arguments can be separated with commas.
|
||||
-E help ... to see the options of the chosen programmer.
|
||||
.It Fl F
|
||||
Normally,
|
||||
.Nm
|
||||
tries to verify that the device signature read from the part is
|
||||
reasonable before continuing. Since it can happen from time to time
|
||||
that a device has a broken (erased or overwritten) device signature
|
||||
but is otherwise operating normally, this options is provided to
|
||||
but is otherwise operating normally, this option is provided to
|
||||
override the check.
|
||||
Also, for programmers like the Atmel STK500 and STK600 which can
|
||||
adjust parameters local to the programming tool (independent of an
|
||||
@@ -613,7 +588,7 @@ No-write: disables writing data to the MCU whilst processing -U
|
||||
.Nm avrdude
|
||||
). The terminal mode continues to write to the device.
|
||||
.It Fl O
|
||||
Perform a RC oscillator run-time calibration according to Atmel
|
||||
Perform an RC oscillator run-time calibration according to Atmel
|
||||
application note AVR053.
|
||||
This is only supported on the STK500v2, AVRISP mkII, and JTAG ICE mkII
|
||||
hardware.
|
||||
@@ -773,10 +748,31 @@ Perform a memory operation as indicated when it is its turn in relation to
|
||||
other -t interactive terminals, -T terminal commands and -U memory
|
||||
operations. The
|
||||
.Ar memory
|
||||
field specifies the memory to operate on. The available memory types are
|
||||
device-dependent, the actual configuration can be viewed with the
|
||||
field specifies the memory to operate on. From version 8.0 the memory
|
||||
field can also be a comma-separated list of memories, eg,
|
||||
.Ar flash,eeprom ;
|
||||
also, Intel Hex or Motorola S-Record files generated by AVRDUDE can store
|
||||
multiple memories. The special memory
|
||||
.Ar ALL
|
||||
expands to all memories that a part has while
|
||||
.Ar all
|
||||
expands to all memories with exception of sub-memories.
|
||||
.Ar etc
|
||||
is the same as
|
||||
.Ar all ;
|
||||
this can be used to change the order in which memories are written to
|
||||
or read from file, eg,
|
||||
.Ar signature,etc
|
||||
is a list of all memories such that the
|
||||
.Ar signature
|
||||
memory comes first. It is possible to remove a memory from the list so far
|
||||
by preceding a minus or backslash, eg,
|
||||
.Ar all,-calibration .
|
||||
The available memory types are device-dependent, the actual configuration
|
||||
can be viewed with the
|
||||
.Cm part
|
||||
command in terminal mode.
|
||||
.Pp
|
||||
Typically, a device's memory configuration at least contains
|
||||
the memories
|
||||
.Ar flash ,
|
||||
@@ -792,10 +788,25 @@ memory contains the three device signature bytes, which should
|
||||
be, but not always are, unique for the part. The
|
||||
.Ar lock
|
||||
memory of one or four bytes typically details whether or not external
|
||||
reading/writing of the flash memory, or parts of it, is allowed. Parts
|
||||
will also typically have fuse bytes, which are read/write memories for
|
||||
configuration of the device and calibration memories that typically
|
||||
contain read-only factory calibration values.
|
||||
reading/writing of the flash memory, or parts of it, is allowed. After
|
||||
restricting access via the lock memory, often the only way to unlock
|
||||
memory is via a chip erase. Parts will also typically have fuse bytes,
|
||||
which are read/write memories for configuration of the device and
|
||||
calibration memories that typically contain read-only factory calibration
|
||||
values.
|
||||
.Pp
|
||||
The flash memory, being physically implemented as NOR-memory, is special
|
||||
in the sense that it is normally only possible to program bits to change
|
||||
from 1 to 0. Before reprogramming takes place normally flash memory has
|
||||
to be erased. Older parts would only offer a chip erase to do so, which
|
||||
also erases EEPROM unless a fuse configuration preserves its contents. If
|
||||
AVRDUDE detects a -U option that writes to a flash memory it will
|
||||
automatically trigger a chip erase for these older parts. ATxmegas or
|
||||
UPDI parts (AVR8X family) offer a page erase, and AVRDUDE takes advantage
|
||||
of that by erasing pages before programming them unless -e (chip erase) or
|
||||
-D (do not erase before writing) was requested. It should be noted that in
|
||||
absence of the -e chip erase option any ATxmega or UPDI flash pages not
|
||||
affected by the programming will retain their previous content.
|
||||
.Pp
|
||||
Classic devices may have the following memories in addition to eeprom, flash, signature and lock:
|
||||
.Bl -tag -width " calibration" -compact
|
||||
@@ -812,11 +823,17 @@ Low fuse byte
|
||||
.It lock
|
||||
Lock byte
|
||||
.It prodsig
|
||||
Signature, calibration byte and serial number in a small read-only memory,
|
||||
Signature, calibration byte(s) and serial number in a small read-only memory,
|
||||
which is only documented to be available for ATmega324PB, ATmega328PB,
|
||||
ATtiny102 and ATtiny104; programmers may or may not be able to read this memory
|
||||
ATtiny102 and ATtiny104;
|
||||
.Nm
|
||||
generally tries to make this memory available, also for parts where it is
|
||||
not documented, but not all programmers may be able to read this memory
|
||||
.It sigrow
|
||||
Memory alias for prodsig
|
||||
.It sernum
|
||||
The serial number part of prodsig; owing to scarce documentation this may not
|
||||
actually turn out to be a serial number or be readable by some programmers
|
||||
.It usersig
|
||||
Three extra flash pages for firmware settings; this memory is not erased
|
||||
during a chip erase. Only some classic parts,
|
||||
@@ -845,6 +862,13 @@ Application flash area
|
||||
Application table flash area
|
||||
.It boot
|
||||
Boot flash area
|
||||
.It calibration
|
||||
An area of 4 (ATxmega-A series) or 5 bytes (ATxmega-B/C/D/E) with
|
||||
oscillator calibration values; this is a sub-memory of prodsig
|
||||
.It fuses
|
||||
A logical memory of 7 bytes containing all fuseX of a part, which can be
|
||||
used to program all fuses at the same time; note that some fuse bytes will
|
||||
be reserved, though
|
||||
.It fuse0
|
||||
A.k.a. jtaguid: JTAG user ID for some devices
|
||||
.It fuse1
|
||||
@@ -857,12 +881,17 @@ Other fuse bytes of ATxmega devices, where
|
||||
is 2, 4 or 5, for system configuration
|
||||
.It prodsig
|
||||
The production signature row is a read-only memory section for factory
|
||||
programmed data such as the signature and calibration values for
|
||||
oscillators or analogue modules; it also contains a serial number that
|
||||
consists of the production lot number, wafer number and wafer coordinates
|
||||
for the part
|
||||
programmed data such as the calibration values for oscillators or analogue
|
||||
modules; it also contains a serial number that consists of the production
|
||||
lot number, wafer number and wafer coordinates for the part
|
||||
.It sernum
|
||||
Serial number with a unique ID for the part consisting of 10 bytes; these
|
||||
are part of the prodsig memory above
|
||||
.It sigrow
|
||||
Memory alias for prodsig
|
||||
.It tempsense
|
||||
A two-byte memory, which is located within prodsig; it contains a 12-bit
|
||||
temperature sensor calibration value
|
||||
.It usersig
|
||||
Additional flash memory page that can be used for firmware settings; this
|
||||
memory is not erased during a chip erase
|
||||
@@ -895,7 +924,7 @@ A.k.a. bootend or bootsize: end of the boot section or the boot size in blocks o
|
||||
.It fusea
|
||||
A.k.a. pdicfg: configures/locks updi access; it is the only fuse that consists of two bytes
|
||||
.It fuses
|
||||
A "logical" memory of up to 16 bytes containing all fuseX of a part, which can be
|
||||
A logical memory of up to 16 bytes containing all fuseX of a part, which can be
|
||||
used to program all fuses at the same time
|
||||
.It osc16err
|
||||
Two bytes typically describing the 16 MHz oscillator frequency error at 3 V and 5 V, respectively
|
||||
@@ -917,10 +946,11 @@ Temperature sensor calibration values
|
||||
.It bootrow
|
||||
Extra page of memory that is only accessible by the MCU in bootloader
|
||||
code; UDPI can read and write this memory only when the device is
|
||||
unlocked; bootrow is not erased during chip erase
|
||||
unlocked
|
||||
.It userrow
|
||||
Extra page of EEPROM memory that can be used for firmware settings; this
|
||||
memory is not erased during a chip erase
|
||||
memory is not erased during a chip erase; UPDI cannot read this memory
|
||||
when the device is locked
|
||||
.It sib
|
||||
Special system information block memory with information about AVR family, chip revision etc.
|
||||
.It io
|
||||
@@ -941,7 +971,10 @@ field specifies what operation to perform:
|
||||
.It Ar r
|
||||
read device memory and write to the specified file
|
||||
.It Ar w
|
||||
read data from the specified file and write to the device memory
|
||||
read data from the specified file and write to the device memories in the
|
||||
list; read-only memories in a memory list are skipped, as are fuses and
|
||||
lock bits when the programmer is a bootloader; writing to single read-only
|
||||
memories fails only if the contents differs between the file and memory
|
||||
.It Ar v
|
||||
read data from both the device and the specified file and perform a verify
|
||||
.El
|
||||
@@ -961,11 +994,11 @@ Intel Hex
|
||||
.It Ar I
|
||||
Intel Hex with comments on download and tolerance of checksum errors on upload
|
||||
.It Ar s
|
||||
Motorola S-record
|
||||
Motorola S-Record
|
||||
.It Ar r
|
||||
raw binary; little-endian byte order, in the case of the flash ROM data
|
||||
raw binary; little-endian byte order, in the case of the flash data
|
||||
.It Ar e
|
||||
ELF (Executable and Linkable Format)
|
||||
ELF (Executable and Linkable Format, for input only)
|
||||
.It Ar m
|
||||
immediate mode; actual byte values are specified on the command line,
|
||||
separated by commas or spaces in place of the filename field of the -U
|
||||
@@ -1016,8 +1049,15 @@ followed by 0x00, and 0x01234 will occupy 4 bytes. See the description of
|
||||
the terminal write command for more details.
|
||||
.Pp
|
||||
In absence of an explicit file format, the default is to use auto
|
||||
detection for input files, and raw binary format for output files. Note
|
||||
that if a
|
||||
detection for input files, raw binary format for output files from a
|
||||
single memory read and Intel Hex with comments when an output file is
|
||||
generated from a list of memories. Note that while
|
||||
.Nm avrdude
|
||||
will generate a single output file from a memory list for all formats with
|
||||
the exception of elf (:e) it only recognises Intel hex (:I or :i),
|
||||
Motorola S-Record (:s) or elf files (:e, generated by the compiler) as
|
||||
valid multi-memory files when reading a file for verifying or writing
|
||||
memories. Note also that if a
|
||||
.Ar filename
|
||||
contains a colon as penultimate character the
|
||||
.Ar format
|
||||
@@ -1073,10 +1113,10 @@ The
|
||||
.Ar addr
|
||||
and
|
||||
.Ar len
|
||||
parameters of the dump, read, write, save and erase commands can be
|
||||
parameters of the dump, read, disasm, write, save and erase commands can be
|
||||
negative with the same syntax as substring computations in perl or python.
|
||||
The table below details their meaning with respect to an example memory of size
|
||||
sz=0x800.
|
||||
sz=0x800 (2048 bytes).
|
||||
.Pp
|
||||
.nf
|
||||
addr len Memory interval Comment
|
||||
@@ -1123,6 +1163,103 @@ and display them (deprecated: use dump memory addr -1).
|
||||
Read all bytes from the specified memory, and display them (deprecated: use dump memory 0 -1).
|
||||
.It Ar read
|
||||
Can be used as an alias for dump.
|
||||
.It Ar disasm [opts] [arguments]
|
||||
Like dump, the disasm command displays a part of the specified memory,
|
||||
albeit by interpreting the memory contents as AVR opcodes and showing it
|
||||
as assembler source code. Unlike dump, the disasm command has options;
|
||||
these control how disasm displays its result (see below). Other than that,
|
||||
the syntax of specifying the memory and its to be processed interval is
|
||||
virtually the same as that of dump: the default disasm length is 32 bytes,
|
||||
though, and sometimes the length can be slightly shorter or longer than
|
||||
requested, so that the memory section for disasm aligns with opcodes.
|
||||
Disasm options, once set, stay in force until switched off, typically by
|
||||
changing the case of the option. This way, a simple disasm without further
|
||||
options can be used to step through memory keeping the appearance. Disasm
|
||||
knows the following options:
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It -g
|
||||
Generate avr-gcc source: this sets -sOFQ and outputs a .text preamble and
|
||||
a main symbol unless the disassembly emits one itself; -G (the default)
|
||||
switches off -g and stops outputting a preamble
|
||||
.It -A
|
||||
Do not show addresses; -a (the default) shows addresses
|
||||
.It -O
|
||||
Do not show opcode bytes; -o (the default) show opcode bytes
|
||||
.It -C
|
||||
Do not show comments; -c (the default) show comments
|
||||
.It -f
|
||||
Show affected flags in SREG, eg, ---SVNZC for the sbiw opcode; -F (the
|
||||
default) do not show SREG flags
|
||||
.It -q
|
||||
Show the number of machine cycles that an opcode takes; -Q (the default)
|
||||
do not show the cycles
|
||||
.It -n
|
||||
Put the opcode full name into comment, eg, subtract immediate from word
|
||||
for the sbiw opcode; -N (the default) do not show the full opcode names
|
||||
.It -e
|
||||
Put a technical explanation of the opcode into the comment, eg, Rd+1:Rd
|
||||
<-- Rd+1:Rd - K for the sbiw opcode; -E (the default) do not show
|
||||
technical explanations
|
||||
.It -S
|
||||
Use AVR instruction set style: this means that register pairs are shown
|
||||
as, eg, in r31:30 instead of r30; -s (the default) use avr-gcc code style
|
||||
.It -L
|
||||
Do not preprocess labels; -l (the default) preprocess jump/call labels
|
||||
.It -d
|
||||
Decode all opcodes including those that are undocumented; -D (the default)
|
||||
decode only opcodes that are valid for the part
|
||||
.It -z
|
||||
Zap the list of jumps and calls before disassembly
|
||||
.It -t=<file>
|
||||
Delete symbols from a previously read tagfile, if any, and read the tagfile
|
||||
<file> for assigning addresses to symbol names
|
||||
.El
|
||||
The tagfile is an ASCII file where each line describes a symbol for code
|
||||
label addresses (L), variable addresses in flash (P) and variables
|
||||
addresses in memory or I/O space (M). Hashmarks start a tagfile comment
|
||||
that extends to the end of the line and is ignored by disasm. Here is a
|
||||
defining example of how a tagfile looks like
|
||||
.nf
|
||||
---------------------------------------------------------------
|
||||
0x7f54 L putch Outputs a char # L are code labels
|
||||
0x7ffe P W 1 version16 A word integer # P are PGM data
|
||||
0x7f80 P A 4 headings Column headers # Auto-aligned strings
|
||||
0x0100 M B 2048 sram 2 kB SRAM # Memory address
|
||||
---------------------------------------------------------------
|
||||
.fi
|
||||
Code labels L can be, eg, function names in program space or goto labels.
|
||||
They use up to four columns separated by white space: the address, the
|
||||
letter L, the symbolic name of the label and an optional comment column
|
||||
for the symbol, which is copied by disasm into the disassembly comment
|
||||
column, should this label be referenced or used by the code. Variable
|
||||
symbols have a P or M in the second column; they can be bytes or words as
|
||||
determined by the letter B or W in the third column and either single
|
||||
variables or arrays as specified by the multiplicity count in the forth
|
||||
column. P symbols, but not M symbols, can also be the base location of
|
||||
nul-terminated strings as encoded by A or S in the third column. Out of
|
||||
necessity, the space occupied by A/S strings varies. The difference
|
||||
between A and S symbols is that the array of A strings might have an
|
||||
additional nul character to auto-align the space occupied by them to an
|
||||
even address. The fifth column is the symbolic name for the P or M address
|
||||
that can be used by disasm to output relevant addresses symbolically. P
|
||||
areas described in the tagfile also tell disasm that the corresponding
|
||||
area is not code and should not be disassembled as such; instead the
|
||||
.byte, .word, .asciz and sometimes at the end of the memory section .ascii
|
||||
directives are used for disassembly of that area. As with L labels, P and
|
||||
M variables may have an optional final comment column pertaining to the
|
||||
symbol that may be output in the disassembly column as and when the
|
||||
corresponding variables are used.
|
||||
.Pp
|
||||
Tagfiles are useful for disassembly to make the output of disasm more
|
||||
readable. They can be built manually and incrementally as one's
|
||||
understanding of the code grows. Alternatively, the bash shell script
|
||||
elf2tag can automatically generate a tag file from the .elf file that
|
||||
produced the flash contents:
|
||||
.Pp
|
||||
$ elf2tag file.elf >file.tag
|
||||
.Pp
|
||||
elf2tag uses the avr-objdump -d disassembly to create L labels and avr-nm
|
||||
to generate M symbols.
|
||||
.It Ar write memory addr data[,] {data[,]}
|
||||
Manually program the respective memory cells, starting at address
|
||||
.Ar addr ,
|
||||
@@ -1201,9 +1338,41 @@ the address information and concatenate the chosen memory segments into
|
||||
the output file. If the file name is - then
|
||||
.Nm
|
||||
writes to stdout.
|
||||
.It Ar backup memlist file[:format]
|
||||
Backup one or more memories to the specified file using the selected
|
||||
format. The default format for a single-memory backup is :r (raw
|
||||
binary); for multi-memory backups it is :I (Intel Hex with comments).
|
||||
Memlist can be a comma separated list of memories just as in the
|
||||
.Ar -U
|
||||
command line argument.
|
||||
.Ar backup
|
||||
flushes the cache before reading memories.
|
||||
.It Ar restore memlist file[:format]
|
||||
Restore one or more memories from the specified file. It is the user's
|
||||
responsibility to erase memories as needed beforehand: some paged memories
|
||||
look like NOR-memory when using certain programmers, meaning programming
|
||||
cannot set bits to 1 (eg, flash under most programmers). These memories
|
||||
need to be erased beforehand using the erase command (see below). The
|
||||
format only needs to be specified if it cannot be automatically detected,
|
||||
eg, when the file is - for standard input. Memlist can be a comma
|
||||
separated list of memories just as in the
|
||||
.Ar -U
|
||||
command line argument.
|
||||
.Ar restore
|
||||
flushes the cache before writing memories and resets the cache after
|
||||
writing memories. Note that restoring read-only memories verifies file
|
||||
contents with the corresponding microprocessor's memories.
|
||||
.It Ar verify memlist file[:format]
|
||||
Compare one or more memories with the specified file.
|
||||
Memlist can be a comma separated list of memories just as in the
|
||||
.Ar -U
|
||||
command line argument.
|
||||
.Ar verify
|
||||
flushes the cache before verifying memories.
|
||||
.It Ar erase
|
||||
Perform a chip erase and discard all pending writes to EEPROM and flash.
|
||||
Note that EEPROM will be preserved if the EESAVE fuse bit is set.
|
||||
Perform a chip erase and discard all pending writes to flash, EEPROM and bootrow.
|
||||
Note that EEPROM will be preserved if the EESAVE fuse bit is active, ie, had
|
||||
a corresponding value at the last reset prior to the operation.
|
||||
.It Ar erase memory
|
||||
Erase the entire specified memory.
|
||||
.It Ar erase memory addr len
|
||||
@@ -1213,8 +1382,8 @@ Synchronise with the device all pending writes to flash, EEPROM, bootrow and
|
||||
usersig. With some programmer and part combinations, flash (and sometimes
|
||||
EEPROM, too) looks like a NOR memory, i.e., a write can only clear bits,
|
||||
never set them. For NOR memories a page erase or, if not available, a chip
|
||||
erase needs to be issued before writing arbitrary data. Bootrow and usersig are
|
||||
generally unaffected by a chip erase. When a memory looks like a NOR
|
||||
erase needs to be issued before writing arbitrary data. Usersig is
|
||||
unaffected by a chip erase. When a memory looks like a NOR
|
||||
memory, either page erase is deployed (e.g., with parts that have PDI/UPDI
|
||||
interfaces), or if that is not available, both EEPROM and flash caches are
|
||||
fully read in, a chip erase command is issued and both EEPROM and flash
|
||||
@@ -1504,6 +1673,30 @@ might leave the EEPROM unerased, at least on some
|
||||
versions of the bootloader.
|
||||
.Ss Programmers accepting extended parameters
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar dryrun
|
||||
.It Ar dryboot
|
||||
These two programmers emulate programming and accept the following parameters:
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar xinit
|
||||
Initialise memories with human-readable patterns. Flash memory will be
|
||||
randomly configured with respect to bootloader, data and code length.
|
||||
Patterns can best be seen with fixed-width font and the :I format
|
||||
by inspecting the generated hex file or by using, eg, -U flash:r:-:I.
|
||||
Patterns in flash memory are executable and represent benign AVR code, ie,
|
||||
no I/O memory access. Choose a fixed seed for reproducible results.
|
||||
.It Ar random
|
||||
Initialise memories with random code and values. Flash memory will be
|
||||
randomly configured with respect to bootloader, data and code length.
|
||||
Random code in flash will be benign, that is, not accessing I/O memories,
|
||||
SRAM or flash. Choose a fixed seed for reproducible results.
|
||||
.It Ar seed=<n>
|
||||
Seed random number generator with <n>; the default is time(NULL).
|
||||
Setting this option with a fixed n > 0 will make the random choices
|
||||
reproducible, ie, they will stay the same between different avrdude
|
||||
runs.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.El
|
||||
.It Ar JTAG ICE mkII
|
||||
.It Ar JTAGICE3
|
||||
.It Ar Atmel-ICE
|
||||
@@ -1532,14 +1725,14 @@ Other JTAG units might require a different bit shift count.
|
||||
.sp 0.5
|
||||
High-voltage UPDI programming is used to enable a UPDI pin that has previously
|
||||
been set to RESET or GPIO mode. Use
|
||||
.Ar -xhvupdi
|
||||
.Ar -x hvupdi
|
||||
to enable high-voltage UPDI initialization for targets that supports this.
|
||||
.It Ar vtarg=VALUE, vtarg
|
||||
.Nm Power Debugger only
|
||||
.sp 0.5
|
||||
The voltage generator can be enabled by setting a target voltage.
|
||||
The current set-voltage can be read by
|
||||
.Ar -xvtarg
|
||||
.Ar -x vtarg
|
||||
alone.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
@@ -1552,9 +1745,9 @@ Switch programmer to AVR or PIC mode, then exit: the PICkit 4 and MPLAB SNAP
|
||||
programmer can only be utilised by
|
||||
.Nm
|
||||
when in AVR mode. Use
|
||||
.Ar -xmode=avr
|
||||
.Ar -x mode=avr
|
||||
for switching to AVR mode, or
|
||||
.Ar -xmode=pic
|
||||
.Ar -x mode=pic
|
||||
for switching to PIC mode.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
@@ -1564,7 +1757,7 @@ Show help menu and exit.
|
||||
.It Ar suffer=VALUE, suffer
|
||||
The SUFFER register allows the user to modify the behavior of the on-board mEDBG.
|
||||
The current state can be read by
|
||||
.Ar -xsuffer
|
||||
.Ar -x suffer
|
||||
alone.
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Bit 7 ARDUINO:
|
||||
@@ -1584,7 +1777,7 @@ Fuses are safe-masked when bit sent to 1. Fuses are unprotected when set to 0
|
||||
.It Ar vtarg_switch=VALUE, vtarg_switch
|
||||
The on-board target voltage switch can be turned on or off by writing a 1 or
|
||||
a 0. The current state can be read by
|
||||
.Ar -xvtarg_switch
|
||||
.Ar -x vtarg_switch
|
||||
alone.
|
||||
Note that the target power switch will always be on after a power cycle.
|
||||
Also note that the smaller Xplained Nano boards does not have a target power switch.
|
||||
@@ -1596,7 +1789,7 @@ Show help menu and exit.
|
||||
.It Ar vtarg=VALUE, vtarg
|
||||
The generated on-board target voltage can be changed by specifying a new voltage.
|
||||
The current set-voltage can be read by
|
||||
.Ar -xvtarg
|
||||
.Ar -x vtarg
|
||||
alone.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
@@ -1607,16 +1800,16 @@ Show help menu and exit.
|
||||
.It Ar vtarg=VALUE, vtarg
|
||||
The generated on-board target voltage can be changed by specifying a new voltage.
|
||||
The current set-voltage can be read by
|
||||
.Ar -xvtarg
|
||||
.Ar -x vtarg
|
||||
alone.
|
||||
.It Ar fosc=VALUE[MHz|M|kHz|k|Hz|H], fosc
|
||||
Set the programmable oscillator frequency. The current frequency can be read by
|
||||
.Ar -xfosc
|
||||
.Ar -x fosc
|
||||
alone.
|
||||
.It Ar varef=VALUE, varef
|
||||
The generated on-board analog reference voltage can be changed by specifying
|
||||
a new reference voltage. The current reference voltage can be read by
|
||||
.Ar -xvaref
|
||||
.Ar -x varef
|
||||
alone.
|
||||
.It Ar varef[0,1]=VALUE, varef[0,1]
|
||||
.Nm STK600 only
|
||||
@@ -1624,9 +1817,9 @@ alone.
|
||||
The generated on-board analog reference voltage for channel 0 or channel 1 can
|
||||
be changed by specifying a new reference voltage.
|
||||
The current reference voltage can be read by
|
||||
.Ar -xvaref0
|
||||
.Ar -x varef0
|
||||
or
|
||||
.Ar -xvaref1
|
||||
.Ar -x varef1
|
||||
alone.
|
||||
.It Ar attemps[=<1..99>]
|
||||
.Nm STK500V1 only
|
||||
@@ -1639,6 +1832,13 @@ original STK500. Used by avrdude for the correct calculation of fosc and sck.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.El
|
||||
.It Ar AVR109
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar autoreset
|
||||
Toggle RTS/DTR lines on port open to issue a hardware reset.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.El
|
||||
.It Ar AVR910
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar devcode=VALUE
|
||||
@@ -1671,13 +1871,15 @@ Show help menu and exit.
|
||||
.It Ar attemps[=<1..99>]
|
||||
Specify how many connection retry attemps to perform before exiting.
|
||||
Defaults to 10 if not specified.
|
||||
.It Ar noautoreset
|
||||
Don't toggle RTS/DTR lines on port open to prevent a hardware reset.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.El
|
||||
.It Ar Urclock
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar showall
|
||||
Show all info for the connected part, then exit. The -xshow... options
|
||||
Show all info for the connected part, then exit. The -x show... options
|
||||
below can be used to assemble a bespoke response consisting of a subset
|
||||
(or only one item) of all available relevant information about the
|
||||
connected part and bootloader.
|
||||
@@ -1686,7 +1888,7 @@ Show a unique Urclock ID stored in either flash or EEPROM of the MCU, then exit.
|
||||
.It Ar id=<E|F>.<addr>.<len>
|
||||
Historically, the Urclock ID was a six-byte unique little-endian number
|
||||
stored in Urclock boards at EEPROM address 257. The location of this
|
||||
number can be set by the -xid=<E|F>.<addr>.<len> extended parameter. E
|
||||
number can be set by the -x id=<E|F>.<addr>.<len> extended parameter. E
|
||||
stands for EEPROM and F stands for flash. A negative address addr counts
|
||||
from the end of EEPROM and flash, respectively. The length len of the
|
||||
Urclock ID can be between 1 and 8 bytes.
|
||||
@@ -1695,7 +1897,7 @@ Show the last-modified date of the input file for the flash application,
|
||||
then exit. If the input file was stdin, the date will be that of the
|
||||
programming. Date and filename are part of the metadata that the urclock
|
||||
programmer stores by default in high flash just under the bootloader; see also
|
||||
-xnometadata.
|
||||
-x nometadata.
|
||||
.It Ar showfilename
|
||||
Show the input filename (or title) of the last flash writing session, then exit.
|
||||
.It Ar title=<string>
|
||||
@@ -1727,7 +1929,7 @@ i.e., typically top of flash, so the urclock programmer can look up the
|
||||
bootloader size itself. In backward-compatibility mode, when programming
|
||||
via other bootloaders, this option can be used to tell the programmer the
|
||||
size, and therefore the location, of the bootloader.
|
||||
.It Ar vectornum=<arg>
|
||||
.It Ar vectornum=<n>
|
||||
Manual override for vector number. Urboot bootloaders put the vector
|
||||
number used by a vector bootloader into a table at the top of flash, so
|
||||
this option is normally not needed for urboot bootloaders. However, it is
|
||||
@@ -1752,7 +1954,7 @@ Upload unchanged flash input files and trim below the bootloader if
|
||||
needed. This is most useful when one has a backup of the full flash and
|
||||
wants to play that back onto the device. No metadata are written in this
|
||||
case and no vector patching happens either if it is a vector bootloader.
|
||||
However, for vector bootloaders, even under the option -xrestore an
|
||||
However, for vector bootloaders, even under the option -x restore an
|
||||
input file will not be uploaded for which the reset vector does not point
|
||||
to the vector bootloader. This is to avoid writing an input file to the
|
||||
device that would render the vector bootloader not functional as it would
|
||||
@@ -1769,20 +1971,22 @@ title) and no date either.
|
||||
On writing to flash do not store metadata except the metadata code byte
|
||||
0xff saying there are no metadata. In particular, no data store frame is
|
||||
programmed.
|
||||
.It Ar noautoreset
|
||||
Don't toggle RTS/DTR lines on port open to prevent a hardware reset.
|
||||
.It Ar nometadata
|
||||
Do not support any metadata. The full flash besides the bootloader is
|
||||
available for the application. If the application is smaller than the
|
||||
available space then a metadata code byte 0xff is stored nevertheless to
|
||||
indicate there are no further metadata available. In absence of
|
||||
-xnometadata, the default for the urclock programmer is to write as much
|
||||
-x nometadata, the default for the urclock programmer is to write as much
|
||||
metadata (filename, data and store information) as the size of the
|
||||
uploaded application and the other extended options allow. The subtle
|
||||
difference between -xnometadata and -xnostore is that the latter always
|
||||
difference between -x nometadata and -x nostore is that the latter always
|
||||
explicitly stores in flash that no further metadata are available, so that
|
||||
a such prepared flash can always be queried with
|
||||
.Nm
|
||||
-xshowall. In contrast to this, it cannot be guaranteed that a -xshowall
|
||||
query on flash prepared with -xnometadata yields useful results.
|
||||
-x showall. In contrast to this, it cannot be guaranteed that a -x showall
|
||||
query on flash prepared with -x nometadata yields useful results.
|
||||
.It Ar delay=<n>
|
||||
Add a <n> ms delay after reset. This can be useful if a board takes a
|
||||
particularly long time to exit from external reset. <n> can be negative,
|
||||
@@ -1791,7 +1995,7 @@ shortened accordingly.
|
||||
.It Ar strict
|
||||
Urclock has a faster, but slightly different strategy than -c arduino to
|
||||
synchronise with the bootloader; some stk500v1 bootloaders cannot cope
|
||||
with this, and they need the -xstrict option.
|
||||
with this, and they need the -x strict option.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.El
|
||||
@@ -1916,6 +2120,8 @@ Add a <n> milliseconds delay after resetting the part through toggling the
|
||||
DTR/RTS lines. This can be useful if a board takes a particularly long
|
||||
time to exit from external reset. <n> can be negative, in which case the
|
||||
default 100 ms delay after issuing reset will be shortened accordingly.
|
||||
.It Ar noautoreset
|
||||
Don't toggle RTS/DTR lines on port open to prevent a hardware reset.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.El
|
||||
@@ -1988,6 +2194,68 @@ the CS line being managed outside the application.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.El
|
||||
.It Ar serprog
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar cs
|
||||
Sets the chip select (CS) to use on supported programmers.
|
||||
Programmers supporting the 0x16 serprog command can have more than the default CS (0).
|
||||
This option allows to choose these additional CSes (1, 2, ...) for programming the AVR.
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.El
|
||||
.El
|
||||
.Ss Programmers accepting exitspec parameter
|
||||
Currently, only the flip2, linuxspi and old school parallel port programmers
|
||||
such as stk200 and dapa support exitspec parameter. These lets the user
|
||||
decide in which state the programmer pins after ended programming session.
|
||||
Multiple exitspec options can be separated with commas.
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar flip2
|
||||
.It Ar linuxspi
|
||||
.It Parallel port programmers
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar help
|
||||
Show help menu and exit.
|
||||
.It Ar reset
|
||||
The
|
||||
.Ql /RESET
|
||||
signal will be left activated at program exit, that is it will be held
|
||||
.Em low ,
|
||||
in order to keep the MCU in reset state afterwards. Note in particular
|
||||
that the programming algorithm for the AT90S1200 device mandates that
|
||||
the
|
||||
.Ql /RESET
|
||||
signal is active
|
||||
.Em before
|
||||
powering up the MCU, so in case an external power supply is used for this
|
||||
MCU type, a previous invocation of
|
||||
.Nm
|
||||
with this option specified is one of the possible ways to guarantee this
|
||||
condition.
|
||||
.It Ar noreset
|
||||
The
|
||||
.Ql /RESET
|
||||
line will be deactivated at program exit, thus allowing the MCU target
|
||||
program to run while the programming hardware remains connected.
|
||||
.El
|
||||
.It Parallel port programmers
|
||||
.Bl -tag -offset indent -width indent
|
||||
.It Ar vcc
|
||||
This option will leave those parallel port pins active
|
||||
.Pq \&i. \&e. Em high
|
||||
that can be used to supply
|
||||
.Ql Vcc
|
||||
power to the MCU.
|
||||
.It Ar novcc
|
||||
This option will pull the
|
||||
.Ql Vcc
|
||||
pins of the parallel port down at program exit.
|
||||
.It Ar d_high
|
||||
This option will leave the 8 data pins on the parallel port active.
|
||||
.Pq \&i. \&e. Em high
|
||||
.It Ar d_low
|
||||
This option will leave the 8 data pins on the parallel port inactive.
|
||||
.Pq \&i. \&e. Em low
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -offset indent -width /dev/ppi0XXX
|
||||
|
||||
31193
src/avrdude.conf.in
31193
src/avrdude.conf.in
File diff suppressed because it is too large
Load Diff
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef avrdude_h
|
||||
#define avrdude_h
|
||||
|
||||
@@ -32,8 +30,7 @@
|
||||
#endif
|
||||
|
||||
extern char *progname; // Name of program, for messages
|
||||
extern char progbuf[]; // Spaces same length as progname
|
||||
|
||||
#define progbuf "" // Used to be for indenting continuation below "avrdude: msg"
|
||||
extern int ovsigck; // Override signature check (-F)
|
||||
extern int verbose; // Verbosity level (-v, -vv, ...)
|
||||
extern int quell_progress; // Quell progress report -q, reduce effective verbosity level (-qq, -qqq)
|
||||
@@ -44,6 +41,7 @@ extern const char *pgmid; // Programmer -c string
|
||||
#define mmt_strdup(s) cfg_strdup(__func__, s)
|
||||
#define mmt_malloc(n) cfg_malloc(__func__, n)
|
||||
#define mmt_realloc(p, n) cfg_realloc(__func__, p, n)
|
||||
#define mmt_sprintf(...) str_sprintf(__VA_ARGS__)
|
||||
#define mmt_free(p) free(p)
|
||||
|
||||
int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int msgmode, int msglvl, const char *format, ...)
|
||||
@@ -63,25 +61,25 @@ int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int
|
||||
#define msg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_TRACE, __VA_ARGS__)
|
||||
#define msg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_TRACE2, __VA_ARGS__)
|
||||
|
||||
#define pmsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_EXT_ERROR, __VA_ARGS__)
|
||||
#define pmsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_ERROR, __VA_ARGS__)
|
||||
#define pmsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_WARNING, __VA_ARGS__)
|
||||
#define pmsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_INFO, __VA_ARGS__)
|
||||
#define pmsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_NOTICE, __VA_ARGS__)
|
||||
#define pmsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_NOTICE2, __VA_ARGS__)
|
||||
#define pmsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_DEBUG, __VA_ARGS__)
|
||||
#define pmsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_TRACE, __VA_ARGS__)
|
||||
#define pmsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_TRACE2, __VA_ARGS__)
|
||||
#define pmsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_UCFIRST|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_EXT_ERROR, __VA_ARGS__)
|
||||
#define pmsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_UCFIRST|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_ERROR, __VA_ARGS__)
|
||||
#define pmsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_UCFIRST|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_WARNING, __VA_ARGS__)
|
||||
#define pmsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_UCFIRST|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_INFO, __VA_ARGS__)
|
||||
#define pmsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_UCFIRST|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_NOTICE, __VA_ARGS__)
|
||||
#define pmsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_UCFIRST|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_NOTICE2, __VA_ARGS__)
|
||||
#define pmsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_UCFIRST|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_DEBUG, __VA_ARGS__)
|
||||
#define pmsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_UCFIRST|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_TRACE, __VA_ARGS__)
|
||||
#define pmsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_UCFIRST|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_TRACE2, __VA_ARGS__)
|
||||
|
||||
#define imsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_EXT_ERROR, __VA_ARGS__)
|
||||
#define imsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_ERROR, __VA_ARGS__)
|
||||
#define imsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_WARNING, __VA_ARGS__)
|
||||
#define imsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_INFO, __VA_ARGS__)
|
||||
#define imsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_NOTICE, __VA_ARGS__)
|
||||
#define imsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_NOTICE2, __VA_ARGS__)
|
||||
#define imsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_DEBUG, __VA_ARGS__)
|
||||
#define imsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_TRACE, __VA_ARGS__)
|
||||
#define imsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_TRACE2, __VA_ARGS__)
|
||||
#define imsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_EXT_ERROR, __VA_ARGS__)
|
||||
#define imsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_ERROR, __VA_ARGS__)
|
||||
#define imsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_WARNING, __VA_ARGS__)
|
||||
#define imsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_INFO, __VA_ARGS__)
|
||||
#define imsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_NOTICE, __VA_ARGS__)
|
||||
#define imsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_NOTICE2, __VA_ARGS__)
|
||||
#define imsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_DEBUG, __VA_ARGS__)
|
||||
#define imsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_TRACE, __VA_ARGS__)
|
||||
#define imsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_FLUSH|MSG2_LEFT_MARGIN, MSG_TRACE2, __VA_ARGS__)
|
||||
|
||||
#define lmsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_LEFT_MARGIN, MSG_EXT_ERROR, __VA_ARGS__)
|
||||
#define lmsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_LEFT_MARGIN, MSG_ERROR, __VA_ARGS__)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
## -*- mode: rpm-spec; -*-
|
||||
##
|
||||
## $Id$
|
||||
##
|
||||
## @configure_input@
|
||||
##
|
||||
|
||||
|
||||
153
src/avrftdi.c
153
src/avrftdi.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrftdi - extension for avrdude, Wolfgang Moser, Ville Voipio
|
||||
* Copyright (C) 2011 Hannes Weisbach, Doug Springer
|
||||
* avrftdi - extension for avrdude
|
||||
* Copyright (C) 2011 Wolfgang Moser, Ville Voipio, Hannes Weisbach, Doug Springer
|
||||
* Copyright (C) 2023 Jeff Kent
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,7 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
/*
|
||||
* Interface to the MPSSE Engine of FTDI Chips using libftdi.
|
||||
*/
|
||||
@@ -52,8 +51,8 @@
|
||||
#ifdef DO_NOT_BUILD_AVRFTDI
|
||||
|
||||
static int avrftdi_noftdi_open(PROGRAMMER *pgm, const char *name) {
|
||||
pmsg_error("no libftdi or libusb support\n");
|
||||
imsg_error("install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again\n");
|
||||
pmsg_error("no libftdi or libusb support; install\n");
|
||||
imsg_error("libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -84,13 +83,13 @@ enum {
|
||||
FTDI_TMS_CS,
|
||||
};
|
||||
|
||||
static int write_flush(avrftdi_t *);
|
||||
static int write_flush(Avrftdi_data *);
|
||||
|
||||
/*
|
||||
* returns a human-readable name for a pin number. The name should match with
|
||||
* the pin names used in FTDI datasheets.
|
||||
*/
|
||||
static char *ftdi_pin_name(avrftdi_t *pdata, struct pindef_t pin) {
|
||||
static char *ftdi_pin_name(Avrftdi_data *pdata, struct pindef pin) {
|
||||
char *str = pdata->name_str;
|
||||
size_t strsiz = sizeof pdata->name_str;
|
||||
|
||||
@@ -145,8 +144,7 @@ static void buf_dump(const unsigned char *buf, int len, char *desc,
|
||||
* calculates the so-called 'divisor'-value from a given frequency.
|
||||
* the divisor is sent to the chip.
|
||||
*/
|
||||
static int set_frequency(avrftdi_t* ftdi, uint32_t freq)
|
||||
{
|
||||
static int set_frequency(Avrftdi_data *ftdi, uint32_t freq) {
|
||||
int32_t clock, divisor;
|
||||
float hs_error, ls_error;
|
||||
uint8_t buf[4], *ptr = buf;
|
||||
@@ -176,22 +174,19 @@ static int set_frequency(avrftdi_t* ftdi, uint32_t freq)
|
||||
}
|
||||
|
||||
if (divisor < 0) {
|
||||
char *f = str_frq(freq, 6), *h = str_frq(clock/2.0, 6);
|
||||
pmsg_warning("frequency %s too high, resetting to %s\n", f, h);
|
||||
mmt_free(f); mmt_free(h);
|
||||
pmsg_warning("frequency %s too high, resetting to %s\n",
|
||||
str_ccfrq(freq, 6), str_ccfrq(clock/2.0, 6));
|
||||
divisor = 0;
|
||||
}
|
||||
|
||||
if (divisor > 65535) {
|
||||
char *f = str_frq(freq, 6), *l = str_frq(clock/2.0 / 65536, 6);
|
||||
pmsg_warning("frequency %s too low, resetting to %s\n", f, l);
|
||||
mmt_free(f); mmt_free(l);
|
||||
pmsg_warning("frequency %s too low, resetting to %s\n",
|
||||
str_ccfrq(freq, 6), str_ccfrq(clock/2.0 / 65536, 6));
|
||||
divisor = 65535;
|
||||
}
|
||||
|
||||
char *f = str_frq(clock/2.0 / (divisor + 1), 6);
|
||||
imsg_notice(" - frequency %s (clock divisor %d = 0x%04x)\n", f, divisor, divisor);
|
||||
mmt_free(f);
|
||||
imsg_notice(" - frequency %s (clock divisor %d = 0x%04x)\n",
|
||||
str_ccfrq(clock/2.0 / (divisor + 1), 6), divisor, divisor);
|
||||
|
||||
*ptr++ = TCK_DIVISOR;
|
||||
*ptr++ = (uint8_t)(divisor & 0xff);
|
||||
@@ -214,8 +209,8 @@ static int set_pin(const PROGRAMMER *pgm, int pinfunc, int value) {
|
||||
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||
return -1;
|
||||
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
struct pindef_t pin = pgm->pin[pinfunc];
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
struct pindef pin = pgm->pin[pinfunc];
|
||||
|
||||
if (pin.mask[0] == 0) {
|
||||
// ignore not defined pins (might be the led or vcc or buff if not needed)
|
||||
@@ -223,9 +218,8 @@ static int set_pin(const PROGRAMMER *pgm, int pinfunc, int value) {
|
||||
}
|
||||
|
||||
pmsg_debug("setting pin %s (%s) as %s: %s (%s active)\n",
|
||||
pinmask_to_str(pin.mask), ftdi_pin_name(pdata, pin),
|
||||
avr_pin_name(pinfunc),
|
||||
(value) ? "high" : "low", (pin.inverse[0]) ? "low" : "high");
|
||||
pinmask_to_str(pin.mask), ftdi_pin_name(pdata, pin), avr_pin_name(pinfunc),
|
||||
(value) ? "high" : "low", (pin.inverse[0]) ? "low" : "high");
|
||||
|
||||
pdata->pin_value = SET_BITS_0(pdata->pin_value, pgm, pinfunc, value);
|
||||
|
||||
@@ -275,7 +269,7 @@ static inline int set_data(const PROGRAMMER *pgm, unsigned char *buf, unsigned c
|
||||
int j;
|
||||
int buf_pos = 0;
|
||||
unsigned char bit = 0x80;
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
|
||||
for (j=0; j<8; j++) {
|
||||
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_SDO,data & bit);
|
||||
@@ -328,14 +322,14 @@ static int avrftdi_transmit_bb(const PROGRAMMER *pgm, unsigned char mode, const
|
||||
{
|
||||
size_t remaining = buf_size;
|
||||
size_t written = 0;
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
size_t blocksize = pdata->rx_buffer_size/2; // we are reading 2 bytes per data byte
|
||||
|
||||
// determine a maximum size of data block
|
||||
size_t max_size = MIN(pdata->ftdic->max_packet_size, (unsigned int) pdata->tx_buffer_size);
|
||||
// select block size so that resulting commands does not exceed max_size if possible
|
||||
blocksize = MAX(1,(max_size-7)/((8*2*6)+(8*1*2)));
|
||||
// msg_info("blocksize %d \n", blocksize);
|
||||
// msg_notice("blocksize %d \n", blocksize);
|
||||
|
||||
unsigned char* send_buffer = alloca((8 * 2 * 6) * blocksize + (8 * 1 * 2) * blocksize + 7);
|
||||
unsigned char* recv_buffer = alloca(2 * 16 * blocksize);
|
||||
@@ -391,7 +385,7 @@ static int avrftdi_transmit_bb(const PROGRAMMER *pgm, unsigned char mode, const
|
||||
* Write is only performed when mode contains MPSSE_DO_WRITE.
|
||||
* Read is only performed when mode contains MPSSE_DO_WRITE and MPSSE_DO_READ.
|
||||
*/
|
||||
static int avrftdi_transmit_mpsse(avrftdi_t* pdata, unsigned char mode, const unsigned char *buf,
|
||||
static int avrftdi_transmit_mpsse(Avrftdi_data *pdata, unsigned char mode, const unsigned char *buf,
|
||||
unsigned char *data, int buf_size)
|
||||
{
|
||||
size_t blocksize;
|
||||
@@ -444,14 +438,14 @@ static int avrftdi_transmit_mpsse(avrftdi_t* pdata, unsigned char mode, const un
|
||||
static inline int avrftdi_transmit(const PROGRAMMER *pgm, unsigned char mode, const unsigned char *buf,
|
||||
unsigned char *data, int buf_size)
|
||||
{
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
if (pdata->use_bitbanging)
|
||||
return avrftdi_transmit_bb(pgm, mode, buf, data, buf_size);
|
||||
else
|
||||
return avrftdi_transmit_mpsse(pdata, mode, buf, data, buf_size);
|
||||
}
|
||||
|
||||
static int write_flush(avrftdi_t* pdata)
|
||||
static int write_flush(Avrftdi_data *pdata)
|
||||
{
|
||||
unsigned char buf[6];
|
||||
|
||||
@@ -504,15 +498,15 @@ static int avrftdi_check_pins_bb(const PROGRAMMER *pgm, bool output) {
|
||||
int pin;
|
||||
|
||||
/* pin checklist. */
|
||||
struct pin_checklist_t pin_checklist[N_PINS];
|
||||
Pin_checklist pin_checklist[N_PINS];
|
||||
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
|
||||
/* value for 8/12/16 bit wide interface */
|
||||
int valid_mask = ((1 << pdata->pin_limit) - 1);
|
||||
|
||||
pmsg_debug("using valid mask bitbanging: 0x%08x\n", valid_mask);
|
||||
struct pindef_t *valid_pins_p = &pdata->valid_pins;
|
||||
struct pindef *valid_pins_p = &pdata->valid_pins;
|
||||
valid_pins_p->mask[0] = valid_mask;
|
||||
valid_pins_p->inverse[0] = valid_mask ;
|
||||
|
||||
@@ -531,11 +525,11 @@ static int avrftdi_check_pins_mpsse(const PROGRAMMER *pgm, bool output) {
|
||||
int pin;
|
||||
|
||||
/* pin checklist. */
|
||||
struct pin_checklist_t pin_checklist[N_PINS];
|
||||
Pin_checklist pin_checklist[N_PINS];
|
||||
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
|
||||
struct pindef_t *valid_pins = pdata->mpsse_pins;
|
||||
struct pindef *valid_pins = pdata->mpsse_pins;
|
||||
|
||||
/* value for 8/12/16 bit wide interface for other pins */
|
||||
int valid_mask = ((1 << pdata->pin_limit) - 1);
|
||||
@@ -547,7 +541,7 @@ static int avrftdi_check_pins_mpsse(const PROGRAMMER *pgm, bool output) {
|
||||
}
|
||||
|
||||
pmsg_debug("using valid mask mpsse: 0x%08x\n", valid_mask);
|
||||
struct pindef_t *valid_pins_others_p = &pdata->other_pins;
|
||||
struct pindef *valid_pins_others_p = &pdata->other_pins;
|
||||
valid_pins_others_p->mask[0] = valid_mask;
|
||||
valid_pins_others_p->inverse[0] = valid_mask ;
|
||||
|
||||
@@ -589,19 +583,19 @@ static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
|
||||
* pin setup *
|
||||
*************/
|
||||
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
|
||||
|
||||
bool pin_check_mpsse = (0 == avrftdi_check_pins_mpsse(pgm, verbose>3));
|
||||
bool pin_check_mpsse = (0 == avrftdi_check_pins_mpsse(pgm, verbose >= MSG_TRACE));
|
||||
|
||||
bool pin_check_bitbanging = (0 == avrftdi_check_pins_bb(pgm, verbose>3));
|
||||
bool pin_check_bitbanging = (0 == avrftdi_check_pins_bb(pgm, verbose >= MSG_TRACE));
|
||||
|
||||
if (!pin_check_mpsse && !pin_check_bitbanging) {
|
||||
pmsg_error("no valid pin configuration found\n");
|
||||
avrftdi_check_pins_bb(pgm, true);
|
||||
imsg_error("pin configuration for FTDI MPSSE must be:\n");
|
||||
pmsg_error("pin configuration for FTDI MPSSE must be:\n");
|
||||
if (pgm->flag == PGM_FL_IS_JTAG) {
|
||||
imsg_error("%s: 0, %s: 1, %s: 2, %s :3 (is: %s, %s, %s, %s)\n",
|
||||
imsg_error(" %s: 0; %s: 1; %s: 2; %s: 3 (is: %s; %s; %s; %s)\n",
|
||||
avr_pin_name(PIN_JTAG_TCK), avr_pin_name(PIN_JTAG_TDI),
|
||||
avr_pin_name(PIN_JTAG_TDO), avr_pin_name(PIN_JTAG_TMS),
|
||||
pins_to_str(&pgm->pin[PIN_JTAG_TCK]),
|
||||
@@ -609,7 +603,7 @@ static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
|
||||
pins_to_str(&pgm->pin[PIN_JTAG_TDO]),
|
||||
pins_to_str(&pgm->pin[PIN_JTAG_TMS]));
|
||||
} else {
|
||||
imsg_error("%s: 0, %s: 1, %s: 2 (is: %s, %s, %s)\n",
|
||||
imsg_error(" %s: 0; %s: 1; %s: 2 (is: %s; %s; %s)\n",
|
||||
avr_pin_name(PIN_AVR_SCK),
|
||||
avr_pin_name(PIN_AVR_SDO),
|
||||
avr_pin_name(PIN_AVR_SDI),
|
||||
@@ -617,14 +611,14 @@ static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SDO]),
|
||||
pins_to_str(&pgm->pin[PIN_AVR_SDI]));
|
||||
}
|
||||
imsg_error("if other pin configuration is used, fallback to slower bitbanging mode is used\n");
|
||||
pmsg_error("if other pin configuration is used, fallback to slower bitbanging mode is used\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdata->use_bitbanging = !pin_check_mpsse;
|
||||
if (pdata->use_bitbanging)
|
||||
imsg_info("because of pin configuration fallback to bitbanging mode\n");
|
||||
pmsg_notice("fallback to bitbanging mode because of pin configuration\n");
|
||||
|
||||
/*
|
||||
* TODO: No need to fail for a wrongly configured led or something.
|
||||
@@ -667,7 +661,7 @@ static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
|
||||
static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
|
||||
int vid, pid, interface, err;
|
||||
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
|
||||
/************************
|
||||
* parameter validation *
|
||||
@@ -694,7 +688,7 @@ static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
|
||||
else if (pgm->usbdev[0] == 'b' || pgm->usbdev[0] == 'B')
|
||||
interface = INTERFACE_B;
|
||||
else {
|
||||
pmsg_warning("invalid interface '%s'. Setting to Interface A\n", pgm->usbdev);
|
||||
pmsg_warning("invalid interface %s; setting to Interface A\n", pgm->usbdev);
|
||||
interface = INTERFACE_A;
|
||||
}
|
||||
|
||||
@@ -708,12 +702,12 @@ static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
|
||||
// Todo: use desc and index argument, currently set to NULL and 0
|
||||
err = ftdi_usb_open_desc_index(pdata->ftdic, vid, pid, NULL, serial, 0);
|
||||
if(err) {
|
||||
pmsg_error("error %d occurred: %s\n", err, ftdi_get_error_string(pdata->ftdic));
|
||||
pmsg_error("%s (%d)\n", ftdi_get_error_string(pdata->ftdic), err);
|
||||
// usb_dev is initialized to the last usb device from probing
|
||||
pdata->ftdic->usb_dev = NULL;
|
||||
return err;
|
||||
} else {
|
||||
pmsg_info("using device VID:PID %04x:%04x and SN %s on interface %c\n",
|
||||
pmsg_notice("using device VID:PID %04x:%04x and SN %s on interface %c\n",
|
||||
vid, pid, serial? serial: "(none)", INTERFACE_A == interface? 'A': 'B');
|
||||
}
|
||||
|
||||
@@ -746,7 +740,7 @@ static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
|
||||
case TYPE_BM:
|
||||
case TYPE_R:
|
||||
pmsg_error("found unsupported device type AM, BM or R\n");
|
||||
imsg_error("avrftdi cannot work with your chip; try the 'synbb' programmer type\n");
|
||||
imsg_error("avrftdi cannot work with your chip; try the synbb programmer type\n");
|
||||
return -1;
|
||||
case TYPE_2232C:
|
||||
pdata->pin_limit = 12;
|
||||
@@ -777,8 +771,7 @@ static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
|
||||
pdata->tx_buffer_size = 2048;
|
||||
break;
|
||||
default:
|
||||
pmsg_warning("unknown device type 0x%02x\n", pdata->ftdic->type);
|
||||
imsg_warning("continuing but no guarantees...\n");
|
||||
pmsg_warning("unknown device type 0x%02x, continuing but no guarantees...\n", pdata->ftdic->type);
|
||||
pdata->pin_limit = 8;
|
||||
pdata->rx_buffer_size = pdata->ftdic->max_packet_size;
|
||||
pdata->tx_buffer_size = pdata->ftdic->max_packet_size;
|
||||
@@ -788,9 +781,8 @@ static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
|
||||
return avrftdi_pin_setup(pgm)? -1: 0;
|
||||
}
|
||||
|
||||
static void avrftdi_close(PROGRAMMER * pgm)
|
||||
{
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
static void avrftdi_close(PROGRAMMER *pgm) {
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
|
||||
if(pdata->ftdic->usb_dev) {
|
||||
set_pin(pgm, PIN_AVR_RESET, ON);
|
||||
@@ -913,7 +905,7 @@ static int avrftdi_lext(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m
|
||||
if(m->op[AVR_OP_LOAD_EXT_ADDR] == NULL)
|
||||
return 0;
|
||||
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
unsigned char buf[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
/* only send load extended address command if high byte changed */
|
||||
@@ -1061,22 +1053,22 @@ static int avrftdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
if(verbose >= MSG_TRACE2)
|
||||
buf_dump(buf, buf_size, "command buffer", 0, 16*2);
|
||||
|
||||
pmsg_info("transmitting buffer of size: %d\n", buf_size);
|
||||
pmsg_notice("transmitting buffer of size: %d\n", buf_size);
|
||||
if (0 > avrftdi_transmit(pgm, MPSSE_DO_WRITE, buf, buf, buf_size))
|
||||
return -1;
|
||||
|
||||
bufptr = buf;
|
||||
|
||||
pmsg_info("using m->buf[%d] = 0x%02x as polling value ", poll_index,
|
||||
pmsg_notice("using m->buf[%d] = 0x%02x as polling value ", poll_index,
|
||||
m->buf[poll_index]);
|
||||
/* poll page write ready */
|
||||
do {
|
||||
msg_info(".");
|
||||
msg_notice(".");
|
||||
|
||||
pgm->read_byte(pgm, p, m, poll_index, &poll_byte);
|
||||
} while (m->buf[poll_index] != poll_byte);
|
||||
|
||||
msg_info("\n");
|
||||
msg_notice("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1095,7 +1087,7 @@ static int avrftdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
static int avrftdi_flash_read(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
unsigned int page_size, unsigned int addr, unsigned int len)
|
||||
{
|
||||
OPCODE * readop;
|
||||
OPCODE *readop;
|
||||
|
||||
unsigned int buf_size = 4 * len + 4;
|
||||
unsigned char* o_buf = alloca(buf_size);
|
||||
@@ -1190,15 +1182,15 @@ static int avrftdi_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||
return -2;
|
||||
}
|
||||
|
||||
static void avrftdi_setup(PROGRAMMER * pgm) {
|
||||
avrftdi_t* pdata;
|
||||
static void avrftdi_setup(PROGRAMMER *pgm) {
|
||||
Avrftdi_data *pdata;
|
||||
|
||||
pgm->cookie = mmt_malloc(sizeof(avrftdi_t));
|
||||
pgm->cookie = mmt_malloc(sizeof(Avrftdi_data));
|
||||
pdata = to_pdata(pgm);
|
||||
|
||||
/* SCK/SDO/SDI are fixed and not invertible? */
|
||||
/* TODO: inverted SCK/SDI/SDO */
|
||||
const struct pindef_t valid_mpsse_pins[4] = {
|
||||
const struct pindef valid_mpsse_pins[4] = {
|
||||
{{0x01}, {0x00}},
|
||||
{{0x02}, {0x00}},
|
||||
{{0x04}, {0x00}},
|
||||
@@ -1220,9 +1212,9 @@ static void avrftdi_setup(PROGRAMMER * pgm) {
|
||||
pdata->lext_byte = 0xff;
|
||||
}
|
||||
|
||||
static void avrftdi_teardown(PROGRAMMER * pgm) {
|
||||
static void avrftdi_teardown(PROGRAMMER *pgm) {
|
||||
if(pgm->cookie) {
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
ftdi_deinit(pdata->ftdic);
|
||||
ftdi_free(pdata->ftdic);
|
||||
mmt_free(pdata);
|
||||
@@ -1234,9 +1226,8 @@ static void avrftdi_teardown(PROGRAMMER * pgm) {
|
||||
/* JTAG functions */
|
||||
/******************/
|
||||
|
||||
static int avrftdi_jtag_reset(const PROGRAMMER *pgm)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
static int avrftdi_jtag_reset(const PROGRAMMER *pgm) {
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
unsigned char buf[3], *ptr = buf;
|
||||
|
||||
/* Unknown -> Reset -> Run-Test/Idle */
|
||||
@@ -1249,9 +1240,8 @@ static int avrftdi_jtag_reset(const PROGRAMMER *pgm)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_ir_out(const PROGRAMMER *pgm, unsigned char ir)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
static int avrftdi_jtag_ir_out(const PROGRAMMER *pgm, unsigned char ir) {
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
unsigned char buf[9], *ptr = buf;
|
||||
|
||||
/* Idle -> Select-DR -> Select-IR -> Capture-IR -> Shift-IR */
|
||||
@@ -1274,9 +1264,8 @@ static int avrftdi_jtag_ir_out(const PROGRAMMER *pgm, unsigned char ir)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int avrftdi_jtag_dr_out(const PROGRAMMER *pgm, unsigned int dr, int bits)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
static int avrftdi_jtag_dr_out(const PROGRAMMER *pgm, unsigned int dr, int bits) {
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
unsigned char buf[18], *ptr = buf;
|
||||
|
||||
if (bits <= 0 || bits > 31) {
|
||||
@@ -1318,7 +1307,7 @@ static int avrftdi_jtag_dr_out(const PROGRAMMER *pgm, unsigned int dr, int bits)
|
||||
static int avrftdi_jtag_dr_inout(const PROGRAMMER *pgm, unsigned int dr,
|
||||
int bits)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
unsigned char buf[19], *ptr = buf;
|
||||
unsigned char bytes = 1, pos;
|
||||
unsigned int dr_in;
|
||||
@@ -1403,7 +1392,7 @@ static int avrftdi_jtag_initialize(const PROGRAMMER *pgm, const AVRPART *p)
|
||||
str_eq(p->id, "m16a") || str_eq(p->id, "m16") ||
|
||||
str_eq(p->id, "m162")) {
|
||||
pmsg_error("programmer type %s is known not to work for %s\n", pgm->type, p->desc);
|
||||
imsg_error("exiting; use -F to carry on regardless\n");
|
||||
pmsg_error("exiting, use -F to carry on regardless\n");
|
||||
return LIBAVRDUDE_EXIT;
|
||||
}
|
||||
}
|
||||
@@ -1423,9 +1412,8 @@ static int avrftdi_jtag_initialize(const PROGRAMMER *pgm, const AVRPART *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void avrftdi_jtag_disable(const PROGRAMMER *pgm)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
static void avrftdi_jtag_disable(const PROGRAMMER *pgm) {
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
|
||||
/* NOP command */
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
@@ -1511,7 +1499,8 @@ static int avrftdi_jtag_read_byte(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
avrftdi_jtag_dr_out(pgm, 0x3600, 15);
|
||||
*value = avrftdi_jtag_dr_inout(pgm, 0x3700, 15) & 0xff;
|
||||
|
||||
} else if (mem_is_sigrow(m)) {
|
||||
} else if (mem_is_in_sigrow(m)) {
|
||||
addr += avr_sigrow_offset(p, m, addr);
|
||||
avrftdi_jtag_ir_out(pgm, JTAG_IR_PROG_COMMANDS);
|
||||
avrftdi_jtag_dr_out(pgm, 0x2300 | JTAG_DR_PROG_SIGCAL_READ, 15);
|
||||
avrftdi_jtag_dr_out(pgm, 0x0300 | (addr/2 & 0xff), 15);
|
||||
@@ -1686,7 +1675,7 @@ static int avrftdi_jtag_paged_read(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
const AVRMEM *m, unsigned int page_size, unsigned int addr,
|
||||
unsigned int n_bytes)
|
||||
{
|
||||
avrftdi_t *pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
unsigned int maxaddr = addr + n_bytes;
|
||||
unsigned char *buf, *ptr;
|
||||
unsigned int bytes;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrftdi - extension for avrdude, Wolfgang Moser, Ville Voipio
|
||||
* Copyright (C) 2011 Hannes Weisbach, Doug Springer
|
||||
* avrftdi - extension for avrdude
|
||||
* Copyright (C) 2011 Wolfgang Moser, Ville Voipio, Hannes Weisbach, Doug Springer
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef avrftdi_h
|
||||
#define avrftdi_h
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ enum jtag_cmd {
|
||||
};
|
||||
|
||||
#define to_pdata(pgm) \
|
||||
((avrftdi_t *)((pgm)->cookie))
|
||||
((Avrftdi_data *)((pgm)->cookie))
|
||||
|
||||
typedef struct avrftdi_s {
|
||||
/* pointer to struct maintained by libftdi to identify the device */
|
||||
@@ -95,10 +95,10 @@ typedef struct avrftdi_s {
|
||||
uint8_t lext_byte;
|
||||
|
||||
char name_str[128]; // Used in ftdi_pin_name()
|
||||
struct pindef_t valid_pins; // Used in avrftdi_check_pins_bb()
|
||||
struct pindef_t mpsse_pins[4]; // Used in avrftdi_check_pins_mpsse()
|
||||
struct pindef_t other_pins; // Used in avrftdi_check_pins_mpsse()
|
||||
} avrftdi_t;
|
||||
struct pindef valid_pins; // Used in avrftdi_check_pins_bb()
|
||||
struct pindef mpsse_pins[4]; // Used in avrftdi_check_pins_mpsse()
|
||||
struct pindef other_pins; // Used in avrftdi_check_pins_mpsse()
|
||||
} Avrftdi_data;
|
||||
|
||||
#endif /* DO_NOT_BUILD_AVRFDTI */
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ static int avrftdi_tpi_program_enable(const PROGRAMMER *pgm, const AVRPART *p);
|
||||
|
||||
#ifdef notyet
|
||||
static void avrftdi_debug_frame(uint16_t frame) {
|
||||
static char bit_name[] = "IDLES01234567PSS";
|
||||
static const char bit_name[] = "IDLES01234567PSS";
|
||||
//static char bit_name[] = "SSP76543210SELDI";
|
||||
char line0[34], line1[34], line2[34];
|
||||
int bit, pos;
|
||||
@@ -64,10 +64,10 @@ int
|
||||
avrftdi_tpi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
int ret;
|
||||
|
||||
avrftdi_t* pdata = to_pdata(pgm);
|
||||
Avrftdi_data *pdata = to_pdata(pgm);
|
||||
unsigned char buf[] = { MPSSE_DO_WRITE | MPSSE_WRITE_NEG | MPSSE_LSB, 0x01, 0x00, 0xff, 0xff };
|
||||
|
||||
pmsg_info("Setting /Reset pin low\n");
|
||||
pmsg_info("setting /Reset pin low\n");
|
||||
pgm->setpin(pgm, PIN_AVR_RESET, OFF);
|
||||
pgm->setpin(pgm, PIN_AVR_SCK, OFF);
|
||||
pgm->setpin(pgm, PIN_AVR_SDO, ON);
|
||||
@@ -82,7 +82,7 @@ avrftdi_tpi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
/*wait at least 20ms bevor issuing spi commands to avr */
|
||||
usleep(20 * 1000);
|
||||
|
||||
pmsg_info("Sending 16 init clock cycles ...\n");
|
||||
pmsg_info("sending 16 init clock cycles ...\n");
|
||||
ret = ftdi_write_data(pdata->ftdic, buf, sizeof(buf));
|
||||
|
||||
return ret;
|
||||
@@ -90,7 +90,7 @@ avrftdi_tpi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
|
||||
|
||||
void avrftdi_tpi_initpgm(PROGRAMMER *pgm) {
|
||||
pmsg_info("Using TPI interface\n");
|
||||
pmsg_info("using TPI interface\n");
|
||||
|
||||
pgm->program_enable = avrftdi_tpi_program_enable;
|
||||
pgm->cmd_tpi = avrftdi_cmd_tpi;
|
||||
@@ -132,7 +132,7 @@ static uint16_t tpi_byte2frame(uint8_t byte) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
static int tpi_frame2byte(uint16_t frame, uint8_t * byte) {
|
||||
static int tpi_frame2byte(uint16_t frame, uint8_t *byte) {
|
||||
/* drop idle and start bit(s) */
|
||||
*byte = (frame >> 5) & 0xff;
|
||||
|
||||
@@ -212,7 +212,7 @@ static int avrftdi_tpi_read_byte(const PROGRAMMER *pgm, unsigned char *byte) {
|
||||
frame = buffer[0] | (buffer[1] << 8);
|
||||
|
||||
err = tpi_frame2byte(frame, byte);
|
||||
pmsg_trace("Frame: 0x%04x, byte: 0x%02x\n", frame, *byte);
|
||||
pmsg_trace("frame: 0x%04x, byte: 0x%02x\n", frame, *byte);
|
||||
|
||||
//avrftdi_debug_frame(frame);
|
||||
|
||||
@@ -250,7 +250,7 @@ static void avrftdi_tpi_disable(const PROGRAMMER *pgm) {
|
||||
unsigned char cmd[] = {TPI_OP_SSTCS(TPIPCR), 0};
|
||||
pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);
|
||||
|
||||
pmsg_info("Leaving Programming mode.\n");
|
||||
pmsg_info("leaving Programming mode\n");
|
||||
}
|
||||
|
||||
#endif /* DO_NOT_BUILD_AVRFTDI */
|
||||
|
||||
2789
src/avrintel.c
2789
src/avrintel.c
File diff suppressed because it is too large
Load Diff
182
src/avrpart.c
182
src/avrpart.c
@@ -1,7 +1,9 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2022- Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
* Copyright (C) 2023- Hans Eirik Bull
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,8 +19,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
@@ -304,12 +304,43 @@ AVRMEM *avr_new_mem(void) {
|
||||
return m;
|
||||
}
|
||||
|
||||
// Create memory from name and size
|
||||
AVRMEM *avr_new_memory(const char *name, int size) {
|
||||
AVRMEM *m = (AVRMEM *) mmt_malloc(sizeof(*m));
|
||||
m->desc = cache_string(name);
|
||||
m->page_size = 1; // Ensure not 0
|
||||
m->size = size;
|
||||
m->buf = mmt_malloc(size);
|
||||
m->tags = mmt_malloc(size);
|
||||
m->initval = -1; // Unknown value represented as -1
|
||||
m->bitmask = -1; // Default to -1
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS *avr_new_memalias(void) {
|
||||
AVRMEM_ALIAS *m = (AVRMEM_ALIAS *) mmt_malloc(sizeof *m);
|
||||
m->desc = cache_string("");
|
||||
return m;
|
||||
}
|
||||
|
||||
// Return longer name of memory including alias if any, eg, fuse7/codesize
|
||||
const char *avr_mem_name(const AVRPART *p, const AVRMEM *mem) {
|
||||
char ret[1024];
|
||||
const int n = sizeof ret - 1;
|
||||
|
||||
strncpy(ret, mem->desc, n/2);
|
||||
ret[n/2] = 0;
|
||||
|
||||
AVRMEM_ALIAS *alias = avr_find_memalias(p, mem);
|
||||
if(alias && alias->desc && *alias->desc) {
|
||||
int l = strlen(ret);
|
||||
ret[l] = '/';
|
||||
strncpy(ret+l+1, alias->desc, n-l-1);
|
||||
ret[n] = 0;
|
||||
}
|
||||
return cache_string(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and initialize memory buffers for each of the device's
|
||||
@@ -462,10 +493,10 @@ AVRMEM *avr_locate_fuse_by_offset(const AVRPART *p, unsigned int off) {
|
||||
}
|
||||
|
||||
// Return the first memory that shares the type incl any fuse identified by offset in fuses
|
||||
AVRMEM *avr_locate_mem_by_type(const AVRPART *p, memtype_t type) {
|
||||
AVRMEM *avr_locate_mem_by_type(const AVRPART *p, Memtype type) {
|
||||
AVRMEM *m;
|
||||
memtype_t off = type & MEM_FUSEOFF_MASK;
|
||||
type &= ~(memtype_t) MEM_FUSEOFF_MASK;
|
||||
Memtype off = type & MEM_FUSEOFF_MASK;
|
||||
type &= ~(Memtype) MEM_FUSEOFF_MASK;
|
||||
|
||||
if(p && p->mem)
|
||||
for(LNODEID ln=lfirst(p->mem); ln; ln=lnext(ln))
|
||||
@@ -510,8 +541,16 @@ int avr_locate_upidx(const AVRPART *p) {
|
||||
return idx;
|
||||
}
|
||||
|
||||
// Return pointer to uP_table entry for part p
|
||||
const Avrintel *avr_locate_uP(const AVRPART *p) {
|
||||
int idx = avr_locate_upidx(p);
|
||||
|
||||
return idx < 0? NULL: uP_table + idx;
|
||||
}
|
||||
|
||||
|
||||
// Return pointer to config table for the part and set number of config bitfields
|
||||
const Configitem_t *avr_locate_configitems(const AVRPART *p, int *ncp) {
|
||||
const Configitem *avr_locate_configitems(const AVRPART *p, int *ncp) {
|
||||
int idx = avr_locate_upidx(p);
|
||||
if(idx < 0)
|
||||
return NULL;
|
||||
@@ -531,7 +570,7 @@ const char * const *avr_locate_isrtable(const AVRPART *p, int *nip) {
|
||||
}
|
||||
|
||||
// Return pointer to register file for the part and set number of registers
|
||||
const Register_file_t *avr_locate_register_file(const AVRPART *p, int *nrp) {
|
||||
const Register_file *avr_locate_register_file(const AVRPART *p, int *nrp) {
|
||||
int idx = avr_locate_upidx(p);
|
||||
if(idx < 0)
|
||||
return NULL;
|
||||
@@ -556,13 +595,13 @@ const Register_file_t *avr_locate_register_file(const AVRPART *p, int *nrp) {
|
||||
* though there are other registers that start with adc, eg, adc.adcsra.
|
||||
*/
|
||||
|
||||
const Register_file_t *avr_locate_register(const Register_file_t *rgf, int nr, const char *reg,
|
||||
const Register_file *avr_locate_register(const Register_file *rgf, int nr, const char *reg,
|
||||
int (*match)(const char *, const char*)) {
|
||||
|
||||
if(!rgf || nr < 1 || !reg || !match)
|
||||
return NULL;
|
||||
|
||||
const Register_file_t *ret = NULL;
|
||||
const Register_file *ret = NULL;
|
||||
int nmatches = 0, eqmatch = match == str_eq;
|
||||
|
||||
for(int i = 0; i < nr; i++) {
|
||||
@@ -597,10 +636,10 @@ const Register_file_t *avr_locate_register(const Register_file_t *rgf, int nr, c
|
||||
* behaviour can be suppressed by specifying a pattern for reg, eg, adc*
|
||||
* together with the matching function str_matched_by.
|
||||
*/
|
||||
const Register_file_t **avr_locate_registerlist(const Register_file_t *rgf, int nr, const char *reg,
|
||||
const Register_file **avr_locate_registerlist(const Register_file *rgf, int nr, const char *reg,
|
||||
int (*match)(const char *, const char*)) {
|
||||
|
||||
const Register_file_t **ret = mmt_malloc(sizeof rgf*(nr>0? nr+1: 1)), **r = ret;
|
||||
const Register_file **ret = mmt_malloc(sizeof rgf*(nr>0? nr+1: 1)), **r = ret;
|
||||
int eqmatch = match == str_eq;
|
||||
|
||||
if(rgf && reg && match)
|
||||
@@ -635,13 +674,13 @@ const Register_file_t **avr_locate_registerlist(const Register_file_t *rgf, int
|
||||
* str_matched_by etc. If name is the full name of a configuration bitfield
|
||||
* then a pointer to that is returned irrespective of the matching function.
|
||||
*/
|
||||
const Configitem_t *avr_locate_config(const Configitem_t *cfg, int nc, const char *name,
|
||||
const Configitem *avr_locate_config(const Configitem *cfg, int nc, const char *name,
|
||||
int (*match)(const char *, const char*)) {
|
||||
|
||||
if(!cfg || nc < 1 || !name || !match)
|
||||
return NULL;
|
||||
|
||||
const Configitem_t *ret = NULL;
|
||||
const Configitem *ret = NULL;
|
||||
int nmatches = 0;
|
||||
|
||||
for(int i = 0; i < nc; i++) {
|
||||
@@ -663,10 +702,10 @@ const Configitem_t *avr_locate_config(const Configitem_t *cfg, int nc, const cha
|
||||
* returned list is confined to this specific entry irrespective of the
|
||||
* matching function.
|
||||
*/
|
||||
const Configitem_t **avr_locate_configlist(const Configitem_t *cfg, int nc, const char *name,
|
||||
const Configitem **avr_locate_configlist(const Configitem *cfg, int nc, const char *name,
|
||||
int (*match)(const char *, const char*)) {
|
||||
|
||||
const Configitem_t **ret = mmt_malloc(sizeof cfg*(nc>0? nc+1: 1)), **r = ret;
|
||||
const Configitem **ret = mmt_malloc(sizeof cfg*(nc>0? nc+1: 1)), **r = ret;
|
||||
|
||||
if(cfg && name && match) {
|
||||
for(int i = 0; i < nc; i++)
|
||||
@@ -684,19 +723,19 @@ const Configitem_t **avr_locate_configlist(const Configitem_t *cfg, int nc, cons
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Return memory associated with config item and fill in pointer to Configitem_t record
|
||||
// Return memory associated with config item and fill in pointer to Configitem record
|
||||
static AVRMEM *avr_locate_config_mem_c_value(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
const char *cname, const Configitem_t **cp, int *valp) {
|
||||
const char *cname, const Configitem **cp, int *valp) {
|
||||
|
||||
int nc = 0;
|
||||
const Configitem_t *cfg = avr_locate_configitems(p, &nc);
|
||||
const Configitem *cfg = avr_locate_configitems(p, &nc);
|
||||
|
||||
if(!cfg || nc < 1) {
|
||||
pmsg_error("avrintel.c does not hold configuration information for %s\n", p->desc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const Configitem_t *c = avr_locate_config(cfg, nc, cname, str_contains);
|
||||
const Configitem *c = avr_locate_config(cfg, nc, cname, str_contains);
|
||||
if(!c) {
|
||||
pmsg_error("%s does not have a unique config item matched by %s\n", p->desc, cname);
|
||||
return NULL;
|
||||
@@ -729,20 +768,21 @@ static AVRMEM *avr_locate_config_mem_c_value(const PROGRAMMER *pgm, const AVRPAR
|
||||
|
||||
// Initialise *valuep with configuration value of named configuration bitfield
|
||||
int avr_get_config_value(const PROGRAMMER *pgm, const AVRPART *p, const char *cname, int *valuep) {
|
||||
const Configitem_t *c;
|
||||
const Configitem *c;
|
||||
int fusel;
|
||||
|
||||
if(!avr_locate_config_mem_c_value(pgm, p, cname, &c, &fusel))
|
||||
return -1;
|
||||
|
||||
*valuep = (fusel & c->mask) >> c->lsh;
|
||||
if(valuep)
|
||||
*valuep = (fusel & c->mask) >> c->lsh;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set configuration value of named configuration bitfield to value
|
||||
int avr_set_config_value(const PROGRAMMER *pgm, const AVRPART *p, const char *cname, int value) {
|
||||
AVRMEM *mem;
|
||||
const Configitem_t *c;
|
||||
const Configitem *c;
|
||||
int fusel;
|
||||
|
||||
if(!(mem=avr_locate_config_mem_c_value(pgm, p, cname, &c, &fusel)))
|
||||
@@ -766,7 +806,7 @@ int avr_set_config_value(const PROGRAMMER *pgm, const AVRPART *p, const char *cn
|
||||
|
||||
|
||||
static char *print_num(const char *fmt, int n) {
|
||||
return str_sprintf(n<10? "%d": fmt, n);
|
||||
return mmt_sprintf(n<10? "%d": fmt, n);
|
||||
}
|
||||
|
||||
static int num_len(const char *fmt, int n) {
|
||||
@@ -835,7 +875,7 @@ void avr_mem_display(FILE *f, const AVRPART *p, const char *prefix) {
|
||||
|
||||
// Create mem desc string including alias if present
|
||||
AVRMEM_ALIAS *a = avr_find_memalias(p, m);
|
||||
char *m_desc_str = str_sprintf("%s%s%s", m->desc, a? "/": "", a? a->desc: "");
|
||||
char *m_desc_str = mmt_sprintf("%s%s%s", m->desc, a? "/": "", a? a->desc: "");
|
||||
|
||||
// Print memory table content
|
||||
if(p->prog_modes & (PM_PDI | PM_UPDI)) {
|
||||
@@ -1029,12 +1069,16 @@ AVRPART *locate_part_by_avr910_devcode(const LISTID parts, int devcode) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Return pointer to first part that has signature sig (unless all 0xff or all 0x00); NULL if no match
|
||||
AVRPART *locate_part_by_signature_pm(const LISTID parts, unsigned char *sig, int sigsize, int prog_modes) {
|
||||
if(parts && sigsize == 3) {
|
||||
for(LNODEID ln=lfirst(parts); ln; ln=lnext(ln)) {
|
||||
AVRPART *p = ldata(ln);
|
||||
if(memcmp(p->signature, sig, 3) == 0 && p->prog_modes & prog_modes)
|
||||
return p;
|
||||
if(!*p->id || *p->id == '.') // Skip stump entries
|
||||
continue;
|
||||
if(!is_memset(p->signature, 0xff, 3) && !is_memset(p->signature, 0, 3))
|
||||
if(!memcmp(p->signature, sig, 3) && p->prog_modes & prog_modes)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -1044,6 +1088,48 @@ AVRPART *locate_part_by_signature(const LISTID parts, unsigned char *sig, int si
|
||||
return locate_part_by_signature_pm(parts, sig, sigsize, PM_ALL);
|
||||
}
|
||||
|
||||
// Return whether two signatures represent SW-compatible parts
|
||||
int avr_sig_compatible(const unsigned char *sig1, const unsigned char *sig2) {
|
||||
// SW-compatible parts (same memories, interrupts and regfiles) despite different signatures
|
||||
static const struct { unsigned char sig[3], equ[3]; } compat[] = {
|
||||
{{0x1e, 0x97, 0x06}, {0x1e, 0x97, 0x05}}, // ATmega1284 vs ATmega1284P
|
||||
{{0x1e, 0xa7, 0x03}, {0x1e, 0xa7, 0x02}}, // ATmega1284RFR2 vs ATmega128RFR2
|
||||
{{0x1e, 0x94, 0x0f}, {0x1e, 0x94, 0x0a}}, // ATmega164A vs ATmega164P=ATmega164PA
|
||||
{{0x1e, 0x94, 0x10}, {0x1e, 0x94, 0x07}}, // ATmega165A vs ATmega165=ATmega165=ATmega165PA
|
||||
{{0x1e, 0x94, 0x06}, {0x1e, 0x94, 0x0b}}, // ATmega168=ATmega168A vs ATmega168P=ATmega168PA
|
||||
{{0x1e, 0x94, 0x11}, {0x1e, 0x94, 0x05}}, // ATmega169A vs ATmega169=ATmega169P=ATmega169PA
|
||||
{{0x1e, 0xa8, 0x03}, {0x1e, 0xa8, 0x02}}, // ATmega2564RFR2 vs ATmega256RFR2
|
||||
{{0x1e, 0x95, 0x15}, {0x1e, 0x95, 0x08}}, // ATmega324A vs ATmega324P
|
||||
{{0x1e, 0x95, 0x15}, {0x1e, 0x95, 0x11}}, // ATmega324A vs ATmega324PA
|
||||
{{0x1e, 0x95, 0x08}, {0x1e, 0x95, 0x11}}, // ATmega324P vs ATmega324PA
|
||||
{{0x1e, 0x95, 0x06}, {0x1e, 0x95, 0x0e}}, // ATmega3250=ATmega3250A vs ATmega3250P=ATmega3250PA
|
||||
{{0x1e, 0x95, 0x05}, {0x1e, 0x95, 0x0d}}, // ATmega325=ATmega325A vs ATmega325P=ATmega325PA
|
||||
{{0x1e, 0x95, 0x04}, {0x1e, 0x95, 0x0c}}, // ATmega3290=ATmega3290A vs ATmega3290P=ATmega3290PA
|
||||
{{0x1e, 0x95, 0x03}, {0x1e, 0x95, 0x0b}}, // ATmega329=ATmega329A vs ATmega329P=ATmega329PA
|
||||
{{0x1e, 0x92, 0x05}, {0x1e, 0x92, 0x0a}}, // ATmega48=ATmega48A vs ATmega48P=ATmega48PA
|
||||
{{0x1e, 0x92, 0x05}, {0x1e, 0x92, 0x0a}}, // ATmega48=ATmega48A vs ATmega48P=ATmega48PA
|
||||
{{0x1e, 0x96, 0x09}, {0x1e, 0x96, 0x0a}}, // ATmega644=ATmega644A vs ATmega644P=ATmega644PA
|
||||
{{0x1e, 0xa6, 0x03}, {0x1e, 0xa6, 0x02}}, // ATmega644RFR2 vs ATmega64RFR2
|
||||
{{0x1e, 0x96, 0x06}, {0x1e, 0x96, 0x0e}}, // ATmega6450=ATmega6450A vs ATmega6450P
|
||||
{{0x1e, 0x96, 0x05}, {0x1e, 0x96, 0x0d}}, // ATmega645=ATmega645A vs ATmega645P
|
||||
{{0x1e, 0x96, 0x04}, {0x1e, 0x96, 0x0c}}, // ATmega6490=ATmega6490A vs ATmega6490P
|
||||
{{0x1e, 0x96, 0x03}, {0x1e, 0x96, 0x0b}}, // ATmega649=ATmega649A vs ATmega649P
|
||||
{{0x1e, 0x93, 0x0a}, {0x1e, 0x93, 0x0f}}, // ATmega88=ATmega88A=ATA6612C vs ATmega88P=ATmega88PA
|
||||
};
|
||||
|
||||
if(!memcmp(sig1, sig2, 3))
|
||||
return 1;
|
||||
|
||||
for(size_t i = 0; i < sizeof compat/sizeof *compat; i++) {
|
||||
if(!memcmp(sig1, compat[i].sig, 3) && !memcmp(sig2, compat[i].equ, 3))
|
||||
return 1;
|
||||
if(!memcmp(sig2, compat[i].sig, 3) && !memcmp(sig1, compat[i].equ, 3))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over the list of avrparts given as "avrparts", and
|
||||
* call the callback function cb for each entry found. cb is being
|
||||
@@ -1066,7 +1152,7 @@ void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie)
|
||||
}
|
||||
|
||||
/*
|
||||
* Compare function to sort the list of programmers
|
||||
* Compare function to sort a list of parts
|
||||
*/
|
||||
static int sort_avrparts_compare(const AVRPART *p1, const AVRPART *p2) {
|
||||
if(p1 == NULL || p1->desc == NULL || p2 == NULL || p2->desc == NULL)
|
||||
@@ -1076,51 +1162,17 @@ static int sort_avrparts_compare(const AVRPART *p1, const AVRPART *p2) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Sort the list of programmers given as "programmers"
|
||||
* Sort the list avrparts of parts
|
||||
*/
|
||||
void sort_avrparts(LISTID avrparts)
|
||||
{
|
||||
lsort(avrparts,(int (*)(void*, void*)) sort_avrparts_compare);
|
||||
}
|
||||
|
||||
const char *avr_prog_modes_str(int pm) {
|
||||
static char type[1024];
|
||||
|
||||
strcpy(type, "0");
|
||||
if(pm & PM_TPI)
|
||||
strcat(type, ", TPI");
|
||||
if(pm & PM_ISP)
|
||||
strcat(type, ", ISP");
|
||||
if(pm & PM_PDI)
|
||||
strcat(type, ", PDI");
|
||||
if(pm & PM_UPDI)
|
||||
strcat(type, ", UPDI");
|
||||
if(pm & PM_HVSP)
|
||||
strcat(type, ", HVSP");
|
||||
if(pm & PM_HVPP)
|
||||
strcat(type, ", HVPP");
|
||||
if(pm & PM_debugWIRE)
|
||||
strcat(type, ", debugWIRE");
|
||||
if(pm & PM_JTAG)
|
||||
strcat(type, ", JTAG");
|
||||
if(pm & PM_JTAGmkI)
|
||||
strcat(type, ", JTAGmkI");
|
||||
if(pm & PM_XMEGAJTAG)
|
||||
strcat(type, ", XMEGAJTAG");
|
||||
if(pm & PM_AVR32JTAG)
|
||||
strcat(type, ", AVR32JTAG");
|
||||
if(pm & PM_aWire)
|
||||
strcat(type, ", aWire");
|
||||
if(pm & PM_SPM)
|
||||
strcat(type, ", SPM");
|
||||
|
||||
return type + (type[1] == 0? 0: 3);
|
||||
}
|
||||
|
||||
|
||||
void avr_display(FILE *f, const AVRPART *p, const char *prefix, int verbose) {
|
||||
fprintf(f, "%sAVR Part : %s\n", prefix, p->desc);
|
||||
fprintf(f, "%sProgramming modes : %s\n", prefix, avr_prog_modes_str(p->prog_modes));
|
||||
fprintf(f, "%sAVR part : %s\n", prefix, p->desc);
|
||||
fprintf(f, "%sProgramming modes : %s\n", prefix, str_prog_modes(p->prog_modes));
|
||||
|
||||
if(verbose > 1) {
|
||||
avr_mem_display(f, p, prefix);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
|
||||
* Copyright (C) 2011 Darell Tan <darell.tan@gmail.com>
|
||||
*
|
||||
@@ -17,7 +17,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
@@ -44,21 +43,12 @@
|
||||
#include "tpi.h"
|
||||
#include "bitbang.h"
|
||||
|
||||
static int delay_decrement;
|
||||
|
||||
#if defined(WIN32)
|
||||
static int has_perfcount;
|
||||
static LARGE_INTEGER freq;
|
||||
#define freq (*(LARGE_INTEGER *)&cx->bb_freq)
|
||||
#else
|
||||
static volatile int done;
|
||||
|
||||
typedef void (*mysighandler_t)(int);
|
||||
static mysighandler_t saved_alarmhandler;
|
||||
|
||||
static void alarmhandler(int signo)
|
||||
{
|
||||
done = 1;
|
||||
signal(SIGALRM, saved_alarmhandler);
|
||||
static void alarmhandler(int signo) {
|
||||
*(volatile int *)&cx->bb_done = 1;
|
||||
signal(SIGALRM, cx->bb_saved_alarmf);
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
@@ -75,7 +65,7 @@ static void bitbang_calibrate_delay(void)
|
||||
*/
|
||||
if (QueryPerformanceFrequency(&freq))
|
||||
{
|
||||
has_perfcount = 1;
|
||||
cx->bb_has_perfcount = 1;
|
||||
pmsg_notice2("using performance counter for bitbang delays\n");
|
||||
}
|
||||
else
|
||||
@@ -90,7 +80,7 @@ static void bitbang_calibrate_delay(void)
|
||||
* comparable hardware.
|
||||
*/
|
||||
pmsg_notice2("using guessed per-microsecond delay count for bitbang delays\n");
|
||||
delay_decrement = 100;
|
||||
cx->bb_delay_decrement = 100;
|
||||
}
|
||||
#else /* !WIN32 */
|
||||
struct itimerval itv;
|
||||
@@ -98,8 +88,8 @@ static void bitbang_calibrate_delay(void)
|
||||
|
||||
pmsg_notice2("calibrating delay loop ...");
|
||||
i = 0;
|
||||
done = 0;
|
||||
saved_alarmhandler = signal(SIGALRM, alarmhandler);
|
||||
*(volatile int *)&cx->bb_done = 0;
|
||||
cx->bb_saved_alarmf = signal(SIGALRM, alarmhandler);
|
||||
/*
|
||||
* Set ITIMER_REAL to 100 ms. All known systems have a timer
|
||||
* granularity of 10 ms or better, so counting the delay cycles
|
||||
@@ -114,16 +104,15 @@ static void bitbang_calibrate_delay(void)
|
||||
itv.it_value.tv_usec = 100000;
|
||||
itv.it_interval.tv_sec = itv.it_interval.tv_usec = 0;
|
||||
setitimer(ITIMER_REAL, &itv, 0);
|
||||
while (!done)
|
||||
while (!*(volatile int *)&cx->bb_done)
|
||||
i--;
|
||||
itv.it_value.tv_sec = itv.it_value.tv_usec = 0;
|
||||
setitimer(ITIMER_REAL, &itv, 0);
|
||||
/*
|
||||
* Calculate back from 100 ms to 1 us.
|
||||
*/
|
||||
delay_decrement = -i / 100000;
|
||||
msg_notice2(" calibrated to %d cycles per us\n",
|
||||
delay_decrement);
|
||||
cx->bb_delay_decrement = -i / 100000;
|
||||
msg_notice2(" calibrated to %d cycles per us\n", cx->bb_delay_decrement);
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
@@ -137,7 +126,7 @@ void bitbang_delay(unsigned int us)
|
||||
#if defined(WIN32)
|
||||
LARGE_INTEGER countNow, countEnd;
|
||||
|
||||
if (has_perfcount)
|
||||
if (cx->bb_has_perfcount)
|
||||
{
|
||||
QueryPerformanceCounter(&countNow);
|
||||
countEnd.QuadPart = countNow.QuadPart + freq.QuadPart * us / 1000000ll;
|
||||
@@ -148,7 +137,7 @@ void bitbang_delay(unsigned int us)
|
||||
else /* no performance counters -- run normal uncalibrated delay */
|
||||
{
|
||||
#endif /* WIN32 */
|
||||
volatile unsigned int del = us * delay_decrement;
|
||||
volatile unsigned int del = us * cx->bb_delay_decrement;
|
||||
|
||||
while (del > 0)
|
||||
del--;
|
||||
@@ -323,17 +312,17 @@ int bitbang_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||
res[i] = bitbang_txrx(pgm, cmd[i]);
|
||||
}
|
||||
|
||||
if(verbose >= 2)
|
||||
if(verbose >= MSG_DEBUG)
|
||||
{
|
||||
msg_notice2("bitbang_cmd(): [ ");
|
||||
msg_debug("%s(): [ ", __func__);
|
||||
for(i = 0; i < 4; i++)
|
||||
msg_notice2("%02X ", cmd[i]);
|
||||
msg_notice2("] [ ");
|
||||
msg_debug("%02X ", cmd[i]);
|
||||
msg_debug("] [ ");
|
||||
for(i = 0; i < 4; i++)
|
||||
{
|
||||
msg_notice2("%02X ", res[i]);
|
||||
msg_debug("%02X ", res[i]);
|
||||
}
|
||||
msg_notice2("]\n");
|
||||
msg_debug("]\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -356,17 +345,17 @@ int bitbang_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||
res[i] = r;
|
||||
}
|
||||
|
||||
if(verbose >= 2)
|
||||
if(verbose >= MSG_DEBUG)
|
||||
{
|
||||
msg_notice2("bitbang_cmd_tpi(): [ ");
|
||||
msg_debug("%s(): [ ", __func__);
|
||||
for(i = 0; i < cmd_len; i++)
|
||||
msg_notice2("%02X ", cmd[i]);
|
||||
msg_notice2("] [ ");
|
||||
msg_debug("%02X ", cmd[i]);
|
||||
msg_debug("] [ ");
|
||||
for(i = 0; i < res_len; i++)
|
||||
{
|
||||
msg_notice2("%02X ", res[i]);
|
||||
msg_debug("%02X ", res[i]);
|
||||
}
|
||||
msg_notice2("]\n");
|
||||
msg_debug("]\n");
|
||||
}
|
||||
|
||||
if (r == -1)
|
||||
@@ -391,17 +380,17 @@ int bitbang_spi(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||
|
||||
pgm->setpin(pgm, PIN_LED_PGM, 1);
|
||||
|
||||
if(verbose >= 2)
|
||||
if(verbose >= MSG_DEBUG)
|
||||
{
|
||||
msg_notice2("bitbang_cmd(): [ ");
|
||||
msg_debug("%s(): [ ", __func__);
|
||||
for(i = 0; i < count; i++)
|
||||
msg_notice2("%02X ", cmd[i]);
|
||||
msg_notice2("] [ ");
|
||||
msg_debug("%02X ", cmd[i]);
|
||||
msg_debug("] [ ");
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
msg_notice2("%02X ", res[i]);
|
||||
msg_debug("%02X ", res[i]);
|
||||
}
|
||||
msg_notice2("]\n");
|
||||
msg_debug("]\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
|
||||
* Copyright (C) 2011 Darell Tan <darell.tan@gmail.com>
|
||||
*
|
||||
@@ -17,7 +17,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef bitbang_h
|
||||
#define bitbang_h
|
||||
|
||||
113
src/buspirate.c
113
src/buspirate.c
@@ -33,8 +33,6 @@
|
||||
* Tested with BusPirate PTH, firmware version 2.1 programming ATmega328P
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -204,7 +202,7 @@ static char *buspirate_readline_noexit(const PROGRAMMER *pgm, char *buf, size_t
|
||||
serial_recv_timeout = PDATA(pgm)->serial_recv_timeout;
|
||||
}
|
||||
serial_recv_timeout = orig_serial_recv_timeout;
|
||||
pmsg_debug("buspirate_readline(): %s%s", buf, *buf && buf[strlen(buf)-1] == '\n'? "": "\n");
|
||||
pmsg_debug("%s(): %s%s", __func__, buf, *buf && buf[strlen(buf)-1] == '\n'? "": "\n");
|
||||
if (! buf[0])
|
||||
return NULL;
|
||||
|
||||
@@ -226,7 +224,7 @@ static int buspirate_send(const PROGRAMMER *pgm, const char *str) {
|
||||
int rc;
|
||||
const char * readline;
|
||||
|
||||
pmsg_debug("buspirate_send(): %s", str);
|
||||
pmsg_debug("%s(): %s", __func__, str);
|
||||
|
||||
if (PDATA(pgm)->flag & BP_FLAG_IN_BINMODE) {
|
||||
pmsg_error("called from binmode\n");
|
||||
@@ -288,17 +286,18 @@ static void buspirate_dummy_6(const PROGRAMMER *pgm, const char *p) {
|
||||
|
||||
/* ====== Config / parameters handling functions ====== */
|
||||
static int buspirate_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
int rv = 0;
|
||||
char reset[10];
|
||||
char *preset = reset; /* for strtok() */
|
||||
unsigned int spifreq;
|
||||
unsigned int rawfreq;
|
||||
unsigned int cpufreq;
|
||||
int serial_recv_timeout;
|
||||
bool help = false;
|
||||
|
||||
for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
if (str_eq(extended_param, "ascii")) {
|
||||
PDATA(pgm)->flag |= BP_FLAG_XPARM_FORCE_ASCII;
|
||||
continue;
|
||||
@@ -316,13 +315,14 @@ static int buspirate_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
|
||||
if (sscanf(extended_param, "spifreq=%u", &spifreq) == 1) {
|
||||
if (spifreq & (~0x07)) {
|
||||
pmsg_error("spifreq must be between 0 and 7\n");
|
||||
imsg_error("see BusPirate manual for details\n");
|
||||
return -1;
|
||||
pmsg_error("spifreq must be between 0 and 7; see BusPirate manual for details\n");
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
if (PDATA(pgm)->flag & BP_FLAG_XPARM_RAWFREQ) {
|
||||
pmsg_error("set either spifreq or rawfreq\n");
|
||||
return -1;
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
PDATA(pgm)->flag |= BP_FLAG_XPARM_SPIFREQ;
|
||||
PDATA(pgm)->spifreq = spifreq;
|
||||
@@ -332,11 +332,13 @@ static int buspirate_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
if (sscanf(extended_param, "rawfreq=%u", &rawfreq) == 1) {
|
||||
if (rawfreq >= 4) {
|
||||
pmsg_error("rawfreq must be between 0 and 3\n");
|
||||
return -1;
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
if (PDATA(pgm)->flag & BP_FLAG_XPARM_SPIFREQ) {
|
||||
pmsg_error("set either spifreq or rawfreq\n");
|
||||
return -1;
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
PDATA(pgm)->flag |= BP_FLAG_XPARM_RAWFREQ;
|
||||
PDATA(pgm)->spifreq = rawfreq;
|
||||
@@ -346,9 +348,9 @@ static int buspirate_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
if (sscanf(extended_param, "cpufreq=%u", &cpufreq) == 1) {
|
||||
/* lower limit comes from 'cpufreq > 4 * spifreq', spifreq in ascii mode is 30kHz. */
|
||||
if (cpufreq < 125 || cpufreq > 4000) {
|
||||
pmsg_error("cpufreq must be between 125 and 4000 kHz\n");
|
||||
imsg_error("see BusPirate manual for details\n");
|
||||
return -1;
|
||||
pmsg_error("cpufreq must be between 125 and 4000 kHz; see BusPirate manual for details\n");
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
PDATA(pgm)->cpufreq = cpufreq;
|
||||
PDATA(pgm)->flag |= BP_FLAG_XPARM_CPUFREQ;
|
||||
@@ -366,8 +368,9 @@ static int buspirate_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
else if (str_caseeq(resetpin, "aux2"))
|
||||
PDATA(pgm)->reset |= BP_RESET_AUX2;
|
||||
else {
|
||||
pmsg_error("reset must be either CS or AUX\n");
|
||||
return -1;
|
||||
pmsg_error("-x reset= value must be either CS, AUX or AUX2\n");
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
PDATA(pgm)->flag |= BP_FLAG_XPARM_RESET;
|
||||
@@ -387,33 +390,38 @@ static int buspirate_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
if (sscanf(extended_param, "serial_recv_timeout=%d", &serial_recv_timeout) == 1) {
|
||||
if (serial_recv_timeout < 1) {
|
||||
pmsg_error("serial_recv_timeout must be greater 0\n");
|
||||
return -1;
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
PDATA(pgm)->serial_recv_timeout = serial_recv_timeout;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -xreset=cs,aux,aux2 Override default reset pin\n");
|
||||
msg_error(" -xspifreq=<0..7> Set binary SPI mode speed\n");
|
||||
msg_error(" -xrawfreq=<0..3> Set \"raw-wire\" SPI mode speed\n");
|
||||
msg_error(" -xascii Use ASCII protocol between BP and Avrdude\n");
|
||||
msg_error(" -xnopagedwrite Disable page write functionality\n");
|
||||
msg_error(" -xnopagedread Disable page read functionality\n");
|
||||
msg_error(" -xcpufreq=<125..4000> Set the AUX pin to output a frequency to n [kHz]\n");
|
||||
msg_error(" -xserial_recv_timeout=<arg> Set serial receive timeout to <arg> [ms]\n");
|
||||
msg_error(" -xpullups Enable internal pull-ups\n");
|
||||
msg_error(" -xhiz SPI HiZ mode (open collector)\n");
|
||||
msg_error(" -xhelp Show this help menu and exit\n");
|
||||
return LIBAVRDUDE_EXIT;;
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
pmsg_error("do not understand extended param '%s'\n", extended_param);
|
||||
return -1;
|
||||
if (!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x reset=[cs|aux|aux2] Override default reset pin\n");
|
||||
msg_error(" -x spifreq=<0..7> Set binary SPI mode speed\n");
|
||||
msg_error(" -x rawfreq=<0..3> Set \"raw-wire\" SPI mode speed\n");
|
||||
msg_error(" -x ascii Use ASCII protocol between BP and Avrdude\n");
|
||||
msg_error(" -x nopagedwrite Disable page write functionality\n");
|
||||
msg_error(" -x nopagedread Disable page read functionality\n");
|
||||
msg_error(" -x cpufreq=<125..4000> Set the AUX pin to output a frequency to <n> kHz\n");
|
||||
msg_error(" -x serial_recv_timeout=<n> Set serial receive timeout to <n> ms\n");
|
||||
msg_error(" -x pullups Enable internal pull-ups\n");
|
||||
msg_error(" -x hiz SPI HiZ mode (open collector)\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int buspirate_verifyconfig(const PROGRAMMER *pgm) {
|
||||
@@ -503,7 +511,7 @@ static void buspirate_reset_from_binmode(const PROGRAMMER *pgm) {
|
||||
return;
|
||||
}
|
||||
|
||||
msg_notice("BusPirate is back in text mode\n");
|
||||
msg_notice2("BusPirate is back in text mode\n");
|
||||
}
|
||||
|
||||
static int buspirate_start_mode_bin(PROGRAMMER *pgm)
|
||||
@@ -548,11 +556,11 @@ static int buspirate_start_mode_bin(PROGRAMMER *pgm)
|
||||
memset(buf, 0, sizeof(buf));
|
||||
buspirate_recv_bin(pgm, buf, 5);
|
||||
if (sscanf((const char*)buf, "BBIO%1d", &PDATA(pgm)->binmode_version) != 1) {
|
||||
pmsg_error("binary mode not confirmed: '%s'\n", buf);
|
||||
pmsg_error("binary mode not confirmed: %s\n", buf);
|
||||
buspirate_reset_from_binmode(pgm);
|
||||
return -1;
|
||||
}
|
||||
msg_notice("BusPirate binmode version: %d\n",
|
||||
msg_notice2("BusPirate binmode version: %d\n",
|
||||
PDATA(pgm)->binmode_version);
|
||||
|
||||
PDATA(pgm)->flag |= BP_FLAG_IN_BINMODE;
|
||||
@@ -564,7 +572,7 @@ static int buspirate_start_mode_bin(PROGRAMMER *pgm)
|
||||
pwm_period = 16000/(PDATA(pgm)->cpufreq) - 1; // oscillator runs at 32MHz, we don't use a prescaler
|
||||
pwm_duty = pwm_period/2; // 50% duty cycle
|
||||
|
||||
msg_notice("setting up PWM for cpufreq\n");
|
||||
msg_notice2("setting up PWM for cpufreq\n");
|
||||
msg_debug("PWM settings: Prescaler=1, Duty Cycle=%hd, Period=%hd\n", pwm_duty, pwm_period);
|
||||
|
||||
buf[0] = 0x12; // pwm setup
|
||||
@@ -586,14 +594,14 @@ static int buspirate_start_mode_bin(PROGRAMMER *pgm)
|
||||
memset(buf, 0, sizeof(buf));
|
||||
buspirate_recv_bin(pgm, buf, 4);
|
||||
if (sscanf((const char*)buf, submode.entered_format, &PDATA(pgm)->submode_version) != 1) {
|
||||
pmsg_error("%s mode not confirmed: '%s'\n", submode.name, buf);
|
||||
pmsg_error("%s mode not confirmed: %s\n", submode.name, buf);
|
||||
buspirate_reset_from_binmode(pgm);
|
||||
return -1;
|
||||
}
|
||||
msg_notice("BusPirate %s version: %d\n",
|
||||
msg_notice2("BusPirate %s version: %d\n",
|
||||
submode.name, PDATA(pgm)->submode_version);
|
||||
if (PDATA(pgm)->flag & BP_FLAG_NOPAGEDWRITE) {
|
||||
pmsg_notice("paged flash write disabled\n");
|
||||
pmsg_notice2("paged flash write disabled\n");
|
||||
pgm->paged_write = NULL;
|
||||
} else {
|
||||
/* Check for write-then-read without !CS/CS and disable paged_write if absent: */
|
||||
@@ -609,7 +617,7 @@ static int buspirate_start_mode_bin(PROGRAMMER *pgm)
|
||||
buf[0] = 0x1;
|
||||
buspirate_send_bin(pgm, buf, 1);
|
||||
|
||||
pmsg_notice("disabling paged flash write (need BusPirate firmware >= v5.10)\n");
|
||||
pmsg_notice2("disabling paged flash write (need BusPirate firmware >= v5.10)\n");
|
||||
|
||||
/* Flush serial buffer: */
|
||||
serial_drain(&pgm->fd, 0);
|
||||
@@ -640,7 +648,7 @@ static int buspirate_start_mode_bin(PROGRAMMER *pgm)
|
||||
|
||||
/* AVR Extended Commands - test for existence */
|
||||
if (PDATA(pgm)->flag & BP_FLAG_NOPAGEDREAD) {
|
||||
pmsg_notice("paged flash read disabled\n");
|
||||
pmsg_notice2("paged flash read disabled\n");
|
||||
pgm->paged_load = NULL;
|
||||
} else {
|
||||
int rv = buspirate_expect_bin_byte(pgm, 0x06, 0x01);
|
||||
@@ -652,9 +660,9 @@ static int buspirate_start_mode_bin(PROGRAMMER *pgm)
|
||||
buspirate_send_bin(pgm, buf2, sizeof(buf2));
|
||||
buspirate_recv_bin(pgm, buf, 3);
|
||||
ver = buf[1] << 8 | buf[2];
|
||||
msg_notice("AVR Extended Commands version %d\n", ver);
|
||||
msg_notice2("AVR Extended Commands version %d\n", ver);
|
||||
} else {
|
||||
msg_notice("AVR Extended Commands not found\n");
|
||||
msg_notice2("AVR Extended Commands not found\n");
|
||||
PDATA(pgm)->flag |= BP_FLAG_NOPAGEDREAD;
|
||||
pgm->paged_load = NULL;
|
||||
}
|
||||
@@ -685,7 +693,7 @@ static int buspirate_start_spi_mode_ascii(const PROGRAMMER *pgm) {
|
||||
}
|
||||
if (spi_cmd == -1) {
|
||||
pmsg_error("SPI mode number not found; does your BusPirate support SPI?\n");
|
||||
imsg_error("try powercycling your BusPirate and try again\n");
|
||||
pmsg_error("try powercycling your BusPirate and try again\n");
|
||||
return -1;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%d\n", spi_cmd);
|
||||
@@ -826,8 +834,7 @@ static void buspirate_powerup(const PROGRAMMER *pgm) {
|
||||
}
|
||||
}
|
||||
|
||||
pmsg_warning("did not get a response to PowerUp command\n");
|
||||
imsg_warning("trying to continue anyway ...\n");
|
||||
pmsg_warning("did not get a response to PowerUp command; trying to continue anyway ...\n");
|
||||
}
|
||||
|
||||
static void buspirate_powerdown(const PROGRAMMER *pgm) {
|
||||
@@ -920,7 +927,7 @@ static int buspirate_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const A
|
||||
unsigned char buf[275];
|
||||
unsigned int addr = 0;
|
||||
|
||||
msg_notice("buspirate_paged_load(..,%s,%d,%d,%d)\n",m->desc,m->page_size,address,n_bytes);
|
||||
msg_debug("buspirate_paged_load(..,%s,%d,%d,%d)\n",m->desc,m->page_size,address,n_bytes);
|
||||
|
||||
// This should never happen, but still ...
|
||||
if (PDATA(pgm)->flag & BP_FLAG_NOPAGEDREAD) {
|
||||
@@ -954,7 +961,7 @@ static int buspirate_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const A
|
||||
buspirate_recv_bin(pgm, buf, 1);
|
||||
|
||||
if (buf[0] != 0x01) {
|
||||
pmsg_error("Paged Read command returned zero\n");
|
||||
pmsg_error("paged read command returned zero\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1181,7 +1188,7 @@ static void buspirate_bb_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
buspirate_recv_bin(pgm, buf, 5);
|
||||
if (sscanf((char*)buf, "BBIO%1d", &PDATA(pgm)->binmode_version) != 1) {
|
||||
pmsg_error("binary mode not confirmed: '%s'\n", buf);
|
||||
pmsg_error("binary mode not confirmed: %s\n", buf);
|
||||
buspirate_reset_from_binmode(pgm);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef buspirate_h
|
||||
#define buspirate_h
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2005, 2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* avrdude interface for the serial programming mode of the Atmel butterfly
|
||||
* evaluation board. This board features a bootloader which uses a protocol
|
||||
@@ -60,6 +58,7 @@ struct pdata
|
||||
int ctype; // Cache one byte for flash
|
||||
unsigned char cvalue;
|
||||
unsigned long caddr;
|
||||
bool autoreset;
|
||||
};
|
||||
|
||||
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
|
||||
@@ -316,7 +315,7 @@ static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
|
||||
if (c == 0)
|
||||
break;
|
||||
msg_notice2(" Device code: 0x%02x\n", (unsigned int) (unsigned char) c);
|
||||
msg_notice2(" Device code: 0x%02x\n", (unsigned char) c);
|
||||
};
|
||||
msg_notice2("\n");
|
||||
|
||||
@@ -361,9 +360,8 @@ static void butterfly_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||
static int butterfly_open(PROGRAMMER *pgm, const char *port) {
|
||||
union pinfo pinfo;
|
||||
pgm->port = port;
|
||||
/*
|
||||
* If baudrate was not specified use 19200 Baud
|
||||
*/
|
||||
|
||||
// If baudrate was not specified use 19200 Baud
|
||||
if(pgm->baudrate == 0) {
|
||||
pgm->baudrate = 19200;
|
||||
}
|
||||
@@ -373,9 +371,22 @@ static int butterfly_open(PROGRAMMER *pgm, const char *port) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* drain any extraneous input
|
||||
*/
|
||||
if(PDATA(pgm)->autoreset) {
|
||||
// This code assumes a negative-logic USB to TTL serial adapter
|
||||
// Set RTS/DTR high to discharge the series-capacitor, if present
|
||||
pmsg_notice2("toggling the DTR/RTS lines to trigger a hardware reset\n");
|
||||
serial_set_dtr_rts(&pgm->fd, 0);
|
||||
usleep(250 * 1000);
|
||||
// Pull the RTS/DTR line low to reset AVR
|
||||
serial_set_dtr_rts(&pgm->fd, 1);
|
||||
// Max 100 us: charging a cap longer creates a high reset spike above Vcc
|
||||
usleep(100);
|
||||
// Set the RTS/DTR line back to high, so direct connection to reset works
|
||||
serial_set_dtr_rts(&pgm->fd, 0);
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
|
||||
// Drain any extraneous input
|
||||
(void) butterfly_drain(pgm, 0);
|
||||
|
||||
return 0;
|
||||
@@ -491,7 +502,9 @@ static int butterfly_read_byte_flash(const PROGRAMMER *pgm, const AVRPART *p, co
|
||||
unsigned long addr, unsigned char * value)
|
||||
{
|
||||
int ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
|
||||
char mtype = mem_is_flash(m)? 'F': mem_is_sigrow(m)? 'P': mem_is_userrow(m)? 'U': '?';
|
||||
char mtype = mem_is_flash(m)? 'F': mem_is_in_sigrow(m)? 'P': mem_is_userrow(m)? 'U': '?';
|
||||
|
||||
addr += avr_sigrow_offset(p, m, addr);
|
||||
|
||||
if(mtype == '?') {
|
||||
pmsg_error("cannot read memory %s\n", m->desc);
|
||||
@@ -533,7 +546,7 @@ static int butterfly_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
{
|
||||
char cmd;
|
||||
|
||||
if (mem_is_flash(m) || mem_is_sigrow(m) || mem_is_userrow(m)) {
|
||||
if (mem_is_flash(m) || mem_is_in_sigrow(m) || mem_is_userrow(m)) {
|
||||
return butterfly_read_byte_flash(pgm, p, m, addr, value);
|
||||
}
|
||||
|
||||
@@ -679,6 +692,37 @@ static int butterfly_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, con
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int butterfly_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
const char *extended_param;
|
||||
int rv = 0;
|
||||
bool help = 0;
|
||||
|
||||
for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
|
||||
if(str_eq(extended_param, "autoreset")) {
|
||||
PDATA(pgm)->autoreset = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_eq(extended_param, "help")) {
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
if (!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x autoreset Toggle RTS/DTR lines on port open to issue a hardware reset\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
const char butterfly_desc[] = "Atmel Butterfly evaluation board; Atmel AppNotes AVR109, AVR911";
|
||||
|
||||
void butterfly_initpgm(PROGRAMMER *pgm) {
|
||||
@@ -712,7 +756,7 @@ void butterfly_initpgm(PROGRAMMER *pgm) {
|
||||
pgm->paged_load = butterfly_paged_load;
|
||||
|
||||
pgm->read_sig_bytes = butterfly_read_sig_bytes;
|
||||
|
||||
pgm->parseextparams = butterfly_parseextparms;
|
||||
pgm->setup = butterfly_setup;
|
||||
pgm->teardown = butterfly_teardown;
|
||||
pgm->flag = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef butterfly_h
|
||||
#define butterfly_h
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
*
|
||||
* avrdude support for CH341A/B
|
||||
* Copyright (C) 2016 Alexey Sadkov, paged access by smr 2023
|
||||
* Copyright (C) 2016 Alexey Sadkov, paged access by smr 2023
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -333,7 +333,7 @@ static int ch341a_spi_cmd(const PROGRAMMER *pgm, const unsigned char *cmd, unsig
|
||||
}
|
||||
|
||||
|
||||
static int ch341a_spi_chip_erase(const struct programmer_t *pgm, const AVRPART *p) {
|
||||
static int ch341a_spi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
unsigned char cmd[4];
|
||||
unsigned char res[4];
|
||||
|
||||
@@ -477,12 +477,12 @@ void ch341a_initpgm(PROGRAMMER *pgm) {
|
||||
// ----------------------------------------------------------------------
|
||||
#else // !defined(HAVE_LIBUSB_1_0)
|
||||
|
||||
static int ch341a_nousb_open(struct programmer_t *pgm, const char *name) {
|
||||
static int ch341a_nousb_open(PROGRAMMER *pgm, const char *name) {
|
||||
pmsg_error("no usb support, please compile again with libusb installed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ch341a_initpgm(PROGRAMMER * pgm) {
|
||||
void ch341a_initpgm(PROGRAMMER *pgm) {
|
||||
strcpy(pgm->type, "ch341a");
|
||||
pgm->open = ch341a_nousb_open;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
*
|
||||
* avrdude support for CH341A/B
|
||||
* Copyright (C) 2016 Alexey Sadkov
|
||||
* Copyright (C) 2016 Alexey Sadkov
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
267
src/config.c
267
src/config.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2022 Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <errno.h>
|
||||
@@ -28,6 +26,7 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
@@ -46,27 +45,27 @@ double default_bitclock;
|
||||
char const *default_linuxgpio;
|
||||
int allow_subshells;
|
||||
|
||||
LISTID string_list;
|
||||
LISTID number_list;
|
||||
PROGRAMMER * current_prog;
|
||||
AVRPART * current_part;
|
||||
AVRMEM * current_mem;
|
||||
int current_strct;
|
||||
LISTID part_list;
|
||||
LISTID programmers;
|
||||
bool is_alias;
|
||||
LISTID string_list;
|
||||
LISTID number_list;
|
||||
PROGRAMMER *current_prog;
|
||||
AVRPART *current_part;
|
||||
AVRMEM *current_mem;
|
||||
int current_strct;
|
||||
LISTID part_list;
|
||||
LISTID programmers;
|
||||
bool is_alias;
|
||||
|
||||
int cfg_lineno;
|
||||
char * cfg_infile;
|
||||
int cfg_lineno;
|
||||
char *cfg_infile;
|
||||
|
||||
extern char * yytext;
|
||||
extern char *yytext;
|
||||
|
||||
#define pgm_comp_desc(x, type) { #x, COMP_PROGRAMMER, offsetof(PROGRAMMER, x), sizeof(((PROGRAMMER *) NULL)->x), type }
|
||||
#define part_comp_desc(x, type) { #x, COMP_AVRPART, offsetof(AVRPART, x), sizeof(((AVRPART *) NULL)->x), type }
|
||||
#define mem_comp_desc(x, type) { #x, COMP_AVRMEM, offsetof(AVRMEM, x), sizeof(((AVRMEM *) NULL)->x), type }
|
||||
|
||||
// Component description for config_gram.y, will be sorted appropriately on first use
|
||||
Component_t avr_comp[] = {
|
||||
Component avr_comp[] = {
|
||||
// PROGRAMMER
|
||||
pgm_comp_desc(desc, COMP_STRING),
|
||||
pgm_comp_desc(prog_modes, COMP_INT),
|
||||
@@ -84,6 +83,7 @@ Component_t avr_comp[] = {
|
||||
part_comp_desc(family_id, COMP_STRING),
|
||||
part_comp_desc(prog_modes, COMP_INT),
|
||||
part_comp_desc(mcuid, COMP_INT),
|
||||
part_comp_desc(archnum, COMP_INT),
|
||||
part_comp_desc(n_interrupts, COMP_INT),
|
||||
part_comp_desc(n_page_erase, COMP_INT),
|
||||
part_comp_desc(n_boot_sections, COMP_INT),
|
||||
@@ -228,8 +228,7 @@ int yywrap()
|
||||
}
|
||||
|
||||
|
||||
int yyerror(char * errmsg, ...)
|
||||
{
|
||||
int yyerror(char *errmsg, ...) {
|
||||
va_list args;
|
||||
|
||||
char message[512];
|
||||
@@ -245,8 +244,7 @@ int yyerror(char * errmsg, ...)
|
||||
}
|
||||
|
||||
|
||||
int yywarning(char * errmsg, ...)
|
||||
{
|
||||
int yywarning(char *errmsg, ...) {
|
||||
va_list args;
|
||||
|
||||
char message[512];
|
||||
@@ -262,15 +260,14 @@ int yywarning(char * errmsg, ...)
|
||||
}
|
||||
|
||||
|
||||
TOKEN * new_token(int primary) {
|
||||
TOKEN * tkn = (TOKEN *) mmt_malloc(sizeof(TOKEN));
|
||||
TOKEN *new_token(int primary) {
|
||||
TOKEN *tkn = (TOKEN *) mmt_malloc(sizeof(TOKEN));
|
||||
tkn->primary = primary;
|
||||
return tkn;
|
||||
}
|
||||
|
||||
|
||||
void free_token(TOKEN * tkn)
|
||||
{
|
||||
void free_token(TOKEN *tkn) {
|
||||
if (tkn) {
|
||||
switch (tkn->value.type) {
|
||||
case V_STR:
|
||||
@@ -287,7 +284,7 @@ void free_token(TOKEN * tkn)
|
||||
|
||||
void free_tokens(int n, ...)
|
||||
{
|
||||
TOKEN * t;
|
||||
TOKEN *t;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, n);
|
||||
@@ -299,10 +296,9 @@ void free_tokens(int n, ...)
|
||||
}
|
||||
|
||||
|
||||
|
||||
TOKEN *new_number(const char *text) {
|
||||
const char *errstr;
|
||||
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||
TOKEN *tkn = new_token(TKN_NUMBER);
|
||||
tkn->value.type = V_NUM;
|
||||
tkn->value.number = str_int(text, STR_INT32, &errstr);
|
||||
if(errstr) {
|
||||
@@ -312,7 +308,7 @@ TOKEN *new_number(const char *text) {
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
msg_info("NUMBER(%d)\n", tkn->value.number);
|
||||
msg_notice("NUMBER(%d)\n", tkn->value.number);
|
||||
#endif
|
||||
|
||||
return tkn;
|
||||
@@ -320,7 +316,7 @@ TOKEN *new_number(const char *text) {
|
||||
|
||||
TOKEN *new_number_real(const char *text) {
|
||||
char *endptr;
|
||||
struct token_t * tkn = new_token(TKN_NUMBER);
|
||||
TOKEN *tkn = new_token(TKN_NUMBER);
|
||||
tkn->value.type = V_NUM_REAL;
|
||||
tkn->value.number_real = strtod(text, &endptr);
|
||||
if(endptr == text || *endptr) {
|
||||
@@ -330,14 +326,14 @@ TOKEN *new_number_real(const char *text) {
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
msg_info("NUMBER(%g)\n", tkn->value.number_real);
|
||||
msg_notice("NUMBER(%g)\n", tkn->value.number_real);
|
||||
#endif
|
||||
|
||||
return tkn;
|
||||
}
|
||||
|
||||
TOKEN *new_constant(const char *con) {
|
||||
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||
TOKEN *tkn = new_token(TKN_NUMBER);
|
||||
int assigned = 1;
|
||||
|
||||
tkn->value.type = V_NUM;
|
||||
@@ -373,19 +369,19 @@ TOKEN *new_constant(const char *con) {
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
msg_info("CONSTANT(%s=%d)\n", con, tkn->value.number);
|
||||
msg_notice("CONSTANT(%s=%d)\n", con, tkn->value.number);
|
||||
#endif
|
||||
|
||||
return tkn;
|
||||
}
|
||||
|
||||
TOKEN *new_string(const char *text) {
|
||||
struct token_t *tkn = new_token(TKN_STRING);
|
||||
TOKEN *tkn = new_token(TKN_STRING);
|
||||
tkn->value.type = V_STR;
|
||||
tkn->value.string = mmt_strdup(text);
|
||||
|
||||
#if DEBUG
|
||||
msg_info("STRING(%s)\n", tkn->value.string);
|
||||
msg_notice("STRING(%s)\n", tkn->value.string);
|
||||
#endif
|
||||
|
||||
return tkn;
|
||||
@@ -397,8 +393,7 @@ TOKEN *new_keyword(int primary) {
|
||||
}
|
||||
|
||||
|
||||
void print_token(TOKEN * tkn)
|
||||
{
|
||||
void print_token(TOKEN *tkn) {
|
||||
if (!tkn)
|
||||
return;
|
||||
|
||||
@@ -428,7 +423,7 @@ void print_token(TOKEN * tkn)
|
||||
void pyytext(void)
|
||||
{
|
||||
#if DEBUG
|
||||
msg_info("TOKEN: %s\n", yytext);
|
||||
msg_notice("TOKEN: %s\n", yytext);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -438,9 +433,8 @@ void pyytext(void)
|
||||
extern int yylex_destroy(void);
|
||||
#endif
|
||||
|
||||
int read_config(const char * file)
|
||||
{
|
||||
FILE * f;
|
||||
int read_config(const char *file) {
|
||||
FILE *f;
|
||||
int r;
|
||||
|
||||
if(!(cfg_infile = realpath(file, NULL))) {
|
||||
@@ -488,8 +482,6 @@ unsigned strhash(const char *str) {
|
||||
}
|
||||
|
||||
|
||||
static char **hstrings[1<<12];
|
||||
|
||||
// Return a copy of the argument as hashed string
|
||||
const char *cache_string(const char *p) {
|
||||
int h, k;
|
||||
@@ -498,32 +490,23 @@ const char *cache_string(const char *p) {
|
||||
if(!p)
|
||||
p = "(NULL)";
|
||||
|
||||
h = strhash(p) % (sizeof hstrings/sizeof*hstrings);
|
||||
if(!(hs=hstrings[h]))
|
||||
hs = hstrings[h] = (char **) mmt_realloc(NULL, (16+1)*sizeof**hstrings);
|
||||
h = strhash(p) % (sizeof cx->cfg_hstrings/sizeof*cx->cfg_hstrings);
|
||||
if(!(hs=cx->cfg_hstrings[h]))
|
||||
hs = cx->cfg_hstrings[h] = (char **) mmt_realloc(NULL, (16+1)*sizeof**cx->cfg_hstrings);
|
||||
|
||||
for(k=0; hs[k]; k++)
|
||||
if(*p == *hs[k] && str_eq(p, hs[k]))
|
||||
return hs[k];
|
||||
|
||||
if(k && k%16 == 0)
|
||||
hstrings[h] = (char **) mmt_realloc(hstrings[h], (k+16+1)*sizeof**hstrings);
|
||||
cx->cfg_hstrings[h] = (char **) mmt_realloc(cx->cfg_hstrings[h], (k+16+1)*sizeof**cx->cfg_hstrings);
|
||||
|
||||
hstrings[h][k+1] = NULL;
|
||||
cx->cfg_hstrings[h][k+1] = NULL;
|
||||
|
||||
return hstrings[h][k] = mmt_strdup(p);
|
||||
return cx->cfg_hstrings[h][k] = mmt_strdup(p);
|
||||
}
|
||||
|
||||
|
||||
static LISTID cfg_comms; // A chain of comment lines
|
||||
static LISTID cfg_prologue; // Comment lines at start of avrdude.conf
|
||||
static char *lkw; // Last seen keyword
|
||||
static int lkw_lineno; // Line number of that
|
||||
|
||||
static LISTID cfg_strctcomms; // Passed on to config_gram.y
|
||||
static LISTID cfg_pushedcomms; // Temporarily pushed main comments
|
||||
static int cfg_pushed; // ... for memory sections
|
||||
|
||||
COMMENT *locate_comment(const LISTID comments, const char *where, int rhs) {
|
||||
if(comments)
|
||||
for(LNODEID ln=lfirst(comments); ln; ln=lnext(ln)) {
|
||||
@@ -536,57 +519,57 @@ COMMENT *locate_comment(const LISTID comments, const char *where, int rhs) {
|
||||
}
|
||||
|
||||
static void addcomment(int rhs) {
|
||||
if(lkw) {
|
||||
if(cx->cfg_lkw) {
|
||||
COMMENT *node = mmt_malloc(sizeof(*node));
|
||||
node->rhs = rhs;
|
||||
node->kw = mmt_strdup(lkw);
|
||||
node->comms = cfg_comms;
|
||||
cfg_comms = NULL;
|
||||
if(!cfg_strctcomms)
|
||||
cfg_strctcomms = lcreat(NULL, 0);
|
||||
ladd(cfg_strctcomms, node);
|
||||
node->kw = mmt_strdup(cx->cfg_lkw);
|
||||
node->comms = cx->cfg_comms;
|
||||
cx->cfg_comms = NULL;
|
||||
if(!cx->cfg_strctcomms)
|
||||
cx->cfg_strctcomms = lcreat(NULL, 0);
|
||||
ladd(cx->cfg_strctcomms, node);
|
||||
}
|
||||
}
|
||||
|
||||
// Capture prologue during parsing (triggered by lexer.l)
|
||||
void cfg_capture_prologue(void) {
|
||||
cfg_prologue = cfg_comms;
|
||||
cfg_comms = NULL;
|
||||
cx->cfg_prologue = cx->cfg_comms;
|
||||
cx->cfg_comms = NULL;
|
||||
}
|
||||
|
||||
LISTID cfg_get_prologue(void) {
|
||||
return cfg_prologue;
|
||||
return cx->cfg_prologue;
|
||||
}
|
||||
|
||||
// Captures comments during parsing
|
||||
void capture_comment_str(const char *com, int lineno) {
|
||||
if(!cfg_comms)
|
||||
cfg_comms = lcreat(NULL, 0);
|
||||
ladd(cfg_comms, mmt_strdup(com));
|
||||
if(!cx->cfg_comms)
|
||||
cx->cfg_comms = lcreat(NULL, 0);
|
||||
ladd(cx->cfg_comms, mmt_strdup(com));
|
||||
|
||||
// Last keyword lineno is the same as this comment's
|
||||
if(lkw && lkw_lineno == lineno)
|
||||
if(cx->cfg_lkw && cx->cfg_lkw_lineno == lineno)
|
||||
addcomment(1); // Register comms to show right of lkw = ...;
|
||||
}
|
||||
|
||||
// Capture assignments (keywords left of =) and associate comments to them
|
||||
void capture_lvalue_kw(const char *kw, int lineno) {
|
||||
if(str_eq(kw, "memory")) { // Push part comments and start memory comments
|
||||
if(!cfg_pushed) { // config_gram.y pops the part comments
|
||||
cfg_pushed = 1;
|
||||
cfg_pushedcomms = cfg_strctcomms;
|
||||
cfg_strctcomms = NULL;
|
||||
if(!cx->cfg_pushed) { // config_gram.y pops the part comments
|
||||
cx->cfg_pushed = 1;
|
||||
cx->cfg_pushedcomms = cx->cfg_strctcomms;
|
||||
cx->cfg_strctcomms = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if(str_eq(kw, "programmer") || str_eq(kw, "serialadapter") || str_eq(kw, "part") || str_eq(kw, "memory"))
|
||||
kw = "*"; // Show comment before programmer/part/memory
|
||||
|
||||
if(lkw)
|
||||
mmt_free(lkw);
|
||||
lkw = mmt_strdup(kw);
|
||||
lkw_lineno = lineno;
|
||||
if(cfg_comms) // Accrued list of # one-line comments
|
||||
if(cx->cfg_lkw)
|
||||
mmt_free(cx->cfg_lkw);
|
||||
cx->cfg_lkw = mmt_strdup(kw);
|
||||
cx->cfg_lkw_lineno = lineno;
|
||||
if(cx->cfg_comms) // Accrued list of # one-line comments
|
||||
addcomment(0); // Register comment to appear before lkw assignment
|
||||
}
|
||||
|
||||
@@ -594,16 +577,16 @@ void capture_lvalue_kw(const char *kw, int lineno) {
|
||||
LISTID cfg_move_comments(void) {
|
||||
capture_lvalue_kw(";", -1);
|
||||
|
||||
LISTID ret = cfg_strctcomms;
|
||||
cfg_strctcomms = NULL;
|
||||
LISTID ret = cx->cfg_strctcomms;
|
||||
cx->cfg_strctcomms = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// config_gram.y calls this after ingressing the memory structure
|
||||
void cfg_pop_comms(void) {
|
||||
if(cfg_pushed) {
|
||||
cfg_pushed = 0;
|
||||
cfg_strctcomms = cfg_pushedcomms;
|
||||
if(cx->cfg_pushed) {
|
||||
cx->cfg_pushed = 0;
|
||||
cx->cfg_strctcomms = cx->cfg_pushedcomms;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -789,12 +772,94 @@ char *cfg_unescape(char *d, const char *s) {
|
||||
return (char *) cfg_unescapeu((unsigned char *) d, (const unsigned char *) s);
|
||||
}
|
||||
|
||||
// Returns the number of characters that a unicode character would need (0-6)
|
||||
static int utf8width(wint_t wc) {
|
||||
if(!(wc & ~0x7fu))
|
||||
return 1;
|
||||
if(!(wc & ~0x7ffu))
|
||||
return 2;
|
||||
if(!(wc & ~0xffffu))
|
||||
return 3;
|
||||
if(!(wc & ~0x1fffffu))
|
||||
return 4;
|
||||
if(!(wc & ~0x3ffffffu))
|
||||
return 5;
|
||||
if(!(wc & ~0x7fffffffu))
|
||||
return 6;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Given the first byte c of a character sequence, how long is the sequence going to be?
|
||||
static int utf8headlen(int c) {
|
||||
return (c & 0xe0) == 0xc0? 2:
|
||||
(c & 0xf0) == 0xe0? 3:
|
||||
(c & 0xf8) == 0xf0? 4: (c & 0xfc) == 0xf8? 5: (c & 0xfe) == 0xfc? 6: 1 /* not a utf8 header byte */ ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the next unicode character from a utf-8 string str with at least
|
||||
* n characters and record the length of the utf-8 string eaten in *lenp
|
||||
* Returns U+FFFD (illegal char) if parsing does not go well
|
||||
*/
|
||||
|
||||
static wint_t nextutf8char(const char *str, int n, int *lenp) {
|
||||
int j, utf8, len;
|
||||
wint_t c, wc = 0;
|
||||
|
||||
c = str[0] & 0xff;
|
||||
if(!(c & 0x80)) { // Simple ASCII - all done
|
||||
if(lenp)
|
||||
*lenp = 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
utf8 = 0; // Possible UTF-8 character, convert to wint_t
|
||||
len = utf8headlen((int) c);
|
||||
if(len > 1 && len <= n) {
|
||||
switch (len) {
|
||||
case 2:
|
||||
wc = c & 0x1f;
|
||||
break;
|
||||
case 3:
|
||||
wc = c & 0xf;
|
||||
break;
|
||||
case 4:
|
||||
wc = c & 0x7;
|
||||
break;
|
||||
case 5:
|
||||
wc = c & 0x3;
|
||||
break;
|
||||
case 6:
|
||||
wc = c & 0x1;
|
||||
break;
|
||||
}
|
||||
for(utf8 = 1, j = 1; j < len; j++) {
|
||||
if((str[j] & 0xc0) != 0x80) {
|
||||
utf8 = 0;
|
||||
break;
|
||||
}
|
||||
wc = (wc << 6) + (str[j] & 0x3f);
|
||||
}
|
||||
}
|
||||
if(utf8 && utf8width(wc) != len) // Sequence code was longer than needed be, make invalid
|
||||
utf8 = 0;
|
||||
|
||||
if(!utf8)
|
||||
len = 1, wc = 0xFFFD; // Illegal character
|
||||
|
||||
if(lenp)
|
||||
*lenp = len;
|
||||
|
||||
return wc;
|
||||
}
|
||||
|
||||
// Return an mmt_malloc'd escaped string that looks like a C-style input string incl quotes
|
||||
char *cfg_escape(const char *s) {
|
||||
char buf[50*1024], *d = buf;
|
||||
|
||||
*d++ = '"';
|
||||
for(; *s && d-buf < (long) sizeof buf-7; s++) {
|
||||
for(; *s && d-buf < (long) sizeof buf - 10; s++) {
|
||||
switch(*s) {
|
||||
case '\n':
|
||||
*d++ = '\\'; *d++ = 'n';
|
||||
@@ -823,7 +888,17 @@ char *cfg_escape(const char *s) {
|
||||
*d++ = '\\'; *d++ = '\"';
|
||||
break;
|
||||
default:
|
||||
if(*s == 0x7f || (unsigned char) *s < 32) {
|
||||
if(*s & 0x80) { // Check for utf8-sequences
|
||||
int chrlen;
|
||||
if(0xFFFD == nextutf8char(s, strlen(s), &chrlen)) { // Invalid UTF-8
|
||||
sprintf(d, "\\%03o", *s & 0xff);
|
||||
d += strlen(d);
|
||||
} else { // Copy over valid UTF-8 character
|
||||
memcpy(d, s, chrlen);
|
||||
d += chrlen;
|
||||
s += chrlen - 1;
|
||||
}
|
||||
} else if(*s == 0x7f || (unsigned char) *s < 32) {
|
||||
sprintf(d, "\\%03o", *s);
|
||||
d += strlen(d);
|
||||
} else
|
||||
@@ -838,23 +913,21 @@ char *cfg_escape(const char *s) {
|
||||
|
||||
|
||||
static int cmp_comp(const void *v1, const void *v2) {
|
||||
const Component_t *c1 = v1, *c2 = v2;
|
||||
const Component *c1 = v1, *c2 = v2;
|
||||
int ret = strcmp(c1->name, c2->name);
|
||||
|
||||
return ret? ret: c1->strct - c2->strct;
|
||||
}
|
||||
|
||||
Component_t *cfg_comp_search(const char *name, int strct) {
|
||||
static int init;
|
||||
Component_t key;
|
||||
|
||||
if(!init++)
|
||||
qsort(avr_comp, sizeof avr_comp/sizeof*avr_comp, sizeof(Component_t), cmp_comp);
|
||||
Component *cfg_comp_search(const char *name, int strct) {
|
||||
Component key;
|
||||
|
||||
if(!cx->cfg_init_search++)
|
||||
qsort(avr_comp, sizeof avr_comp/sizeof*avr_comp, sizeof(Component), cmp_comp);
|
||||
|
||||
key.name = name;
|
||||
key.strct = strct;
|
||||
return bsearch(&key, avr_comp, sizeof avr_comp/sizeof*avr_comp, sizeof(Component_t), cmp_comp);
|
||||
return bsearch(&key, avr_comp, sizeof avr_comp/sizeof*avr_comp, sizeof(Component), cmp_comp);
|
||||
}
|
||||
|
||||
|
||||
@@ -898,7 +971,7 @@ const char *cfg_comp_type(int type) {
|
||||
|
||||
|
||||
// Used by config_gram.y to assign a component in one of the relevant structures with a value
|
||||
void cfg_assign(char *sp, int strct, Component_t *cp, VALUE *v) {
|
||||
void cfg_assign(char *sp, int strct, Component *cp, VALUE *v) {
|
||||
const char *str;
|
||||
int num;
|
||||
|
||||
@@ -912,7 +985,7 @@ void cfg_assign(char *sp, int strct, Component_t *cp, VALUE *v) {
|
||||
cp->name, cfg_strct_name(strct), cfg_comp_type(cp->type), cfg_v_type(v->type));
|
||||
return;
|
||||
}
|
||||
// TODO: consider endianess (code currently assumes little endian)
|
||||
// TODO: consider endianness (code currently assumes little endian)
|
||||
num = v->number;
|
||||
memcpy(sp+cp->offset, &num, cp->size);
|
||||
break;
|
||||
|
||||
46
src/config.h
46
src/config.h
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* These are the internal definitions needed for config parsing */
|
||||
|
||||
#ifndef config_h
|
||||
@@ -62,7 +60,7 @@ typedef struct { // Description of a component in a structure
|
||||
const char *name; // Component name
|
||||
int strct; // Structure, eg, COMP_AVRPART
|
||||
int offset, size, type; // Location, size and type within structure
|
||||
} Component_t;
|
||||
} Component;
|
||||
|
||||
|
||||
enum { // Value types for VALUE struct
|
||||
@@ -73,34 +71,34 @@ enum { // Value types for VALUE struct
|
||||
V_COMPONENT,
|
||||
};
|
||||
|
||||
typedef struct value_t {
|
||||
int type;
|
||||
typedef struct {
|
||||
int type;
|
||||
union {
|
||||
int number;
|
||||
double number_real;
|
||||
char * string;
|
||||
Component_t *comp;
|
||||
int number;
|
||||
double number_real;
|
||||
char *string;
|
||||
Component *comp;
|
||||
};
|
||||
} VALUE;
|
||||
|
||||
|
||||
typedef struct token_t {
|
||||
typedef struct token {
|
||||
int primary;
|
||||
VALUE value;
|
||||
} TOKEN;
|
||||
typedef struct token_t *token_p;
|
||||
typedef struct token *token_p;
|
||||
|
||||
|
||||
extern FILE * yyin;
|
||||
extern PROGRAMMER * current_prog;
|
||||
extern AVRPART * current_part;
|
||||
extern AVRMEM * current_mem;
|
||||
extern int current_strct;
|
||||
extern int cfg_lineno;
|
||||
extern char * cfg_infile;
|
||||
extern LISTID string_list;
|
||||
extern LISTID number_list;
|
||||
extern bool is_alias; // current entry is alias
|
||||
extern FILE *yyin;
|
||||
extern PROGRAMMER *current_prog;
|
||||
extern AVRPART *current_part;
|
||||
extern AVRMEM *current_mem;
|
||||
extern int current_strct;
|
||||
extern int cfg_lineno;
|
||||
extern char *cfg_infile;
|
||||
extern LISTID string_list;
|
||||
extern LISTID number_list;
|
||||
extern bool is_alias; // current entry is alias
|
||||
|
||||
|
||||
#if !defined(HAS_YYSTYPE)
|
||||
@@ -152,13 +150,13 @@ LISTID cfg_move_comments(void);
|
||||
|
||||
void cfg_pop_comms(void);
|
||||
|
||||
Component_t *cfg_comp_search(const char *name, int strct);
|
||||
Component *cfg_comp_search(const char *name, int strct);
|
||||
|
||||
const char *cfg_v_type(int type);
|
||||
|
||||
const char *cfg_strct_name(int strct);
|
||||
|
||||
void cfg_assign(char *sp, int strct, Component_t *cp, VALUE *v);
|
||||
void cfg_assign(char *sp, int strct, Component *cp, VALUE *v);
|
||||
|
||||
void cfg_update_mcuid(AVRPART *part);
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2022- Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,7 +18,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
%{
|
||||
|
||||
#include "ac_cfg.h"
|
||||
@@ -50,7 +50,7 @@ static int assign_pin_list(int invert);
|
||||
static int which_opcode(TOKEN * opcode);
|
||||
static int parse_cmdbits(OPCODE * op, int opnum);
|
||||
|
||||
static int pin_name;
|
||||
#define pin_name (cx->cfgy_pin_name)
|
||||
%}
|
||||
|
||||
%token K_NULL;
|
||||
@@ -274,6 +274,9 @@ prog_def :
|
||||
yyerror("programmer type not specified");
|
||||
YYABORT;
|
||||
}
|
||||
if(!current_prog->prog_modes && cx->lex_kw_is_programmer)
|
||||
yywarning("programmer %s fails to specify prog_modes = PM_...;",
|
||||
(char *) ldata(lfirst(current_prog->id)));
|
||||
for(LNODEID ln = lfirst(current_prog->id); ln; ln = lnext(ln)) {
|
||||
char *id = ldata(ln);
|
||||
if((existing_prog = locate_programmer(programmers, id))) {
|
||||
@@ -335,6 +338,10 @@ part_def :
|
||||
|
||||
cfg_update_mcuid(current_part);
|
||||
|
||||
Memtype and_mask = ~ ( // Remove in-flash/in-sigrow attributes if no respective memories
|
||||
(!avr_locate_flash(current_part)? MEM_IN_FLASH: 0) |
|
||||
(!avr_locate_sigrow(current_part)? MEM_IN_SIGROW: 0));
|
||||
|
||||
// Sanity checks for memory sizes and compute/override num_pages entry
|
||||
for (ln=lfirst(current_part->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
@@ -363,6 +370,20 @@ part_def :
|
||||
|
||||
m->num_pages = m->size / m->page_size;
|
||||
}
|
||||
|
||||
m->type &= and_mask;
|
||||
// Remove MEM_IN_SIGROW attribute from classic calibration and classic/XMEGA signature mem
|
||||
if(current_part->prog_modes & PM_Classic) {
|
||||
if(mem_is_signature(m))
|
||||
m->type &= ~MEM_IN_SIGROW;
|
||||
if(mem_is_calibration(m))
|
||||
m->type &= ~MEM_IN_SIGROW;
|
||||
} else if(current_part->prog_modes & PM_PDI) {
|
||||
if(mem_is_signature(m))
|
||||
m->type &= ~MEM_IN_SIGROW;
|
||||
}
|
||||
if(fileio_mem_offset(current_part, m) == ~0U)
|
||||
yywarning("revise fileio_mem_offset(), avrdude.conf entry or memory type assignment");
|
||||
}
|
||||
|
||||
existing_part = locate_part(part_list, current_part->id);
|
||||
@@ -458,7 +479,7 @@ prog_parm_type:
|
||||
|
||||
prog_parm_type_id:
|
||||
TKN_STRING {
|
||||
const struct programmer_type_t * pgm_type = locate_programmer_type($1->value.string);
|
||||
const PROGRAMMER_TYPE *pgm_type = locate_programmer_type($1->value.string);
|
||||
if (pgm_type == NULL) {
|
||||
yyerror("programmer type %s not found", $1->value.string);
|
||||
free_token($1);
|
||||
@@ -549,7 +570,10 @@ pin_number_non_empty:
|
||||
pin_number:
|
||||
pin_number_non_empty
|
||||
|
|
||||
/* empty */ { pin_clear_all(&(current_prog->pin[pin_name])); }
|
||||
/* empty */ {
|
||||
if(pin_name >= 0 && pin_name < N_PINS)
|
||||
pin_clear_all(&(current_prog->pin[pin_name]));
|
||||
}
|
||||
;
|
||||
|
||||
pin_list_element:
|
||||
@@ -568,7 +592,10 @@ pin_list_non_empty:
|
||||
pin_list:
|
||||
pin_list_non_empty
|
||||
|
|
||||
/* empty */ { pin_clear_all(&(current_prog->pin[pin_name])); }
|
||||
/* empty */ {
|
||||
if(pin_name >= 0 && pin_name < N_PINS)
|
||||
pin_clear_all(&(current_prog->pin[pin_name]));
|
||||
}
|
||||
;
|
||||
|
||||
prog_parm_pins:
|
||||
@@ -1368,11 +1395,11 @@ static int parse_cmdbits(OPCODE * op, int opnum)
|
||||
case 'a':
|
||||
sb = opnum == AVR_OP_LOAD_EXT_ADDR? bitno+8: bitno-8; // should be this number
|
||||
if(bitno < 8 || bitno > 23) {
|
||||
if(!current_mem || !mem_is_sigrow(current_mem)) // Known exemption
|
||||
if(!current_mem || !mem_is_in_sigrow(current_mem)) // Known exemptions
|
||||
yywarning("address bits don't normally appear in Bytes 0 or 3 of SPI commands");
|
||||
} else if((bn & 31) != sb) {
|
||||
if(!current_part || !str_casestarts(current_part->desc, "AT89S5")) // Exempt AT89S5x
|
||||
if(!current_mem || !mem_is_sigrow(current_mem)) // and prodsig
|
||||
if(!current_mem || !mem_is_in_sigrow(current_mem)) // ... and prodsig/sernum
|
||||
yywarning("a%d would normally be expected to be a%d", bn, sb);
|
||||
} else if(bn < 0 || bn > 31)
|
||||
yywarning("invalid address bit a%d, using a%d", bn, bn & 31);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# avrdude - A Downloader/Uploader for AVR device programmers
|
||||
# Copyright (C) 2003, 2004 Theodore A. Roth <troth@openavr.org>
|
||||
# Copyright (C) 2003, 2004 Theodore A. Roth <troth@openavr.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -16,10 +16,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
# Process this file with autoreconf to produce a configure script.
|
||||
|
||||
dnl A few tool releases with release dates for orientation which tool
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Eric B. Weddington <eric@ecentral.com>
|
||||
* Copyright (C) 2024 Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -27,24 +27,10 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
static char *filename;
|
||||
|
||||
void win_sys_config_set(char sys_config[PATH_MAX])
|
||||
{
|
||||
sys_config[0] = 0;
|
||||
|
||||
/* Use Windows API call to search for the Windows default system config file.*/
|
||||
SearchPath(NULL, SYSTEM_CONF_FILE, NULL, PATH_MAX, sys_config, &filename);
|
||||
return;
|
||||
}
|
||||
|
||||
void win_usr_config_set(char usr_config[PATH_MAX])
|
||||
{
|
||||
usr_config[0] = 0;
|
||||
|
||||
/* Use Windows API call to search for the Windows default user config file. */
|
||||
SearchPath(NULL, USER_CONF_FILE, NULL, PATH_MAX, usr_config, &filename);
|
||||
return;
|
||||
// Store the full path of a file using a registry-dependent system search path
|
||||
int win_set_path(char *path, int n, const char *file) {
|
||||
*path = 0;
|
||||
return SearchPath(NULL, file, NULL, n, path, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Code to program an Atmel AVR device through one of the supported
|
||||
* programmers.
|
||||
@@ -59,14 +57,14 @@
|
||||
// - Output again with -p*/s or -c*/s (no /i) and use that for final avrdude.conf
|
||||
// - Remove entries from below tables
|
||||
|
||||
static struct {
|
||||
static const struct {
|
||||
const char *pgmid, *var, *value;
|
||||
} pgminj[] = {
|
||||
// Add triples here, eg, {"stk500v2", "prog_modes", "PM_TPI|PM_ISP"},
|
||||
{NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
static struct {
|
||||
static const struct {
|
||||
const char *mcu, *var, *value;
|
||||
} ptinj[] = {
|
||||
// Add triples here, eg, {"ATmega328P", "mcuid", "999"},
|
||||
@@ -133,43 +131,6 @@ static void printallopcodes(const AVRPART *p, const char *d, OPCODE * const *opa
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Programming modes
|
||||
|
||||
static char *prog_modes_str(int pm) {
|
||||
static char type[1024];
|
||||
|
||||
strcpy(type, "0");
|
||||
if(pm & PM_SPM)
|
||||
strcat(type, " | PM_SPM");
|
||||
if(pm & PM_TPI)
|
||||
strcat(type, " | PM_TPI");
|
||||
if(pm & PM_ISP)
|
||||
strcat(type, " | PM_ISP");
|
||||
if(pm & PM_PDI)
|
||||
strcat(type, " | PM_PDI");
|
||||
if(pm & PM_UPDI)
|
||||
strcat(type, " | PM_UPDI");
|
||||
if(pm & PM_HVSP)
|
||||
strcat(type, " | PM_HVSP");
|
||||
if(pm & PM_HVPP)
|
||||
strcat(type, " | PM_HVPP");
|
||||
if(pm & PM_debugWIRE)
|
||||
strcat(type, " | PM_debugWIRE");
|
||||
if(pm & PM_JTAG)
|
||||
strcat(type, " | PM_JTAG");
|
||||
if(pm & PM_JTAGmkI)
|
||||
strcat(type, " | PM_JTAGmkI");
|
||||
if(pm & PM_XMEGAJTAG)
|
||||
strcat(type, " | PM_XMEGAJTAG");
|
||||
if(pm & PM_AVR32JTAG)
|
||||
strcat(type, " | PM_AVR32JTAG");
|
||||
if(pm & PM_aWire)
|
||||
strcat(type, " | PM_aWire");
|
||||
|
||||
return type + (type[1] == 0? 0: 4);
|
||||
}
|
||||
|
||||
static char *extra_features_str(int m) {
|
||||
static char mode[1024];
|
||||
|
||||
@@ -251,6 +212,9 @@ static char *dev_sprintf(const char *fmt, ...) {
|
||||
|
||||
static int dev_nprinted;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
#endif
|
||||
int dev_message(int msglvl, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
int rc = 0;
|
||||
@@ -406,8 +370,15 @@ static int avrmem_deep_copy(AVRMEMdeep *d, const AVRMEM *m) {
|
||||
// Copy over the SPI operations themselves
|
||||
memset(d->ops, 0, sizeof d->ops);
|
||||
for(size_t i=0; i<AVR_OP_MAX; i++)
|
||||
if(m->op[i])
|
||||
if(m->op[i]) {
|
||||
d->ops[i] = *m->op[i];
|
||||
for(int b=0; b<32; b++) { // Replace x with 0 as they are treated the same
|
||||
if(d->ops[i].bit[b].type == AVR_CMDBIT_IGNORE) {
|
||||
d->ops[i].bit[b].type = AVR_CMDBIT_VALUE;
|
||||
d->ops[i].bit[b].value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -529,11 +500,6 @@ static void dev_raw_dump(const void *v, int nbytes, const char *name, const char
|
||||
}
|
||||
}
|
||||
|
||||
static int _is_all_zero(const void *p, size_t n) {
|
||||
const char *q = (const char *) p;
|
||||
return n <= 0 || (*q == 0 && memcmp(q, q+1, n-1) == 0);
|
||||
}
|
||||
|
||||
static char *opsnm(const char *pre, int opnum) {
|
||||
static char ret[128];
|
||||
sprintf(ret, "%.31s.%.95s", pre, opcodename(opnum));
|
||||
@@ -547,7 +513,7 @@ static void dev_part_raw(const AVRPART *part) {
|
||||
dev_raw_dump(&dp, (char *)&dp.base-(char *)&dp, part->desc, "part.intro", 0);
|
||||
dev_raw_dump(&dp.base, sizeof dp.base, part->desc, "part", 0);
|
||||
for(int i=0; i<AVR_OP_MAX; i++)
|
||||
if(!_is_all_zero(dp.ops+i, sizeof*dp.ops))
|
||||
if(!is_memset(dp.ops+i, 0, sizeof*dp.ops))
|
||||
dev_raw_dump(dp.ops+i, sizeof*dp.ops, part->desc, opsnm("part", i), 1);
|
||||
|
||||
for(int i=0; i<di; i++) {
|
||||
@@ -556,7 +522,7 @@ static void dev_part_raw(const AVRPART *part) {
|
||||
dev_raw_dump(nm, sizeof dp.mems[i].descbuf, part->desc, nm, i+2);
|
||||
dev_raw_dump(&dp.mems[i].base, sizeof dp.mems[i].base, part->desc, nm, i+2);
|
||||
for(int j=0; j<AVR_OP_MAX; j++)
|
||||
if(!_is_all_zero(dp.mems[i].ops+j, sizeof(OPCODE)))
|
||||
if(!is_memset(dp.mems[i].ops+j, 0, sizeof(OPCODE)))
|
||||
dev_raw_dump(dp.mems[i].ops+j, sizeof(OPCODE), part->desc, opsnm(nm, j), i+2);
|
||||
}
|
||||
}
|
||||
@@ -572,7 +538,7 @@ static void dev_part_strct(const AVRPART *p, bool tsv, const AVRPART *base, bool
|
||||
|
||||
if(!cp || !dev_has_subsstr_comms(cp->comms, del)) {
|
||||
dev_info("%s\n", del);
|
||||
dev_info("# %.*s\n", strlen(descstr)-2, descstr+1); // Remove double quotes
|
||||
dev_info("# %.*s\n", (int) strlen(descstr)-2, descstr+1); // Remove double quotes
|
||||
dev_info("%s\n\n", del);
|
||||
}
|
||||
if(cp)
|
||||
@@ -620,12 +586,13 @@ static void dev_part_strct(const AVRPART *p, bool tsv, const AVRPART *base, bool
|
||||
}
|
||||
|
||||
_if_partout_str(strcmp, cfg_escape(p->family_id), family_id);
|
||||
_if_partout_str(intcmp, mmt_strdup(prog_modes_str(p->prog_modes)), prog_modes);
|
||||
_if_partout_str(intcmp, mmt_strdup(dev_prog_modes(p->prog_modes)), prog_modes);
|
||||
if(p->mcuid == 21) {
|
||||
_if_partout_str(intcmp, mmt_strdup("XVII + IV"), mcuid);
|
||||
} else {
|
||||
_if_partout(intcmp, "%d", mcuid);
|
||||
}
|
||||
_if_partout(intcmp, "%d", archnum);
|
||||
_if_partout(intcmp, "%d", n_interrupts);
|
||||
_if_partout(intcmp, "%d", n_page_erase);
|
||||
_if_partout(intcmp, "%d", n_boot_sections);
|
||||
@@ -731,7 +698,7 @@ static void dev_part_strct(const AVRPART *p, bool tsv, const AVRPART *base, bool
|
||||
bm = base? dev_locate_mem(base, avr_mem_order[mi].str): NULL;
|
||||
|
||||
if(!m && bm && !tsv)
|
||||
dev_info("\n memory \"%s\" %*s= NULL;\n", bm->desc, 13 > strlen(bm->desc)? 13-strlen(bm->desc): 0, "");
|
||||
dev_info("\n memory \"%s\" %*s= NULL;\n", bm->desc, 13 > strlen(bm->desc)? 13 - (int) strlen(bm->desc): 0, "");
|
||||
|
||||
if(!m)
|
||||
continue;
|
||||
@@ -869,9 +836,42 @@ void dev_output_pgm_part(int dev_opt_c, const char *programmer, int dev_opt_p, c
|
||||
}
|
||||
|
||||
|
||||
// -p */[dASsrcow*ti]
|
||||
// Which programming modes should be considered, given the flags?
|
||||
static int prog_modes_in_flags(int prog_modes, const char *flags) {
|
||||
int pm = 0, quirky = 0;
|
||||
|
||||
for(const char *p = flags; *p; p++)
|
||||
switch(*p) {
|
||||
case 'B': pm |= PM_SPM; break;
|
||||
case 'C': pm |= PM_TPI | PM_ISP | PM_HVSP | PM_HVPP | PM_debugWIRE | PM_JTAG | PM_JTAGmkI; break;
|
||||
case 'U': pm |= PM_UPDI; break;
|
||||
case 'P': pm |= PM_PDI; break;
|
||||
case 'T': pm |= PM_TPI; break;
|
||||
case 'I': pm |= PM_ISP; break;
|
||||
case 'J': pm |= PM_JTAG | PM_JTAGmkI | PM_XMEGAJTAG; break;
|
||||
case 'W': pm |= PM_debugWIRE; break;
|
||||
case 'H': pm |= PM_HVPP | PM_HVSP; break;
|
||||
case 'Q': pm |= PM_ALL & ~(PM_SPM | PM_UPDI | PM_PDI | PM_TPI | PM_ISP | PM_JTAG | PM_JTAGmkI |
|
||||
PM_XMEGAJTAG | PM_debugWIRE | PM_HVPP | PM_HVSP);
|
||||
quirky = 1;
|
||||
}
|
||||
|
||||
return (prog_modes == 0 && quirky) || !pm || (prog_modes & pm);
|
||||
}
|
||||
|
||||
// Return pointer to uP_table entry for part p
|
||||
static const Avrintel *silent_locate_uP(const AVRPART *p) {
|
||||
int bakverb = verbose, idx;
|
||||
verbose = -123;
|
||||
idx = avr_locate_upidx(p);
|
||||
verbose = bakverb;
|
||||
|
||||
return idx < 0? NULL: uP_table + idx;
|
||||
}
|
||||
|
||||
// -p <wildcard>/[dsASRvcreow*tiBCUPTIJWHQ]
|
||||
void dev_output_part_defs(char *partdesc) {
|
||||
bool cmdok, waits, opspi, descs, astrc, strct, cmpst, injct, raw, all, tsv;
|
||||
bool cmdok, waits, opspi, descs, vtabs, confs, regis, astrc, strct, cmpst, injct, raw, all, tsv;
|
||||
char *flags;
|
||||
int nprinted;
|
||||
AVRPART *nullpart = avr_new_part();
|
||||
@@ -882,29 +882,34 @@ void dev_output_part_defs(char *partdesc) {
|
||||
if(!flags && str_eq(partdesc, "*")) // Treat -p * as if it was -p */s
|
||||
flags = "s";
|
||||
|
||||
if(!*flags || !strchr("cdoASsrw*ti", *flags)) {
|
||||
dev_info("%s: flags for developer option -p <wildcard>/<flags> not recognised\n", progname);
|
||||
if(!*flags || !strchr("dsASRvcreow*tiBCUPTIJWHQ", *flags)) {
|
||||
dev_info("Error: flags for developer option -p <wildcard>/<flags> not recognised\n");
|
||||
dev_info(
|
||||
"Wildcard examples (these need protecting in the shell through quoting):\n"
|
||||
" * all known parts\n"
|
||||
" ATtiny10 just this part\n"
|
||||
" *32[0-9] matches ATmega329, ATmega325 and ATmega328\n"
|
||||
" *32? matches ATmega329, ATmega32A, ATmega325 and ATmega328\n"
|
||||
" * all known parts\n"
|
||||
" ATtiny10 just this part\n"
|
||||
" *32[0-9] matches ATmega329, ATmega325 and ATmega328\n"
|
||||
" *32? matches ATmega329, ATmega32A, ATmega325 and ATmega328\n"
|
||||
"Flags (one or more of the characters below):\n"
|
||||
" d description of core part features\n"
|
||||
" A show entries of avrdude.conf parts with all values\n"
|
||||
" S show entries of avrdude.conf parts with necessary values\n"
|
||||
" s show short entries of avrdude.conf parts using parent\n"
|
||||
" r show entries of avrdude.conf parts as raw dump\n"
|
||||
" c check and report errors in address bits of SPI commands\n"
|
||||
" o opcodes for SPI programming parts and memories\n"
|
||||
" w wd_... constants for ISP parts\n"
|
||||
" * all of the above except s and S\n"
|
||||
" t use tab separated values as much as possible\n"
|
||||
" i inject assignments from source code table\n"
|
||||
" d description of core part features\n"
|
||||
" s show short entries of avrdude.conf parts using parent\n"
|
||||
" A show entries of avrdude.conf parts with all values\n"
|
||||
" S show entries of avrdude.conf parts with necessary values\n"
|
||||
" R show entries of avrdude.conf parts as raw dump\n"
|
||||
" v list interrupt vector names\n"
|
||||
" c list configuration options in fuses\n"
|
||||
" r list registers with I/O address and size\n"
|
||||
" e check and report errors in address bits of SPI commands\n"
|
||||
" o opcodes for SPI programming parts and memories\n"
|
||||
" w wd_... constants for ISP parts\n"
|
||||
" * as first character: all of the above except s and S\n"
|
||||
" BCUPTIJWHQ only Boot/Classic/UPDI/PDI/TPI/ISP/JTAG/debugWire/HV/quirky MUCs\n"
|
||||
" t use tab separated values as much as possible\n"
|
||||
" i inject assignments from source code table\n"
|
||||
"Examples:\n"
|
||||
" $ avrdude -p ATmega328P/s\n"
|
||||
" $ avrdude -p m328*/st | grep chip_erase_delay\n"
|
||||
" $ avrdude -p ATmega*/Ud | wc -l\n"
|
||||
" avrdude -p*/r | sort\n"
|
||||
"Notes:\n"
|
||||
" -p * is the same as -p */s\n"
|
||||
@@ -912,25 +917,27 @@ void dev_output_part_defs(char *partdesc) {
|
||||
" Leaving no space after -p can be an OK substitute for quoting in shells\n"
|
||||
" /s, /S and /A outputs are designed to be used as input in avrdude.conf\n"
|
||||
" Sorted /r output should stay invariant when rearranging avrdude.conf\n"
|
||||
" The /c, /o and /w flags are less generic and may be removed sometime\n"
|
||||
" The /e, /o and /w flags are less generic and may be removed sometime\n"
|
||||
" These options are just to help development, so not further documented\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
all = *flags == '*';
|
||||
cmdok = all || !!strchr(flags, 'c');
|
||||
descs = all || !!strchr(flags, 'd');
|
||||
vtabs = all || !!strchr(flags, 'v');
|
||||
confs = all || !!strchr(flags, 'c');
|
||||
regis = all || !!strchr(flags, 'r');
|
||||
cmdok = all || !!strchr(flags, 'e');
|
||||
opspi = all || !!strchr(flags, 'o');
|
||||
waits = all || !!strchr(flags, 'w');
|
||||
astrc = all || !!strchr(flags, 'A');
|
||||
raw = all || !!strchr(flags, 'r');
|
||||
raw = all || !!strchr(flags, 'R');
|
||||
strct = !!strchr(flags, 'S');
|
||||
cmpst = !!strchr(flags, 's');
|
||||
tsv = !!strchr(flags, 't');
|
||||
injct = !!strchr(flags, 'i');
|
||||
|
||||
|
||||
// Go through all memories and add them to the memory order list
|
||||
for(LNODEID ln1 = lfirst(part_list); ln1; ln1 = lnext(ln1)) {
|
||||
AVRPART *p = ldata(ln1);
|
||||
@@ -960,6 +967,8 @@ void dev_output_part_defs(char *partdesc) {
|
||||
|
||||
if(!part_eq(p, partdesc, str_casematch))
|
||||
continue;
|
||||
if(!prog_modes_in_flags(p->prog_modes, flags))
|
||||
continue;
|
||||
|
||||
if(astrc || strct || cmpst)
|
||||
dev_part_strct(p, tsv,
|
||||
@@ -995,6 +1004,7 @@ void dev_output_part_defs(char *partdesc) {
|
||||
int ok, nfuses;
|
||||
AVRMEM *m;
|
||||
OPCODE *oc;
|
||||
const Avrintel *up;
|
||||
|
||||
ok = 2047;
|
||||
nfuses = 0;
|
||||
@@ -1124,10 +1134,33 @@ void dev_output_part_defs(char *partdesc) {
|
||||
nfuses,
|
||||
ok,
|
||||
p->flags,
|
||||
prog_modes_str(p->prog_modes),
|
||||
dev_prog_modes(p->prog_modes),
|
||||
p->config_file, p->lineno
|
||||
);
|
||||
}
|
||||
|
||||
if(vtabs && (up = silent_locate_uP(p)) && up->isrtable)
|
||||
for(int i=0; i < up->ninterrupts; i++)
|
||||
dev_info(".vtab\t%s\t%d\t%s\n", p->desc, i, up->isrtable[i]);
|
||||
|
||||
if(confs && (up = silent_locate_uP(p)) && up->cfgtable)
|
||||
for(int i=0; i < up->nconfigs; i++) {
|
||||
const Configitem *cp = up->cfgtable+i;
|
||||
unsigned c, n = cp->nvalues;
|
||||
if(!n || !cp->vlist) { // Count bits set in mask
|
||||
for(n = cp->mask, c=0; n; c++)
|
||||
n &= n-1;
|
||||
n = 1<<c;
|
||||
}
|
||||
dev_info(".cfgt\t%s\t%d\t%s\n", p->desc, n, cp->name);
|
||||
if(cp->vlist && verbose)
|
||||
for(int k=0; k < cp->nvalues; k++)
|
||||
dev_info(".cfgv\t%s\t\tvalue\t%d\t%s\n", p->desc, cp->vlist[k].value, cp->vlist[k].label);
|
||||
}
|
||||
|
||||
if(regis && (up = silent_locate_uP(p)) && up->regf)
|
||||
for(int i=0; i < up->nregisters; i++)
|
||||
dev_info(".regf\t%s\t0x%02x\t%d\t%s\n", p->desc, up->regf[i].addr, up->regf[i].size, up->regf[i].reg);
|
||||
}
|
||||
|
||||
if(opspi) {
|
||||
@@ -1217,7 +1250,7 @@ static void dev_pgm_raw(const PROGRAMMER *pgm) {
|
||||
}
|
||||
|
||||
|
||||
static const char *connstr(conntype_t conntype) {
|
||||
static const char *connstr(Conntype conntype) {
|
||||
switch(conntype) {
|
||||
case CONNTYPE_LINUXGPIO: return "linuxgpio";
|
||||
case CONNTYPE_PARALLEL: return "parallel";
|
||||
@@ -1280,7 +1313,7 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
|
||||
if(!firstid)
|
||||
dev_info("/");
|
||||
firstid = 0;
|
||||
dev_info("%s", ldata(ln));
|
||||
dev_info("%s", (char *) ldata(ln));
|
||||
}
|
||||
dev_info("\n%s\n\n", del);
|
||||
}
|
||||
@@ -1289,9 +1322,9 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
|
||||
|
||||
const char *prog_sea = is_programmer(pgm)? "programmer": is_serialadapter(pgm)? "serialadapter": "programmer";
|
||||
if(pgm->parent_id && *pgm->parent_id)
|
||||
dev_info("%s parent \"%s\" # %s\n", prog_sea, pgm->parent_id, ldata(lfirst(pgm->id)));
|
||||
dev_info("%s parent \"%s\" # %s\n", prog_sea, pgm->parent_id, (char *) ldata(lfirst(pgm->id)));
|
||||
else
|
||||
dev_info("%s # %s\n", prog_sea, ldata(lfirst(pgm->id)));
|
||||
dev_info("%s # %s\n", prog_sea, (char *) ldata(lfirst(pgm->id)));
|
||||
}
|
||||
|
||||
if(tsv)
|
||||
@@ -1318,7 +1351,7 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
|
||||
_if_pgmout_str(strcmp, cfg_escape(pgm->desc), desc);
|
||||
if(!base || base->initpgm != pgm->initpgm)
|
||||
_pgmout_fmt("type", "\"%s\"", locate_programmer_type_id(pgm->initpgm));
|
||||
_if_pgmout_str(intcmp, mmt_strdup(prog_modes_str(pgm->prog_modes)), prog_modes);
|
||||
_if_pgmout_str(intcmp, mmt_strdup(dev_prog_modes(pgm->prog_modes)), prog_modes);
|
||||
_if_pgmout_str(boolcmp, mmt_strdup(pgm->is_serialadapter? "yes": "no"), is_serialadapter);
|
||||
_if_pgmout_str(intcmp, mmt_strdup(extra_features_str(pgm->extra_features)), extra_features);
|
||||
if(!base || base->conntype != pgm->conntype)
|
||||
@@ -1346,13 +1379,10 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
|
||||
_if_pgmout_str(strcmp, cfg_escape(pgm->usbproduct), usbproduct);
|
||||
|
||||
for(int i=0; i<N_PINS; i++) {
|
||||
char *str = pins_to_strdup(pgm->pin+i);
|
||||
char *bstr = base? pins_to_strdup(base->pin+i): NULL;
|
||||
const char *str = pins_to_str(pgm->pin+i);
|
||||
const char *bstr = base? pins_to_str(base->pin+i): NULL;
|
||||
if(!base || !str_eq(bstr, str))
|
||||
_pgmout_fmt(avr_pin_lcname(i), "%s", str);
|
||||
|
||||
mmt_free(str);
|
||||
mmt_free(bstr);
|
||||
}
|
||||
|
||||
pgmstr = dev_hvupdi_support_liststr(pgm);
|
||||
@@ -1383,9 +1413,9 @@ static void dev_pgm_strct(const PROGRAMMER *pgm, bool tsv, const PROGRAMMER *bas
|
||||
}
|
||||
|
||||
|
||||
// -c */[ASsrti]
|
||||
// -c <wildcard>/[dASsrtiBUPTIJWHQ]
|
||||
void dev_output_pgm_defs(char *pgmidcp) {
|
||||
bool astrc, strct, cmpst, raw, tsv, injct;
|
||||
bool descs, astrc, strct, cmpst, raw, tsv, injct;
|
||||
char *flags;
|
||||
int nprinted;
|
||||
PROGRAMMER *nullpgm = pgm_new();
|
||||
@@ -1396,8 +1426,8 @@ void dev_output_pgm_defs(char *pgmidcp) {
|
||||
if(!flags && str_eq(pgmidcp, "*")) // Treat -c * as if it was -c */s
|
||||
flags = "s";
|
||||
|
||||
if(!*flags || !strchr("ASsrti", *flags)) {
|
||||
dev_info("%s: flags for developer option -c <wildcard>/<flags> not recognised\n", progname);
|
||||
if(!*flags || !strchr("dASsrtiBUPTIJWHQ", *flags)) {
|
||||
dev_info("Error: flags for developer option -c <wildcard>/<flags> not recognised\n");
|
||||
dev_info(
|
||||
"Wildcard examples (these need protecting in the shell through quoting):\n"
|
||||
" * all known programmers\n"
|
||||
@@ -1405,12 +1435,14 @@ void dev_output_pgm_defs(char *pgmidcp) {
|
||||
" jtag*pdi matches jtag2pdi, jtag3pdi, jtag3updi and jtag2updi\n"
|
||||
" jtag?pdi matches jtag2pdi and jtag3pdi\n"
|
||||
"Flags (one or more of the characters below):\n"
|
||||
" A show entries of avrdude.conf programmers with all values\n"
|
||||
" S show entries of avrdude.conf programmers with necessary values\n"
|
||||
" s show short entries of avrdude.conf programmers using parent\n"
|
||||
" r show entries of avrdude.conf programmers as raw dump\n"
|
||||
" t use tab separated values as much as possible\n"
|
||||
" i inject assignments from source code table\n"
|
||||
" d description of core programmer features\n"
|
||||
" A show entries of avrdude.conf programmers with all values\n"
|
||||
" S show entries of avrdude.conf programmers with necessary values\n"
|
||||
" s show short entries of avrdude.conf programmers using parent\n"
|
||||
" r show entries of avrdude.conf programmers as raw dump\n"
|
||||
" t use tab separated values as much as possible\n"
|
||||
" i inject assignments from source code table\n"
|
||||
" BUPTIJWHQ only Bootloader/UPDI/PDI/TPI/ISP/JTAG/debugWire/HV/quirky MUCs\n"
|
||||
"Examples:\n"
|
||||
" $ avrdude -c usbasp/s\n"
|
||||
" $ avrdude -c */st | grep baudrate\n"
|
||||
@@ -1429,6 +1461,7 @@ void dev_output_pgm_defs(char *pgmidcp) {
|
||||
astrc = !!strchr(flags, 'A');
|
||||
strct = !!strchr(flags, 'S');
|
||||
cmpst = !!strchr(flags, 's');
|
||||
descs = !!strchr(flags, 'd');
|
||||
raw = !!strchr(flags, 'r');
|
||||
tsv = !!strchr(flags, 't');
|
||||
injct = !!strchr(flags, 'i');
|
||||
@@ -1447,8 +1480,10 @@ void dev_output_pgm_defs(char *pgmidcp) {
|
||||
}
|
||||
if(!matched)
|
||||
continue;
|
||||
if(!prog_modes_in_flags(pgm->prog_modes, flags))
|
||||
continue;
|
||||
|
||||
if(dev_nprinted > nprinted) {
|
||||
if(!descs && dev_nprinted > nprinted) {
|
||||
dev_info("\n");
|
||||
nprinted = dev_nprinted;
|
||||
}
|
||||
@@ -1460,6 +1495,19 @@ void dev_output_pgm_defs(char *pgmidcp) {
|
||||
pgm->parent_id && *pgm->parent_id? locate_programmer(programmers, pgm->parent_id): nullpgm,
|
||||
injct);
|
||||
|
||||
if(descs)
|
||||
for(LNODEID idn=lfirst(pgm->id); idn; idn=lnext(idn)) {
|
||||
char *id = ldata(idn);
|
||||
int len = 19-strlen(id);
|
||||
dev_info("%s '%s' =>%*s ['%s', '%s'], # %s %d\n",
|
||||
tsv? ".desc": " ",
|
||||
id, len > 0? len: 0, "",
|
||||
dev_prog_modes(pgm->prog_modes),
|
||||
pgm->desc,
|
||||
pgm->config_file, pgm->lineno
|
||||
);
|
||||
}
|
||||
|
||||
if(raw)
|
||||
dev_pgm_raw(pgm);
|
||||
}
|
||||
|
||||
34
src/dfu.c
34
src/dfu.c
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -88,8 +86,6 @@ int dfu_upload(struct dfu_dev *dfu, void * ptr, int size) {
|
||||
* is sent to the device.
|
||||
*/
|
||||
|
||||
static uint16_t wIndex = 0;
|
||||
|
||||
/* INTERNAL FUNCTION PROTOTYPES
|
||||
*/
|
||||
|
||||
@@ -196,7 +192,7 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmsg_notice("found VID=0x%04x PID=0x%04x at %s:%s\n",
|
||||
pmsg_notice2("found VID=0x%04x PID=0x%04x at %s:%s\n",
|
||||
found->descriptor.idVendor, found->descriptor.idProduct,
|
||||
found->bus->dirname, found->filename);
|
||||
|
||||
@@ -253,7 +249,7 @@ int dfu_getstatus(struct dfu_dev *dfu, struct dfu_status *status)
|
||||
{
|
||||
int result;
|
||||
|
||||
pmsg_trace("dfu_getstatus(): issuing control IN message\n");
|
||||
pmsg_trace("%s(): issuing control IN message\n", __func__);
|
||||
|
||||
result = usb_control_msg(dfu->dev_handle,
|
||||
0x80 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_GETSTATUS, 0, 0,
|
||||
@@ -274,7 +270,7 @@ int dfu_getstatus(struct dfu_dev *dfu, struct dfu_status *status)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmsg_trace("dfu_getstatus(): bStatus 0x%02x, bwPollTimeout %d, bState 0x%02x, iString %d\n",
|
||||
pmsg_trace("%s(): bStatus 0x%02x, bwPollTimeout %d, bState 0x%02x, iString %d\n", __func__,
|
||||
status->bStatus,
|
||||
status->bwPollTimeout[0] | (status->bwPollTimeout[1] << 8) | (status->bwPollTimeout[2] << 16),
|
||||
status->bState,
|
||||
@@ -287,7 +283,7 @@ int dfu_clrstatus(struct dfu_dev *dfu)
|
||||
{
|
||||
int result;
|
||||
|
||||
pmsg_trace("dfu_clrstatus(): issuing control OUT message\n");
|
||||
pmsg_trace("%s(): issuing control OUT message\n", __func__);
|
||||
|
||||
result = usb_control_msg(dfu->dev_handle,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_CLRSTATUS, 0, 0,
|
||||
@@ -305,7 +301,7 @@ int dfu_abort(struct dfu_dev *dfu)
|
||||
{
|
||||
int result;
|
||||
|
||||
pmsg_trace("dfu_abort(): issuing control OUT message\n");
|
||||
pmsg_trace("%s(): issuing control OUT message\n", __func__);
|
||||
|
||||
result = usb_control_msg(dfu->dev_handle,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_ABORT, 0, 0,
|
||||
@@ -324,11 +320,11 @@ int dfu_dnload(struct dfu_dev *dfu, void *ptr, int size)
|
||||
{
|
||||
int result;
|
||||
|
||||
pmsg_trace("dfu_dnload(): issuing control OUT message, wIndex = %d, ptr = %p, size = %d\n",
|
||||
wIndex, ptr, size);
|
||||
pmsg_trace("%s(): issuing control OUT message, wIndex = %d, ptr = %p, size = %d\n", __func__,
|
||||
cx->dfu_wIndex, ptr, size);
|
||||
|
||||
result = usb_control_msg(dfu->dev_handle,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_DNLOAD, wIndex++, 0,
|
||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_DNLOAD, cx->dfu_wIndex++, 0,
|
||||
ptr, size, dfu->timeout);
|
||||
|
||||
if (result < 0) {
|
||||
@@ -353,11 +349,11 @@ int dfu_upload(struct dfu_dev *dfu, void *ptr, int size)
|
||||
{
|
||||
int result;
|
||||
|
||||
pmsg_trace("dfu_upload(): issuing control IN message, wIndex = %d, ptr = %p, size = %d\n",
|
||||
wIndex, ptr, size);
|
||||
pmsg_trace("%s(): issuing control IN message, wIndex = %d, ptr = %p, size = %d\n", __func__,
|
||||
cx->dfu_wIndex, ptr, size);
|
||||
|
||||
result = usb_control_msg(dfu->dev_handle,
|
||||
0x80 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_UPLOAD, wIndex++, 0,
|
||||
0x80 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_UPLOAD, cx->dfu_wIndex++, 0,
|
||||
ptr, size, dfu->timeout);
|
||||
|
||||
if (result < 0) {
|
||||
@@ -394,10 +390,10 @@ void dfu_show_info(struct dfu_dev *dfu)
|
||||
msg_info(" USB Product : 0x%04hX\n",
|
||||
(unsigned short) dfu->dev_desc.idProduct);
|
||||
|
||||
msg_info(" USB Release : %hu.%hu.%hu\n",
|
||||
((unsigned short) dfu->dev_desc.bcdDevice >> 8) & 0xFF,
|
||||
((unsigned short) dfu->dev_desc.bcdDevice >> 4) & 0xF,
|
||||
((unsigned short) dfu->dev_desc.bcdDevice >> 0) & 0xF);
|
||||
msg_info(" USB Release : %u.%u.%u\n",
|
||||
(dfu->dev_desc.bcdDevice >> 8) & 0xFF,
|
||||
(dfu->dev_desc.bcdDevice >> 4) & 0xF,
|
||||
(dfu->dev_desc.bcdDevice >> 0) & 0xF);
|
||||
|
||||
if (dfu->serno_str != NULL)
|
||||
msg_info(" USB Serial No : %s\n", dfu->serno_str);
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef dfu_h
|
||||
#define dfu_h
|
||||
|
||||
|
||||
1192
src/disasm.c
Normal file
1192
src/disasm.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# avrdude - A Downloader/Uploader for AVR device programmers
|
||||
# Copyright (C) 2003 Theodore A. Roth <troth@openavr.org>
|
||||
# Copyright (C) 2003 Theodore A. Roth <troth@openavr.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -16,10 +16,6 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
|
||||
GENERATED_TEXINFOS = \
|
||||
$(builddir)/programmers.texi \
|
||||
$(builddir)/parts.texi \
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
824
src/dryrun.c
824
src/dryrun.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* AVRDUDE - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2022 Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
* Copyright (C) 2022- Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* The dryrun programmer emulates a physical programmer by allocating a copy of the part and
|
||||
* pretending all operations work well.
|
||||
@@ -42,23 +40,35 @@
|
||||
#include "dryrun.h"
|
||||
#include "dryrun_private.h"
|
||||
|
||||
#define random() rand() // For platform independence
|
||||
#define srandom(n) srand(n)
|
||||
|
||||
// Context of the programmer
|
||||
typedef enum {
|
||||
DRY_NOBOOTLOADER, // No bootloader, taking to an ordinary programmer
|
||||
DRY_TOP, // Bootloader and it sits at top of flash
|
||||
DRY_BOTTOM, // Bootloader sits at bottom of flash (UPDI parts)
|
||||
} dry_prog_t;
|
||||
} Dry_prog;
|
||||
|
||||
typedef struct {
|
||||
AVRPART *dp;
|
||||
dry_prog_t bl; // Bootloader and, if so, at top/bottom of flash?
|
||||
int blsize; // Bootloader size min(flash size/4, 512)
|
||||
} dryrun_t;
|
||||
Dry_prog bl; // Bootloader and, if so, at top/bottom of flash?
|
||||
int init; // Initialise memories with something interesting
|
||||
int random; // Random initialisation of memories
|
||||
int seed; // Seed for random number generator
|
||||
// Flash configuration irrespective of -c programming is bootloading or not
|
||||
int appstart, appsize; // Start and size of application section
|
||||
int datastart, datasize; // Start and size of application data section (if any)
|
||||
int bootstart, bootsize; // Start and size of boot section (if any)
|
||||
int initialised; // 1 once the part memories are initialised
|
||||
} Dryrun_data;
|
||||
|
||||
// Use private programmer data as if they were a global structure dry
|
||||
#define dry (*(dryrun_t *)(pgm->cookie))
|
||||
#define dry (*(Dryrun_data *)(pgm->cookie))
|
||||
|
||||
#define Return(...) do { pmsg_error(__VA_ARGS__); msg_error("\n"); return -1; } while (0)
|
||||
#define Retwarning(...) do { pmsg_warning(__VA_ARGS__); \
|
||||
msg_warning("; not initialising %s memories\n", p->desc); return -1; } while (0)
|
||||
|
||||
static int dryrun_readonly(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||
unsigned int addr);
|
||||
@@ -76,19 +86,40 @@ static int dryrun_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const
|
||||
}
|
||||
|
||||
|
||||
// Emulate chip erase (only erase flash, pretend EESAVE fuse is active - FIXME: check EESAVE fuse)
|
||||
// Emulate chip erase
|
||||
static int dryrun_chip_erase(const PROGRAMMER *pgm, const AVRPART *punused) {
|
||||
AVRMEM *flm;
|
||||
AVRMEM *mem;
|
||||
|
||||
pmsg_debug("%s()\n", __func__);
|
||||
if(!dry.dp)
|
||||
Return("no dryrun device?");
|
||||
if(!(flm = avr_locate_flash(dry.dp)))
|
||||
if(!(mem = avr_locate_flash(dry.dp)))
|
||||
Return("cannot locate %s flash memory for chip erase", dry.dp->desc);
|
||||
if(flm->size < 1)
|
||||
Return("cannot erase %s flash memory owing to its size %d", dry.dp->desc, flm->size);
|
||||
if(mem->size < 1)
|
||||
Return("cannot erase %s flash memory owing to its size %d", dry.dp->desc, mem->size);
|
||||
|
||||
memset(flm->buf, 0xff, flm->size);
|
||||
if(dry.bl) { // Bootloaders won't overwrite themselves
|
||||
memset(mem->buf + (dry.bl == DRY_TOP? 0: dry.bootsize), 0xff, mem->size-dry.bootsize);
|
||||
return 0; // Assume that's all a bootloader does
|
||||
}
|
||||
|
||||
memset(mem->buf, 0xff, mem->size);
|
||||
|
||||
int eesave, bakverb = verbose;
|
||||
verbose = -123;
|
||||
if((mem = avr_locate_eeprom(dry.dp))) // Check whether EEPROM needs erasing
|
||||
if(avr_get_config_value(pgm, dry.dp, "eesave", &eesave) == 0 && eesave == !(dry.dp->prog_modes & PM_UPDI))
|
||||
if(mem->size > 0)
|
||||
memset(mem->buf, 0xff, mem->size);
|
||||
verbose = bakverb;
|
||||
|
||||
if((mem = avr_locate_bootrow(dry.dp))) // Also erase bootrow if it's there
|
||||
if(mem->size > 0)
|
||||
memset(mem->buf, 0xff, mem->size);
|
||||
|
||||
if((mem = avr_locate_lock(dry.dp)))
|
||||
if(mem->initval != -1 && mem->size > 0 && mem->size <= (int) sizeof(mem->initval))
|
||||
memcpy(mem->buf, &mem->initval, mem->size); // FIXME: relying on little endian here
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -113,120 +144,598 @@ static int dryrun_cmd(const PROGRAMMER *pgm, const unsigned char *cmd, unsigned
|
||||
}
|
||||
|
||||
|
||||
static int dryrun_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
unsigned int addr) {
|
||||
|
||||
pmsg_debug("%s(%s, 0x%04x)\n", __func__, m->desc, addr);
|
||||
if(!dry.dp)
|
||||
Return("no dryrun device?");
|
||||
|
||||
AVRMEM *dmem;
|
||||
if(!(dmem = avr_locate_mem(dry.dp, m->desc)))
|
||||
Return("cannot locate %s %s memory for paged write", dry.dp->desc, m->desc);
|
||||
|
||||
if(!avr_has_paged_access(pgm, dmem) || addr >= (unsigned) dmem->size)
|
||||
Return("%s does not support paged access", dmem->desc);
|
||||
addr &= ~(dmem->page_size-1);
|
||||
if(addr + dmem->page_size > (unsigned) dmem->size)
|
||||
Return("%s page erase of %s reaches outside %s?", dmem->desc,
|
||||
str_ccinterval(addr, addr + dmem->page_size-1), str_ccinterval(0, dmem->size-1));
|
||||
|
||||
memset(dmem->buf+addr, 0xff, dmem->page_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dryrun_program_enable(const PROGRAMMER *pgm, const AVRPART *p_unused) {
|
||||
pmsg_debug("%s()\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Randomly set configuration values for bootloading, bootloader size and codesize, if any
|
||||
static void randflashconfig(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
const Avrintel *up, const Configitem *cp, int nc) {
|
||||
|
||||
if(up && p->prog_modes & PM_UPDI) {
|
||||
int sectorsize = up->bootsize > 0? up->bootsize: 256;
|
||||
int nsectors = up->flashsize/sectorsize;
|
||||
int bootsize = random() % (nsectors > 4? nsectors/4: nsectors);
|
||||
int codesize = !bootsize || random()%3? 0: bootsize + random()%(nsectors - bootsize);
|
||||
|
||||
int size = !!avr_locate_config(cp, nc, "bootsize", str_eq);
|
||||
avr_set_config_value(pgm, p, size? "bootsize": "bootend", bootsize);
|
||||
avr_set_config_value(pgm, p, size? "codesize": "append", codesize);
|
||||
} else if(up && up->nboots >0 && (p->prog_modes & (PM_Classic | PM_PDI))) {
|
||||
avr_set_config_value(pgm, p, "bootrst", random() % 2);
|
||||
if(up->nboots == 4)
|
||||
avr_set_config_value(pgm, p, "bootsz", random() % 4);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute app, data and boot start/size
|
||||
static int flashlayout(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *flm,
|
||||
const Avrintel *up, const Configitem *cp, int nc) {
|
||||
|
||||
AVRMEM *m;
|
||||
|
||||
if(p->prog_modes & PM_UPDI) {
|
||||
int nbootsec = 0, ncodesec = 0;
|
||||
|
||||
int size = !!avr_locate_config(cp, nc, "bootsize", str_eq);
|
||||
avr_get_config_value(pgm, p, size? "bootsize": "bootend", &nbootsec);
|
||||
avr_get_config_value(pgm, p, size? "codesize": "append", &ncodesec);
|
||||
if(nbootsec == 0 || (ncodesec && ncodesec <= nbootsec)) { // Treat boot section for code
|
||||
dry.bootstart = 0, dry.bootsize = 0;
|
||||
dry.appstart = 0, dry.appsize = nbootsec? nbootsec*up->bootsize: up->flashsize;
|
||||
} else { // Distinct boot and application section
|
||||
dry.bootstart = 0, dry.bootsize = nbootsec*up->bootsize;
|
||||
dry.appstart = dry.bootsize;
|
||||
dry.appsize = ncodesec? (ncodesec - nbootsec) * up->bootsize: up->flashsize - dry.appstart;
|
||||
}
|
||||
dry.datasize = up->flashsize - dry.bootsize - dry.appsize; // Remainder is apptable
|
||||
dry.datastart = dry.datasize? dry.bootsize + dry.appsize: 0;
|
||||
} else if(p->prog_modes & (PM_Classic | PM_PDI)) {
|
||||
dry.bootstart = 0, dry.bootsize = 0;
|
||||
if(up->nboots) {
|
||||
int bootrst = 1;
|
||||
avr_get_config_value(pgm, p, "bootrst", &bootrst);
|
||||
if(bootrst == 0) { // Jump to bootloader on reset
|
||||
if((p->prog_modes & PM_PDI) && (m = avr_locate_boot(p)) && m->size > 0) {
|
||||
dry.bootstart = m->offset - flm->offset;
|
||||
dry.bootsize = m->size;
|
||||
} else if(p->prog_modes & PM_Classic) {
|
||||
if(up->nboots == 4) {
|
||||
int bootsz = 0;
|
||||
avr_get_config_value(pgm, p, "bootsz", &bootsz);
|
||||
dry.bootsize = (8>>bootsz) * up->bootsize;
|
||||
} else
|
||||
dry.bootsize = up->bootsize;
|
||||
dry.bootstart = up->flashsize - dry.bootsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
dry.datastart = 0, dry.datasize = 0;
|
||||
if((p->prog_modes & PM_PDI) && (m = avr_locate_apptable(p)) && m->size > 0) {
|
||||
dry.datastart = m->offset - flm->offset;
|
||||
dry.datasize = up->flashsize - dry.datastart - dry.bootsize;
|
||||
}
|
||||
dry.appstart = 0, dry.appsize = up->flashsize - dry.datasize - dry.bootsize;
|
||||
}
|
||||
|
||||
// Sanity checks
|
||||
if(dry.appsize < 0)
|
||||
Retwarning("negative application size");
|
||||
if(dry.appstart < 0 || dry.appstart+dry.appsize > up->flashsize)
|
||||
Retwarning("application section %s outside flash [0, 0x%04x]",
|
||||
str_ccinterval(dry.appstart, dry.appstart+dry.appsize-1), up->flashsize-1);
|
||||
|
||||
if(dry.datasize < 0)
|
||||
Retwarning("negative apptable size");
|
||||
if(dry.datastart < 0 || dry.datastart+dry.datasize > up->flashsize)
|
||||
Retwarning("apptable section %s outside flash [0, 0x%04x]",
|
||||
str_ccinterval(dry.datastart, dry.datastart+dry.datasize-1), up->flashsize-1);
|
||||
|
||||
if(dry.bootsize < 0)
|
||||
Retwarning("negative boot section size");
|
||||
if(dry.bootstart < 0 || dry.bootstart+dry.bootsize > up->flashsize)
|
||||
Retwarning("boot section %s outside flassh [0, 0x%04x]",
|
||||
str_ccinterval(dry.bootstart, dry.bootstart+dry.bootsize-1), up->flashsize-1);
|
||||
|
||||
if(dry.appsize + dry.datasize + dry.bootsize != up->flashsize)
|
||||
Retwarning("section sizes do not add up (0x%x) to flash size 0x%x",
|
||||
dry.appsize + dry.datasize + dry.bootsize, up->flashsize);
|
||||
|
||||
if(!dry.appsize)
|
||||
Retwarning("no application section");
|
||||
|
||||
if(p->prog_modes & PM_UPDI) {
|
||||
if(dry.bootsize && dry.appstart != dry.bootsize)
|
||||
Retwarning("application section %s does not touch boot section %s",
|
||||
str_ccinterval(dry.appstart, dry.appstart+dry.appsize-1),
|
||||
str_ccinterval(dry.bootstart, dry.bootstart+dry.bootsize-1));
|
||||
if(dry.datasize && dry.datastart != dry.bootsize + dry.appsize)
|
||||
Retwarning("apptable section %s does not touch code section %s",
|
||||
str_ccinterval(dry.datastart, dry.datastart+dry.appsize-1),
|
||||
str_ccinterval(0, dry.bootsize+dry.appsize-1));
|
||||
} else {
|
||||
if(dry.datasize && dry.datastart != dry.appsize && dry.appstart !=0)
|
||||
Retwarning("apptable section %s does not touch application section %s",
|
||||
str_ccinterval(dry.datastart, dry.datastart+dry.appsize-1),
|
||||
str_ccinterval(dry.appstart, dry.appstart+dry.appsize-1));
|
||||
if(dry.datasize && dry.bootsize && dry.bootstart != dry.appsize + dry.datasize)
|
||||
Retwarning("apptable section %s does not touch boot section %s",
|
||||
str_ccinterval(dry.datastart, dry.datastart+dry.appsize-1),
|
||||
str_ccinterval(dry.bootstart, dry.bootstart+dry.bootsize-1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Write a vector table to flash addr and return number of bytes written
|
||||
static int putvectortable(const AVRPART *p, const AVRMEM *flm, int addr) {
|
||||
int vecsz = flm->size <= 8192? 2: 4, ret = p->n_interrupts * vecsz;
|
||||
int app = (ret + vecsz - 2)/2; // Distance to application in words
|
||||
|
||||
for(int i = 0; i < ret; i += vecsz) { // First store rjmps to after table
|
||||
flm->buf[addr + i] = app;
|
||||
flm->buf[addr + i + 1] = 0xc0 + (app>>8); // rjmp app, rjmp app, ...
|
||||
app -= vecsz/2;
|
||||
}
|
||||
for(int i=0; i < vecsz; i++) // Leave one vector gap
|
||||
flm->buf[addr + ret++] = ' ';
|
||||
|
||||
flm->buf[addr + ret++] = 0xff; // Put endless lopp as application
|
||||
flm->buf[addr + ret++] = 0xcf;
|
||||
|
||||
// Then round up to multiples of 32
|
||||
while(ret%32)
|
||||
flm->buf[addr + ret++] = ' ';
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Human-readable messages in flash shown with, eg, avrdude -c dryrun -p m168 -xinit -Uflash:r:-:I
|
||||
static const int u384[] = {
|
||||
0x00000800, 0x08000800, 0x1c4218ca, 0x08a5284a, 0x1842184e, 0x00000000, 0x00000000, 0x08010000,
|
||||
0x08010000, 0x08c53086, 0x00430942, 0x08653082,
|
||||
}, u512[] = {
|
||||
0x20000800, 0x20000800, 0xf71c7b51, 0x28a288d1, 0x28a28851, 0x28a28859, 0xc71c7856, 0x00000000,
|
||||
0x80020000, 0x80020000, 0x8f22f1cd, 0x80920a23, 0x870e0a21, 0x08120a21, 0x87a2f1c1, 0x00000000,
|
||||
}, bdata[] = {
|
||||
0x00000000, 0x00000001, 0x00000001, 0x08000001, 0x08000001, 0xfe381c1d, 0x08442223, 0x08824121,
|
||||
0x08824121, 0x08824121, 0x08442223, 0xf0381c1d, 0x00000000, 0x00000000, 0x00400000, 0x00400000,
|
||||
0x00400000, 0x00400000, 0x785c0e3c, 0x88621102, 0x84422081, 0xfc422081, 0x04422081, 0x04621102,
|
||||
0xf85c0e3c, 0x00000000, 0x00000000, 0x00000000,
|
||||
}, adata[] = {
|
||||
0x00000020, 0x00000020, 0x00040020, 0x00040020, 0x3c7f1e2e, 0x40042031, 0x40042021, 0x7c043e21,
|
||||
0x42042121, 0x42042131, 0xfc787e2e, 0x00000000, 0x00000000, 0x00000000,
|
||||
}, rocks[] = {
|
||||
0x00000004, 0x0000003c, 0x000000fc, 0x000007fc, 0x00001ffc, 0x0000ffe0, 0x0003ff00, 0x001ffc00,
|
||||
0x007fc000, 0x03fe0000, 0x07f00000, 0x07800000, 0x07e00000, 0x07fc0000, 0x03ff0000, 0x007fe000,
|
||||
0x001ffc00, 0x0003ff00, 0x0000ffe0, 0x00001ffc, 0x000007fc, 0x000000fc, 0x0000003c, 0x00000004,
|
||||
0x04000000, 0x07800000, 0x07e00000, 0x07fc0000, 0x07ff0000, 0x00ffe000, 0x003ff800, 0x0007ff00,
|
||||
0x0001ffc0, 0x00003ff8, 0x00000ffc, 0x000001fc, 0x0000007c, 0x000003fc, 0x00001ff8, 0x0000ffc0,
|
||||
0x0003ff00, 0x001ff800, 0x00ffe000, 0x03ff0000, 0x07fc0000, 0x07e00000, 0x07800000, 0x04000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x07fffffc, 0x07fffffc, 0x07fffffc, 0x07007000, 0x07007000,
|
||||
0x07007c00, 0x0700fe00, 0x0700ff00, 0x0781ffc0, 0x07c3cfe0, 0x03ffc3f0, 0x03ff81fc, 0x01ff00fc,
|
||||
0x007c003c, 0x0000001c, 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x07fffffc, 0x07fffffc,
|
||||
0x07fffffc, 0x0700001c, 0x0700001c, 0x0700001c, 0x0700003c, 0x03800038, 0x03c00078, 0x03e000f0,
|
||||
0x01f803f0, 0x00ffffe0, 0x003fff00, 0x0007f800, 0x00000000, 0x00000000, 0x00000000, 0x07ffff00,
|
||||
0x07ffffc0, 0x07fffff0, 0x000000f8, 0x00000038, 0x0000003c, 0x0000001c, 0x0000003c, 0x00000078,
|
||||
0x000000f8, 0x07fffff0, 0x07ffffc0, 0x07ffff00, 0x00000000, 0x00000000, 0x00000000, 0x07fffffc,
|
||||
0x07fffffc, 0x07fffffc, 0x0700001c, 0x0700001c, 0x0700001c, 0x0700003c, 0x03800038, 0x03c00078,
|
||||
0x03e000f0, 0x01f803f0, 0x00ffffe0, 0x003fff00, 0x0007f800, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x07fffffc, 0x07fffffc, 0x07fffffc, 0x0700e01c, 0x0700e01c, 0x0700e01c, 0x0700e01c, 0x0700e01c,
|
||||
0x0700e01c, 0x0700e01c, 0x0700001c, 0x0700001c, 0x0000001c, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x007ffffc, 0x007ffffc, 0x007ffffc, 0x00070000,
|
||||
0x000e0000, 0x001c0000, 0x00380000, 0x00380000, 0x00700000, 0x00700000, 0x007f0000, 0x007f0000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x0000fe00, 0x0007ffc0, 0x000fffe0, 0x003f01f8, 0x003c0078,
|
||||
0x0078003c, 0x0070001c, 0x0070001c, 0x0078003c, 0x003c0078, 0x003f01f8, 0x000fffe0, 0x0007ffc0,
|
||||
0x0000fe00, 0x00000000, 0x00000000, 0x00000000, 0x0000fe00, 0x0003ffc0, 0x000fffe0, 0x001f01f0,
|
||||
0x003c0078, 0x0078003c, 0x0070001c, 0x0070001c, 0x0070001c, 0x0078003c, 0x00380038, 0x00380038,
|
||||
0x00000000, 0x00000000, 0x00000000, 0xfffffffc, 0xfffffffc, 0xfffffffc, 0x00003000, 0x00007800,
|
||||
0x0000fc00, 0x0003fe00, 0x0007ff00, 0x000fcf80, 0x001f87c0, 0x007f03f0, 0x007e01f8, 0x007800fc,
|
||||
0x0070007c, 0x0060003c, 0x0040001c, 0x0000000c, 0x00000004, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000078, 0x000f8038, 0x001fc038, 0x003fe03c, 0x003fe01c, 0x0038f01c, 0x0078f01c, 0x0070701c,
|
||||
0x0070381c, 0x00703c1c, 0x00703c3c, 0x00701e78, 0x00781ff8, 0x00380fe0, 0x000003c0, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x7ffffc3c, 0x7ffffc3c, 0x7ffffc3c, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
};
|
||||
|
||||
const struct { const int *bits, n32; } banner[] = {
|
||||
{u384, sizeof u384/sizeof*u384},
|
||||
{u512, sizeof u512/sizeof*u512},
|
||||
{bdata, sizeof bdata/sizeof*bdata},
|
||||
{adata, sizeof adata/sizeof*adata},
|
||||
{rocks, sizeof rocks/sizeof*rocks},
|
||||
{rocks, sizeof rocks/sizeof*rocks}, // Sic, dummy entry for RND
|
||||
};
|
||||
|
||||
enum { U384, U512, BDATA, ADATA, ROCKS, RND };
|
||||
|
||||
/*
|
||||
* Given a bit stream, put a sequence of '@' or ' ' into flash; note they are
|
||||
* all benign opcodes that do not touch memory or the I/O area:
|
||||
* " ": and r2, r0
|
||||
* "@ ": and r4, r0
|
||||
* " @": sbci r18, 0
|
||||
* "@@": sbci r20, 0
|
||||
*/
|
||||
static void putbanner(const AVRMEM *flm, int addr, int n, int bi) {
|
||||
const int *bp = banner[bi].bits, len = n/10 + random()%(9*n/10);
|
||||
|
||||
for(int i=0; i<n; ) {
|
||||
int scan = bi == RND? random(): *bp;
|
||||
for(int j=0; j<32; j++) {
|
||||
flm->buf[addr++] = scan & 1? '@': ' ';
|
||||
scan >>= 1;
|
||||
if(++i == n)
|
||||
break;
|
||||
}
|
||||
if(++bp == banner[bi].bits + banner[bi].n32) {
|
||||
bp = banner[bi].bits;
|
||||
if(i > len) // Stop repeating banner after some threshold
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Is the opcode of benign nature, ie, not touching SRAM, I/O regs or flash?
|
||||
static int is_benign_opcode(int op) {
|
||||
static const struct { int mask, result; } benign[] = {
|
||||
{0xfc00, 0x0c00}, // 0000 11rd dddd rrrr: add Rd, Rr
|
||||
{0xfc00, 0x1c00}, // 0001 11rd dddd rrrr: adc Rd, Rr
|
||||
{0xff00, 0x9600}, // 1001 0110 KKdd KKKK: adiw Rd, K
|
||||
{0xfc00, 0x1800}, // 0001 10rd dddd rrrr: sub Rd, Rr
|
||||
{0xf000, 0x5000}, // 0101 KKKK dddd KKKK: subi Rd, K
|
||||
{0xfc00, 0x0800}, // 0000 10rd dddd rrrr: sbc Rd, Rr
|
||||
{0xf000, 0x4000}, // 0100 KKKK dddd KKKK: sbci Rd, K
|
||||
{0xff00, 0x9700}, // 1001 0111 KKdd KKKK: sbiw Rd, K
|
||||
{0xfc00, 0x2000}, // 0010 00rd dddd rrrr: and Rd, Rr
|
||||
{0xf000, 0x7000}, // 0111 KKKK dddd KKKK: andi Rd, K
|
||||
{0xfc00, 0x2800}, // 0010 10rd dddd rrrr: or Rd, Rr
|
||||
{0xf000, 0x6000}, // 0110 KKKK dddd KKKK: ori Rd, K
|
||||
{0xfc00, 0x2400}, // 0010 01rd dddd rrrr: eor Rd, Rr
|
||||
{0xfe0f, 0x9400}, // 1001 010d dddd 0000: com Rd
|
||||
{0xfe0f, 0x9401}, // 1001 010d dddd 0001: neg Rd
|
||||
{0xfe0f, 0x9403}, // 1001 010d dddd 0011: inc Rd
|
||||
{0xfe0f, 0x940a}, // 1001 010d dddd 1010: dec Rd
|
||||
{0xfc00, 0x9c00}, // 1001 11rd dddd rrrr: mul Rd, Rr
|
||||
{0xff00, 0x0200}, // 0000 0010 dddd rrrr: muls Rd, Rr
|
||||
{0xff88, 0x0300}, // 0000 0011 0ddd 0rrr: mulsu Rd, Rr
|
||||
{0xff88, 0x0308}, // 0000 0011 0ddd 1rrr: fmul Rd, Rr
|
||||
{0xff88, 0x0380}, // 0000 0011 1ddd 0rrr: fmuls Rd, Rr
|
||||
{0xff88, 0x0388}, // 0000 0011 1ddd 1rrr: fmulsu Rd, Rr
|
||||
// {0xff0f, 0x940b}, // 1001 0100 KKKK 1011: des K
|
||||
{0xfc00, 0x1000}, // 0001 00rd dddd rrrr: cpse Rd, Rr
|
||||
{0xfc00, 0x1400}, // 0001 01rd dddd rrrr: cp Rd, Rr
|
||||
{0xfc00, 0x0400}, // 0000 01rd dddd rrrr: cpc Rd, Rr
|
||||
{0xf000, 0x3000}, // 0011 KKKK dddd KKKK: cpi Rd, K
|
||||
{0xfe08, 0xfc00}, // 1111 110r rrrr 0bbb: sbrc Rr, b
|
||||
{0xfe08, 0xfe00}, // 1111 111r rrrr 0bbb: sbrs Rr, b
|
||||
{0xfc00, 0x2c00}, // 0010 11rd dddd rrrr: mov Rd, Rr
|
||||
{0xff00, 0x0100}, // 0000 0001 dddd rrrr: movw Rd, Rr
|
||||
{0xf000, 0xe000}, // 1110 KKKK dddd KKKK: ldi Rd, K
|
||||
{0xfe0f, 0x9406}, // 1001 010d dddd 0110: lsr Rd
|
||||
{0xfe0f, 0x9407}, // 1001 010d dddd 0111: ror Rd
|
||||
{0xfe0f, 0x9405}, // 1001 010d dddd 0101: asr Rd
|
||||
{0xfe0f, 0x9402}, // 1001 010d dddd 0010: swap Rd
|
||||
{0xfe08, 0xfa00}, // 1111 101d dddd 0bbb: bst Rr, b
|
||||
{0xfe08, 0xf800}, // 1111 100d dddd 0bbb: bld Rd, b
|
||||
{0xffff, 0x9408}, // 1001 0100 0000 1000: sec
|
||||
{0xffff, 0x9488}, // 1001 0100 1000 1000: clc
|
||||
{0xffff, 0x9428}, // 1001 0100 0010 1000: sen
|
||||
{0xffff, 0x94a8}, // 1001 0100 1010 1000: cln
|
||||
{0xffff, 0x9418}, // 1001 0100 0001 1000: sez
|
||||
{0xffff, 0x9498}, // 1001 0100 1001 1000: clz
|
||||
{0xffff, 0x94f8}, // 1001 0100 1111 1000: cli
|
||||
{0xffff, 0x9448}, // 1001 0100 0100 1000: ses
|
||||
{0xffff, 0x94c8}, // 1001 0100 1100 1000: cls
|
||||
{0xffff, 0x9438}, // 1001 0100 0011 1000: sev
|
||||
{0xffff, 0x94b8}, // 1001 0100 1011 1000: clv
|
||||
{0xffff, 0x9468}, // 1001 0100 0110 1000: set
|
||||
{0xffff, 0x94e8}, // 1001 0100 1110 1000: clt
|
||||
{0xffff, 0x9458}, // 1001 0100 0101 1000: seh
|
||||
{0xffff, 0x94d8}, // 1001 0100 1101 1000: clh
|
||||
{0xffff, 0x95a8}, // 1001 0101 1010 1000: wdr
|
||||
{0xffff, 0x0000}, // 0000 0000 0000 0000: nop
|
||||
};
|
||||
|
||||
for(size_t i = 0; i < sizeof benign/sizeof*benign; i++)
|
||||
if((op & benign[i].mask) == benign[i].result)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Put n/2 random benign opcodes into memory at addr
|
||||
static void putcode(const AVRMEM *flm, int addr, int n) {
|
||||
int i = 0, op;
|
||||
|
||||
if(n < 2)
|
||||
return;
|
||||
if(n < 4)
|
||||
goto endless;
|
||||
|
||||
for(; i < n/2 - 2; i++) {
|
||||
do {
|
||||
op = random() & 0xffff;
|
||||
} while(!is_benign_opcode(op));
|
||||
flm->buf[addr + 2*i] = op; // FIXME: relying on little endian here (and below)
|
||||
flm->buf[addr + 2*i + 1] = op>>8;
|
||||
}
|
||||
|
||||
flm->buf[addr+2*i] = 0;
|
||||
flm->buf[addr+2*i+1] = 0; // nop (in case last opcode was of skip-next-instruction type
|
||||
i++;
|
||||
|
||||
endless:
|
||||
flm->buf[addr+2*i] = 255;
|
||||
flm->buf[addr+2*i+1] = 0xcf; // rjmp .-2 (endless loop)
|
||||
}
|
||||
|
||||
|
||||
// Write valid opcodes to flash (banners for -xinit, random code for -xrandom)
|
||||
static void putflash(const PROGRAMMER *pgm, const AVRMEM *flm, int addr, int n, int bi) {
|
||||
if(dry.random) {
|
||||
switch(bi) {
|
||||
case U384: case U512: case BDATA: // Bootloader stuff, reduce code length a little
|
||||
n -= random()%(n/8);
|
||||
break;
|
||||
case ADATA: case ROCKS: // Set random code length in [n/4, n]
|
||||
n -= random()%(3*n/4);
|
||||
}
|
||||
if(bi != ADATA) {
|
||||
putcode(flm, addr, n);
|
||||
return;
|
||||
}
|
||||
bi = RND; // Make apptable data random @/space sequences
|
||||
}
|
||||
putbanner(flm, addr, n, bi);
|
||||
}
|
||||
|
||||
// Initialise a user writable memory other than flash or fuses
|
||||
static void putother(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, const char *str) {
|
||||
const char *name = avr_mem_name(p, m);
|
||||
int len = strlen(str);
|
||||
|
||||
if(len > m->size)
|
||||
len = m->size;
|
||||
if(len <= 0)
|
||||
return;
|
||||
|
||||
memset(m->buf, 0xff, m->size);
|
||||
|
||||
if(dry.random)
|
||||
putbanner(m, 0, m->size, RND);
|
||||
else
|
||||
for(int i = 0; i < m->size/3; i += len)
|
||||
if(m->size - i > len)
|
||||
memcpy(m->buf + i, str, len);
|
||||
|
||||
if((len = strlen(name)) > m->size)
|
||||
len = m->size;
|
||||
memcpy(m->buf+m->size-len, name, len);
|
||||
if(len < m->size)
|
||||
m->buf[m->size-len-1] = ' ';
|
||||
}
|
||||
|
||||
// Copy chunk in one flash memory to other overlapping flash memories (think XMEGA)
|
||||
static void sharedflash(const PROGRAMMER *pgm, const AVRMEM *fm, unsigned addr, int chunk) {
|
||||
for(LNODEID ln=lfirst(dry.dp->mem); ln; ln=lnext(ln)) {
|
||||
AVRMEM *m = ldata(ln);
|
||||
if(mem_is_in_flash(m) && fm != m) { // Overlapping region?
|
||||
unsigned int cpaddr = addr + fm->offset - m->offset;
|
||||
if(cpaddr < (unsigned int) m->size && cpaddr + chunk <= (unsigned int) m->size)
|
||||
memmove(m->buf+cpaddr, fm->buf+addr, chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void dryrun_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||
pmsg_debug("%s()\n", __func__);
|
||||
|
||||
AVRMEM *flm = avr_locate_flash(p);
|
||||
if(flm && flm->size >= 1024) {
|
||||
if(pgm->prog_modes & PM_SPM)
|
||||
dry.bl = (p->prog_modes & PM_UPDI)? DRY_BOTTOM: DRY_TOP;
|
||||
dry.blsize = flm->size/4;
|
||||
if(dry.blsize > 512)
|
||||
dry.blsize = 512;
|
||||
}
|
||||
if(dry.dp) // Already configured
|
||||
return;
|
||||
|
||||
if(!dry.dp) {
|
||||
unsigned char inifuses[16]; // For fuses, which is made up from fuse0, fuse1, ...
|
||||
AVRMEM *fusesm = NULL, *prodsigm = NULL, *calm;
|
||||
dry.dp = avr_dup_part(p); // Allocate dryrun part
|
||||
unsigned char inifuses[16]; // For fuses: made up from fuse0, fuse1, ...
|
||||
AVRMEM *m, *fusesm = NULL, *prodsigm = NULL, *calm;
|
||||
AVRPART *q = dry.dp = avr_dup_part(p); // Allocate dryrun part and abbreviate with q
|
||||
|
||||
memset(inifuses, 0xff, sizeof inifuses);
|
||||
// Initialise the device with factory setting and erase flash/EEPROM to 0xff
|
||||
for (LNODEID ln=lfirst(dry.dp->mem); ln; ln=lnext(ln)) {
|
||||
AVRMEM *m = ldata(ln);
|
||||
if(mem_is_in_flash(m) || mem_is_eeprom(m)) {
|
||||
memset(inifuses, 0xff, sizeof inifuses);
|
||||
srandom(dry.seed? dry.seed: time(NULL));
|
||||
|
||||
// Initialise the device with factory setting and erase flash/EEPROM to 0xff
|
||||
for (LNODEID ln=lfirst(q->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
if(mem_is_in_flash(m) || mem_is_eeprom(m)) {
|
||||
memset(m->buf, 0xff, m->size);
|
||||
} else if(mem_is_fuses(m)) {
|
||||
fusesm = m;
|
||||
} else if(mem_is_a_fuse(m) || mem_is_lock(m)) {
|
||||
// Lock, eg, can have 4 bytes: still allow initialisation from initval
|
||||
if(m->initval != -1 && m->size >=1 && m->size <= (int) sizeof(m->initval)) {
|
||||
memcpy(m->buf, &m->initval, m->size); // FIXME: relying on little endian here
|
||||
if(mem_is_a_fuse(m)) {
|
||||
int fno = mem_fuse_offset(m);
|
||||
for(int i = 0; i < m->size && fno+i < (int) sizeof inifuses; i++) // pdicfg has 2 bytes
|
||||
inifuses[fno+i] = m->initval >> 8*i;
|
||||
}
|
||||
} else {
|
||||
memset(m->buf, 0xff, m->size);
|
||||
// Overwrite ficticious bootloader section with block of endless loops
|
||||
if(dry.bl && (mem_is_boot(m) || mem_is_flash(m)))
|
||||
for(int i = dry.bl == DRY_TOP? m->size-dry.blsize: 0, end = i+dry.blsize, n = 0; i+1 < end; i+=2, n++)
|
||||
m->buf[i] = 255-n, m->buf[i+1] = 0xcf; // rjmp .-2, rjmp .-4, ...
|
||||
} else if(mem_is_fuses(m)) {
|
||||
fusesm = m;
|
||||
} else if(mem_is_a_fuse(m) || mem_is_lock(m)) {
|
||||
// Lock, eg, can have 4 bytes: still allow initialisation from initval
|
||||
if(m->initval != -1 && m->size >=1 && m->size <= (int) sizeof(m->initval)) {
|
||||
memcpy(m->buf, &m->initval, m->size); // FIXME: relying on little endian here
|
||||
if(mem_is_a_fuse(m)) {
|
||||
int fno = mem_fuse_offset(m);
|
||||
for(int i = 0; i < m->size && fno+i < (int) sizeof inifuses; i++) // pdicfg has 2 bytes
|
||||
inifuses[fno+i] = m->initval >> 8*i;
|
||||
}
|
||||
} else {
|
||||
memset(m->buf, 0xff, m->size);
|
||||
}
|
||||
} else if(mem_is_signature(m) && (int) sizeof(dry.dp->signature) == m->size) {
|
||||
memcpy(m->buf, dry.dp->signature, m->size);
|
||||
} else if(mem_is_calibration(m)) {
|
||||
memset(m->buf, 'U', m->size); // 'U' for uncalibrated or unknown :)
|
||||
} else if(mem_is_osc16err(m)) {
|
||||
memset(m->buf, 'e', m->size);
|
||||
} else if(mem_is_osc20err(m)) {
|
||||
memset(m->buf, 'E', m->size);
|
||||
} else if(mem_is_osccal16(m)) {
|
||||
memset(m->buf, 'o', m->size);
|
||||
} else if(mem_is_osccal20(m)) {
|
||||
memset(m->buf, 'O', m->size);
|
||||
} else if(mem_is_sib(m)) {
|
||||
memset(m->buf, 'S', m->size);
|
||||
} else if( mem_is_tempsense(m)) {
|
||||
memset(m->buf, 'T', m->size); // 'T' for temperature calibration values
|
||||
} else if(mem_is_sernum(m)) {
|
||||
for(int i = 0; i < m->size; i++) // Set serial number UTSRQPONM...
|
||||
m->buf[i] = 'U'-i >= 'A'? 'U'-i: 0xff;
|
||||
} else if(mem_is_sigrow(m) && m->size >= 6) {
|
||||
prodsigm = m;
|
||||
memset(m->buf, 0xff, m->size);
|
||||
if(p->prog_modes & PM_PDI) {
|
||||
m->buf[0] = m->buf[1] = 'U';
|
||||
} else if(!(p->prog_modes & PM_UPDI)) { // Classic parts: signature at even addresses
|
||||
for(int i=0; i<3; i++)
|
||||
m->buf[2*i] = dry.dp->signature[i];
|
||||
}
|
||||
} else if(mem_is_io(m)) { // Initialise reset values (if known)
|
||||
int nr;
|
||||
const Register_file_t *rf = avr_locate_register_file(p, &nr);
|
||||
if(rf)
|
||||
for(int i = 0; i < nr; i++)
|
||||
if(rf[i].initval != -1 && rf[i].size > 0 && rf[i].size < 5)
|
||||
if(rf[i].addr >= 0 && rf[i].addr+rf[i].size <= m->size)
|
||||
for(int k = 0; k < rf[i].size; k++) // FIXME: Assume little endian compiler
|
||||
m->buf[rf[i].addr+k] = ((unsigned char *) &rf[i].initval)[k];
|
||||
}
|
||||
}
|
||||
if(prodsigm) {
|
||||
if(p->prog_modes & PM_UPDI) {
|
||||
for (LNODEID ln=lfirst(dry.dp->mem); ln; ln=lnext(ln)) {
|
||||
AVRMEM *m = ldata(ln);
|
||||
if(m->buf == prodsigm->buf) // Skip prodsig memory
|
||||
continue;
|
||||
int off = m->offset - prodsigm->offset;
|
||||
int cpy = m->size;
|
||||
// Submemory of prodsig, eg, signature and tempsense? Copy into prodsig
|
||||
if(off >= 0 && off+cpy <= prodsigm->size)
|
||||
memcpy(prodsigm->buf + off, m->buf, cpy);
|
||||
}
|
||||
}
|
||||
if(!(p->prog_modes & (PM_PDI|PM_UPDI)) && (calm = avr_locate_calibration(dry.dp))) {
|
||||
// Calibration bytes of classic parts are interspersed with signature
|
||||
for(int i=0; i<calm->size; i++)
|
||||
if(2*i+1 < prodsigm->size)
|
||||
prodsigm->buf[2*i+1] = 'U';
|
||||
}
|
||||
}
|
||||
if(fusesm) {
|
||||
size_t fusz = fusesm->size;
|
||||
memcpy(fusesm->buf, inifuses, fusz < sizeof inifuses? fusz: sizeof inifuses);
|
||||
} else if(mem_is_signature(m) && (int) sizeof(q->signature) == m->size) {
|
||||
memcpy(m->buf, q->signature, m->size);
|
||||
} else if(mem_is_calibration(m)) {
|
||||
memset(m->buf, 'U', m->size); // 'U' for uncalibrated or unknown :)
|
||||
} else if(mem_is_osc16err(m)) {
|
||||
memset(m->buf, 'e', m->size);
|
||||
} else if(mem_is_osc20err(m)) {
|
||||
memset(m->buf, 'E', m->size);
|
||||
} else if(mem_is_osccal16(m)) {
|
||||
memset(m->buf, 'o', m->size);
|
||||
} else if(mem_is_osccal20(m)) {
|
||||
memset(m->buf, 'O', m->size);
|
||||
} else if(mem_is_sib(m)) {
|
||||
memset(m->buf, 'S', m->size);
|
||||
} else if( mem_is_tempsense(m)) {
|
||||
memset(m->buf, 'T', m->size); // 'T' for temperature calibration values
|
||||
} else if(mem_is_sernum(m)) {
|
||||
for(int i = 0; i < m->size; i++) // Set serial number UTSRQPONM...
|
||||
m->buf[i] = dry.random? 'A'+random()%26: 'U'-i >= 'A'? 'U'-i: 0xff;
|
||||
} else if(mem_is_sigrow(m) && m->size >= 6) {
|
||||
prodsigm = m;
|
||||
memset(m->buf, 0xff, m->size);
|
||||
// Classic parts: signature at even addresses
|
||||
int n = q->prog_modes & PM_TPI? 1: 2; // ... unless it's the TPI parts t102/t104
|
||||
if(q->prog_modes & PM_Classic)
|
||||
for(int i=0; i<3; i++)
|
||||
m->buf[n*i] = q->signature[i];
|
||||
} else if(mem_is_io(m)) { // Initialise reset values (if known)
|
||||
int nr;
|
||||
const Register_file *rf = avr_locate_register_file(q, &nr);
|
||||
if(rf)
|
||||
for(int i = 0; i < nr; i++)
|
||||
if(rf[i].initval != -1 && rf[i].size > 0 && rf[i].size < 5)
|
||||
if(rf[i].addr >= 0 && rf[i].addr+rf[i].size <= m->size)
|
||||
for(int k = 0; k < rf[i].size; k++) // FIXME: Assume little endian compiler
|
||||
m->buf[rf[i].addr+k] = ((unsigned char *) &rf[i].initval)[k];
|
||||
}
|
||||
}
|
||||
if(prodsigm) {
|
||||
if(q->prog_modes & (PM_UPDI | PM_PDI)) {
|
||||
for (LNODEID ln=lfirst(q->mem); ln; ln=lnext(ln)) {
|
||||
AVRMEM *m = ldata(ln);
|
||||
if(m->buf == prodsigm->buf) // Skip prodsig memory
|
||||
continue;
|
||||
int off = m->offset - prodsigm->offset;
|
||||
int cpy = m->size;
|
||||
// Submemory of prodsig, eg, signature and tempsense? Copy into prodsig
|
||||
if(off >= 0 && off+cpy <= prodsigm->size)
|
||||
memcpy(prodsigm->buf + off, m->buf, cpy);
|
||||
}
|
||||
}
|
||||
if((q->prog_modes & PM_Classic) && (calm = avr_locate_calibration(q))) {
|
||||
// Calibration bytes of classic parts are interspersed with signature
|
||||
int n, tpi = !!(q->prog_modes & PM_TPI); // ... unless it's the TPI parts t102/t104
|
||||
for(int i=0; i<calm->size; i++) {
|
||||
if((n = tpi? 3+i: 2*i+1) < prodsigm->size)
|
||||
prodsigm->buf[n] = 'U';
|
||||
}
|
||||
}
|
||||
if((q->prog_modes & PM_Classic) && (m = avr_locate_sernum(q))) { // m324pb/m328pb, t102/t104
|
||||
int off = m->offset - prodsigm->offset;
|
||||
int cpy = m->size;
|
||||
if(off >= 0 && off+cpy <= prodsigm->size)
|
||||
memcpy(prodsigm->buf + off, m->buf, cpy);
|
||||
}
|
||||
}
|
||||
if(fusesm) {
|
||||
size_t fusz = fusesm->size;
|
||||
memcpy(fusesm->buf, inifuses, fusz < sizeof inifuses? fusz: sizeof inifuses);
|
||||
}
|
||||
|
||||
return;
|
||||
// Is the programmer a bootloader?
|
||||
if((m = avr_locate_flash(q)) && m->size >= 1024 && (pgm->prog_modes & PM_SPM))
|
||||
dry.bl = (q->prog_modes & PM_UPDI)? DRY_BOTTOM: DRY_TOP;
|
||||
|
||||
// So that dryrun can emulate AVRDUDE page erase
|
||||
if(!(pgm->prog_modes & PM_SPM) && (q->prog_modes & (PM_PDI | PM_UPDI)))
|
||||
pgm->page_erase = dryrun_page_erase;
|
||||
|
||||
if(!dry.random && !dry.init) // OK, no further initialisation needed
|
||||
return;
|
||||
|
||||
int nc, bakverb = verbose;
|
||||
verbose = -123; // Silently retrieve uP_table[] entry and config list
|
||||
const Avrintel *up = avr_locate_uP(q);
|
||||
const Configitem *cp = avr_locate_configitems(q, &nc);
|
||||
verbose = bakverb;
|
||||
AVRMEM *flm = avr_locate_flash(q);
|
||||
AVRMEM *ee = avr_locate_eeprom(q);
|
||||
int incons = flm && up && (
|
||||
up->flashsize != flm->size || flm->size <= 0 ||
|
||||
(ee && (up->eeprompagesize != ee->page_size || ee->page_size <= 0)) ||
|
||||
up->nboots != q->n_boot_sections || up->nboots < 0 ||
|
||||
up->bootsize != q->boot_section_size || up->bootsize < 0 ||
|
||||
memcmp(up->sigs, q->signature, 3)
|
||||
);
|
||||
|
||||
// Ensure can use up and cp with impunity
|
||||
if(!flm || !up || incons || !cp) {
|
||||
pmsg_warning("%s for %s; not initialising memories beyond factory settings\n", !flm? "no flash":
|
||||
!up? "no uP_table[] entry": incons? "inconsistent upP_table[] entry": "no config table", q->desc);
|
||||
return;
|
||||
}
|
||||
|
||||
randflashconfig(pgm, q, up, cp, nc);
|
||||
if(flashlayout(pgm, q, flm, up, cp, nc) < 0)
|
||||
return;
|
||||
|
||||
int vtb = putvectortable(q, flm, dry.appstart), urbtsz = 0;
|
||||
|
||||
int urboot = random()%3 && dry.bootsize <= 512 && flm->size >= 1024 &&
|
||||
flm->size >= 4*dry.bootsize && (q->prog_modes & PM_Classic) && (q->prog_modes & PM_SPM);
|
||||
if(urboot) { // Give some classic parts a small bootloader
|
||||
int ps = flm->page_size;
|
||||
urbtsz = dry.bootsize? dry.bootsize: flm->size > 32768? 512: flm->size < 16384? 256: 384;
|
||||
urbtsz = (urbtsz + ps-1)/ps*ps;
|
||||
if(!dry.bootsize && !dry.datasize) {
|
||||
dry.bootsize += urbtsz;
|
||||
dry.appsize -= urbtsz;
|
||||
dry.bootstart = dry.appsize;
|
||||
}
|
||||
int ubaddr = dry.bootstart;
|
||||
putflash(pgm, flm, ubaddr, urbtsz, urbtsz==384? U384: U512);
|
||||
flm->buf[ubaddr] = 0xff; flm->buf[ubaddr+1] = 0xcf; // rjmp .-2
|
||||
} else if(dry.bootsize) {
|
||||
int btb = 0;
|
||||
if(dry.bootsize >= 2048)
|
||||
btb = putvectortable(q, flm, dry.bootstart);
|
||||
putflash(pgm, flm, dry.bootstart + btb, dry.bootsize - btb, BDATA);
|
||||
flm->buf[dry.bootstart] = 0xff; flm->buf[dry.bootstart+1] = 0xcf; // rjmp .-2
|
||||
}
|
||||
|
||||
if(dry.datasize) {
|
||||
putflash(pgm, flm, dry.datastart, dry.datasize, ADATA);
|
||||
}
|
||||
|
||||
putflash(pgm, flm, dry.appstart+vtb, dry.appsize-vtb-urbtsz, ROCKS);
|
||||
|
||||
for(int i = 0; i < flm->size; i += flm->page_size)
|
||||
sharedflash(pgm, flm, i, flm->page_size);
|
||||
|
||||
if((m = avr_locate_eeprom(q)))
|
||||
putother(pgm, q, m, "The quick brown fox jumps over the lazy dog. ");
|
||||
if((m = avr_locate_userrow(q)))
|
||||
putother(pgm, q, m, "The five boxing wizards jump quickly. ");
|
||||
if((m = avr_locate_bootrow(q)))
|
||||
putother(pgm, q, m, "Lorem ipsum dolor sit amet. ");
|
||||
|
||||
dry.initialised = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -290,7 +799,7 @@ static int dryrun_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||
Return("no dryrun device?");
|
||||
|
||||
if(n_bytes) {
|
||||
AVRMEM *dmem, *dm2;
|
||||
AVRMEM *dmem;
|
||||
int mchr, chunk;
|
||||
unsigned int end;
|
||||
|
||||
@@ -314,33 +823,14 @@ static int dryrun_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||
|
||||
for(; addr < end; addr += chunk) {
|
||||
chunk = end-addr < page_size? end-addr: page_size;
|
||||
// Return write error for protected bootloader region
|
||||
if(dry.bl && (mem_is_boot(m) || mem_is_flash(m)))
|
||||
if(dryrun_readonly(pgm, p, m, addr))
|
||||
if(memcmp(dmem->buf+addr, m->buf+addr, chunk))
|
||||
Return("Write error on protected bootloader region %s [0x%04x, 0x%04x]\n", m->desc,
|
||||
dry.bl == DRY_TOP? m->size-dry.blsize: 0, dry.bl == DRY_TOP? m->size-1: dry.blsize-1);
|
||||
// @@@ Check for bootloader write protection here
|
||||
|
||||
// Unless it is a bootloader flash looks like NOR-memory
|
||||
(mchr == 'F' && !dry.bl? memand: memcpy)(dmem->buf+addr, m->buf+addr, chunk);
|
||||
|
||||
// Copy chunk to overlapping XMEGA's apptable, application, boot and flash memories
|
||||
if(mchr == 'F') {
|
||||
if(mem_is_flash(dmem)) {
|
||||
for(LNODEID ln=lfirst(dry.dp->mem); ln; ln=lnext(ln)) {
|
||||
dm2 = ldata(ln);
|
||||
if(mem_is_in_flash(dm2) && !mem_is_flash(dm2)) { // Overlapping region?
|
||||
unsigned int cpaddr = addr + dmem->offset - dm2->offset;
|
||||
if(cpaddr < (unsigned int) dm2->size && cpaddr + chunk <= (unsigned int) dm2->size)
|
||||
memcpy(dm2->buf+cpaddr, dmem->buf+addr, chunk);
|
||||
}
|
||||
}
|
||||
} else if((dm2 = avr_locate_flash(dry.dp))) {
|
||||
unsigned int cpaddr = addr + dmem->offset - dm2->offset;
|
||||
if(cpaddr < (unsigned int) dm2->size && cpaddr + chunk <= (unsigned int) dm2->size)
|
||||
memcpy(dm2->buf+cpaddr, dmem->buf+addr, chunk);
|
||||
}
|
||||
}
|
||||
if(mchr == 'F')
|
||||
sharedflash(pgm, dmem, addr, chunk);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +905,7 @@ int dryrun_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
Return("cannot write byte to %s %s as address 0x%04lx outside range [0, 0x%04x]",
|
||||
dry.dp->desc, dmem->desc, addr, dmem->size-1);
|
||||
|
||||
if(!(p->prog_modes & (PM_UPDI | PM_aWire))) { // Initialise unused bits in classic & XMEGA parts
|
||||
if(p->prog_modes & (PM_Classic | PM_PDI)) { // Initialise unused bits in classic & XMEGA parts
|
||||
int bitmask = avr_mem_bitmask(dry.dp, dmem, addr);
|
||||
// Read-modify-write for bitmasked memory
|
||||
data = (data & bitmask) | (dmem->buf[addr] & ~bitmask);
|
||||
@@ -461,7 +951,7 @@ int dryrun_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
Return("cannot read byte %s %s as address 0x%04lx outside range [0, 0x%04x]",
|
||||
dry.dp->desc, dmem->desc, addr, dmem->size-1);
|
||||
|
||||
if(!dry.bl && (mem_is_io(dmem) || mem_is_sram(dmem)) && !(p->prog_modes & (PM_UPDI | PM_PDI)))
|
||||
if(!dry.bl && (mem_is_io(dmem) || mem_is_sram(dmem)) && (p->prog_modes & PM_Classic))
|
||||
Return("classic part io/sram memories cannot be read externally");
|
||||
|
||||
*value = dmem->buf[addr];
|
||||
@@ -502,7 +992,7 @@ static int dryrun_vfy_led(const PROGRAMMER *pgm, int value) {
|
||||
|
||||
|
||||
static void dryrun_display(const PROGRAMMER *pgm, const char *p_unused) {
|
||||
imsg_info("%c%s programmer for %s\n", toupper(*pgmid), pgmid+1, dry.dp? dry.dp->desc: partdesc? partdesc: "???");
|
||||
// imsg_info("%c%s programmer for %s\n", toupper(*pgmid), pgmid+1, dry.dp? dry.dp->desc: partdesc? partdesc: "???");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -520,12 +1010,9 @@ static int dryrun_readonly(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Bootloader restictions: emulate a bootloader for dryboot
|
||||
if(mem_is_boot(mem) || mem_is_flash(mem))
|
||||
if(dry.bl == DRY_TOP? (int) addr >= mem->size-dry.blsize: (int) addr < dry.blsize)
|
||||
return 1;
|
||||
// @@@ check for bootloader write protection
|
||||
|
||||
if(mem_is_in_fuses(mem) || mem_is_lock(mem))
|
||||
if(dry.initialised && (mem_is_in_fuses(mem) || mem_is_lock(mem)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -535,7 +1022,7 @@ static int dryrun_readonly(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
static void dryrun_setup(PROGRAMMER *pgm) {
|
||||
pmsg_debug("%s()\n", __func__);
|
||||
// Allocate dry
|
||||
pgm->cookie = mmt_malloc(sizeof(dryrun_t));
|
||||
pgm->cookie = mmt_malloc(sizeof(Dryrun_data));
|
||||
}
|
||||
|
||||
|
||||
@@ -546,6 +1033,56 @@ static void dryrun_teardown(PROGRAMMER *pgm) {
|
||||
}
|
||||
|
||||
|
||||
static int dryrun_parseextparams(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
int rc = 0;
|
||||
bool help = false;
|
||||
|
||||
for(LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *xpara = ldata(ln);
|
||||
|
||||
if(str_starts(xpara, "init")) {
|
||||
dry.init = 1;
|
||||
continue;
|
||||
}
|
||||
if(str_starts(xpara, "random")) {
|
||||
dry.random = 1;
|
||||
continue;
|
||||
}
|
||||
if(str_starts(xpara, "seed=")) {
|
||||
const char *errptr;
|
||||
int seed = str_int(strchr(xpara, '=')+1, STR_INT32, &errptr);
|
||||
if(errptr) {
|
||||
pmsg_error("cannot parse %s seed value: %s\n", xpara, errptr);
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
dry.seed = seed;
|
||||
continue;
|
||||
}
|
||||
if(str_eq(xpara, "help")) {
|
||||
help = true;
|
||||
rc = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
if(!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", xpara);
|
||||
rc = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x init Initialise memories with human-readable patterns (1, 2, 3)\n");
|
||||
msg_error(" -x random Initialise memories with random code/values (1, 3)\n");
|
||||
msg_error(" -x seed=<n> Seed random number generator with <n>, n>0, default time(NULL)\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
msg_error("Notes:\n");
|
||||
msg_error(" (1) -x init and -x random randomly configure flash wrt boot/data/code length\n");
|
||||
msg_error(" (2) Patterns can best be seen with fixed-width font on -U flash:r:-:I\n");
|
||||
msg_error(" (3) Choose, eg, -x seed=1 for reproducible flash configuration and output\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
const char dryrun_desc[] = "Dryrun programmer for testing avrdude";
|
||||
|
||||
void dryrun_initpgm(PROGRAMMER *pgm) {
|
||||
@@ -579,4 +1116,5 @@ void dryrun_initpgm(PROGRAMMER *pgm) {
|
||||
pgm->teardown = dryrun_teardown;
|
||||
pgm->term_keep_alive = dryrun_term_keep_alive;
|
||||
pgm->readonly = dryrun_readonly;
|
||||
pgm->parseextparams = dryrun_parseextparams;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2022 Stefan Rueger <stefan.rueger@dryruns.com>
|
||||
* Copyright (C) 2022 Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef dryrun_h__
|
||||
#define dryrun_h__
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef dryrun_private_h__
|
||||
#define dryrun_private_h__
|
||||
|
||||
|
||||
47
src/elf2tag
Executable file
47
src/elf2tag
Executable file
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Part of the AVRDUDE project https://github.com/avrdudes/avrdude
|
||||
# Published under GNU General Public License, version 2 (GPL-2.0)
|
||||
# Copyright (C) 2007 Johannes Bauer <JohannesBauer@gmx.de>
|
||||
# Copyright (C) 2024 Small modifications by Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
|
||||
progname=$(basename "$0")
|
||||
for pgm in sort grep awk avr-objdump avr-nm; do
|
||||
hash $pgm 2>/dev/null || { echo "$progname: $pgm does not seem to be installed, exiting"; exit 1; }
|
||||
done
|
||||
|
||||
if [ "$1" == "" ]; then
|
||||
cat <<END
|
||||
Syntax: $progname <file>.elf
|
||||
Function: output a tagfile suitable for the avrdude disasm -t=<tagfile> command
|
||||
Options: none
|
||||
END
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "# Automatically generated tagfile via ${progname} ${1}"
|
||||
avr-objdump -d "$1" | grep '<.*>:' | awk '{
|
||||
ADDR = strtonum("0x" $1);
|
||||
printf("0x%04x L %s\n", ADDR, substr($2, 2, length($2) - 3));
|
||||
}'
|
||||
echo
|
||||
avr-nm "$1" | grep '^0080' | sort | grep -Ev '_(_bss_start|_data_end|_data_start|_bss_end|edata|DATA_REGION_ORIGIN)' | awk '
|
||||
{
|
||||
ADDR = strtonum("0x" $1) - strtonum("0x800000");
|
||||
if (LAST != "") {
|
||||
STARTADDR = LAST;
|
||||
ENDADDR = ADDR - 1;
|
||||
SYMBOL = LASTSYM;
|
||||
SIZE = ENDADDR - STARTADDR + 1;
|
||||
if (SIZE == 1) {
|
||||
printf("0x%04x M B 1 %s\n", STARTADDR, SYMBOL);
|
||||
} else if (SIZE == 2) {
|
||||
printf("0x%04x M W 1 %s\n", STARTADDR, SYMBOL);
|
||||
} else {
|
||||
printf("0x%04x M B %d %s\n", STARTADDR, SIZE, SYMBOL);
|
||||
}
|
||||
|
||||
}
|
||||
LAST = ADDR;
|
||||
LASTSYM = $3;
|
||||
}'
|
||||
511
src/fileio.c
511
src/fileio.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2023 Stefan Rueger <stefan.rueger@urclocks.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <limits.h>
|
||||
@@ -150,10 +148,130 @@ FILEFMT fileio_format(char c) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Same as fileio_format(ch) but show error message with originator who and list possible formats
|
||||
FILEFMT fileio_format_with_errmsg(char ch, const char *who) {
|
||||
FILEFMT format = fileio_format(ch);
|
||||
if(format == FMT_ERROR) {
|
||||
pmsg_error("%sinvalid file format :%c; known formats are\n", who? who: "", ch);
|
||||
for(int f, c, i=0; i<62; i++) {
|
||||
c = i<10? '0'+i: (i&1? 'A': 'a') + (i-10)/2;
|
||||
f = fileio_format(c);
|
||||
if(f != FMT_ERROR)
|
||||
msg_error(" :%c %s\n", c, fileio_fmtstr(f));
|
||||
}
|
||||
}
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
// Multi-memory file flat address space layout (also used by avr-gcc's elf)
|
||||
|
||||
enum {
|
||||
MULTI_FLASH, MULTI_DATA, MULTI_EEPROM,
|
||||
MULTI_FUSES, MULTI_LOCK,
|
||||
MULTI_SIGROW, MULTI_USERROW, MULTI_BOOTROW,
|
||||
MULTI_N,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
unsigned base, size;
|
||||
const char *name;
|
||||
} mulmem[] = {
|
||||
{ 0, 0x800000, "flash"}, // rjmp/call can only address 8 MiB in AVR8 architectures
|
||||
{0x800000, 0x10000, "data"}, // IO/SRAM
|
||||
{0x810000, 0x10000, "EEPROM"},
|
||||
{0x820000, 0x10000, "fuses"},
|
||||
{0x830000, 0x10000, "lock"},
|
||||
{0x840000, 0x10000, "sigrow"},
|
||||
{0x850000, 0x10000, "userrow"},
|
||||
{0x860000, 0x10000, "bootrow"},
|
||||
};
|
||||
|
||||
#define ANY_MEM_SIZE (mulmem[MULTI_N-1].base + mulmem[MULTI_N-1].size)
|
||||
|
||||
#define MBASE(n) (mulmem[MULTI_ ## n].base)
|
||||
#define MSIZE(n) (mulmem[MULTI_ ## n].size)
|
||||
#define MEND(n) (MBASE(n) + MSIZE(n) - 1)
|
||||
|
||||
// Memory that holds all possible multi-memories as laid out above
|
||||
AVRMEM *fileio_any_memory(const char *name) {
|
||||
return avr_new_memory(name, ANY_MEM_SIZE);
|
||||
}
|
||||
|
||||
#define boffset(p, basemem) baseoffset((p), avr_locate_ ## basemem(p), # basemem)
|
||||
|
||||
static int baseoffset(const AVRPART *p, const AVRMEM *base, const char *memname) {
|
||||
if(!base)
|
||||
pmsg_error("failed to locate %s memory in %s\n", memname, p->desc);
|
||||
return base? base->offset: 0;
|
||||
}
|
||||
|
||||
// Extends where memory is put in flat address space of .elf files
|
||||
unsigned fileio_mem_offset(const AVRPART *p, const AVRMEM *mem) {
|
||||
if(mem->type == 0 && mem->size == (int) ANY_MEM_SIZE)
|
||||
return 0;
|
||||
|
||||
unsigned location =
|
||||
mem_is_in_flash(mem)? MBASE(FLASH) + mem->offset - boffset(p, flash):
|
||||
mem_is_io(mem) || mem_is_sram(mem)? MBASE(DATA) + mem->offset:
|
||||
mem_is_eeprom(mem)? MBASE(EEPROM):
|
||||
mem_is_in_fuses(mem)? MBASE(FUSES) + mem_fuse_offset(mem):
|
||||
mem_is_lock(mem)? MBASE(LOCK):
|
||||
// Classic parts intersperse signature and calibration bytes, this code places them together
|
||||
(p->prog_modes & PM_Classic) && mem_is_signature(mem)? MBASE(SIGROW):
|
||||
(p->prog_modes & PM_Classic) && mem_is_calibration(mem)? MBASE(SIGROW)+3:
|
||||
(p->prog_modes & PM_Classic) && mem_is_in_sigrow(mem)? MBASE(SIGROW)+0x10+mem->offset-boffset(p, sigrow):
|
||||
// XMEGA parts have signature separate from prodsig, place prodsig at +0x10 as above
|
||||
(p->prog_modes & PM_PDI) && mem_is_signature(mem)? MBASE(SIGROW):
|
||||
(p->prog_modes & PM_PDI) && mem_is_in_sigrow(mem)? MBASE(SIGROW)+0x10 + mem->offset - boffset(p, sigrow):
|
||||
(p->prog_modes & PM_UPDI) && mem_is_in_sigrow(mem)? MBASE(SIGROW) + mem->offset - boffset(p, sigrow):
|
||||
mem_is_sib(mem)? MBASE(SIGROW) + 0x1000: // Arbitrary 0x1000 offset in signature section for sib
|
||||
mem_is_userrow(mem)? MBASE(USERROW):
|
||||
mem_is_bootrow(mem)? MBASE(BOOTROW):
|
||||
~0U;
|
||||
|
||||
if(location == ~0U)
|
||||
pmsg_error("unable to locate %s's %s in multi-memory address space\n", p->desc, mem->desc);
|
||||
else if(location >= ANY_MEM_SIZE || location + mem->size > ANY_MEM_SIZE) { // Overflow
|
||||
pmsg_error("%s's %s location [0x%06x, 0x%06x] outside flat address space [0, 0x%06x]\n",
|
||||
p->desc, mem->desc, location, location + mem->size-1, ANY_MEM_SIZE-1);
|
||||
location = ~0U;
|
||||
} else if(location <= MEND(FLASH) && location + mem->size > MEND(FLASH)+1) {
|
||||
pmsg_error("%s's %s location [0x%06x, 0x%06x] straddles flash section boundary 0x%06x\n",
|
||||
p->desc, mem->desc, location, location + mem->size-1, MEND(FLASH)+1);
|
||||
location = ~0U;
|
||||
} else if(location > MEND(FLASH) && location/0x10000 != (location + mem->size-1)/0x10000) {
|
||||
pmsg_error("%s's %s memory location [0x%06x, 0x%06x] straddles memory section boundary 0x%02x0000\n",
|
||||
p->desc, mem->desc, location, location + mem->size-1, 1+location/0x10000);
|
||||
location = ~0U;
|
||||
}
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
static const char *memlabel(const AVRPART *p, const AVRMEM *m, unsigned addr, int n) {
|
||||
if(m->size < (int) ANY_MEM_SIZE) // Ordinary (single) memory
|
||||
return addr? NULL: m->desc;
|
||||
|
||||
// Inverse lookup of which memory could have been mapped to this address
|
||||
for(LNODEID lm = lfirst(p->mem); lm; lm = lnext(lm))
|
||||
if(fileio_mem_offset(p, (m = ldata(lm))) == addr && n == m->size)
|
||||
return avr_mem_name(p, m);
|
||||
|
||||
for(LNODEID lm = lfirst(p->mem); lm; lm = lnext(lm))
|
||||
if(fileio_mem_offset(p, (m = ldata(lm))) == addr)
|
||||
return avr_mem_name(p, m);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Tells lower level .hex/.srec routines whether to write intros/outros
|
||||
typedef enum {
|
||||
FIRST_SEG = 1,
|
||||
LAST_SEG = 2,
|
||||
} Segorder_t;
|
||||
} Segorder;
|
||||
|
||||
|
||||
static void print_ihex_extended_addr(int n_64k, FILE *outf) {
|
||||
@@ -163,6 +281,8 @@ static void print_ihex_extended_addr(int n_64k, FILE *outf) {
|
||||
fprintf(outf, ":02000004%02X%02X%02X\n", hi, lo, cksum);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Binary buffer to Intel Hex, see https://en.wikipedia.org/wiki/Intel_HEX
|
||||
*
|
||||
@@ -176,10 +296,10 @@ static void print_ihex_extended_addr(int n_64k, FILE *outf) {
|
||||
* Return the maximum memory address within mem->buf that was read from
|
||||
* plus one. If an error occurs, return -1.
|
||||
*/
|
||||
static int b2ihex(const unsigned char *buf, const Segment_t *segp, Segorder_t where,
|
||||
int recsize, int startaddr, const char *outfile_unused, FILE *outf,
|
||||
FILEFMT ffmt) {
|
||||
static int b2ihex(const AVRPART *p, const AVRMEM *mem, const Segment *segp, Segorder where,
|
||||
int recsize, int startaddr, const char *outfile_unused, FILE *outf, FILEFMT ffmt) {
|
||||
|
||||
const unsigned char *buf = mem->buf;
|
||||
int bufsize = segp->len;
|
||||
unsigned int nextaddr;
|
||||
int n, hiaddr, n_64k;
|
||||
@@ -208,7 +328,7 @@ static int b2ihex(const unsigned char *buf, const Segment_t *segp, Segorder_t wh
|
||||
|
||||
if (n) {
|
||||
fprintf(outf, ":%02X%04X00", n, nextaddr);
|
||||
unsigned char cksum = n + ((nextaddr >> 8) & 0x0ff) + (nextaddr & 0x0ff);
|
||||
unsigned char c, cksum = n + ((nextaddr >> 8) & 0x0ff) + (nextaddr & 0x0ff);
|
||||
for(int i=0; i<n; i++) {
|
||||
fprintf(outf, "%02X", buf[i]);
|
||||
cksum += buf[i];
|
||||
@@ -217,13 +337,23 @@ static int b2ihex(const unsigned char *buf, const Segment_t *segp, Segorder_t wh
|
||||
fprintf(outf, "%02X", cksum);
|
||||
|
||||
if(ffmt == FMT_IHXC) { /* Print comment with address and ASCII dump */
|
||||
const char *name = memlabel(p, mem, n_64k*0x10000 + nextaddr, n);
|
||||
|
||||
for(int i=n; i<recsize; i++)
|
||||
fprintf(outf, " ");
|
||||
fprintf(outf, " // %05x> ", n_64k*0x10000 + nextaddr);
|
||||
for(int i=0; i<n; i++) {
|
||||
unsigned char c = buf[i] & 0x7f;
|
||||
/* Print space as _ so that line is one word */
|
||||
putc(c == ' '? '_': c < ' ' || c == 0x7f? '.': c, outf);
|
||||
for(int i=0; i<n; i++)
|
||||
if(n < 9 && name)
|
||||
fprintf(outf, "%s0x%02x", i? " ": "", buf[i]);
|
||||
else
|
||||
putc((c = buf[i] & 0x7f) < ' ' || c == 0x7f? '.': c, outf);
|
||||
if(name) {
|
||||
fprintf(outf, " %s", name);
|
||||
if((str_eq(name, "sigrow") || str_eq(name, "signature")) && !nextaddr) {
|
||||
const char *mculist = str_ccmcunames_signature(buf, PM_ALL);
|
||||
if(*mculist)
|
||||
fprintf(outf, " (%s)", mculist);
|
||||
}
|
||||
}
|
||||
}
|
||||
putc('\n', outf);
|
||||
@@ -258,7 +388,6 @@ static int ihex_readrec(struct ihexsrec *ihex, char * rec) {
|
||||
int offset, len;
|
||||
char * e;
|
||||
unsigned char cksum;
|
||||
int rc;
|
||||
|
||||
len = strlen(rec);
|
||||
offset = 1;
|
||||
@@ -320,37 +449,62 @@ static int ihex_readrec(struct ihexsrec *ihex, char * rec) {
|
||||
if (e == buf || *e != 0)
|
||||
return -1;
|
||||
|
||||
rc = -cksum & 0x000000ff;
|
||||
pmsg_debug("read ihex record type 0x%02x at 0x%04x with %2d bytes and chksum 0x%02x (0x%02x)\n",
|
||||
ihex->rectyp, ihex->loadofs, ihex->reclen, ihex->cksum, -cksum & 0xff);
|
||||
|
||||
return rc;
|
||||
return -cksum & 0xff;
|
||||
}
|
||||
|
||||
|
||||
// Extract correct memory from large any memory assuming multi-memory model
|
||||
static int any2mem(const AVRPART *p, const AVRMEM *mem, const Segment *segp,
|
||||
const AVRMEM *any, unsigned maxsize) {
|
||||
|
||||
// Compute location for multi-memory file input
|
||||
unsigned location = maxsize > MEND(FLASH)+1? fileio_mem_offset(p, mem): 0;
|
||||
|
||||
if(location == ~0U)
|
||||
return -1;
|
||||
|
||||
unsigned ret = 0;
|
||||
// Copy over memory to right place and return highest written address plus one
|
||||
for(unsigned i = segp->addr, end = segp->addr + segp->len; i < end; i++)
|
||||
if(any->tags[location + i]) {
|
||||
mem->buf[i] = any->buf[location + i];
|
||||
mem->tags[i] = any->tags[location + i];
|
||||
ret = i+1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Intel Hex to binary buffer
|
||||
*
|
||||
* Given an open file 'inf' which contains Intel Hex formatted data,
|
||||
* parse the file and lay it out within the memory buffer pointed to
|
||||
* by mem->buf. The segment within buf, segp, is honoured; if data
|
||||
* were to fall outside of the memory segment, an error is generated.
|
||||
* Given an open file 'inf' which contains Intel Hex formatted data, parse
|
||||
* the file, which potentially contains many AVR memories, and lay it out
|
||||
* in a temporary AVR "any memory". This also determines whether inf
|
||||
* contains the AVR memory mem to write to. Only the segment within
|
||||
* mem->buf, segp, is written to.
|
||||
*
|
||||
* Return the maximum memory address within mem->buf that was written
|
||||
* plus one. If an error occurs, return -1.
|
||||
* Return 0 if nothing was written, otherwise the maximum memory address
|
||||
* within mem->buf that was written plus one. On error, return -1.
|
||||
*/
|
||||
static int ihex2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
const Segment_t *segp, unsigned int fileoffset, FILEFMT ffmt) {
|
||||
static int ihex2b(const char *infile, FILE *inf, const AVRPART *p, const AVRMEM *mem,
|
||||
const Segment *segp, unsigned int fileoffset, FILEFMT ffmt) {
|
||||
|
||||
const char *errstr;
|
||||
unsigned int nextaddr, baseaddr, maxaddr;
|
||||
int lineno, rc, digits;
|
||||
int lineno, rc;
|
||||
struct ihexsrec ihex;
|
||||
|
||||
lineno = 0;
|
||||
baseaddr = 0;
|
||||
maxaddr = 0;
|
||||
nextaddr = 0;
|
||||
digits = mem->size > 0x10000? 5: 4;
|
||||
rewind(inf);
|
||||
|
||||
AVRMEM *any = fileio_any_memory("any");
|
||||
|
||||
for(char *buffer; (buffer = str_fgets(inf, &errstr)); mmt_free(buffer)) {
|
||||
lineno++;
|
||||
@@ -363,48 +517,78 @@ static int ihex2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
if(rc < 0) {
|
||||
pmsg_error("invalid record at line %d of %s\n", lineno, infile);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
if(rc != ihex.cksum) {
|
||||
if(ffmt == FMT_IHEX) {
|
||||
pmsg_error("checksum mismatch at line %d of %s\n", lineno, infile);
|
||||
imsg_error("checksum=0x%02x, computed checksum=0x%02x\n", ihex.cksum, rc);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
// Just warn with more permissive format FMT_IHXC
|
||||
pmsg_notice("checksum mismatch at line %d of %s\n", lineno, infile);
|
||||
imsg_notice("checksum=0x%02x, computed checksum=0x%02x\n", ihex.cksum, rc);
|
||||
}
|
||||
|
||||
unsigned below = 0, anysize = any->size;
|
||||
switch (ihex.rectyp) {
|
||||
case 0: /* data record */
|
||||
if (fileoffset != 0 && ihex.loadofs + baseaddr < fileoffset) {
|
||||
pmsg_error("address 0x%04x out of range (below fileoffset 0x%x) at line %d of %s\n",
|
||||
if(ihex.loadofs + baseaddr < fileoffset) {
|
||||
if(!ovsigck) {
|
||||
pmsg_error("address 0x%06x below memory offset 0x%x at line %d of %s;\n",
|
||||
ihex.loadofs + baseaddr, fileoffset, lineno, infile);
|
||||
imsg_error("use -F to skip this check\n");
|
||||
mmt_free(buffer);
|
||||
goto error;
|
||||
}
|
||||
pmsg_warning("address 0x%06x below memory offset 0x%x at line %d of %s: ",
|
||||
ihex.loadofs + baseaddr, fileoffset, lineno, infile);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
below = fileoffset - baseaddr - ihex.loadofs;
|
||||
if(below < ihex.reclen) { // Clip record
|
||||
ihex.reclen -= below;
|
||||
ihex.loadofs += below;
|
||||
} else { // Nothing to write
|
||||
ihex.reclen = 0;
|
||||
}
|
||||
msg_warning("%s record\n", ihex.reclen? "clipping": "ignoring");
|
||||
}
|
||||
nextaddr = ihex.loadofs + baseaddr - fileoffset;
|
||||
unsigned int beg = segp->addr, end = segp->addr + segp->len-1;
|
||||
if(nextaddr < beg || nextaddr + ihex.reclen-1 > end) {
|
||||
pmsg_error("Intel Hex record [0x%0*x, 0x%0*x] out of range [0x%0*x, 0x%0*x]\n",
|
||||
digits, nextaddr, digits, nextaddr+ihex.reclen-1, digits, beg, digits, end);
|
||||
imsg_error("at line %d of %s\n", lineno, infile);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
if(ihex.reclen && nextaddr + ihex.reclen > anysize) {
|
||||
if(!ovsigck) {
|
||||
pmsg_error("Intel Hex record [0x%06x, 0x%06x] out of range [0, 0x%06x]\n",
|
||||
nextaddr, nextaddr+ihex.reclen-1, anysize-1);
|
||||
imsg_error("at line %d of %s; use -F to skip this check\n", lineno, infile);
|
||||
mmt_free(buffer);
|
||||
goto error;
|
||||
}
|
||||
pmsg_warning("Intel Hex record [0x%06x, 0x%06x] out of range [0, 0x%06x]: ",
|
||||
nextaddr, nextaddr+ihex.reclen-1, anysize-1);
|
||||
if(ihex.reclen && nextaddr + ihex.reclen > anysize) {
|
||||
unsigned above = nextaddr + ihex.reclen - anysize;
|
||||
ihex.reclen = above < ihex.reclen? ihex.reclen - above: 0; // Clip or zap
|
||||
}
|
||||
msg_warning("%s it\n", ihex.reclen? "clipping": "ignoring");
|
||||
}
|
||||
for(int i=0; i<ihex.reclen; i++) {
|
||||
mem->buf[nextaddr+i] = ihex.data[i];
|
||||
mem->tags[nextaddr+i] = TAG_ALLOCATED;
|
||||
any->buf[nextaddr+i] = ihex.data[below + i];
|
||||
any->tags[nextaddr+i] = TAG_ALLOCATED;
|
||||
}
|
||||
if (nextaddr+ihex.reclen > maxaddr)
|
||||
if(!ovsigck && nextaddr == mulmem[MULTI_SIGROW].base && ihex.reclen >= 3)
|
||||
if(!avr_sig_compatible(p->signature, any->buf+nextaddr)) {
|
||||
pmsg_error("signature of %s incompatible with file's (%s);\n", p->desc,
|
||||
str_ccmcunames_signature(any->buf+nextaddr, PM_ALL));
|
||||
imsg_error("use -F to override this check\n");
|
||||
mmt_free(buffer);
|
||||
goto error;
|
||||
}
|
||||
if(ihex.reclen && nextaddr+ihex.reclen > maxaddr)
|
||||
maxaddr = nextaddr+ihex.reclen;
|
||||
break;
|
||||
|
||||
case 1: /* end of file record */
|
||||
mmt_free(buffer);
|
||||
return maxaddr;
|
||||
goto done;
|
||||
|
||||
case 2: /* extended segment address record */
|
||||
baseaddr = (ihex.data[0] << 8 | ihex.data[1]) << 4;
|
||||
@@ -426,22 +610,32 @@ static int ihex2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
pmsg_error("do not know how to deal with rectype=%d "
|
||||
"at line %d of %s\n", ihex.rectyp, lineno, infile);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if(errstr) {
|
||||
pmsg_error("read error in Intel Hex file %s: %s\n", infile, errstr);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (maxaddr == 0) {
|
||||
pmsg_error("no valid record found in Intel Hex file %s\n", infile);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pmsg_warning("no end of file record found for Intel Hex file %s\n", infile);
|
||||
return maxaddr;
|
||||
|
||||
done:
|
||||
rc = any2mem(p, mem, segp, any, maxaddr);
|
||||
avr_free_mem(any);
|
||||
if(!rc)
|
||||
pmsg_warning("no %s data found in Intel Hex file %s\n", mem->desc, infile);
|
||||
return rc;
|
||||
|
||||
error:
|
||||
avr_free_mem(any);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static unsigned int cksum_srec(const unsigned char *buf, int n, unsigned addr, int addr_width) {
|
||||
@@ -458,12 +652,12 @@ static unsigned int cksum_srec(const unsigned char *buf, int n, unsigned addr, i
|
||||
|
||||
|
||||
// Binary to Motorola S-Record, see https://en.wikipedia.org/wiki/SREC_(file_format)
|
||||
static int b2srec(const AVRMEM *mem, const Segment_t *segp, Segorder_t where,
|
||||
static int b2srec(const AVRMEM *mem, const Segment *segp, Segorder where,
|
||||
int recsize, int startaddr, const char *outfile_unused, FILE *outf) {
|
||||
|
||||
const unsigned char *buf;
|
||||
unsigned int nextaddr;
|
||||
int n, hiaddr, addr_width, reccount;
|
||||
int n, hiaddr, addr_width;
|
||||
|
||||
buf = mem->buf + segp->addr;
|
||||
nextaddr = startaddr + segp->addr;
|
||||
@@ -500,9 +694,9 @@ static int b2srec(const AVRMEM *mem, const Segment_t *segp, Segorder_t where,
|
||||
for(int i = 0; i < len; i++)
|
||||
fprintf(outf, "%02X", s[i]);
|
||||
fprintf(outf, "%02X\n", cksum_srec((unsigned char *) s, len, 0, 2));
|
||||
cx->reccount = 0;
|
||||
}
|
||||
|
||||
reccount = 0;
|
||||
for(int bufsize = segp->len; bufsize; bufsize -= n) {
|
||||
n = recsize;
|
||||
if(n > bufsize)
|
||||
@@ -516,15 +710,15 @@ static int b2srec(const AVRMEM *mem, const Segment_t *segp, Segorder_t where,
|
||||
buf += n;
|
||||
nextaddr += n;
|
||||
hiaddr +=n;
|
||||
reccount++;
|
||||
cx->reccount++;
|
||||
}
|
||||
|
||||
// Add S5/6 record count record and S7/8/9 end of data record
|
||||
if(where & LAST_SEG) {
|
||||
if(reccount >= 0 && reccount <= 0xffffff) {
|
||||
int wd = reccount <= 0xffff? 2: 3;
|
||||
fprintf(outf, "S%c%02X%0*X%02X\n", '5' + (wd == 3), wd + 1, 2*wd, reccount,
|
||||
cksum_srec(NULL, 0, reccount, wd));
|
||||
if(cx->reccount >= 0 && cx->reccount <= 0xffffff) {
|
||||
int wd = cx->reccount <= 0xffff? 2: 3;
|
||||
fprintf(outf, "S%c%02X%0*X%02X\n", '5' + (wd == 3), wd + 1, 2*wd, cx->reccount,
|
||||
cksum_srec(NULL, 0, cx->reccount, wd));
|
||||
}
|
||||
fprintf(outf, "S%c%02X%0*X", endrec, addr_width + 1, 2*addr_width, startaddr);
|
||||
fprintf(outf, "%02X\n", cksum_srec(NULL, 0, startaddr, addr_width));
|
||||
@@ -608,20 +802,22 @@ static int srec_readrec(struct ihexsrec *srec, char *rec) {
|
||||
}
|
||||
|
||||
// Motorola S-Record to binary
|
||||
static int srec2b(const char *infile, FILE * inf,
|
||||
const AVRMEM *mem, const Segment_t *segp, unsigned int fileoffset) {
|
||||
static int srec2b(const char *infile, FILE * inf, const AVRPART *p,
|
||||
const AVRMEM *mem, const Segment *segp, unsigned int fileoffset) {
|
||||
|
||||
const char *errstr;
|
||||
unsigned int nextaddr, maxaddr;
|
||||
struct ihexsrec srec;
|
||||
int lineno, rc, digits, hexdigs;
|
||||
int lineno, rc, hexdigs;
|
||||
unsigned int reccount;
|
||||
unsigned char datarec;
|
||||
|
||||
lineno = 0;
|
||||
maxaddr = 0;
|
||||
reccount = 0;
|
||||
digits = mem->size > 0x10000? 5: 4;
|
||||
rewind(inf);
|
||||
|
||||
AVRMEM *any = fileio_any_memory("any");
|
||||
|
||||
for(char *buffer; (buffer = str_fgets(inf, &errstr)); mmt_free(buffer)) {
|
||||
lineno++;
|
||||
@@ -634,13 +830,13 @@ static int srec2b(const char *infile, FILE * inf,
|
||||
if(rc < 0) {
|
||||
pmsg_error("invalid record at line %d of %s\n", lineno, infile);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
if(rc != srec.cksum) {
|
||||
pmsg_error("checksum mismatch at line %d of %s\n", lineno, infile);
|
||||
imsg_error("checksum=0x%02x, computed checksum=0x%02x\n", srec.cksum, rc);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
datarec=0;
|
||||
@@ -666,14 +862,14 @@ static int srec2b(const char *infile, FILE * inf,
|
||||
case '4': // S4: symbol record (LSI extension)
|
||||
pmsg_error("not supported record at line %d of %s\n", lineno, infile);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
goto error;
|
||||
|
||||
case '5': // S5: count of S1, S2 and S3 records previously tx'd
|
||||
if (srec.loadofs != reccount){
|
||||
pmsg_error("count of transmitted data records mismatch at line %d of %s\n", lineno, infile);
|
||||
imsg_error("transmitted data records= %d, expected value= %d\n", reccount, srec.loadofs);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -681,37 +877,68 @@ static int srec2b(const char *infile, FILE * inf,
|
||||
case '8': // S8: end record for 24 bit addresses
|
||||
case '9': // S9: end record for 16 bit addresses
|
||||
mmt_free(buffer);
|
||||
return maxaddr;
|
||||
goto done;
|
||||
|
||||
default:
|
||||
pmsg_error("do not know how to deal with rectype S%d at line %d of %s\n",
|
||||
srec.rectyp, lineno, infile);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (datarec == 1) {
|
||||
nextaddr = srec.loadofs;
|
||||
unsigned below = 0, anysize = any->size;
|
||||
if (nextaddr < fileoffset) {
|
||||
pmsg_error("address 0x%0*x below memory offset at line %d of %s\n",
|
||||
hexdigs, nextaddr, lineno, infile);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
if(!ovsigck) {
|
||||
pmsg_error("address 0x%0*x below memory offset 0x%x at line %d of %s\n",
|
||||
hexdigs, nextaddr, fileoffset, lineno, infile);
|
||||
imsg_error("use -F to skip this check\n");
|
||||
mmt_free(buffer);
|
||||
goto error;
|
||||
}
|
||||
pmsg_warning("address 0x%0*x below memory offset 0x%x at line %d of %s: ",
|
||||
hexdigs, nextaddr, fileoffset, lineno, infile);
|
||||
below = fileoffset - nextaddr;
|
||||
if(below < srec.reclen) { // Clip record
|
||||
nextaddr += below;
|
||||
srec.reclen -= below;
|
||||
} else { // Ignore record
|
||||
srec.reclen = 0;
|
||||
}
|
||||
msg_warning("%s record\n", srec.reclen? "clipping": "ignoring");
|
||||
}
|
||||
nextaddr -= fileoffset;
|
||||
unsigned int beg = segp->addr, end = segp->addr + segp->len-1;
|
||||
if(nextaddr < beg || nextaddr + srec.reclen-1 > end) {
|
||||
pmsg_error("Motorola S-Record [0x%0*x, 0x%0*x] out of range [0x%0*x, 0x%0*x]\n",
|
||||
digits, nextaddr, digits, nextaddr+srec.reclen-1, digits, beg, digits, end);
|
||||
imsg_error("at line %d of %s\n", lineno, infile);
|
||||
mmt_free(buffer);
|
||||
return -1;
|
||||
if(srec.reclen && nextaddr + srec.reclen > anysize) {
|
||||
if(!ovsigck) {
|
||||
pmsg_error("Motorola S-Record [0x%06x, 0x%06x] out of range [0, 0x%06x]\n",
|
||||
nextaddr, nextaddr+srec.reclen-1, anysize-1);
|
||||
imsg_error("at line %d of %s; use -F to skip this check\n", lineno, infile);
|
||||
mmt_free(buffer);
|
||||
goto error;
|
||||
}
|
||||
pmsg_warning("Motorola S-Record [0x%06x, 0x%06x] out of range [0, 0x%06x]: ",
|
||||
nextaddr, nextaddr+srec.reclen-1, anysize-1);
|
||||
if(srec.reclen && nextaddr + srec.reclen > anysize) {
|
||||
unsigned above = nextaddr + srec.reclen - anysize;
|
||||
srec.reclen = above < srec.reclen? srec.reclen - above: 0; // Clip or zap
|
||||
}
|
||||
msg_warning("%s it\n", srec.reclen? "clipping": "ignoring");
|
||||
}
|
||||
for(int i=0; i<srec.reclen; i++) {
|
||||
mem->buf[nextaddr+i] = srec.data[i];
|
||||
mem->tags[nextaddr+i] = TAG_ALLOCATED;
|
||||
any->buf[nextaddr+i] = srec.data[below + i];
|
||||
any->tags[nextaddr+i] = TAG_ALLOCATED;
|
||||
}
|
||||
if (nextaddr+srec.reclen > maxaddr)
|
||||
if(!ovsigck && nextaddr == mulmem[MULTI_SIGROW].base && srec.reclen >= 3)
|
||||
if(!avr_sig_compatible(p->signature, any->buf+nextaddr)) {
|
||||
pmsg_error("signature of %s incompatible with file's (%s);\n", p->desc,
|
||||
str_ccmcunames_signature(any->buf+nextaddr, PM_ALL));
|
||||
imsg_error("use -F to override this check\n");
|
||||
mmt_free(buffer);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(srec.reclen && nextaddr+srec.reclen > maxaddr)
|
||||
maxaddr = nextaddr+srec.reclen;
|
||||
reccount++;
|
||||
}
|
||||
@@ -719,11 +946,20 @@ static int srec2b(const char *infile, FILE * inf,
|
||||
|
||||
if(errstr) {
|
||||
pmsg_error("read error in Motorola S-Record file %s: %s\n", infile, errstr);
|
||||
return -1;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pmsg_warning("no end of file record found for Motorola S-Records file %s\n", infile);
|
||||
return maxaddr;
|
||||
done:
|
||||
rc = any2mem(p, mem, segp, any, maxaddr);
|
||||
avr_free_mem(any);
|
||||
if(!rc)
|
||||
pmsg_warning("no %s data found in Motorola S-Record file %s\n", mem->desc, infile);
|
||||
return rc;
|
||||
|
||||
error:
|
||||
avr_free_mem(any);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -740,8 +976,7 @@ static int srec2b(const char *infile, FILE * inf,
|
||||
* the entire ELF file "as is" (including things like the program
|
||||
* header table itself).
|
||||
*/
|
||||
static inline
|
||||
int is_section_in_segment(Elf32_Shdr *sh, Elf32_Phdr *ph)
|
||||
static inline int is_section_in_segment(Elf32_Shdr *sh, Elf32_Phdr *ph)
|
||||
{
|
||||
if (sh->sh_offset < ph->p_offset)
|
||||
return 0;
|
||||
@@ -768,32 +1003,36 @@ static int elf_mem_limits(const AVRMEM *mem, const AVRPART *p,
|
||||
}
|
||||
} else {
|
||||
if (mem_is_in_flash(mem)) {
|
||||
*lowbound = 0;
|
||||
*highbound = 0x7Fffff; // Max 8 MiB
|
||||
*lowbound = MBASE(FLASH);
|
||||
*highbound = MEND(FLASH); // Max 8 MiB
|
||||
*fileoff = 0;
|
||||
} else if (mem_is_io(mem) || mem_is_sram(mem)) { // IO & SRAM in data space
|
||||
*lowbound = 0x800000 + mem->offset;
|
||||
*highbound = 0x80ffff;
|
||||
*lowbound = MBASE(DATA) + mem->offset;
|
||||
*highbound = MEND(DATA);
|
||||
*fileoff = 0;
|
||||
} else if (mem_is_eeprom(mem)) {
|
||||
*lowbound = 0x810000;
|
||||
*highbound = 0x81ffff; // Max 64 KiB
|
||||
*lowbound = MBASE(EEPROM);
|
||||
*highbound = MEND(EEPROM); // Max 64 KiB
|
||||
*fileoff = 0;
|
||||
} else if (mem_is_a_fuse(mem) || mem_is_fuses(mem)) {
|
||||
*lowbound = 0x820000;
|
||||
*highbound = 0x82ffff;
|
||||
*lowbound = MBASE(FUSES);
|
||||
*highbound = MEND(FUSES);
|
||||
*fileoff = mem_is_a_fuse(mem)? mem_fuse_offset(mem): 0;
|
||||
} else if (mem_is_lock(mem)) { // Lock or lockbits
|
||||
*lowbound = 0x830000;
|
||||
*highbound = 0x83ffff;
|
||||
*lowbound = MBASE(LOCK);
|
||||
*highbound = MEND(LOCK);
|
||||
*fileoff = 0;
|
||||
} else if (mem_is_signature(mem)) { // Read only
|
||||
*lowbound = 0x840000;
|
||||
*highbound = 0x84ffff;
|
||||
*lowbound = MBASE(SIGROW);
|
||||
*highbound = MEND(SIGROW);
|
||||
*fileoff = 0;
|
||||
} else if (mem_is_userrow(mem)) { // usersig or userrow
|
||||
*lowbound = 0x850000;
|
||||
*highbound = 0x85ffff;
|
||||
*lowbound = MBASE(USERROW);
|
||||
*highbound = MEND(USERROW);
|
||||
*fileoff = 0;
|
||||
} else if (mem_is_bootrow(mem)) {
|
||||
*lowbound = MBASE(BOOTROW);
|
||||
*highbound = MEND(BOOTROW);
|
||||
*fileoff = 0;
|
||||
} else {
|
||||
rv = -1;
|
||||
@@ -806,7 +1045,7 @@ static int elf_mem_limits(const AVRMEM *mem, const AVRPART *p,
|
||||
|
||||
// ELF format to binary (the memory segment to read into is ignored)
|
||||
static int elf2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
const AVRPART *p, const Segment_t *segp_unused, unsigned int fileoffset_unused) {
|
||||
const AVRPART *p, const Segment *segp_unused, unsigned int fileoffset_unused) {
|
||||
|
||||
Elf *e;
|
||||
int rv = 0, size = 0;
|
||||
@@ -857,16 +1096,16 @@ static int elf2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
}
|
||||
|
||||
const char *endianname;
|
||||
unsigned char endianess;
|
||||
unsigned char endianness;
|
||||
if (p->prog_modes & PM_aWire) { // AVR32
|
||||
endianess = ELFDATA2MSB;
|
||||
endianness = ELFDATA2MSB;
|
||||
endianname = "little";
|
||||
} else {
|
||||
endianess = ELFDATA2LSB;
|
||||
endianness = ELFDATA2LSB;
|
||||
endianname = "big";
|
||||
}
|
||||
if (id[EI_CLASS] != ELFCLASS32 ||
|
||||
id[EI_DATA] != endianess) {
|
||||
id[EI_DATA] != endianness) {
|
||||
pmsg_error("ELF file %s is not a 32-bit, %s-endian file that was expected\n",
|
||||
infile, endianname);
|
||||
goto done;
|
||||
@@ -921,8 +1160,8 @@ static int elf2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
if (ph[i].p_type != PT_LOAD || ph[i].p_filesz == 0)
|
||||
continue;
|
||||
|
||||
pmsg_notice2("considering PT_LOAD program header entry #%d\n", (int) i);
|
||||
imsg_notice2("p_vaddr 0x%x, p_paddr 0x%x, p_filesz %d\n", ph[i].p_vaddr, ph[i].p_paddr, ph[i].p_filesz);
|
||||
pmsg_debug("considering PT_LOAD program header entry #%d\n", (int) i);
|
||||
imsg_debug("p_vaddr 0x%x, p_paddr 0x%x, p_filesz %d\n", ph[i].p_vaddr, ph[i].p_paddr, ph[i].p_filesz);
|
||||
|
||||
Elf_Scn *scn = NULL;
|
||||
while ((scn = elf_nextscn(e, scn)) != NULL) {
|
||||
@@ -947,10 +1186,10 @@ static int elf2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
const char *sname = sndx? elf_strptr(e, sndx, sh->sh_name): "*unknown*";
|
||||
unsigned int lma = ph[i].p_paddr + sh->sh_offset - ph[i].p_offset;
|
||||
|
||||
pmsg_notice2("found section %s, LMA 0x%x, sh_size %u\n", sname, lma, sh->sh_size);
|
||||
pmsg_debug("found section %s, LMA 0x%x, sh_size %u\n", sname, lma, sh->sh_size);
|
||||
|
||||
if(!(lma >= low && lma + sh->sh_size < high)) {
|
||||
imsg_notice2("skipping %s (inappropriate for %s)\n", sname, mem->desc);
|
||||
pmsg_debug("skipping %s (inappropriate for %s)\n", sname, mem->desc);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
@@ -970,7 +1209,7 @@ static int elf2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
|
||||
Elf_Data *d = NULL;
|
||||
while ((d = elf_getdata(scn, d)) != NULL) {
|
||||
imsg_notice2("data block: d_buf %p, d_off 0x%x, d_size %ld\n",
|
||||
pmsg_debug("data block: d_buf %p, d_off 0x%x, d_size %ld\n",
|
||||
d->d_buf, (unsigned int)d->d_off, (long) d->d_size);
|
||||
if (mem->size == 1) {
|
||||
if (d->d_off != 0) {
|
||||
@@ -980,7 +1219,7 @@ static int elf2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
pmsg_error("ELF file section does not contain byte at offset %d\n", foff);
|
||||
rv = -1;
|
||||
} else {
|
||||
imsg_notice2("extracting one byte from file offset %d\n", foff);
|
||||
pmsg_debug("extracting one byte from file offset %d\n", foff);
|
||||
mem->buf[0] = ((unsigned char *)d->d_buf)[foff];
|
||||
mem->tags[0] = TAG_ALLOCATED;
|
||||
size = 1;
|
||||
@@ -992,7 +1231,7 @@ static int elf2b(const char *infile, FILE *inf, const AVRMEM *mem,
|
||||
if(idx >= 0 && idx < mem->size && end >= 0 && end <= mem->size && end-idx >= 0) {
|
||||
if (end > size)
|
||||
size = end;
|
||||
imsg_debug("writing %d bytes to mem offset 0x%x\n", end-idx, idx);
|
||||
pmsg_debug("writing %d bytes to mem offset 0x%x\n", end-idx, idx);
|
||||
memcpy(mem->buf + idx, d->d_buf, end-idx);
|
||||
memset(mem->tags + idx, TAG_ALLOCATED, end-idx);
|
||||
} else {
|
||||
@@ -1013,7 +1252,7 @@ done:
|
||||
|
||||
// Read/write binary files and return highest memory addr set + 1
|
||||
static int fileio_rbin(struct fioparms *fio, const char *filename, FILE *f,
|
||||
const AVRMEM *mem, const Segment_t *segp) {
|
||||
const AVRMEM *mem, const Segment *segp) {
|
||||
|
||||
int rc;
|
||||
switch (fio->op) {
|
||||
@@ -1041,7 +1280,7 @@ static int fileio_rbin(struct fioparms *fio, const char *filename, FILE *f,
|
||||
|
||||
|
||||
static int fileio_imm(struct fioparms *fio, const char *fname, FILE *f_unused,
|
||||
const AVRMEM *mem, const Segment_t *segp) {
|
||||
const AVRMEM *mem, const Segment *segp) {
|
||||
|
||||
char *tok, *p, *line;
|
||||
const char *errstr;
|
||||
@@ -1080,17 +1319,17 @@ static int fileio_imm(struct fioparms *fio, const char *fname, FILE *f_unused,
|
||||
|
||||
|
||||
static int fileio_ihex(struct fioparms *fio, const char *filename, FILE *f,
|
||||
const AVRMEM *mem, const Segment_t *segp, FILEFMT ffmt, Segorder_t where) {
|
||||
const AVRPART *p, const AVRMEM *mem, const Segment *segp, FILEFMT ffmt, Segorder where) {
|
||||
|
||||
int rc;
|
||||
|
||||
switch (fio->op) {
|
||||
case FIO_WRITE:
|
||||
rc = b2ihex(mem->buf, segp, where, 32, fio->fileoffset, filename, f, ffmt);
|
||||
rc = b2ihex(p, mem, segp, where, 32, fio->fileoffset, filename, f, ffmt);
|
||||
break;
|
||||
|
||||
case FIO_READ:
|
||||
rc = ihex2b(filename, f, mem, segp, fio->fileoffset, ffmt);
|
||||
rc = ihex2b(filename, f, p, mem, segp, fio->fileoffset, ffmt);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1103,7 +1342,7 @@ static int fileio_ihex(struct fioparms *fio, const char *filename, FILE *f,
|
||||
|
||||
|
||||
static int fileio_srec(struct fioparms *fio, const char *filename, FILE *f,
|
||||
const AVRMEM *mem, const Segment_t *segp, Segorder_t where) {
|
||||
const AVRPART* p, const AVRMEM *mem, const Segment *segp, Segorder where) {
|
||||
|
||||
int rc;
|
||||
|
||||
@@ -1113,7 +1352,7 @@ static int fileio_srec(struct fioparms *fio, const char *filename, FILE *f,
|
||||
break;
|
||||
|
||||
case FIO_READ:
|
||||
rc = srec2b(filename, f, mem, segp, fio->fileoffset);
|
||||
rc = srec2b(filename, f, p, mem, segp, fio->fileoffset);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1127,7 +1366,7 @@ static int fileio_srec(struct fioparms *fio, const char *filename, FILE *f,
|
||||
|
||||
#ifdef HAVE_LIBELF
|
||||
static int fileio_elf(struct fioparms *fio, const char *filename, FILE *f,
|
||||
const AVRMEM *mem, const AVRPART *p, const Segment_t *segp) {
|
||||
const AVRMEM *mem, const AVRPART *p, const Segment *segp) {
|
||||
|
||||
int rc;
|
||||
|
||||
@@ -1151,7 +1390,7 @@ static int fileio_elf(struct fioparms *fio, const char *filename, FILE *f,
|
||||
#endif
|
||||
|
||||
|
||||
static int b2num(const char *filename, FILE *f, const AVRMEM *mem, const Segment_t *segp, FILEFMT fmt) {
|
||||
static int b2num(const char *filename, FILE *f, const AVRMEM *mem, const Segment *segp, FILEFMT fmt) {
|
||||
const char *prefix;
|
||||
int base;
|
||||
|
||||
@@ -1215,7 +1454,7 @@ static int b2num(const char *filename, FILE *f, const AVRMEM *mem, const Segment
|
||||
}
|
||||
|
||||
|
||||
static int num2b(const char *filename, FILE *f, const AVRMEM *mem, const Segment_t *segp) {
|
||||
static int num2b(const char *filename, FILE *f, const AVRMEM *mem, const Segment *segp) {
|
||||
const char *geterr = NULL;
|
||||
char *line;
|
||||
int n = segp->addr, end = segp->addr + segp->len;
|
||||
@@ -1251,7 +1490,7 @@ static int num2b(const char *filename, FILE *f, const AVRMEM *mem, const Segment
|
||||
|
||||
|
||||
static int fileio_num(struct fioparms *fio, const char *filename, FILE *f,
|
||||
const AVRMEM *mem, const Segment_t *segp, FILEFMT fmt) {
|
||||
const AVRMEM *mem, const Segment *segp, FILEFMT fmt) {
|
||||
|
||||
switch (fio->op) {
|
||||
case FIO_WRITE:
|
||||
@@ -1410,6 +1649,16 @@ int fileio_fmt_autodetect(const char *fname) {
|
||||
}
|
||||
|
||||
|
||||
int fileio_mem(int op, const char *filename, FILEFMT format,
|
||||
const AVRPART *p, const AVRMEM *mem, int size) {
|
||||
|
||||
if(size < 0 || op == FIO_READ || op == FIO_READ_FOR_VERIFY)
|
||||
size = mem->size;
|
||||
|
||||
const Segment seg = {0, size};
|
||||
return fileio_segments(op, filename, format, p, mem, 1, &seg);
|
||||
}
|
||||
|
||||
|
||||
int fileio(int op, const char *filename, FILEFMT format,
|
||||
const AVRPART *p, const char *memstr, int size) {
|
||||
@@ -1420,16 +1669,12 @@ int fileio(int op, const char *filename, FILEFMT format,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(size < 0 || op == FIO_READ || op == FIO_READ_FOR_VERIFY)
|
||||
size = mem->size;
|
||||
|
||||
const Segment_t seg = {0, size};
|
||||
return fileio_segments(op, filename, format, p, mem, 1, &seg);
|
||||
return fileio_mem(op, filename, format, p, mem, size);
|
||||
}
|
||||
|
||||
|
||||
// Normalise segment address and length to be non-negative
|
||||
int segment_normalise(const AVRMEM *mem, Segment_t *segp) {
|
||||
int segment_normalise(const AVRMEM *mem, Segment *segp) {
|
||||
int addr = segp->addr, len = segp->len, maxsize = mem->size;
|
||||
int digits = maxsize > 0x10000? 5: 4;
|
||||
|
||||
@@ -1459,7 +1704,7 @@ int segment_normalise(const AVRMEM *mem, Segment_t *segp) {
|
||||
|
||||
|
||||
static int fileio_segments_normalise(int oprwv, const char *filename, FILEFMT format,
|
||||
const AVRPART *p, const AVRMEM *mem, int n, Segment_t *seglist) {
|
||||
const AVRPART *p, const AVRMEM *mem, int n, Segment *seglist) {
|
||||
|
||||
int op, rc;
|
||||
FILE * f;
|
||||
@@ -1489,7 +1734,7 @@ static int fileio_segments_normalise(int oprwv, const char *filename, FILEFMT fo
|
||||
int format_detect;
|
||||
|
||||
if (using_stdio) {
|
||||
pmsg_error("cannot auto detect file format when using stdin/out\n");
|
||||
pmsg_error("cannot auto detect file format when using stdin/out;\n");
|
||||
imsg_error("please specify a file format and try again\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1541,10 +1786,8 @@ static int fileio_segments_normalise(int oprwv, const char *filename, FILEFMT fo
|
||||
if(fio.op == FIO_READ) // Fill unspecified memory in segment
|
||||
memset(mem->buf+addr, 0xff, len);
|
||||
memset(mem->tags+addr, 0, len);
|
||||
Segorder_t where = 0;
|
||||
|
||||
if(i == 0)
|
||||
where |= FIRST_SEG;
|
||||
Segorder where = i == 0? FIRST_SEG: 0;
|
||||
if(i+1 == n)
|
||||
where |= LAST_SEG;
|
||||
|
||||
@@ -1552,11 +1795,11 @@ static int fileio_segments_normalise(int oprwv, const char *filename, FILEFMT fo
|
||||
switch(format) {
|
||||
case FMT_IHEX:
|
||||
case FMT_IHXC:
|
||||
thisrc = fileio_ihex(&fio, fname, f, mem, seglist+i, format, where);
|
||||
thisrc = fileio_ihex(&fio, fname, f, p, mem, seglist+i, format, where);
|
||||
break;
|
||||
|
||||
case FMT_SREC:
|
||||
thisrc = fileio_srec(&fio, fname, f, mem, seglist+i, where);
|
||||
thisrc = fileio_srec(&fio, fname, f, p, mem, seglist+i, where);
|
||||
break;
|
||||
|
||||
case FMT_RBIN:
|
||||
@@ -1610,9 +1853,9 @@ static int fileio_segments_normalise(int oprwv, const char *filename, FILEFMT fo
|
||||
}
|
||||
|
||||
int fileio_segments(int oprwv, const char *filename, FILEFMT format,
|
||||
const AVRPART *p, const AVRMEM *mem, int n, const Segment_t *list) {
|
||||
const AVRPART *p, const AVRMEM *mem, int n, const Segment *list) {
|
||||
|
||||
Segment_t *seglist = mmt_malloc(n*sizeof*seglist);
|
||||
Segment *seglist = mmt_malloc(n*sizeof*seglist);
|
||||
memcpy(seglist, list, n*sizeof*seglist);
|
||||
int ret = fileio_segments_normalise(oprwv, filename, format, p, mem, n, seglist);
|
||||
mmt_free(seglist);
|
||||
|
||||
28
src/flip1.c
28
src/flip1.c
@@ -19,8 +19,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -240,7 +238,7 @@ static int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||
}
|
||||
if (!ovsigck && (part->prog_modes & PM_PDI)) {
|
||||
pmsg_error("flip1 (FLIP protocol version 1) is for AT90USB* and ATmega*U* devices\n");
|
||||
imsg_error("for Xmega devices, use flip2 (or use -F to bypass this check)\n");
|
||||
imsg_error("for Xmega devices, use flip2 or use -F to bypass this check\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -336,7 +334,7 @@ static int flip1_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||
int aux_result;
|
||||
unsigned int default_timeout = FLIP1(pgm)->dfu->timeout;
|
||||
|
||||
pmsg_notice2("flip_chip_erase()\n");
|
||||
pmsg_debug("flip_chip_erase()\n");
|
||||
|
||||
struct flip1_cmd cmd = {
|
||||
FLIP1_CMD_WRITE_COMMAND, { 0, 0xff }
|
||||
@@ -471,7 +469,7 @@ static int flip1_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const A
|
||||
}
|
||||
|
||||
static int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem) {
|
||||
pmsg_notice2("flip1_read_sig_bytes(): ");
|
||||
pmsg_debug("%s(): ", __func__);
|
||||
|
||||
if (FLIP1(pgm)->dfu == NULL)
|
||||
return -1;
|
||||
@@ -494,7 +492,7 @@ static int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, cons
|
||||
FLIP1_CMD_READ_COMMAND, FLIP1_READ_FAMILY_CODE
|
||||
};
|
||||
|
||||
msg_notice2("from device\n");
|
||||
msg_debug("from device\n");
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
@@ -534,7 +532,7 @@ static int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, cons
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_notice2("cached\n");
|
||||
msg_debug("cached\n");
|
||||
}
|
||||
|
||||
memcpy(mem->buf, FLIP1(pgm)->part_sig, sizeof(FLIP1(pgm)->part_sig));
|
||||
@@ -573,7 +571,7 @@ static int flip1_read_memory(const PROGRAMMER *pgm,
|
||||
unsigned int default_timeout = dfu->timeout;
|
||||
|
||||
|
||||
pmsg_notice2("flip_read_memory(%s, 0x%04x, %d)\n", flip1_mem_unit_str(mem_unit), addr, size);
|
||||
pmsg_debug("flip_read_memory(%s, 0x%04x, %d)\n", flip1_mem_unit_str(mem_unit), addr, size);
|
||||
|
||||
/*
|
||||
* As this function is called once per page, no need to handle 64
|
||||
@@ -615,14 +613,8 @@ static int flip1_read_memory(const PROGRAMMER *pgm,
|
||||
|
||||
if (cmd_result < 0 && aux_result == 0 &&
|
||||
status.bStatus == DFU_STATUS_ERR_WRITE) {
|
||||
if (FLIP1(pgm)->security_mode_flag == 0) {
|
||||
msg_error("\n");
|
||||
pmsg_error("\n");
|
||||
imsg_error("***********************************************************************\n");
|
||||
imsg_error("Maybe the device is in ``security mode´´, and needs a chip erase first?\n");
|
||||
imsg_error("***********************************************************************\n");
|
||||
msg_error("\n");
|
||||
}
|
||||
if (FLIP1(pgm)->security_mode_flag == 0)
|
||||
pmsg_error("maybe the device is in security mode and needs a chip erase first?\n");
|
||||
FLIP1(pgm)->security_mode_flag = 1;
|
||||
}
|
||||
|
||||
@@ -664,7 +656,7 @@ static int flip1_write_memory(struct dfu_dev *dfu,
|
||||
unsigned int default_timeout = dfu->timeout;
|
||||
unsigned char *buf;
|
||||
|
||||
pmsg_notice2("flip_write_memory(%s, 0x%04x, %d)\n",
|
||||
pmsg_debug("flip_write_memory(%s, 0x%04x, %d)\n",
|
||||
flip1_mem_unit_str(mem_unit), addr, size);
|
||||
|
||||
if (size < 32) {
|
||||
@@ -764,7 +756,7 @@ static int flip1_set_mem_page(struct dfu_dev *dfu, unsigned short page_addr) {
|
||||
}
|
||||
|
||||
static const char *flip1_status_str(const struct dfu_status *status) {
|
||||
static const char *msg[] = {
|
||||
static const char * const msg[] = {
|
||||
"No error condition is present",
|
||||
"File is not targeted for use by this device",
|
||||
"File is for this device but fails some vendor-specific verification test",
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef flip1_h
|
||||
#define flip1_h
|
||||
|
||||
|
||||
42
src/flip2.c
42
src/flip2.c
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -232,9 +230,8 @@ static int flip2_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||
}
|
||||
|
||||
if (!ovsigck && !(part->prog_modes & PM_PDI)) {
|
||||
pmsg_error("flip2 (FLIP protocol version 2) is for Xmega devices\n");
|
||||
imsg_error("for AT90USB* or ATmega*U* devices, use flip1\n");
|
||||
imsg_error("(or use -F to bypass this check)\n");
|
||||
pmsg_error("flip2 (FLIP protocol version 2) is for Xmega devices;\n");
|
||||
imsg_error("for AT90USB* or ATmega*U* devices use flip1 or use -F to bypass this check\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -336,7 +333,7 @@ static int flip2_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||
int cmd_result = 0;
|
||||
int aux_result;
|
||||
|
||||
pmsg_notice2("flip_chip_erase()\n");
|
||||
pmsg_debug("flip_chip_erase()\n");
|
||||
|
||||
struct flip2_cmd cmd = {
|
||||
FLIP2_CMD_GROUP_EXEC, FLIP2_CMD_CHIP_ERASE, { 0xFF, 0, 0, 0 }
|
||||
@@ -494,6 +491,8 @@ static int flip2_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const A
|
||||
// Parse the -E option flag
|
||||
static int flip2_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
|
||||
char *cp, *s, *str = mmt_strdup(sp);
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
s = str;
|
||||
while ((cp = strtok(s, ","))) {
|
||||
@@ -506,12 +505,25 @@ static int flip2_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
|
||||
pgm->exit_reset = EXIT_RESET_DISABLED;
|
||||
continue;
|
||||
}
|
||||
if (str_eq(cp, "help")) {
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
if (!help) {
|
||||
pmsg_error("invalid exitspec parameter -E %s\n", cp);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s exitspec parameter options:\n", progname, pgmid);
|
||||
msg_error(" -E reset Application will not start automatically after programming session\n");
|
||||
msg_error(" -E noreset Application will start automatically after programming session\n");
|
||||
msg_error(" -E help Show this help menu and exit\n");
|
||||
mmt_free(str);
|
||||
return -1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
mmt_free(str);
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int flip2_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem) {
|
||||
@@ -555,9 +567,9 @@ static void flip2_show_info(struct flip2 *flip2) {
|
||||
(char) (flip2->part_rev / 26 - 1 + 'A'),
|
||||
(char) (flip2->part_rev % 26 + 'A'));
|
||||
|
||||
msg_info(" Bootloader version : 2.%hu.%hu\n",
|
||||
((unsigned short) flip2->boot_ver >> 4) & 0xF,
|
||||
((unsigned short) flip2->boot_ver >> 0) & 0xF);
|
||||
msg_info(" Bootloader version : 2.%u.%u\n",
|
||||
(flip2->boot_ver >> 4) & 0xF,
|
||||
(flip2->boot_ver >> 0) & 0xF);
|
||||
|
||||
msg_info(" USB max packet size : %hu\n",
|
||||
(unsigned short) flip2->dfu->dev_desc.bMaxPacketSize0);
|
||||
@@ -572,7 +584,7 @@ static int flip2_read_memory(struct dfu_dev *dfu,
|
||||
int read_size;
|
||||
int result;
|
||||
|
||||
pmsg_notice2("flip_read_memory(%s, 0x%04x, %d)\n", flip2_mem_unit_str(mem_unit), addr, size);
|
||||
pmsg_debug("flip_read_memory(%s, 0x%04x, %d)\n", flip2_mem_unit_str(mem_unit), addr, size);
|
||||
|
||||
result = flip2_set_mem_unit(dfu, mem_unit);
|
||||
|
||||
@@ -629,7 +641,7 @@ static int flip2_write_memory(struct dfu_dev *dfu,
|
||||
int write_size;
|
||||
int result;
|
||||
|
||||
pmsg_notice2("flip_write_memory(%s, 0x%04x, %d)\n", flip2_mem_unit_str(mem_unit), addr, size);
|
||||
pmsg_debug("flip_write_memory(%s, 0x%04x, %d)\n", flip2_mem_unit_str(mem_unit), addr, size);
|
||||
|
||||
result = flip2_set_mem_unit(dfu, mem_unit);
|
||||
|
||||
@@ -778,7 +790,7 @@ flip2_read_max1k_status:
|
||||
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
||||
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
||||
{
|
||||
pmsg_error("address out of range [0x%04hX,0x%04hX]\n", offset, offset+size-1);
|
||||
pmsg_error("address out of range [0x%04X,0x%04X]\n", offset, (offset+size-1) & 0xffff);
|
||||
} else
|
||||
pmsg_error("DFU status %s\n", flip2_status_str(&status));
|
||||
dfu_clrstatus(dfu);
|
||||
@@ -836,7 +848,7 @@ static int flip2_write_max1k(struct dfu_dev *dfu,
|
||||
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
||||
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
||||
{
|
||||
pmsg_error("address out of range [0x%04hX,0x%04hX]\n", offset, offset+size-1);
|
||||
pmsg_error("address out of range [0x%04X,0x%04X]\n", offset, (offset+size-1) & 0xffff);
|
||||
} else
|
||||
pmsg_error("DFU status %s\n", flip2_status_str(&status));
|
||||
dfu_clrstatus(dfu);
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef flip2_h
|
||||
#define flip2_h
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef freebsd_ppi_h
|
||||
#define freebsd_ppi_h
|
||||
|
||||
|
||||
36
src/ft245r.c
36
src/ft245r.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* AVRDUDE - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* some code:
|
||||
* Copyright (C) 2011-2012 Roger E. Wolff <R.E.Wolff@BitWizard.nl>
|
||||
*
|
||||
@@ -19,8 +19,6 @@
|
||||
*/
|
||||
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/* ft245r -- FT245R/FT232R Synchronous BitBangMode Programmer
|
||||
default pin assign
|
||||
FT232R / FT245R
|
||||
@@ -236,7 +234,7 @@ static int ft245r_flush(const PROGRAMMER *pgm) {
|
||||
avail = len;
|
||||
|
||||
#if FT245R_DEBUG
|
||||
msg_info("%s: writing %d bytes\n", __func__, avail);
|
||||
msg_notice("%s: writing %d bytes\n", __func__, avail);
|
||||
#endif
|
||||
rv = ftdi_write_data(my.handle, src, avail);
|
||||
if (rv != avail) {
|
||||
@@ -279,7 +277,7 @@ static int ft245r_recv(const PROGRAMMER *pgm, unsigned char *buf, size_t len) {
|
||||
ft245r_fill(pgm);
|
||||
|
||||
#if FT245R_DEBUG
|
||||
msg_info("%s: discarding %d, consuming %lu bytes\n", __func__, my.rx.discard, (unsigned long) len);
|
||||
msg_notice("%s: discarding %d, consuming %lu bytes\n", __func__, my.rx.discard, (unsigned long) len);
|
||||
#endif
|
||||
while (my.rx.discard > 0) {
|
||||
int result = ft245r_rx_buf_fill_and_get(pgm);
|
||||
@@ -378,7 +376,7 @@ static int ft245r_set_bitclock(const PROGRAMMER *pgm) {
|
||||
|
||||
r = ftdi_set_baudrate(my.handle, ftdi_rate);
|
||||
if (r) {
|
||||
msg_error("set baudrate %d failed with error '%s'\n", rate, ftdi_get_error_string (my.handle));
|
||||
msg_error("setting baudrate %d failed with error %s\n", rate, ftdi_get_error_string (my.handle));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -392,7 +390,7 @@ static int get_pin(const PROGRAMMER *pgm, int pinname) {
|
||||
if (ftdi_read_pins(my.handle, &byte) != 0)
|
||||
return -1;
|
||||
if (FT245R_DEBUG)
|
||||
msg_info("%s: in 0x%02x\n", __func__, byte);
|
||||
msg_notice("%s: in 0x%02x\n", __func__, byte);
|
||||
return GET_BITS_0(byte, pgm, pinname) != 0;
|
||||
}
|
||||
|
||||
@@ -790,23 +788,23 @@ static int ft245r_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||
for (i = 0; i < res_len; ++i)
|
||||
if ((ret = ft245r_tpi_rx(pgm, &res[i])) < 0)
|
||||
break;
|
||||
if (verbose >= 2) {
|
||||
msg_notice2("%s: [ ", __func__);
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("%s: [ ", __func__);
|
||||
for (i = 0; i < cmd_len; i++)
|
||||
msg_notice2("%02X ", cmd[i]);
|
||||
msg_notice2("] [ ");
|
||||
msg_debug("%02X ", cmd[i]);
|
||||
msg_debug("] [ ");
|
||||
for(i = 0; i < res_len; i++)
|
||||
msg_notice2("%02X ", res[i]);
|
||||
msg_notice2("]\n");
|
||||
msg_debug("%02X ", res[i]);
|
||||
msg_debug("]\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* lower 8 pins are accepted, they might be also inverted */
|
||||
static const struct pindef_t valid_pins = {{0xff}, {0xff}} ;
|
||||
static const struct pindef valid_pins = {{0xff}, {0xff}};
|
||||
|
||||
static const struct pin_checklist_t pin_checklist[] = {
|
||||
static const Pin_checklist pin_checklist[] = {
|
||||
{ PIN_AVR_SCK, 1, &valid_pins},
|
||||
{ PIN_AVR_SDO, 1, &valid_pins},
|
||||
{ PIN_AVR_SDI, 1, &valid_pins},
|
||||
@@ -830,12 +828,12 @@ static int ft245r_open(PROGRAMMER *pgm, const char *port) {
|
||||
|
||||
// read device string cut after 8 chars (max. length of serial number)
|
||||
if ((sscanf(port, "usb:%8s", device) != 1)) {
|
||||
pmsg_notice("ft245r_open(): no device identifier in portname, using default\n");
|
||||
pmsg_notice("%s(): no device identifier in portname, using default\n", __func__);
|
||||
pgm->usbsn = cache_string("");
|
||||
devnum = 0;
|
||||
} else {
|
||||
if (strlen(device) == 8 ){ // serial number
|
||||
pmsg_notice2("ft245r_open(): serial number parsed as: %s\n", device);
|
||||
pmsg_notice2("%s(): serial number parsed as: %s\n", __func__, device);
|
||||
// copy serial number to pgm struct
|
||||
pgm->usbsn = cache_string(device);
|
||||
// and use first device with matching serial (should be unique)
|
||||
@@ -848,13 +846,13 @@ static int ft245r_open(PROGRAMMER *pgm, const char *port) {
|
||||
if ((startptr==endptr) || (*endptr != '\0')) {
|
||||
devnum = -1;
|
||||
}
|
||||
pmsg_notice2("ft245r_open(): device number parsed as: %d\n", devnum);
|
||||
pmsg_notice2("%s(): device number parsed as: %d\n", __func__, devnum);
|
||||
}
|
||||
}
|
||||
|
||||
// if something went wrong before abort with helpful message
|
||||
if (devnum < 0) {
|
||||
pmsg_error("invalid portname '%s': use^ 'ft[0-9]+' or serial number\n", port);
|
||||
pmsg_error("invalid port name %s: use ft[0-9]+ or serial number\n", port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
245
src/jtag3.c
245
src/jtag3.c
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2012 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2017 Jan Egil Ruud <janegil.ruud@microchip.com>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,8 +18,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* avrdude interface for Atmel JTAGICE3 programmer
|
||||
*/
|
||||
@@ -206,7 +205,7 @@ static void jtag3_print_data(unsigned char *b, size_t s) {
|
||||
}
|
||||
|
||||
static void jtag3_prmsg(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
|
||||
if (verbose >= 4) {
|
||||
if (verbose >= MSG_TRACE) {
|
||||
size_t i;
|
||||
|
||||
msg_trace("Raw message:\n");
|
||||
@@ -336,7 +335,7 @@ static int jtag3_errcode(int reason) {
|
||||
}
|
||||
|
||||
static void jtag3_prevent(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
|
||||
if (verbose >= 4) {
|
||||
if (verbose >= MSG_TRACE) {
|
||||
size_t i;
|
||||
|
||||
msg_trace("Raw event:\n");
|
||||
@@ -430,7 +429,7 @@ int jtag3_send(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
|
||||
return jtag3_edbg_send(pgm, data, len);
|
||||
|
||||
msg_debug("\n");
|
||||
pmsg_debug("jtag3_send(): sending %lu bytes\n", (unsigned long) len);
|
||||
pmsg_debug("%s(): sending %lu bytes\n", __func__, (unsigned long) len);
|
||||
|
||||
buf = mmt_malloc(len + 4);
|
||||
buf[0] = TOKEN;
|
||||
@@ -454,20 +453,20 @@ static int jtag3_edbg_send(const PROGRAMMER *pgm, unsigned char *data, size_t le
|
||||
unsigned char status[USBDEV_MAX_XFER_3];
|
||||
int rv;
|
||||
|
||||
if (verbose >= 4) {
|
||||
if (verbose >= MSG_TRACE) {
|
||||
memset(buf, 0, USBDEV_MAX_XFER_3);
|
||||
memset(status, 0, USBDEV_MAX_XFER_3);
|
||||
}
|
||||
|
||||
msg_debug("\n");
|
||||
pmsg_debug("jtag3_edbg_send(): sending %lu bytes\n", (unsigned long) len);
|
||||
pmsg_debug("%s(): sending %lu bytes\n", __func__, (unsigned long) len);
|
||||
|
||||
/* 4 bytes overhead for CMD, fragment #, and length info */
|
||||
int max_xfer = pgm->fd.usb.max_xfer;
|
||||
|
||||
int nfragments = (len + max_xfer - 1) / max_xfer;
|
||||
if (nfragments > 1) {
|
||||
pmsg_debug("jtag3_edbg_send(): fragmenting into %d packets\n", nfragments);
|
||||
pmsg_debug("%s(): fragmenting into %d packets\n", __func__, nfragments);
|
||||
}
|
||||
int frag;
|
||||
for (frag = 0; frag < nfragments; frag++) {
|
||||
@@ -505,20 +504,20 @@ static int jtag3_edbg_send(const PROGRAMMER *pgm, unsigned char *data, size_t le
|
||||
}
|
||||
|
||||
if (serial_send(&pgm->fd, buf, max_xfer) != 0) {
|
||||
pmsg_notice("jtag3_edbg_send(): unable to send command to serial port\n");
|
||||
pmsg_notice("%s(): unable to send command to serial port\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
rv = serial_recv(&pgm->fd, status, max_xfer);
|
||||
|
||||
if (rv < 0) {
|
||||
/* timeout in receive */
|
||||
pmsg_notice2("jtag3_edbg_send(): timeout receiving packet\n");
|
||||
pmsg_notice2("%s(): timeout receiving packet\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
if (status[0] != EDBG_VENDOR_AVR_CMD ||
|
||||
(frag == nfragments - 1 && status[1] != 0x01)) {
|
||||
/* what to do in this case? */
|
||||
pmsg_notice("jtag3_edbg_send(): unexpected response 0x%02x, 0x%02x\n", status[0], status[1]);
|
||||
pmsg_notice("%s(): unexpected response 0x%02x, 0x%02x\n", __func__, status[0], status[1]);
|
||||
}
|
||||
data += this_len;
|
||||
len -= this_len;
|
||||
@@ -538,7 +537,7 @@ static int jtag3_edbg_prepare(const PROGRAMMER *pgm) {
|
||||
msg_debug("\n");
|
||||
pmsg_debug("jtag3_edbg_prepare()\n");
|
||||
|
||||
if (verbose >= 4)
|
||||
if (verbose >= MSG_TRACE)
|
||||
memset(buf, 0, USBDEV_MAX_XFER_3);
|
||||
|
||||
buf[0] = CMSISDAP_CMD_CONNECT;
|
||||
@@ -555,7 +554,7 @@ static int jtag3_edbg_prepare(const PROGRAMMER *pgm) {
|
||||
if (status[0] != CMSISDAP_CMD_CONNECT ||
|
||||
status[1] == 0)
|
||||
pmsg_error("unexpected response 0x%02x, 0x%02x\n", status[0], status[1]);
|
||||
pmsg_notice2("jtag3_edbg_prepare(): connection status 0x%02x\n", status[1]);
|
||||
pmsg_notice2("%s(): connection status 0x%02x\n", __func__, status[1]);
|
||||
|
||||
buf[0] = CMSISDAP_CMD_LED;
|
||||
buf[1] = CMSISDAP_LED_CONNECT;
|
||||
@@ -588,38 +587,38 @@ static int jtag3_edbg_signoff(const PROGRAMMER *pgm) {
|
||||
msg_debug("\n");
|
||||
pmsg_debug("jtag3_edbg_signoff()\n");
|
||||
|
||||
if (verbose >= 4)
|
||||
if (verbose >= MSG_TRACE)
|
||||
memset(buf, 0, USBDEV_MAX_XFER_3);
|
||||
|
||||
buf[0] = CMSISDAP_CMD_LED;
|
||||
buf[1] = CMSISDAP_LED_CONNECT;
|
||||
buf[2] = 0;
|
||||
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
|
||||
pmsg_notice("jtag3_edbg_signoff(): unable to send command to serial port\n");
|
||||
pmsg_notice("%s(): unable to send command to serial port\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
|
||||
if (rv != pgm->fd.usb.max_xfer) {
|
||||
pmsg_notice("jtag3_edbg_signoff(): unable to read from serial port (%d)\n", rv);
|
||||
pmsg_notice("%s(): unable to read from serial port (%d)\n", __func__, rv);
|
||||
return -1;
|
||||
}
|
||||
if (status[0] != CMSISDAP_CMD_LED ||
|
||||
status[1] != 0)
|
||||
pmsg_notice("jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n", status[0], status[1]);
|
||||
pmsg_notice("%s(): unexpected response 0x%02x, 0x%02x\n", __func__, status[0], status[1]);
|
||||
|
||||
buf[0] = CMSISDAP_CMD_DISCONNECT;
|
||||
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
|
||||
pmsg_notice("jtag3_edbg_signoff(): unable to send command to serial port\n");
|
||||
pmsg_notice("%s(): unable to send command to serial port\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
|
||||
if (rv != pgm->fd.usb.max_xfer) {
|
||||
pmsg_notice("jtag3_edbg_signoff(): unable to read from serial port (%d)\n", rv);
|
||||
pmsg_notice("%s(): unable to read from serial port (%d)\n", __func__, rv);
|
||||
return -1;
|
||||
}
|
||||
if (status[0] != CMSISDAP_CMD_DISCONNECT ||
|
||||
status[1] != 0)
|
||||
pmsg_notice("jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n", status[0], status[1]);
|
||||
pmsg_notice("%s(): unexpected response 0x%02x, 0x%02x\n", __func__, status[0], status[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -651,7 +650,7 @@ static int jtag3_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
rv = serial_recv(&pgm->fd, buf, pgm->fd.usb.max_xfer);
|
||||
|
||||
if (rv < 0) {
|
||||
pmsg_notice2("jtag3_recv_frame(): timeout receiving packet\n");
|
||||
pmsg_notice2("%s(): timeout receiving packet\n", __func__);
|
||||
mmt_free(buf);
|
||||
return -1;
|
||||
}
|
||||
@@ -680,7 +679,7 @@ static int jtag3_edbg_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
request[0] = EDBG_VENDOR_AVR_RSP;
|
||||
|
||||
if (serial_send(&pgm->fd, request, pgm->fd.usb.max_xfer) != 0) {
|
||||
pmsg_notice("jtag3_edbg_recv(): unable to send CMSIS-DAP vendor command\n");
|
||||
pmsg_notice("%s(): unable to send CMSIS-DAP vendor command\n", __func__);
|
||||
mmt_free(request);
|
||||
mmt_free(*msg);
|
||||
return -1;
|
||||
@@ -690,14 +689,14 @@ static int jtag3_edbg_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
|
||||
if (rv < 0) {
|
||||
/* timeout in receive */
|
||||
pmsg_notice2("jtag3_edbg_recv(): timeout receiving packet\n");
|
||||
pmsg_notice2("%s(): timeout receiving packet\n", __func__);
|
||||
mmt_free(*msg);
|
||||
mmt_free(request);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf[0] != EDBG_VENDOR_AVR_RSP) {
|
||||
pmsg_notice("jtag3_edbg_recv(): unexpected response 0x%02x\n", buf[0]);
|
||||
pmsg_notice("%s(): unexpected response 0x%02x\n", __func__, buf[0]);
|
||||
mmt_free(*msg);
|
||||
mmt_free(request);
|
||||
return -1;
|
||||
@@ -707,7 +706,7 @@ static int jtag3_edbg_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
// Documentation says:
|
||||
// "FragmentInfo 0x00 indicates that no response data is
|
||||
// available, and the rest of the packet is ignored."
|
||||
pmsg_notice("jtag3_edbg_recv(): no response available\n");
|
||||
pmsg_notice("%s(): no response available\n", __func__);
|
||||
mmt_free(*msg);
|
||||
mmt_free(request);
|
||||
return -1;
|
||||
@@ -720,8 +719,7 @@ static int jtag3_edbg_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
thisfrag = 1;
|
||||
} else {
|
||||
if (nfrags != (buf[1] & 0x0F)) {
|
||||
pmsg_notice("jtag3_edbg_recv(): "
|
||||
"Inconsistent # of fragments; had %d, now %d\n",
|
||||
pmsg_notice("%s(): inconsistent # of fragments; had %d, now %d\n", __func__,
|
||||
nfrags, (buf[1] & 0x0F));
|
||||
mmt_free(*msg);
|
||||
mmt_free(request);
|
||||
@@ -729,8 +727,7 @@ static int jtag3_edbg_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
}
|
||||
}
|
||||
if (thisfrag != ((buf[1] >> 4) & 0x0F)) {
|
||||
pmsg_notice("jtag3_edbg_recv(): "
|
||||
"inconsistent fragment number; expect %d, got %d\n",
|
||||
pmsg_notice("%s(): inconsistent fragment number; expect %d, got %d\n", __func__,
|
||||
thisfrag, ((buf[1] >> 4) & 0x0F));
|
||||
mmt_free(*msg);
|
||||
mmt_free(request);
|
||||
@@ -739,11 +736,11 @@ static int jtag3_edbg_recv_frame(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
|
||||
int thislen = (buf[2] << 8) | buf[3];
|
||||
if (thislen > rv + 4) {
|
||||
pmsg_notice("jtag3_edbg_recv(): unexpected length value (%d > %d)\n", thislen, rv + 4);
|
||||
pmsg_notice("%s(): unexpected length value (%d > %d)\n", __func__, thislen, rv + 4);
|
||||
thislen = rv + 4;
|
||||
}
|
||||
if (len + thislen > USBDEV_MAX_XFER_3) {
|
||||
pmsg_notice("jtag3_edbg_recv(): length exceeds max size (%d > %d)\n", len + thislen, USBDEV_MAX_XFER_3);
|
||||
pmsg_notice("%s(): length exceeds max size (%d > %d)\n", __func__, len + thislen, USBDEV_MAX_XFER_3);
|
||||
thislen = USBDEV_MAX_XFER_3 - len;
|
||||
}
|
||||
memmove(buf, buf + 4, thislen);
|
||||
@@ -765,7 +762,7 @@ int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
return rv;
|
||||
|
||||
if ((rv & USB_RECV_FLAG_EVENT) != 0) {
|
||||
if (verbose >= 3)
|
||||
if (verbose >= MSG_DEBUG)
|
||||
jtag3_prevent(pgm, *msg, rv & USB_RECV_LENGTH_MASK);
|
||||
|
||||
mmt_free(*msg);
|
||||
@@ -774,8 +771,7 @@ int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
|
||||
rv &= USB_RECV_LENGTH_MASK;
|
||||
r_seqno = ((*msg)[2] << 8) | (*msg)[1];
|
||||
pmsg_debug("jtag3_recv(): "
|
||||
"Got message seqno %d (command_sequence == %d)\n", r_seqno, PDATA(pgm)->command_sequence);
|
||||
pmsg_debug("%s(): got message seqno %d (command_sequence == %d)\n", __func__, r_seqno, PDATA(pgm)->command_sequence);
|
||||
if (r_seqno == PDATA(pgm)->command_sequence) {
|
||||
if (++(PDATA(pgm)->command_sequence) == 0xffff)
|
||||
PDATA(pgm)->command_sequence = 0;
|
||||
@@ -794,8 +790,7 @@ int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
|
||||
return rv;
|
||||
}
|
||||
pmsg_notice2("jtag3_recv(): "
|
||||
"got wrong sequence number, %u != %u\n", r_seqno, PDATA(pgm)->command_sequence);
|
||||
pmsg_notice2("%s(): got wrong sequence number, %u != %u\n", __func__, r_seqno, PDATA(pgm)->command_sequence);
|
||||
|
||||
mmt_free(*msg);
|
||||
}
|
||||
@@ -816,7 +811,7 @@ int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen
|
||||
if (status == 0)
|
||||
mmt_free(*resp);
|
||||
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||
} else if (verbose >= 3) {
|
||||
} else if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtag3_prmsg(pgm, *resp, status);
|
||||
} else {
|
||||
@@ -1010,7 +1005,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
if (pgm->fd.usb.max_xfer < USBDEV_MAX_XFER_3 && (pgm->flag & PGM_FL_IS_EDBG) == 0) {
|
||||
if (ovsigck) {
|
||||
pmsg_warning("JTAGICE3's firmware %d.%d is broken on USB 1.1 connections\n", parm[0], parm[1]);
|
||||
imsg_warning("forced to continue by option -F; THIS PUTS THE DEVICE'S DATA INTEGRITY AT RISK!\n");
|
||||
imsg_warning("forced to continue by option -F; this puts the device's data integrity at risk!\n");
|
||||
} else {
|
||||
pmsg_error("JTAGICE3's firmware %d.%d is broken on USB 1.1 connections\n", parm[0], parm[1]);
|
||||
return -1;
|
||||
@@ -1069,8 +1064,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
if (pgm->bitclock != 0.0 && PDATA(pgm)->set_sck != NULL) {
|
||||
unsigned int clock = 1E-3 / pgm->bitclock; /* kHz */
|
||||
pmsg_notice2("jtag3_initialize(): "
|
||||
"trying to set JTAG clock to %u kHz\n", clock);
|
||||
pmsg_notice2("%s(): trying to set JTAG clock to %u kHz\n", __func__, clock);
|
||||
parm[0] = clock & 0xff;
|
||||
parm[1] = (clock >> 8) & 0xff;
|
||||
if (PDATA(pgm)->set_sck(pgm, parm) < 0)
|
||||
@@ -1078,8 +1072,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
|
||||
if (conn == PARM3_CONN_JTAG) {
|
||||
pmsg_notice2("jtag3_initialize(): "
|
||||
"trying to set JTAG daisy-chain info to %d,%d,%d,%d\n",
|
||||
pmsg_notice2("%s(): trying to set JTAG daisy-chain info to %d,%d,%d,%d\n", __func__,
|
||||
PDATA(pgm)->jtagchain[0], PDATA(pgm)->jtagchain[1],
|
||||
PDATA(pgm)->jtagchain[2], PDATA(pgm)->jtagchain[3]);
|
||||
if (jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_JTAGCHAIN, PDATA(pgm)->jtagchain, 4) < 0)
|
||||
@@ -1118,7 +1111,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
imsg_info("Vtarg switch setting changed from %u to %u\n", PDATA(pgm)->vtarg_switch_data[0], PDATA(pgm)->vtarg_switch_data[1]);
|
||||
// Exit early is the target power switch is off and print sensible info message
|
||||
if (PDATA(pgm)->vtarg_switch_data[1] == 0) {
|
||||
imsg_info("Turn on the Vtarg switch to establish connection with the target\n\n");
|
||||
pmsg_info("turn on the Vtarg switch to establish connection with the target\n\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1183,8 +1176,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
u32_to_b4(xd.nvm_prod_sig_offset, m->offset);
|
||||
}
|
||||
}
|
||||
if(p->prog_modes & (PM_PDI | PM_UPDI))
|
||||
u32_to_b4(xd.nvm_data_offset, DATA_OFFSET);
|
||||
u32_to_b4(xd.nvm_data_offset, DATA_OFFSET);
|
||||
|
||||
if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0)
|
||||
return -1;
|
||||
@@ -1244,8 +1236,7 @@ static int jtag3_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
|
||||
// Generate UPDI high-voltage pulse if user asks for it and hardware supports it
|
||||
if (p->prog_modes & PM_UPDI &&
|
||||
PDATA(pgm)->use_hvupdi == true &&
|
||||
if (PDATA(pgm)->use_hvupdi == true &&
|
||||
p->hvupdi_variant != HV_UPDI_VARIANT_1) {
|
||||
parm[0] = PARM3_UPDI_HV_NONE;
|
||||
for (LNODEID ln = lfirst(pgm->hvupdi_support); ln; ln = lnext(ln)) {
|
||||
@@ -1451,27 +1442,26 @@ static void jtag3_disable(const PROGRAMMER *pgm) {
|
||||
|
||||
static void jtag3_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||
// Page erase only useful for classic parts with usersig mem or AVR8X/XMEGAs
|
||||
if(!(p->prog_modes & (PM_PDI | PM_UPDI)))
|
||||
if(p->prog_modes & PM_Classic)
|
||||
if(!avr_locate_usersig(p))
|
||||
pgm->page_erase = NULL;
|
||||
}
|
||||
|
||||
static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
for(ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
for(LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
if(str_starts(extended_param, "jtagchain=") && (pgm->prog_modes & (PM_JTAG | PM_XMEGAJTAG | PM_AVR32JTAG))) {
|
||||
unsigned int ub, ua, bb, ba;
|
||||
if(sscanf(extended_param, "jtagchain=%u,%u,%u,%u", &ub, &ua, &bb, &ba) != 4) {
|
||||
pmsg_error("invalid JTAG chain %s\n", extended_param);
|
||||
pmsg_error("invalid JTAG chain in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
pmsg_notice2("jtag3_parseextparms(): JTAG chain parsed as:\n");
|
||||
pmsg_notice2("%s(): JTAG chain parsed as:\n", __func__);
|
||||
imsg_notice2("%u units before, %u units after, %u bits before, %u bits after\n",
|
||||
ub, ua, bb, ba);
|
||||
PDATA(pgm)->jtagchain[0] = ub;
|
||||
@@ -1493,7 +1483,7 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
break;
|
||||
}
|
||||
if(!str_eq(extended_param, "hvupdi")) {
|
||||
pmsg_error("invalid -xhvupdi value %s. Use -xhvupdi\n", extended_param);
|
||||
pmsg_error("invalid assignment in -x %s; use -x hvupdi\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
@@ -1512,13 +1502,13 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
// Set SUFFER value
|
||||
if(str_starts(extended_param, "suffer=")) {
|
||||
if(sscanf(extended_param, "suffer=%hhi", PDATA(pgm)->suffer_data+1) < 1) {
|
||||
pmsg_error("invalid -xsuffer=<value> %s\n", extended_param);
|
||||
pmsg_error("invalid value in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
if((PDATA(pgm)->suffer_data[1] & 0x78) != 0x78) {
|
||||
PDATA(pgm)->suffer_data[1] |= 0x78;
|
||||
pmsg_info("setting -xsuffer=0x%02x so that reserved bits 3..6 are set\n",
|
||||
pmsg_info("setting -x suffer=0x%02x so that reserved bits 3..6 are set\n",
|
||||
PDATA(pgm)->suffer_data[1]);
|
||||
}
|
||||
PDATA(pgm)->suffer_set = true;
|
||||
@@ -1529,7 +1519,7 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
PDATA(pgm)->suffer_get = true;
|
||||
continue;
|
||||
}
|
||||
pmsg_error("invalid suffer setting %s. Use -xsuffer or -xsuffer=<arg>\n", extended_param);
|
||||
pmsg_error("invalid setting in -x %s; use -x suffer or -x suffer=<n>\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
@@ -1541,7 +1531,7 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
if(str_starts(extended_param, "vtarg_switch=")) {
|
||||
int sscanf_success = sscanf(extended_param, "vtarg_switch=%hhi", PDATA(pgm)->vtarg_switch_data+1);
|
||||
if(sscanf_success < 1 || PDATA(pgm)->vtarg_switch_data[1] > 1) {
|
||||
pmsg_error("invalid vtarg_switch value %s\n", extended_param);
|
||||
pmsg_error("invalid value in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
@@ -1553,7 +1543,7 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
PDATA(pgm)->vtarg_switch_get = true;
|
||||
continue;
|
||||
}
|
||||
pmsg_error("invalid vtarg_switch setting %s. Use -xvtarg_switch or -xvtarg_switch=<0..1>\n", extended_param);
|
||||
pmsg_error("invalid setting in -x %s; use -x vtarg_switch or -x vtarg_switch=<0..1>\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
@@ -1567,7 +1557,7 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
int sscanf_success = sscanf(extended_param, "vtarg=%lf", &vtarg_set_val);
|
||||
PDATA(pgm)->vtarg_data = (double)((int)(vtarg_set_val * 100 + .5)) / 100;
|
||||
if(sscanf_success < 1 || vtarg_set_val < 0) {
|
||||
pmsg_error("invalid vtarg value %s\n", extended_param);
|
||||
pmsg_error("invalid value in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
@@ -1579,7 +1569,7 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
PDATA(pgm)->vtarg_get = true;
|
||||
continue;
|
||||
}
|
||||
pmsg_error("invalid vtarg setting %s. Use -xvtarg or -xvtarg=<arg>\n", extended_param);
|
||||
pmsg_error("invalid setting in -x %s; use -x vtarg or -x vtarg=<dbl>\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
@@ -1597,37 +1587,43 @@ static int jtag3_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
PDATA(pgm)->pk4_snap_mode = PK4_SNAP_MODE_PIC;
|
||||
continue;
|
||||
}
|
||||
pmsg_error("invalid mode setting %s. Use -xmode=avr or -xmode=pic\n", extended_param);
|
||||
pmsg_error("invalid setting in -x %s; use -x mode=avr or -x mode=pic\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
if(str_eq(pgm->type, "JTAGICE3"))
|
||||
msg_error(" -xjtagchain=UB,UA,BB,BA Setup the JTAG scan chain order\n");
|
||||
if(lsize(pgm->hvupdi_support) > 1)
|
||||
msg_error(" -xhvupdi Enable high-voltage UPDI initialization\n");
|
||||
if(pgm->extra_features & HAS_SUFFER) {
|
||||
msg_error(" -xsuffer Read SUFFER register value\n");
|
||||
msg_error(" -xsuffer=<arg> Set SUFFER register value\n");
|
||||
}
|
||||
if(pgm->extra_features & HAS_VTARG_SWITCH) {
|
||||
msg_error(" -xvtarg_switch Read on-board target voltage switch state\n");
|
||||
msg_error(" -xvtarg_switch=<0..1> Set on-board target voltage switch state\n");
|
||||
}
|
||||
if(pgm->extra_features & HAS_VTARG_ADJ) {
|
||||
msg_error(" -xvtarg Read on-board target supply voltage\n");
|
||||
msg_error(" -xvtarg=<arg> Set on-board target supply voltage\n");
|
||||
}
|
||||
if(str_starts(pgmid, "pickit4") || str_starts(pgmid, "snap"))
|
||||
msg_error(" -xmode=avr|pic Set programmer to AVR or PIC mode, then exit\n");
|
||||
msg_error (" -xhelp Show this help menu and exit\n");
|
||||
return LIBAVRDUDE_EXIT;;
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
pmsg_error("invalid extended parameter %s\n", extended_param);
|
||||
rv = -1;
|
||||
if (!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
if(str_eq(pgm->type, "JTAGICE3")) {
|
||||
msg_error(" -x jtagchain=UB,UA,BB,BA Setup the JTAG scan chain order\n");
|
||||
msg_error(" UB/UA = units before/after, BB/BA = bits before/after\n");
|
||||
}
|
||||
if(lsize(pgm->hvupdi_support) > 1)
|
||||
msg_error(" -x hvupdi Enable high-voltage UPDI initialization\n");
|
||||
if(pgm->extra_features & HAS_SUFFER) {
|
||||
msg_error(" -x suffer Read SUFFER register value\n");
|
||||
msg_error(" -x suffer=<n> Set SUFFER register to <n> (0x.. hex, 0.. oct or dec)\n");
|
||||
}
|
||||
if(pgm->extra_features & HAS_VTARG_SWITCH) {
|
||||
msg_error(" -x vtarg_switch Read on-board target voltage switch state\n");
|
||||
msg_error(" -x vtarg_switch=<0..1> Set on-board target voltage switch state\n");
|
||||
}
|
||||
if(pgm->extra_features & HAS_VTARG_ADJ) {
|
||||
msg_error(" -x vtarg Read on-board target supply voltage\n");
|
||||
msg_error(" -x vtarg=<dbl> Set on-board target supply voltage to <dbl> V\n");
|
||||
}
|
||||
if(str_starts(pgmid, "pickit4") || str_starts(pgmid, "snap"))
|
||||
msg_error(" -x mode=avr|pic Set programmer to AVR or PIC mode, then exit\n");
|
||||
msg_error (" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
@@ -1712,7 +1708,7 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port, int mode_switch) {
|
||||
pmsg_error("%s in %s mode detected\n",
|
||||
pgmstr, pinfo.usbinfo.pid == bl_pid? "bootloader": "PIC");
|
||||
if(mode_switch == PK4_SNAP_MODE_AVR) {
|
||||
imsg_error("switching to AVR mode\n");
|
||||
imsg_error("switching to AVR mode; ");
|
||||
if(pinfo.usbinfo.pid == bl_pid)
|
||||
serial_send(&pgm->fd, exit_bl_cmd, sizeof(exit_bl_cmd));
|
||||
else {
|
||||
@@ -1720,10 +1716,10 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port, int mode_switch) {
|
||||
usleep(250*1000);
|
||||
serial_send(&pgm->fd, reset_cmd, sizeof(reset_cmd));
|
||||
}
|
||||
imsg_error("please run Avrdude again to continue the session\n\n");
|
||||
imsg_error("run %s again to continue the session\n\n", progname);
|
||||
} else {
|
||||
imsg_error("to switch into AVR mode try\n");
|
||||
imsg_error("avrdude -c%s -p%s -P%s -xmode=avr\n", pgmid, partdesc, port);
|
||||
pmsg_error("to switch into AVR mode try\n");
|
||||
imsg_error("$ %s -c%s -p%s -P%s -x mode=avr\n", progname, pgmid, partdesc, port);
|
||||
}
|
||||
serial_close(&pgm->fd);
|
||||
return LIBAVRDUDE_EXIT;;
|
||||
@@ -1749,7 +1745,7 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port, int mode_switch) {
|
||||
}
|
||||
|
||||
if (mode_switch == PK4_SNAP_MODE_AVR)
|
||||
pmsg_warning("programmer is already in AVR mode. Ignoring -xmode");
|
||||
pmsg_warning("programmer is already in AVR mode, ignoring -x mode");
|
||||
|
||||
// The event EP has been deleted by usb_open(), so we are
|
||||
// running on a CMSIS-DAP device, using EDBG protocol
|
||||
@@ -1767,13 +1763,13 @@ int jtag3_open_common(PROGRAMMER *pgm, const char *port, int mode_switch) {
|
||||
|
||||
// Switch from AVR to PIC mode
|
||||
if (mode_switch == PK4_SNAP_MODE_PIC) {
|
||||
imsg_error("switching to PIC mode\n");
|
||||
imsg_error("switching to PIC mode: ");
|
||||
unsigned char *resp, buf[] = {SCOPE_GENERAL, CMD3_FW_UPGRADE, 0x00, 0x00, 0x70, 0x6d, 0x6a};
|
||||
if (jtag3_command(pgm, buf, sizeof(buf), &resp, "enter PIC mode") < 0) {
|
||||
imsg_error("entering PIC mode failed\n");
|
||||
msg_error("entering PIC mode failed\n");
|
||||
return -1;
|
||||
}
|
||||
imsg_error("PIC mode switch successful\n");
|
||||
msg_error("PIC mode switch successful\n");
|
||||
serial_close(&pgm->fd);
|
||||
return LIBAVRDUDE_EXIT;;
|
||||
}
|
||||
@@ -1866,7 +1862,7 @@ static int jtag3_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AVRME
|
||||
|
||||
pmsg_notice2("jtag3_page_erase(.., %s, 0x%x)\n", m->desc, addr);
|
||||
|
||||
if(!(p->prog_modes & (PM_PDI | PM_UPDI)) && !mem_is_userrow(m)) {
|
||||
if((p->prog_modes & PM_Classic) && !mem_is_userrow(m)) {
|
||||
pmsg_error("page erase only available for AVR8X/XMEGAs or classic-part usersig mem\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1971,8 +1967,7 @@ static int jtag3_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRM
|
||||
block_size = maxaddr - addr;
|
||||
else
|
||||
block_size = page_size;
|
||||
pmsg_debug("jtag3_paged_write(): "
|
||||
"block_size at addr %d is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr %d is %d\n", __func__, addr, block_size);
|
||||
|
||||
if (dynamic_mtype)
|
||||
cmd[3] = jtag3_mtype(pgm, p, addr);
|
||||
@@ -2062,8 +2057,7 @@ static int jtag3_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRME
|
||||
block_size = maxaddr - addr;
|
||||
else
|
||||
block_size = page_size;
|
||||
pmsg_debug("jtag3_paged_load(): "
|
||||
"block_size at addr %d is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr %d is %d\n", __func__, addr, block_size);
|
||||
|
||||
if (dynamic_mtype)
|
||||
cmd[3] = jtag3_mtype(pgm, p, addr);
|
||||
@@ -2107,7 +2101,7 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
|
||||
paddr = jtag3_memaddr(pgm, p, mem, addr);
|
||||
if (paddr != addr)
|
||||
imsg_notice2("mapped to address: 0x%lx\n", paddr);
|
||||
imsg_debug("addr 0x%lx mapped to address 0x%lx\n", addr, paddr);
|
||||
paddr = 0;
|
||||
|
||||
if (mem->size < 1) {
|
||||
@@ -2130,13 +2124,13 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
|
||||
cmd[3] = p->prog_modes & (PM_PDI | PM_UPDI)? MTYPE_FLASH: MTYPE_FLASH_PAGE;
|
||||
if (mem_is_in_flash(mem)) {
|
||||
addr += mem->offset & (512 * 1024 - 1); /* max 512 KiB flash */
|
||||
addr += mem->offset & (512 * 1024 - 1); /* max 512 KiB flash @@@ could be max 8M */
|
||||
pagesize = PDATA(pgm)->flash_pagesize;
|
||||
paddr = addr & ~(pagesize - 1);
|
||||
paddr_ptr = &PDATA(pgm)->flash_pageaddr;
|
||||
cache_ptr = PDATA(pgm)->flash_pagecache;
|
||||
} else if (mem_is_eeprom(mem)) {
|
||||
if ( (pgm->flag & PGM_FL_IS_DW) || (p->prog_modes & PM_PDI) || (p->prog_modes & PM_UPDI) ) {
|
||||
if ((pgm->flag & PGM_FL_IS_DW) || (p->prog_modes & (PM_PDI | PM_UPDI))) {
|
||||
cmd[3] = MTYPE_EEPROM;
|
||||
} else {
|
||||
cmd[3] = MTYPE_EEPROM_PAGE;
|
||||
@@ -2166,19 +2160,7 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
if (pgm->flag & PGM_FL_IS_DW)
|
||||
unsupp = 1;
|
||||
}
|
||||
} else if (mem_is_sernum(mem)) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (mem_is_osccal16(mem)) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (mem_is_osccal20(mem)) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (mem_is_tempsense(mem)) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (mem_is_osc16err(mem)) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (mem_is_osc20err(mem)) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (mem_is_calibration(mem)) {
|
||||
} else if ((p->prog_modes & PM_Classic) && mem_is_calibration(mem)) { // Classic part calibration
|
||||
cmd[3] = MTYPE_OSCCAL_BYTE;
|
||||
if (pgm->flag & PGM_FL_IS_DW)
|
||||
unsupp = 1;
|
||||
@@ -2225,6 +2207,11 @@ static int jtag3_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM
|
||||
msg_error("address out of range for signature memory: %lu\n", addr);
|
||||
return -1;
|
||||
}
|
||||
} else if(mem_is_in_sigrow(mem)) { // sigrow sub-memories but not signature nor sigrow itself
|
||||
cmd[3] = (p->prog_modes & PM_UPDI)? MTYPE_SIGN_JTAG: MTYPE_PRODSIG;
|
||||
AVRMEM *sigrow = avr_locate_sigrow(p);
|
||||
if(sigrow)
|
||||
addr += mem->offset - sigrow->offset; // Adjust offset for parent memory
|
||||
} else {
|
||||
pmsg_error("unknown memory %s\n", mem->desc);
|
||||
return -1;
|
||||
@@ -2484,7 +2471,7 @@ int jtag3_getparm(const PROGRAMMER *pgm, unsigned char scope,
|
||||
|
||||
c = resp[1];
|
||||
if (c != RSP3_DATA || status < 3) {
|
||||
pmsg_notice("jtag3_getparm(): bad response to %s\n", descr);
|
||||
pmsg_notice("%s(): bad response to %s\n", __func__, descr);
|
||||
mmt_free(resp);
|
||||
return -1;
|
||||
}
|
||||
@@ -2551,7 +2538,7 @@ int jtag3_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *sib) {
|
||||
|
||||
memcpy(sib, resp+3, AVR_SIBLEN);
|
||||
sib[AVR_SIBLEN-1] = 0; // Zero terminate string
|
||||
pmsg_debug("jtag3_read_sib(): received SIB: %s\n", sib);
|
||||
pmsg_debug("%s(): received SIB: %s\n", __func__, sib);
|
||||
mmt_free(resp);
|
||||
return 0;
|
||||
}
|
||||
@@ -2573,7 +2560,7 @@ int jtag3_read_chip_rev(const PROGRAMMER *pgm, const AVRPART *p, unsigned char *
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmsg_debug("jtag3_read_chip_rev(): received chip silicon revision: 0x%02x\n", *chip_rev);
|
||||
pmsg_debug("%s(): received chip silicon revision: 0x%02x\n", __func__, *chip_rev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2590,7 +2577,7 @@ int jtag3_set_vtarget(const PROGRAMMER *pgm, double v) {
|
||||
uaref = b2_to_u16(buf);
|
||||
u16_to_b2(buf, utarg);
|
||||
|
||||
pmsg_notice2("jtag3_set_vtarget(): changing V[target] from %.1f to %.1f\n", uaref / 1000.0, v);
|
||||
pmsg_notice2("%s(): changing V[target] from %.1f to %.1f\n", __func__, uaref / 1000.0, v);
|
||||
|
||||
if (jtag3_setparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, sizeof(buf)) < 0) {
|
||||
pmsg_error("cannot confirm new V[target] value\n");
|
||||
@@ -2823,7 +2810,7 @@ static unsigned char tpi_get_mtype(const AVRMEM *m) {
|
||||
mem_is_lock(m)? XPRG_MEM_TYPE_LOCKBITS:
|
||||
mem_is_calibration(m)? XPRG_MEM_TYPE_LOCKBITS: // Sic, uses offset to distingish memories
|
||||
mem_is_signature(m)? XPRG_MEM_TYPE_LOCKBITS:
|
||||
mem_is_sigrow(m)? XPRG_MEM_TYPE_LOCKBITS:
|
||||
mem_is_in_sigrow(m)? XPRG_MEM_TYPE_LOCKBITS:
|
||||
XPRG_MEM_TYPE_APPL; // Sic, TPI parts do not have eeprom
|
||||
}
|
||||
|
||||
@@ -2860,7 +2847,7 @@ int jtag3_recv_tpi(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
rv = jtag3_recv(pgm, msg);
|
||||
|
||||
if (rv <= 0) {
|
||||
pmsg_error("jtag3_recv_tpi(): unable to receive\n");
|
||||
pmsg_error("%s(): unable to receive\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
rv = rv - 1;
|
||||
@@ -3043,10 +3030,12 @@ static int jtag3_write_byte_tpi(const PROGRAMMER *pgm, const AVRPART *p, const A
|
||||
return -1;
|
||||
}
|
||||
|
||||
status = jtag3_erase_tpi(pgm, p, mem, addr);
|
||||
if (status < 0) {
|
||||
pmsg_error("error in communication, received status 0x%02x\n", status);
|
||||
return -1;
|
||||
if (mem_is_a_fuse(mem) || mem_is_flash(mem)) {
|
||||
status = jtag3_erase_tpi(pgm, p, mem, addr);
|
||||
if (status < 0) {
|
||||
pmsg_error("error in communication, received status 0x%02x\n", status);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
paddr = mem->offset + addr;
|
||||
@@ -3147,8 +3136,7 @@ static int jtag3_paged_load_tpi(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
block_size = maxaddr - addr;
|
||||
else
|
||||
block_size = page_size;
|
||||
pmsg_debug("jtag3_paged_load_tpi(): "
|
||||
"block_size at addr 0x%x is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr 0x%x is %d\n", __func__, addr, block_size);
|
||||
|
||||
u32_to_b4_big_endian((cmd+2), addr + m->offset); // Address
|
||||
u16_to_b2_big_endian((cmd+6), block_size); // Size
|
||||
@@ -3207,8 +3195,7 @@ static int jtag3_paged_write_tpi(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
block_size = maxaddr - addr;
|
||||
else
|
||||
block_size = page_size;
|
||||
pmsg_debug("jtag3_paged_write(): "
|
||||
"block_size at addr 0x%x is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr 0x%x is %d\n", __func__, addr, block_size);
|
||||
|
||||
u32_to_b4_big_endian((cmd+3), addr + m->offset); // Address
|
||||
u16_to_b2_big_endian((cmd+7), page_size); // Size
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2012 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2017 Jan Egil Ruud <janegil.ruud@microchip.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef jtag3_h
|
||||
#define jtag3_h
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2012 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2017 Jan Egil Ruud <janegil.ruud@microchip.com>
|
||||
*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,8 +18,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
/*
|
||||
* JTAGICE3 definitions
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* avrdude interface for Atmel JTAG ICE (mkI) programmer
|
||||
*/
|
||||
@@ -119,7 +117,7 @@ static void u16_to_b2(unsigned char *b, unsigned short l) {
|
||||
}
|
||||
|
||||
static void jtagmkI_prmsg(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
|
||||
if (verbose >= 4) {
|
||||
if (verbose >= MSG_TRACE) {
|
||||
msg_trace("Raw message:\n");
|
||||
|
||||
size_t i;
|
||||
@@ -175,7 +173,7 @@ static int jtagmkI_send(const PROGRAMMER *pgm, unsigned char *data, size_t len)
|
||||
unsigned char *buf;
|
||||
|
||||
msg_debug("\n");
|
||||
pmsg_debug("jtagmkI_send(): sending %u bytes\n", (unsigned int) len);
|
||||
pmsg_debug("%s(): sending %u bytes\n", __func__, (unsigned int) len);
|
||||
|
||||
buf = mmt_malloc(len + 2);
|
||||
memcpy(buf, data, len);
|
||||
@@ -199,7 +197,7 @@ static int jtagmkI_recv(const PROGRAMMER *pgm, unsigned char *buf, size_t len) {
|
||||
pmsg_error("unable to send command to serial port\n");
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkI_prmsg(pgm, buf, len);
|
||||
}
|
||||
@@ -227,7 +225,7 @@ static int jtagmkI_resync(const PROGRAMMER *pgm, int maxtries, int signon) {
|
||||
|
||||
/* Get the sign-on information. */
|
||||
buf[0] = CMD_GET_SYNC;
|
||||
pmsg_notice2("jtagmkI_resync(): sending sync command: ");
|
||||
pmsg_notice2("%s(): sending sync command: ", __func__);
|
||||
|
||||
if (serial_send(&pgm->fd, buf, 1) != 0) {
|
||||
msg_error("\n");
|
||||
@@ -255,7 +253,7 @@ static int jtagmkI_resync(const PROGRAMMER *pgm, int maxtries, int signon) {
|
||||
buf[1] = 'E';
|
||||
buf[2] = ' ';
|
||||
buf[3] = ' ';
|
||||
pmsg_notice2("jtagmkI_resync(): sending sign-on command: ");
|
||||
pmsg_notice2("%s(): sending sign-on command: ", __func__);
|
||||
|
||||
if (serial_send(&pgm->fd, buf, 4) != 0) {
|
||||
msg_error("\n");
|
||||
@@ -270,8 +268,7 @@ static int jtagmkI_resync(const PROGRAMMER *pgm, int maxtries, int signon) {
|
||||
}
|
||||
}
|
||||
if (tries >= maxtries) {
|
||||
pmsg_notice2("jtagmkI_resync(): "
|
||||
"timeout/error communicating with programmer\n");
|
||||
pmsg_notice2("%s(): timeout/error communicating with programmer\n", __func__);
|
||||
serial_recv_timeout = otimeout;
|
||||
return -1;
|
||||
}
|
||||
@@ -290,7 +287,7 @@ static int jtagmkI_getsync(const PROGRAMMER *pgm) {
|
||||
|
||||
jtagmkI_drain(pgm, 0);
|
||||
|
||||
pmsg_notice2("jtagmkI_getsync(): sending sign-on command; ");
|
||||
pmsg_notice2("%s(): sending sign-on command; ", __func__);
|
||||
|
||||
buf[0] = CMD_GET_SIGNON;
|
||||
jtagmkI_send(pgm, buf, 1);
|
||||
@@ -309,7 +306,7 @@ static int jtagmkI_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
unsigned char buf[1], resp[2];
|
||||
|
||||
buf[0] = CMD_CHIP_ERASE;
|
||||
pmsg_notice2("jtagmkI_chip_erase(): sending chip erase command: ");
|
||||
pmsg_notice2("%s(): sending chip erase command: ", __func__);
|
||||
jtagmkI_send(pgm, buf, 1);
|
||||
if (jtagmkI_recv(pgm, resp, 2) < 0)
|
||||
return -1;
|
||||
@@ -350,8 +347,7 @@ static void jtagmkI_set_devdescr(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
}
|
||||
|
||||
pmsg_notice2("jtagmkI_set_devdescr(): "
|
||||
"Sending set device descriptor command: ");
|
||||
pmsg_notice2("%s(): sending set device descriptor command: ", __func__);
|
||||
jtagmkI_send(pgm, (unsigned char *)&sendbuf, sizeof(sendbuf));
|
||||
|
||||
if (jtagmkI_recv(pgm, resp, 2) < 0)
|
||||
@@ -371,7 +367,7 @@ static int jtagmkI_reset(const PROGRAMMER *pgm) {
|
||||
unsigned char buf[1], resp[2];
|
||||
|
||||
buf[0] = CMD_RESET;
|
||||
pmsg_notice2("jtagmkI_reset(): sending reset command: ");
|
||||
pmsg_notice2("%s(): sending reset command: ", __func__);
|
||||
jtagmkI_send(pgm, buf, 1);
|
||||
|
||||
if (jtagmkI_recv(pgm, resp, 2) < 0)
|
||||
@@ -398,8 +394,7 @@ static int jtagmkI_program_enable(const PROGRAMMER *pgm) {
|
||||
return 0;
|
||||
|
||||
buf[0] = CMD_ENTER_PROGMODE;
|
||||
pmsg_notice2("jtagmkI_program_enable(): "
|
||||
"Sending enter progmode command: ");
|
||||
pmsg_notice2("%s(): sending enter progmode command: ", __func__);
|
||||
jtagmkI_send(pgm, buf, 1);
|
||||
|
||||
if (jtagmkI_recv(pgm, resp, 2) < 0)
|
||||
@@ -425,7 +420,7 @@ static int jtagmkI_program_disable(const PROGRAMMER *pgm) {
|
||||
|
||||
if (pgm->fd.ifd != -1) {
|
||||
buf[0] = CMD_LEAVE_PROGMODE;
|
||||
pmsg_notice2("jtagmkI_program_disable(): sending leave progmode command: ");
|
||||
pmsg_notice2("%s(): sending leave progmode command: ", __func__);
|
||||
jtagmkI_send(pgm, buf, 1);
|
||||
|
||||
if (jtagmkI_recv(pgm, resp, 2) < 0)
|
||||
@@ -471,8 +466,7 @@ static int jtagmkI_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
if ((b = jtagmkI_get_baud(pgm->baudrate)) == 0) {
|
||||
pmsg_error("unsupported baudrate %d\n", pgm->baudrate);
|
||||
} else {
|
||||
pmsg_notice2("jtagmkI_initialize(): "
|
||||
"trying to set baudrate to %d\n", pgm->baudrate);
|
||||
pmsg_notice2("%s(): trying to set baudrate to %d\n", __func__, pgm->baudrate);
|
||||
if (jtagmkI_setparm(pgm, PARM_BITRATE, b) == 0) {
|
||||
PDATA(pgm)->initial_baudrate = pgm->baudrate; /* don't adjust again later */
|
||||
serial_setparams(&pgm->fd, pgm->baudrate, SERIAL_8N1);
|
||||
@@ -481,8 +475,7 @@ static int jtagmkI_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
|
||||
if (pgm->bitclock != 0.0) {
|
||||
pmsg_notice2("jtagmkI_initialize(): "
|
||||
"trying to set JTAG clock period to %.1f us\n", pgm->bitclock);
|
||||
pmsg_notice2("%s(): trying to set JTAG clock period to %.1f us\n", __func__, pgm->bitclock);
|
||||
if (jtagmkI_set_sck_period(pgm, pgm->bitclock) != 0)
|
||||
return -1;
|
||||
}
|
||||
@@ -550,7 +543,7 @@ static int jtagmkI_open(PROGRAMMER *pgm, const char *port) {
|
||||
union pinfo pinfo;
|
||||
pinfo.serialinfo.baud = baudtab[i].baud;
|
||||
pinfo.serialinfo.cflags = SERIAL_8N1;
|
||||
pmsg_notice2("jtagmkI_open(): trying to sync at baud rate %ld:\n", pinfo.serialinfo.baud);
|
||||
pmsg_notice2("%s(): trying to sync at baud rate %ld:\n", __func__, pinfo.serialinfo.baud);
|
||||
if (serial_open(port, pinfo, &pgm->fd)==-1) {
|
||||
return -1;
|
||||
}
|
||||
@@ -562,7 +555,7 @@ static int jtagmkI_open(PROGRAMMER *pgm, const char *port) {
|
||||
|
||||
if (jtagmkI_getsync(pgm) == 0) {
|
||||
PDATA(pgm)->initial_baudrate = baudtab[i].baud;
|
||||
pmsg_notice2("jtagmkI_open(): succeeded\n");
|
||||
pmsg_notice2("%s(): succeeded\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -590,8 +583,7 @@ static void jtagmkI_close(PROGRAMMER *pgm) {
|
||||
if ((b = jtagmkI_get_baud(PDATA(pgm)->initial_baudrate)) == 0) {
|
||||
pmsg_error("unsupported baudrate %d\n", PDATA(pgm)->initial_baudrate);
|
||||
} else {
|
||||
pmsg_notice2("jtagmkI_close(): "
|
||||
"trying to set baudrate to %d\n", PDATA(pgm)->initial_baudrate);
|
||||
pmsg_notice2("%s(): trying to set baudrate to %d\n", __func__, PDATA(pgm)->initial_baudrate);
|
||||
if (jtagmkI_setparm(pgm, PARM_BITRATE, b) == 0) {
|
||||
serial_setparams(&pgm->fd, pgm->baudrate, SERIAL_8N1);
|
||||
}
|
||||
@@ -660,8 +652,7 @@ static int jtagmkI_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
block_size = n_bytes;
|
||||
else
|
||||
block_size = page_size;
|
||||
pmsg_debug("jtagmkI_paged_write(): "
|
||||
"block_size at addr %d is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr %d is %d\n", __func__, addr, block_size);
|
||||
|
||||
/* We always write full pages. */
|
||||
send_size = page_size;
|
||||
@@ -673,8 +664,7 @@ static int jtagmkI_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
u32_to_b3(cmd + 3, addr);
|
||||
}
|
||||
|
||||
pmsg_notice2("jtagmkI_paged_write(): "
|
||||
"sending write memory command: ");
|
||||
pmsg_notice2("%s(): sending write memory command: ", __func__);
|
||||
|
||||
/* First part, send the write command. */
|
||||
jtagmkI_send(pgm, cmd, 6);
|
||||
@@ -773,8 +763,7 @@ static int jtagmkI_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||
block_size = n_bytes;
|
||||
else
|
||||
block_size = page_size;
|
||||
pmsg_debug("jtagmkI_paged_load(): "
|
||||
"block_size at addr %d is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr %d is %d\n", __func__, addr, block_size);
|
||||
|
||||
if (is_flash) {
|
||||
read_size = 2 * ((block_size + 1) / 2); /* round up */
|
||||
@@ -786,7 +775,7 @@ static int jtagmkI_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||
u32_to_b3(cmd + 3, addr);
|
||||
}
|
||||
|
||||
pmsg_notice2("jtagmkI_paged_load(): sending read memory command: ");
|
||||
pmsg_notice2("%s(): sending read memory command: ", __func__);
|
||||
|
||||
jtagmkI_send(pgm, cmd, 6);
|
||||
if (jtagmkI_recv(pgm, resp, read_size + 3) < 0)
|
||||
@@ -852,7 +841,8 @@ static int jtagmkI_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRM
|
||||
cmd[1] = MTYPE_OSCCAL_BYTE;
|
||||
} else if (mem_is_signature(mem)) {
|
||||
cmd[1] = MTYPE_SIGN_JTAG;
|
||||
} else if (mem_is_sigrow(mem)) {
|
||||
} else if (mem_is_in_sigrow(mem)) {
|
||||
addr += avr_sigrow_offset(p, mem, addr);
|
||||
cmd[1] = addr&1? MTYPE_OSCCAL_BYTE: MTYPE_SIGN_JTAG;
|
||||
addr /= 2;
|
||||
} else {
|
||||
@@ -1097,8 +1087,7 @@ static int jtagmkI_getparm(const PROGRAMMER *pgm, const unsigned char parm,
|
||||
|
||||
buf[0] = CMD_GET_PARAM;
|
||||
buf[1] = parm;
|
||||
pmsg_notice2("jtagmkI_getparm(): "
|
||||
"Sending get parameter command (parm 0x%02x): ", parm);
|
||||
pmsg_notice2("%s(): sending get parameter command (parm 0x%02x): ", __func__, parm);
|
||||
jtagmkI_send(pgm, buf, 2);
|
||||
|
||||
if (jtagmkI_recv(pgm, resp, 3) < 0)
|
||||
@@ -1133,8 +1122,7 @@ static int jtagmkI_setparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||
buf[0] = CMD_SET_PARAM;
|
||||
buf[1] = parm;
|
||||
buf[2] = value;
|
||||
pmsg_notice2("jtagmkI_setparm(): "
|
||||
"Sending set parameter command (parm 0x%02x): ", parm);
|
||||
pmsg_notice2("%s(): sending set parameter command (parm 0x%02x): ", __func__, parm);
|
||||
jtagmkI_send(pgm, buf, 3);
|
||||
if (jtagmkI_recv(pgm, resp, 2) < 0)
|
||||
return -1;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef jtagmkI_h
|
||||
#define jtagmkI_h
|
||||
|
||||
|
||||
197
src/jtagmkII.c
197
src/jtagmkII.c
@@ -21,8 +21,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* avrdude interface for Atmel JTAG ICE mkII programmer
|
||||
*
|
||||
@@ -262,7 +260,7 @@ static void jtagmkII_print_memory(unsigned char *b, size_t s) {
|
||||
static void jtagmkII_prmsg(const PROGRAMMER *pgm_unused, unsigned char *data, size_t len) {
|
||||
size_t i;
|
||||
|
||||
if (verbose >= 4) {
|
||||
if (verbose >= MSG_TRACE) {
|
||||
msg_trace("Raw message:\n");
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
@@ -403,7 +401,7 @@ int jtagmkII_send(const PROGRAMMER *pgm, unsigned char *data, size_t len) {
|
||||
unsigned char *buf;
|
||||
|
||||
msg_debug("\n");
|
||||
pmsg_debug("jtagmkII_send(): sending %lu bytes\n", (unsigned long) len);
|
||||
pmsg_debug("%s(): sending %lu bytes\n", __func__, (unsigned long) len);
|
||||
|
||||
buf = mmt_malloc(len + 10);
|
||||
buf[0] = MESSAGE_START;
|
||||
@@ -480,7 +478,7 @@ static int jtagmkII_recv_frame(const PROGRAMMER *pgm, unsigned char **msg,
|
||||
if (rv != 0) {
|
||||
timedout:
|
||||
/* timeout in receive */
|
||||
pmsg_notice2("jtagmkII_recv(): timeout receiving packet\n");
|
||||
pmsg_notice2("%s(): timeout receiving packet\n", __func__);
|
||||
mmt_free(buf);
|
||||
return -1;
|
||||
}
|
||||
@@ -543,7 +541,7 @@ static int jtagmkII_recv_frame(const PROGRAMMER *pgm, unsigned char **msg,
|
||||
if (state == sCSUM2 && buf) {
|
||||
if (crcverify(buf, msglen + 10)) {
|
||||
if (verbose >= 9)
|
||||
pmsg_trace2("jtagmkII_recv(): CRC OK");
|
||||
pmsg_trace2("%s(): CRC OK", __func__);
|
||||
state = sDONE;
|
||||
} else {
|
||||
pmsg_error("wrong checksum\n");
|
||||
@@ -582,7 +580,7 @@ int jtagmkII_recv(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
for (;;) {
|
||||
if ((rv = jtagmkII_recv_frame(pgm, msg, &r_seqno)) <= 0)
|
||||
return rv;
|
||||
pmsg_debug("jtagmkII_recv(): got message seqno %d (command_sequence == %d)\n",
|
||||
pmsg_debug("%s(): got message seqno %d (command_sequence == %d)\n", __func__,
|
||||
r_seqno, PDATA(pgm)->command_sequence);
|
||||
if (r_seqno == PDATA(pgm)->command_sequence) {
|
||||
if (++(PDATA(pgm)->command_sequence) == 0xffff)
|
||||
@@ -594,15 +592,15 @@ int jtagmkII_recv(const PROGRAMMER *pgm, unsigned char **msg) {
|
||||
*/
|
||||
memmove(*msg, *msg + 8, rv);
|
||||
|
||||
if(verbose > 3)
|
||||
if(verbose >= MSG_TRACE)
|
||||
trace_buffer(__func__, *msg, rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
if (r_seqno == 0xffff) {
|
||||
pmsg_debug("jtagmkII_recv(): got asynchronous event\n");
|
||||
pmsg_debug("%s(): got asynchronous event\n", __func__);
|
||||
} else {
|
||||
pmsg_notice2("jtagmkII_recv(): got wrong sequence number, %u != %u\n",
|
||||
pmsg_notice2("%s(): got wrong sequence number, %u != %u\n", __func__,
|
||||
r_seqno, PDATA(pgm)->command_sequence);
|
||||
}
|
||||
mmt_free(*msg);
|
||||
@@ -640,7 +638,7 @@ int jtagmkII_getsync(const PROGRAMMER *pgm, int mode) {
|
||||
if (status <= 0) {
|
||||
pmsg_warning("attempt %d of %d: sign-on command: status %d\n",
|
||||
tries + 1, MAXTRIES, status);
|
||||
} else if (verbose >= 3) {
|
||||
} else if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -705,7 +703,7 @@ int jtagmkII_getsync(const PROGRAMMER *pgm, int mode) {
|
||||
PDATA(pgm)->device_descriptor_length -= 2;
|
||||
}
|
||||
if (mode != EMULATOR_MODE_SPI)
|
||||
pmsg_notice2("jtagmkII_getsync(): using a %u-byte device descriptor\n",
|
||||
pmsg_notice2("%s(): using a %u-byte device descriptor\n", __func__,
|
||||
(unsigned) PDATA(pgm)->device_descriptor_length);
|
||||
if (mode == EMULATOR_MODE_SPI) {
|
||||
PDATA(pgm)->device_descriptor_length = 0;
|
||||
@@ -770,7 +768,7 @@ retry:
|
||||
|
||||
/* GET SYNC forces the target into STOPPED mode */
|
||||
buf[0] = CMND_GET_SYNC;
|
||||
pmsg_notice2("jtagmkII_getsync(): sending get sync command: ");
|
||||
pmsg_notice2("%s(): sending get sync command: ", __func__);
|
||||
jtagmkII_send(pgm, buf, 1);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -779,7 +777,7 @@ retry:
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -810,7 +808,7 @@ static int jtagmkII_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
buf[0] = CMND_CHIP_ERASE;
|
||||
len = 1;
|
||||
}
|
||||
pmsg_notice2("jtagmkII_chip_erase(): sending %schip erase command: ",
|
||||
pmsg_notice2("%s(): sending %schip erase command: ", __func__,
|
||||
p->prog_modes & (PM_PDI | PM_UPDI)? "Xmega ": "");
|
||||
jtagmkII_send(pgm, buf, len);
|
||||
|
||||
@@ -820,7 +818,7 @@ static int jtagmkII_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -832,7 +830,7 @@ static int jtagmkII_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(p->prog_modes & (PM_PDI | PM_UPDI)))
|
||||
if (p->prog_modes & PM_Classic)
|
||||
pgm->initialize(pgm, p);
|
||||
|
||||
PDATA(pgm)->recently_written = 1;
|
||||
@@ -892,10 +890,9 @@ static void jtagmkII_set_devdescr(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
}
|
||||
sendbuf.dd.ucCacheType =
|
||||
p->prog_modes & (PM_PDI | PM_UPDI)? 0x02 /* ATxmega */: 0x00;
|
||||
p->prog_modes & (PM_PDI | PM_UPDI)? 0x02: 0x00;
|
||||
|
||||
pmsg_notice2("jtagmkII_set_devdescr(): "
|
||||
"Sending set device descriptor command: ");
|
||||
pmsg_notice2("%s(): sending set device descriptor command: ", __func__);
|
||||
jtagmkII_send(pgm, (unsigned char *)&sendbuf,
|
||||
PDATA(pgm)->device_descriptor_length + sizeof(unsigned char));
|
||||
|
||||
@@ -905,7 +902,7 @@ static void jtagmkII_set_devdescr(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -975,7 +972,7 @@ static void jtagmkII_set_xmega_params(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -1006,7 +1003,7 @@ static int jtagmkII_reset(const PROGRAMMER *pgm, unsigned char flags) {
|
||||
|
||||
buf[0] = (pgm->flag & PGM_FL_IS_DW)? CMND_FORCED_STOP: CMND_RESET;
|
||||
buf[1] = (pgm->flag & PGM_FL_IS_DW)? 1: flags;
|
||||
pmsg_notice2("jtagmkII_reset(): sending %s command: ",
|
||||
pmsg_notice2("%s(): sending %s command: ", __func__,
|
||||
(pgm->flag & PGM_FL_IS_DW)? "stop": "reset");
|
||||
jtagmkII_send(pgm, buf, 2);
|
||||
|
||||
@@ -1016,7 +1013,7 @@ static int jtagmkII_reset(const PROGRAMMER *pgm, unsigned char flags) {
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -1045,8 +1042,7 @@ static int jtagmkII_program_enable(const PROGRAMMER *pgm) {
|
||||
|
||||
for (use_ext_reset = 0; use_ext_reset <= 1; use_ext_reset++) {
|
||||
buf[0] = CMND_ENTER_PROGMODE;
|
||||
pmsg_notice2("jtagmkII_program_enable(): "
|
||||
"Sending enter progmode command: ");
|
||||
pmsg_notice2("%s(): sending enter progmode command: ", __func__);
|
||||
jtagmkII_send(pgm, buf, 1);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -1055,7 +1051,7 @@ static int jtagmkII_program_enable(const PROGRAMMER *pgm) {
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -1091,8 +1087,7 @@ static int jtagmkII_program_disable(const PROGRAMMER *pgm) {
|
||||
return 0;
|
||||
|
||||
buf[0] = CMND_LEAVE_PROGMODE;
|
||||
pmsg_notice2("jtagmkII_program_disable(): "
|
||||
"Sending leave progmode command: ");
|
||||
pmsg_notice2("%s(): sending leave progmode command: ", __func__);
|
||||
jtagmkII_send(pgm, buf, 1);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -1101,7 +1096,7 @@ static int jtagmkII_program_disable(const PROGRAMMER *pgm) {
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -1175,7 +1170,7 @@ static int jtagmkII_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
const char *ifname;
|
||||
|
||||
if (PDATA(pgm)->rts_mode != RTS_MODE_DEFAULT) {
|
||||
pmsg_info("forcing serial DTR/RTS handshake lines %s\n",
|
||||
pmsg_notice("forcing serial DTR/RTS handshake lines %s\n",
|
||||
PDATA(pgm)->rts_mode == RTS_MODE_LOW ? "LOW" : "HIGH");
|
||||
}
|
||||
|
||||
@@ -1210,15 +1205,13 @@ static int jtagmkII_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
if ((b = jtagmkII_get_baud(pgm->baudrate)) == 0) {
|
||||
pmsg_error("unsupported baudrate %d\n", pgm->baudrate);
|
||||
} else {
|
||||
pmsg_notice2("jtagmkII_initialize(): "
|
||||
"trying to set baudrate to %d\n", pgm->baudrate);
|
||||
pmsg_notice2("%s(): trying to set baudrate to %d\n", __func__, pgm->baudrate);
|
||||
if (jtagmkII_setparm(pgm, PAR_BAUD_RATE, &b) == 0)
|
||||
serial_setparams(&pgm->fd, pgm->baudrate, SERIAL_8N1);
|
||||
}
|
||||
}
|
||||
if ((pgm->flag & PGM_FL_IS_JTAG) && pgm->bitclock != 0.0) {
|
||||
pmsg_notice2("jtagmkII_initialize(): "
|
||||
"trying to set JTAG clock period to %.1f us\n", pgm->bitclock);
|
||||
pmsg_notice2("%s(): trying to set JTAG clock period to %.1f us\n", __func__, pgm->bitclock);
|
||||
if (jtagmkII_set_sck_period(pgm, pgm->bitclock) != 0)
|
||||
return -1;
|
||||
}
|
||||
@@ -1292,7 +1285,7 @@ static int jtagmkII_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((pgm->flag & PGM_FL_IS_JTAG) && !(p->prog_modes & (PM_PDI | PM_UPDI))) {
|
||||
if ((pgm->flag & PGM_FL_IS_JTAG) && (p->prog_modes & PM_Classic)) {
|
||||
int ocden = 0;
|
||||
if(avr_get_config_value(pgm, p, "ocden", &ocden) == 0 && ocden) // ocden == 1 means disabled
|
||||
pmsg_warning("OCDEN fuse not programmed, single-byte EEPROM updates not possible\n");
|
||||
@@ -1323,7 +1316,7 @@ static void jtagmkII_disable(const PROGRAMMER *pgm) {
|
||||
|
||||
static void jtagmkII_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||
// Page erase only useful for classic parts with usersig mem or AVR8X/XMEGAs
|
||||
if(!(p->prog_modes & (PM_PDI | PM_UPDI)))
|
||||
if(p->prog_modes & PM_Classic)
|
||||
if(!avr_locate_usersig(p))
|
||||
pgm->page_erase = NULL;
|
||||
|
||||
@@ -1334,29 +1327,27 @@ static void jtagmkII_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
|
||||
static int jtagmkII_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
if (pgm->flag & PGM_FL_IS_JTAG) {
|
||||
if (str_eq(extended_param, "jtagchain=")) {
|
||||
if (str_starts(extended_param, "jtagchain=")) {
|
||||
unsigned int ub, ua, bb, ba;
|
||||
if (sscanf(extended_param, "jtagchain=%u,%u,%u,%u", &ub, &ua, &bb, &ba) != 4) {
|
||||
pmsg_error("invalid JTAG chain '%s'\n", extended_param);
|
||||
pmsg_error("invalid JTAG chain in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
continue;
|
||||
}
|
||||
pmsg_notice2("jtagmkII_parseextparms(): JTAG chain parsed as:\n");
|
||||
pmsg_notice2("%s(): JTAG chain parsed as:\n", __func__);
|
||||
imsg_notice2("%u units before, %u units after, %u bits before, %u bits after\n",
|
||||
ub, ua, bb, ba);
|
||||
PDATA(pgm)->jtagchain[0] = ub;
|
||||
PDATA(pgm)->jtagchain[1] = ua;
|
||||
PDATA(pgm)->jtagchain[2] = bb;
|
||||
PDATA(pgm)->jtagchain[3] = ba;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -1370,24 +1361,29 @@ static int jtagmkII_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
PDATA(pgm)->rts_mode = RTS_MODE_HIGH;
|
||||
} else {
|
||||
pmsg_error("RTS/DTR mode must be LOW or HIGH\n");
|
||||
return -1;
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
if (pgm->flag & PGM_FL_IS_JTAG)
|
||||
msg_error(" -xjtagchain=UB,UA,BB,BA Setup the JTAG scan chain order\n");
|
||||
if (pgm->flag & PGM_FL_IS_PDI)
|
||||
msg_error(" -xrtsdtr=low,high Force RTS/DTR lines low or high state during programming\n");
|
||||
msg_error( " -xhelp Show this help menu and exit\n");
|
||||
return LIBAVRDUDE_EXIT;;
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
pmsg_error("invalid extended parameter '%s'\n", extended_param);
|
||||
rv = -1;
|
||||
if (!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
if (pgm->flag & PGM_FL_IS_JTAG)
|
||||
msg_error(" -x jtagchain=UB,UA,BB,BA Setup the JTAG scan chain order\n");
|
||||
if (pgm->flag & PGM_FL_IS_PDI)
|
||||
msg_error(" -x rtsdtr=low,high Force RTS/DTR lines low or high state during programming\n");
|
||||
msg_error( " -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
@@ -1726,7 +1722,7 @@ void jtagmkII_close(PROGRAMMER * pgm)
|
||||
if (pgm->flag & (PGM_FL_IS_PDI | PGM_FL_IS_JTAG)) {
|
||||
/* When in PDI or JTAG mode, restart target. */
|
||||
buf[0] = CMND_GO;
|
||||
pmsg_notice2("jtagmkII_close(): sending GO command: ");
|
||||
pmsg_notice2("%s(): sending GO command: ", __func__);
|
||||
jtagmkII_send(pgm, buf, 1);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -1734,7 +1730,7 @@ void jtagmkII_close(PROGRAMMER * pgm)
|
||||
msg_notice2("\n");
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
} else {
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -1748,7 +1744,7 @@ void jtagmkII_close(PROGRAMMER * pgm)
|
||||
}
|
||||
|
||||
buf[0] = CMND_SIGN_OFF;
|
||||
pmsg_notice2("jtagmkII_close(): sending sign-off command: ");
|
||||
pmsg_notice2("%s(): sending sign-off command: ", __func__);
|
||||
jtagmkII_send(pgm, buf, 1);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -1757,7 +1753,7 @@ void jtagmkII_close(PROGRAMMER * pgm)
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -1769,7 +1765,7 @@ void jtagmkII_close(PROGRAMMER * pgm)
|
||||
}
|
||||
|
||||
if (PDATA(pgm)->rts_mode != RTS_MODE_DEFAULT) {
|
||||
pmsg_info("releasing DTR/RTS handshake lines\n");
|
||||
pmsg_notice("releasing DTR/RTS handshake lines\n");
|
||||
serial_set_dtr_rts(&pgm->fd, 0);
|
||||
}
|
||||
|
||||
@@ -1796,7 +1792,7 @@ static int jtagmkII_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
|
||||
pmsg_notice2("jtagmkII_page_erase(.., %s, 0x%x)\n", m->desc, addr);
|
||||
|
||||
if (!(p->prog_modes & (PM_PDI | PM_UPDI)) && !mem_is_userrow(m)) {
|
||||
if ((p->prog_modes & PM_Classic) && !mem_is_userrow(m)) {
|
||||
pmsg_error("page erase only available for AVR8X/XMEGAs or classic-part usersig mem\n");
|
||||
return -1;
|
||||
}
|
||||
@@ -1836,8 +1832,7 @@ static int jtagmkII_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
tries = 0;
|
||||
|
||||
retry:
|
||||
pmsg_notice2("jtagmkII_page_erase(): "
|
||||
"Sending Xmega erase command: ");
|
||||
pmsg_notice2("%s(): sending Xmega erase command: ", __func__);
|
||||
jtagmkII_send(pgm, cmd, sizeof cmd);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -1852,7 +1847,7 @@ static int jtagmkII_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
serial_recv_timeout = otimeout;
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -1929,8 +1924,7 @@ static int jtagmkII_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const A
|
||||
block_size = maxaddr - addr;
|
||||
else
|
||||
block_size = page_size;
|
||||
pmsg_debug("jtagmkII_paged_write(): "
|
||||
"block_size at addr %d is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr %d is %d\n", __func__, addr, block_size);
|
||||
|
||||
if (dynamic_mtype)
|
||||
cmd[1] = jtagmkII_mtype(pgm, p, addr);
|
||||
@@ -1951,8 +1945,7 @@ static int jtagmkII_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const A
|
||||
tries = 0;
|
||||
|
||||
retry:
|
||||
pmsg_notice2("jtagmkII_paged_write(): "
|
||||
"Sending write memory command: ");
|
||||
pmsg_notice2("%s(): sending write memory command: ", __func__);
|
||||
jtagmkII_send(pgm, cmd, page_size + 10);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -1968,7 +1961,7 @@ static int jtagmkII_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const A
|
||||
serial_recv_timeout = otimeout;
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -2034,8 +2027,7 @@ static int jtagmkII_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
block_size = maxaddr - addr;
|
||||
else
|
||||
block_size = page_size;
|
||||
pmsg_debug("jtagmkII_paged_load(): "
|
||||
"block_size at addr %d is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr %d is %d\n", __func__, addr, block_size);
|
||||
|
||||
if (dynamic_mtype)
|
||||
cmd[1] = jtagmkII_mtype(pgm, p, addr);
|
||||
@@ -2046,7 +2038,7 @@ static int jtagmkII_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
tries = 0;
|
||||
|
||||
retry:
|
||||
pmsg_notice2("jtagmkII_paged_load(): sending read memory command: ");
|
||||
pmsg_notice2("%s(): sending read memory command: ", __func__);
|
||||
jtagmkII_send(pgm, cmd, 10);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -2061,7 +2053,7 @@ static int jtagmkII_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
serial_recv_timeout = otimeout;
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -2098,7 +2090,7 @@ static int jtagmkII_read_chip_rev(const PROGRAMMER *pgm, const AVRPART *p, unsig
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmsg_debug("jtagmkII_read_chip_rev(): received chip silicon revision: 0x%02x\n", *chip_rev);
|
||||
pmsg_debug("%s(): received chip silicon revision: 0x%02x\n", __func__, *chip_rev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2139,7 +2131,7 @@ static int jtagmkII_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||
}
|
||||
} else if(mem_is_a_fuse(mem) || mem_is_fuses(mem)) {
|
||||
cmd[1] = MTYPE_FUSE_BITS;
|
||||
if(!(p->prog_modes & (PM_PDI | PM_UPDI)) && mem_is_a_fuse(mem))
|
||||
if((p->prog_modes & PM_Classic) && mem_is_a_fuse(mem))
|
||||
addr = mem_fuse_offset(mem);
|
||||
if (pgm->flag & PGM_FL_IS_DW)
|
||||
unsupp = 1;
|
||||
@@ -2193,6 +2185,9 @@ static int jtagmkII_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||
} else if ((p->prog_modes & (PM_PDI | PM_UPDI)) && mem_is_in_sigrow(mem)) {
|
||||
cmd[1] = MTYPE_PRODSIG;
|
||||
pmsg_notice2("in_sigrow addr 0x%05lx\n", addr);
|
||||
} else if (mem_is_in_sigrow(mem)) { // Classic part
|
||||
cmd[1] = addr&1? MTYPE_OSCCAL_BYTE: MTYPE_SIGN_JTAG;
|
||||
addr /= 2;
|
||||
} else if (mem_is_io(mem) || mem_is_sram(mem)) {
|
||||
cmd[1] = MTYPE_FLASH;
|
||||
addr += avr_data_offset(p);
|
||||
@@ -2234,7 +2229,7 @@ static int jtagmkII_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVR
|
||||
|
||||
tries = 0;
|
||||
retry:
|
||||
pmsg_notice2("jtagmkII_read_byte(): sending read memory command: ");
|
||||
pmsg_notice2("%s(): sending read memory command: ", __func__);
|
||||
jtagmkII_send(pgm, cmd, 10);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -2248,7 +2243,7 @@ retry:
|
||||
resp = 0;
|
||||
goto fail;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -2308,7 +2303,7 @@ static int jtagmkII_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
|
||||
} else if (mem_is_a_fuse(mem) || mem_is_fuses(mem)) {
|
||||
cmd[1] = MTYPE_FUSE_BITS;
|
||||
if(!(p->prog_modes & (PM_PDI | PM_UPDI)) && mem_is_a_fuse(mem))
|
||||
if((p->prog_modes & PM_Classic) && mem_is_a_fuse(mem))
|
||||
addr = mem_fuse_offset(mem);
|
||||
if (pgm->flag & PGM_FL_IS_DW)
|
||||
unsupp = 1;
|
||||
@@ -2353,20 +2348,19 @@ static int jtagmkII_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AV
|
||||
|
||||
tries = 0;
|
||||
retry:
|
||||
pmsg_notice2("jtagmkII_write_byte(): sending write memory command: ");
|
||||
pmsg_notice2("%s(): sending write memory command: ", __func__);
|
||||
jtagmkII_send(pgm, cmd, 10 + writesize);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
if (status <= 0) {
|
||||
msg_notice2("\n");
|
||||
pmsg_notice2("jtagmkII_write_byte(): "
|
||||
"timeout/error communicating with programmer (status %d)\n", status);
|
||||
pmsg_notice2("%s(): timeout/error communicating with programmer (status %d)\n", __func__, status);
|
||||
if (tries++ < 3)
|
||||
goto retry;
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
goto fail;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -2445,8 +2439,7 @@ int jtagmkII_getparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||
|
||||
buf[0] = CMND_GET_PARAMETER;
|
||||
buf[1] = parm;
|
||||
pmsg_notice2("jtagmkII_getparm(): "
|
||||
"Sending get parameter command (parm 0x%02x): ", parm);
|
||||
pmsg_notice2("%s(): sending get parameter command (parm 0x%02x): ", __func__, parm);
|
||||
jtagmkII_send(pgm, buf, 2);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -2455,7 +2448,7 @@ int jtagmkII_getparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -2520,7 +2513,7 @@ static int jtagmkII_setparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return -1;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -2649,8 +2642,7 @@ static int jtagmkII_avr32_reset(const PROGRAMMER *pgm, unsigned char val,
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
if (status != 2 || resp[0] != 0x87 || resp[1] != ret1) {
|
||||
pmsg_notice("jtagmkII_avr32_reset(): "
|
||||
"Get_IR, expecting %2.2x but got %2.2x\n", ret1, resp[1]);
|
||||
pmsg_notice("%s(): Get_IR, expecting %2.2x but got %2.2x\n", __func__, ret1, resp[1]);
|
||||
|
||||
//return -1;
|
||||
}
|
||||
@@ -2663,8 +2655,7 @@ static int jtagmkII_avr32_reset(const PROGRAMMER *pgm, unsigned char val,
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
if (status != 2 || resp[0] != 0x87 || resp[1] != ret2) {
|
||||
pmsg_notice("jtagmkII_avr32_reset(): "
|
||||
"Get_XXX, expecting %2.2x but got %2.2x\n", ret2, resp[1]);
|
||||
pmsg_notice("%s(): Get_XXX, expecting %2.2x but got %2.2x\n", __func__, ret2, resp[1]);
|
||||
//return -1;
|
||||
}
|
||||
|
||||
@@ -3003,12 +2994,10 @@ static int jtagmkII_initialize32(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
resp[3] != p->signature[1] ||
|
||||
resp[4] != p->signature[2]) {
|
||||
if (ovsigck) {
|
||||
pmsg_warning("expected signature for %s is %02X %02X %02X\n", p->desc,
|
||||
p->signature[0], p->signature[1], p->signature[2]);
|
||||
pmsg_warning("expected signature for %s is%s\n", p->desc, str_cchex(p->signature, 3, 1));
|
||||
} else {
|
||||
pmsg_error("expected signature for %s is %02X %02X %02X\n", p->desc,
|
||||
p->signature[0], p->signature[1], p->signature[2]);
|
||||
imsg_error("double check chip or use -F to override this check\n");
|
||||
pmsg_error("expected signature for %s is%s;\n", p->desc, str_cchex(p->signature, 3, 1));
|
||||
imsg_error("double check chip or use -F to carry on regardless\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -3123,7 +3112,7 @@ static unsigned long jtagmkII_read_SABaddr(const PROGRAMMER *pgm, unsigned long
|
||||
mmt_free(resp);
|
||||
|
||||
msg_notice2("\n");
|
||||
pmsg_notice("jtagmkII_read_SABaddr(): OCD Register %lx -> %4.4lx\n", addr, val);
|
||||
pmsg_notice("%s(): OCD Register %lx -> %4.4lx\n", __func__, addr, val);
|
||||
serial_recv_timeout = otimeout;
|
||||
return val;
|
||||
}
|
||||
@@ -3150,7 +3139,7 @@ static int jtagmkII_write_SABaddr(const PROGRAMMER *pgm, unsigned long addr,
|
||||
}
|
||||
|
||||
msg_notice2("\n");
|
||||
pmsg_notice("jtagmkII_write_SABaddr(): OCD Register %lx -> %4.4lx\n", addr, val);
|
||||
pmsg_notice("%s(): OCD Register %lx -> %4.4lx\n", __func__, addr, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3252,7 +3241,7 @@ static void jtagmkII_close32(PROGRAMMER * pgm) {
|
||||
mmt_free(resp);
|
||||
|
||||
buf[0] = CMND_SIGN_OFF;
|
||||
pmsg_notice2("jtagmkII_close(): sending sign-off command: ");
|
||||
pmsg_notice2("%s(): sending sign-off command: ", __func__);
|
||||
jtagmkII_send(pgm, buf, 1);
|
||||
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
@@ -3261,7 +3250,7 @@ static void jtagmkII_close32(PROGRAMMER * pgm) {
|
||||
pmsg_error("timeout/error communicating with programmer (status %d)\n", status);
|
||||
return;
|
||||
}
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -3319,8 +3308,7 @@ static int jtagmkII_paged_load32(const PROGRAMMER *pgm, const AVRPART *p_unused,
|
||||
for (; addr < maxaddr; addr += block_size) {
|
||||
block_size = maxaddr - addr < (unsigned int) pgm->page_size?
|
||||
maxaddr - addr: (unsigned int) pgm->page_size;
|
||||
pmsg_debug("jtagmkII_paged_load32(): "
|
||||
"block_size at addr %d is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr %d is %d\n", __func__, addr, block_size);
|
||||
|
||||
u32_to_b4r(cmd + 3, m->offset + addr);
|
||||
|
||||
@@ -3329,7 +3317,7 @@ static int jtagmkII_paged_load32(const PROGRAMMER *pgm, const AVRPART *p_unused,
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
if(status<0) {lineno = __LINE__; goto eRR;}
|
||||
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
@@ -3414,8 +3402,7 @@ static int jtagmkII_paged_write32(const PROGRAMMER *pgm, const AVRPART *p_unused
|
||||
for(blocks=0; blocks<2; ++blocks) {
|
||||
block_size = maxaddr - addr < (unsigned int) pgm->page_size?
|
||||
maxaddr - addr: (unsigned int) pgm->page_size;
|
||||
pmsg_debug("jtagmkII_paged_write32(): "
|
||||
"block_size at addr %d is %d\n", addr, block_size);
|
||||
pmsg_debug("%s(): block_size at addr %d is %d\n", __func__, addr, block_size);
|
||||
|
||||
u32_to_b4r(cmd + 6, m->offset + addr);
|
||||
memset(cmd + 10, 0xff, pgm->page_size);
|
||||
@@ -3426,7 +3413,7 @@ static int jtagmkII_paged_write32(const PROGRAMMER *pgm, const AVRPART *p_unused
|
||||
status = jtagmkII_recv(pgm, &resp);
|
||||
if (status<0) {lineno = __LINE__; goto eRR;}
|
||||
|
||||
if (verbose >= 3) {
|
||||
if (verbose >= MSG_DEBUG) {
|
||||
msg_debug("\n");
|
||||
jtagmkII_prmsg(pgm, resp, status);
|
||||
} else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004, 2006 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2002-2004, 2006 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef jtagmkII_h
|
||||
#define jtagmkII_h
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
/*
|
||||
* JTAG ICE mkII definitions
|
||||
@@ -335,7 +333,7 @@ typedef enum
|
||||
* In appnote AVR067, struct device_descriptor is written with
|
||||
* int/long field types. We cannot use them directly, as they were
|
||||
* neither properly aligned for portability, nor did they care for
|
||||
* endianess issues. We thus use arrays of unsigned chars, plus
|
||||
* endianness issues. We thus use arrays of unsigned chars, plus
|
||||
* conversion macros.
|
||||
*/
|
||||
struct device_descriptor
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
/*
|
||||
* JTAG ICE mkI definitions
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
#define CHECK 15 // Check LED needs changing
|
||||
|
||||
// Keep track of LED status and set LED 0 .. LED_N-1 physically on or off
|
||||
static void led_direct(const PROGRAMMER *pgm, leds_t *ls, int led, int what) {
|
||||
static void led_direct(const PROGRAMMER *pgm, Leds *ls, int led, int what) {
|
||||
if(what ^ !!(ls->phy & (1<<led))) {
|
||||
switch(led) {
|
||||
case LED_RDY:
|
||||
@@ -82,7 +82,7 @@ static void led_direct(const PROGRAMMER *pgm, leds_t *ls, int led, int what) {
|
||||
}
|
||||
|
||||
// Physical level of LED setting, deal with max blinking frequency LED_FMAX
|
||||
static void led_physical(const PROGRAMMER *pgm, leds_t *ls, int led, int what) {
|
||||
static void led_physical(const PROGRAMMER *pgm, Leds *ls, int led, int what) {
|
||||
if(led < 0 || led >= LED_N) // Sanity
|
||||
return;
|
||||
|
||||
@@ -125,7 +125,7 @@ static void led_physical(const PROGRAMMER *pgm, leds_t *ls, int led, int what) {
|
||||
// Logical level of setting LEDs, passes on to physical level
|
||||
int led_set(const PROGRAMMER *pgm, int led) {
|
||||
// leds should always be allocated, but if not use dummy
|
||||
leds_t sanity = { 0, 0, 0, 0, 0, {0, } }, *ls = pgm->leds? pgm->leds: &sanity;
|
||||
Leds sanity = { 0, 0, 0, 0, 0, {0, } }, *ls = pgm->leds? pgm->leds: &sanity;
|
||||
int what = led >= 0 && led < LED_N && !(ls->now & (1<<led))? TON: CHECK;
|
||||
|
||||
switch(led) {
|
||||
@@ -174,7 +174,7 @@ int led_clr(const PROGRAMMER *pgm, int led) {
|
||||
}
|
||||
|
||||
// pgm->leds should always be allocated, but if not use dummy
|
||||
leds_t sanity = { 0, 0, 0, 0, 0, {0, } }, *ls = pgm->leds? pgm->leds: &sanity;
|
||||
Leds sanity = { 0, 0, 0, 0, 0, {0, } }, *ls = pgm->leds? pgm->leds: &sanity;
|
||||
int what = ls->now & (1<<led)? TOFF: CHECK;
|
||||
|
||||
// Record logical level
|
||||
|
||||
11
src/lexer.l
11
src/lexer.l
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
%{
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
@@ -149,7 +147,7 @@ INF [Ii][Nn][Ff]([Ii][Nn][Ii][Tt][Yy])?
|
||||
|
||||
|
||||
(?x: desc | prog_modes | is_serialadapter | extra_features | baudrate | usbvid | usbdev | usbsn | usbvendor | usbproduct |
|
||||
family_id | mcuid | n_interrupts | n_page_erase | n_boot_sections | boot_section_size |
|
||||
family_id | mcuid | archnum | n_interrupts | n_page_erase | n_boot_sections | boot_section_size |
|
||||
hvupdi_variant | stk500_devcode | avr910_devcode | chip_erase_delay | pagel | bs2 |
|
||||
timeout | stabdelay | cmdexedelay | synchloops | bytedelay | pollindex | pollvalue | predelay | postdelay | pollmethod |
|
||||
hventerstabdelay | progmodedelay | latchcycles | togglevtg | poweroffdelay | resetdelayms | resetdelayus | resetdelay | hvleavestabdelay |
|
||||
@@ -159,7 +157,7 @@ INF [Ii][Nn][Ff]([Ii][Nn][Ii][Tt][Yy])?
|
||||
paged | size | num_pages | initval | bitmask | n_word_writes | offset | min_write_delay | max_write_delay | pwroff_after_write |
|
||||
readback_p1 | readback_p2 | mode | delay | blocksize | readsize ) {
|
||||
/* struct components for PROGRAMMER, AVRPART and AVRMEM */
|
||||
Component_t *cp = cfg_comp_search(yytext, current_strct);
|
||||
Component *cp = cfg_comp_search(yytext, current_strct);
|
||||
if(!cp) {
|
||||
yyerror("unknown component %s in %s", yytext, cfg_strct_name(current_strct));
|
||||
return YYERRCODE;
|
||||
@@ -226,7 +224,8 @@ part { yylval=NULL; ccap(); current_strct = COMP_AVRPART; return K_P
|
||||
pgm_enable { yylval=new_token(K_PGM_ENABLE); ccap(); return K_PGM_ENABLE; }
|
||||
pgmled { yylval=NULL; ccap(); return K_PGMLED; }
|
||||
pp_controlstack { yylval=NULL; ccap(); return K_PP_CONTROLSTACK; }
|
||||
(programmer|serialadapter) { yylval=NULL; ccap(); current_strct = COMP_PROGRAMMER; return K_PROGRAMMER; }
|
||||
(programmer|serialadapter) { yylval=NULL; ccap(); current_strct = COMP_PROGRAMMER;
|
||||
cx->lex_kw_is_programmer = *yytext == 'p'; return K_PROGRAMMER; }
|
||||
rdyled { yylval=NULL; ccap(); return K_RDYLED; }
|
||||
read { yylval=new_token(K_READ); ccap(); return K_READ; }
|
||||
read_hi { yylval=new_token(K_READ_HI); ccap(); return K_READ_HI; }
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
700
src/libavrdude.h
700
src/libavrdude.h
File diff suppressed because it is too large
Load Diff
@@ -254,7 +254,7 @@ typedef void * LNODEID;
|
||||
typedef void * LISTID;
|
||||
typedef struct avrmem AVRMEM;
|
||||
typedef struct avrmem_alias AVRMEM_ALIAS;
|
||||
typedef struct programmer_t PROGRAMMER;
|
||||
typedef struct programmer PROGRAMMER;
|
||||
typedef void pgm_initpgm(PROGRAMMER*);
|
||||
|
||||
enum msglvl {
|
||||
@@ -405,9 +405,9 @@ typedef enum {
|
||||
|
||||
// https://stackoverflow.com/questions/11023940/how-do-i-get-swig-to-automatically-wrap-an-emulated-this-pointer-to-a-c-struct/11029809#11029809
|
||||
// Make sure the wrapped function doesn't expect an input for this:
|
||||
%typemap(in, numinputs=0) struct programmer_t *pgm "$1=NULL;"
|
||||
%typemap(in, numinputs=0) struct programmer *pgm "$1=NULL;"
|
||||
// Slightly abuse check typemap, but it needs to happen after the rest of the arguments have been set:
|
||||
%typemap(check) struct programmer_t *pgm {
|
||||
%typemap(check) struct programmer *pgm {
|
||||
$1 = arg1;
|
||||
}
|
||||
|
||||
@@ -518,19 +518,19 @@ typedef enum {
|
||||
SWIG_exception_fail(SWIG_RuntimeError, "pgm->get_sck_period is NULL");
|
||||
}
|
||||
}
|
||||
%typemap(check) (struct programmer_t *pgm_setup) {
|
||||
%typemap(check) (struct programmer *pgm_setup) {
|
||||
if ((arg1)->setup == NULL) {
|
||||
SWIG_exception_fail(SWIG_RuntimeError, "pgm->setup is NULL");
|
||||
}
|
||||
}
|
||||
%typemap(check) (struct programmer_t *pgm_teardown) {
|
||||
%typemap(check) (struct programmer *pgm_teardown) {
|
||||
if ((arg1)->teardown == NULL) {
|
||||
SWIG_exception_fail(SWIG_RuntimeError, "pgm->teardown is NULL");
|
||||
}
|
||||
}
|
||||
|
||||
%immutable;
|
||||
typedef struct programmer_t {
|
||||
typedef struct programmer {
|
||||
LISTID id;
|
||||
const char *desc;
|
||||
int prog_modes; // Programming interfaces, see #define PM_...
|
||||
@@ -543,49 +543,49 @@ typedef struct programmer_t {
|
||||
char type[PGM_TYPELEN];
|
||||
|
||||
// methods; they must *not* be declares as pointers
|
||||
void initpgm (struct programmer_t *pgm); // Sets up the AVRDUDE programmer
|
||||
int initialize (const struct programmer_t *pgm, const AVRPART *p); // Sets up the physical programmer
|
||||
void setup (struct programmer_t *pgm);
|
||||
void teardown (struct programmer_t *pgm);
|
||||
int parseextparams (const struct programmer_t *pgm, const LISTID xparams);
|
||||
int parseexitspecs (struct programmer_t *pgm, const char *s);
|
||||
int open (struct programmer_t *pgm, const char *port);
|
||||
void close (struct programmer_t *pgm);
|
||||
void enable (struct programmer_t *pgm, const AVRPART *p);
|
||||
void disable (const struct programmer_t *pgm);
|
||||
int read_sib (const struct programmer_t *pgm, const AVRPART *p, char *sib);
|
||||
void powerup (const struct programmer_t *pgm);
|
||||
void powerdown (const struct programmer_t *pgm);
|
||||
void initpgm (struct programmer *pgm); // Sets up the AVRDUDE programmer
|
||||
int initialize (const struct programmer *pgm, const AVRPART *p); // Sets up the physical programmer
|
||||
void setup (struct programmer *pgm);
|
||||
void teardown (struct programmer *pgm);
|
||||
int parseextparams (const struct programmer *pgm, const LISTID xparams);
|
||||
int parseexitspecs (struct programmer *pgm, const char *s);
|
||||
int open (struct programmer *pgm, const char *port);
|
||||
void close (struct programmer *pgm);
|
||||
void enable (struct programmer *pgm, const AVRPART *p);
|
||||
void disable (const struct programmer *pgm);
|
||||
int read_sib (const struct programmer *pgm, const AVRPART *p, char *sib);
|
||||
void powerup (const struct programmer *pgm);
|
||||
void powerdown (const struct programmer *pgm);
|
||||
|
||||
int chip_erase (const struct programmer_t *pgm, const AVRPART *p);
|
||||
int term_keep_alive(const struct programmer_t *pgm, const AVRPART *p);
|
||||
int end_programming(const struct programmer_t *pgm, const AVRPART *p);
|
||||
int chip_erase (const struct programmer *pgm, const AVRPART *p);
|
||||
int term_keep_alive(const struct programmer *pgm, const AVRPART *p);
|
||||
int end_programming(const struct programmer *pgm, const AVRPART *p);
|
||||
|
||||
void print_parms (const struct programmer_t *pgm, FILE *f_parms);
|
||||
int set_vtarget (const struct programmer_t *pgm, double vtarg_in);
|
||||
int get_vtarget (const struct programmer_t *pgm, double *vtarg_out);
|
||||
int set_varef (const struct programmer_t *pgm, unsigned int chan, double varef_in);
|
||||
int get_varef (const struct programmer_t *pgm, unsigned int chan, double *varef_out);
|
||||
int set_fosc (const struct programmer_t *pgm, double fosc_in);
|
||||
int get_fosc (const struct programmer_t *pgm, double *fosc_out);
|
||||
int set_sck_period (const struct programmer_t *pgm, double sck_in);
|
||||
int get_sck_period (const struct programmer_t *pgm, double *sck_out);
|
||||
void print_parms (const struct programmer *pgm, FILE *f_parms);
|
||||
int set_vtarget (const struct programmer *pgm, double vtarg_in);
|
||||
int get_vtarget (const struct programmer *pgm, double *vtarg_out);
|
||||
int set_varef (const struct programmer *pgm, unsigned int chan, double varef_in);
|
||||
int get_varef (const struct programmer *pgm, unsigned int chan, double *varef_out);
|
||||
int set_fosc (const struct programmer *pgm, double fosc_in);
|
||||
int get_fosc (const struct programmer *pgm, double *fosc_out);
|
||||
int set_sck_period (const struct programmer *pgm, double sck_in);
|
||||
int get_sck_period (const struct programmer *pgm, double *sck_out);
|
||||
// Cached r/w API for terminal reads/writes
|
||||
int write_byte_cached(const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
int write_byte_cached(const struct programmer *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
unsigned long addr, unsigned char value);
|
||||
int read_byte_cached(const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
int read_byte_cached(const struct programmer *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,
|
||||
int chip_erase_cached(const struct programmer *pgm, const AVRPART *p);
|
||||
int page_erase_cached(const struct programmer *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
unsigned int baseaddr);
|
||||
int readonly (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
int readonly (const struct programmer *pgm, const AVRPART *p, const AVRMEM *m,
|
||||
unsigned int addr);
|
||||
int flush_cache (const struct programmer_t *pgm, const AVRPART *p);
|
||||
int reset_cache (const struct programmer_t *pgm, const AVRPART *p);
|
||||
int flush_cache (const struct programmer *pgm, const AVRPART *p);
|
||||
int reset_cache (const struct programmer *pgm, const AVRPART *p);
|
||||
|
||||
} PROGRAMMER;
|
||||
%mutable;
|
||||
%clear struct programmer_t *pgm;
|
||||
%clear struct programmer *pgm;
|
||||
|
||||
// Config file handling
|
||||
int init_config(void);
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef linux_ppdev_h
|
||||
#define linux_ppdev_h
|
||||
|
||||
|
||||
@@ -733,7 +733,7 @@ void linuxgpio_initpgm(PROGRAMMER *pgm) {
|
||||
|
||||
#ifdef HAVE_LIBGPIOD
|
||||
if (libgpiod_is_working()) {
|
||||
msg_info("using libgpiod for linuxgpio\n");
|
||||
msg_notice("using libgpiod for linuxgpio\n");
|
||||
pgm->display = linuxgpio_libgpiod_display;
|
||||
pgm->open = linuxgpio_libgpiod_open;
|
||||
pgm->close = linuxgpio_libgpiod_close;
|
||||
@@ -741,7 +741,7 @@ void linuxgpio_initpgm(PROGRAMMER *pgm) {
|
||||
pgm->getpin = linuxgpio_libgpiod_getpin;
|
||||
pgm->highpulsepin = linuxgpio_libgpiod_highpulsepin;
|
||||
} else {
|
||||
msg_info("falling back to sysfs for linuxgpio\n");
|
||||
msg_notice("falling back to sysfs for linuxgpio\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -381,6 +381,8 @@ static int linuxspi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
|
||||
static int linuxspi_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
|
||||
char *cp, *s, *str = mmt_strdup(sp);
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
s = str;
|
||||
while ((cp = strtok(s, ","))) {
|
||||
@@ -393,35 +395,52 @@ static int linuxspi_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
|
||||
pgm->exit_reset = EXIT_RESET_DISABLED;
|
||||
continue;
|
||||
}
|
||||
if (str_eq(cp, "help")) {
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
if (!help) {
|
||||
pmsg_error("invalid exitspec parameter -E %s\n", cp);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s exitspec parameter options:\n", progname, pgmid);
|
||||
msg_error(" -E reset Programmer will keep the reset line low after programming session\n");
|
||||
msg_error(" -E noreset Programmer will not keep the reset line low after programming session\n");
|
||||
msg_error(" -E help Show this help menu and exit\n");
|
||||
mmt_free(str);
|
||||
return -1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
mmt_free(str);
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int linuxspi_parseextparams(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
int rc = 0;
|
||||
bool help = false;
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
if (str_eq(extended_param, "disable_no_cs")) {
|
||||
my.disable_no_cs = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -xdisable_no_cs Do not use the SPI_NO_CS bit for the SPI driver\n");
|
||||
msg_error(" -xhelp Show this help menu and exit\n");
|
||||
return LIBAVRDUDE_EXIT;
|
||||
help = true;
|
||||
rc = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
pmsg_error("invalid extended parameter '%s'\n", extended_param);
|
||||
rc = -1;
|
||||
if (!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rc = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x disable_no_cs Do not use the SPI_NO_CS bit for the SPI driver\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2013 Kevin Cuzner <kevin@kevincuner.com>
|
||||
* Copyright (C) 2013 Kevin Cuzner <kevin@kevincuzner.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 1990-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 1990-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
|
||||
368
src/main.c
368
src/main.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2005 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2000-2005 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Code to program an Atmel AVR device through one of the supported
|
||||
* programmers.
|
||||
@@ -52,10 +50,7 @@
|
||||
#include "config.h"
|
||||
#include "developer_opts.h"
|
||||
|
||||
char * progname;
|
||||
char progbuf[PATH_MAX]; /* temporary buffer of spaces the same
|
||||
length as progname; used for lining up
|
||||
multiline messages */
|
||||
char * progname = "avrdude";
|
||||
|
||||
static const char *avrdude_message_type(int msglvl) {
|
||||
switch(msglvl) {
|
||||
@@ -122,9 +117,20 @@ int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int
|
||||
}
|
||||
}
|
||||
|
||||
if(msgmode & MSG2_PROGNAME) {
|
||||
fprintf(fp, "%s", progname);
|
||||
if(verbose >= MSG_NOTICE && (msgmode & MSG2_FUNCTION))
|
||||
if(msgmode & (MSG2_PROGNAME | MSG2_TYPE)) {
|
||||
if(msgmode & MSG2_PROGNAME) {
|
||||
fprintf(fp, "%s", progname);
|
||||
bols[bi].bol = 0;
|
||||
}
|
||||
if(msgmode & MSG2_TYPE) {
|
||||
const char *mt = avrdude_message_type(msglvl);
|
||||
if(bols[bi].bol)
|
||||
fprintf(fp, "%c%s", msgmode & (MSG2_UCFIRST)? toupper(*mt & 0xff): *mt, mt+1);
|
||||
else
|
||||
fprintf(fp, " %s", mt);
|
||||
bols[bi].bol = 0;
|
||||
}
|
||||
if(verbose >= MSG_NOTICE2 && (msgmode & MSG2_FUNCTION))
|
||||
fprintf(fp, " %s()", func);
|
||||
if(verbose >= MSG_DEBUG && (msgmode & MSG2_FILELINE)) {
|
||||
const char *pr = strrchr(file, '/'); // Only print basename
|
||||
@@ -135,10 +141,7 @@ int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int
|
||||
pr = pr? pr+1: file;
|
||||
fprintf(fp, " [%s:%d]", pr, lno);
|
||||
}
|
||||
if(msgmode & MSG2_TYPE)
|
||||
fprintf(fp, " %s", avrdude_message_type(msglvl));
|
||||
fprintf(fp, ": ");
|
||||
bols[bi].bol = 0;
|
||||
} else if(msgmode & MSG2_INDENT1) {
|
||||
fprintf(fp, "%*s", (int) strlen(progname)+1, "");
|
||||
bols[bi].bol = 0;
|
||||
@@ -168,8 +171,11 @@ int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(*p) {
|
||||
fprintf(fp, "%s", p); // Finally: print!
|
||||
if(*p) { // Finally: print!
|
||||
if(bols[bi].bol && (msgmode & MSG2_UCFIRST))
|
||||
fprintf(fp, "%c%s", toupper(*p & 0xff), p+1);
|
||||
else
|
||||
fprintf(fp, "%s", p);
|
||||
bols[bi].bol = p[strlen(p)-1] == '\n';
|
||||
}
|
||||
mmt_free(p);
|
||||
@@ -188,6 +194,9 @@ struct list_walk_cookie
|
||||
const char *prefix;
|
||||
};
|
||||
|
||||
|
||||
libavrdude_context *cx; // Context pointer, eventually the only global variable
|
||||
|
||||
static LISTID updates = NULL;
|
||||
|
||||
static LISTID extended_params = NULL;
|
||||
@@ -215,8 +224,8 @@ static void usage(void)
|
||||
char *home = getenv("HOME");
|
||||
size_t l = home? strlen(home): 0;
|
||||
char *cfg = home && str_casestarts(usr_config, home)?
|
||||
str_sprintf("~/%s", usr_config+l+(usr_config[l]=='/')):
|
||||
str_sprintf("%s", usr_config);
|
||||
mmt_sprintf("~/%s", usr_config+l+(usr_config[l]=='/')):
|
||||
mmt_sprintf("%s", usr_config);
|
||||
|
||||
msg_error(
|
||||
"Usage: %s [options]\n"
|
||||
@@ -233,13 +242,13 @@ static void usage(void)
|
||||
" -c <wildcard>/<flags> Run developer options for matched programmers,\n"
|
||||
" e.g., -c 'ur*'/s for programmer info/definition\n"
|
||||
" -A Disable trailing-0xff removal for file/AVR read\n"
|
||||
" -D Disable auto erase for flash memory; implies -A\n"
|
||||
" -D Disable auto-erase for flash memory; implies -A\n"
|
||||
" -i <delay> ISP Clock Delay [in microseconds]\n"
|
||||
" -P <port> Connection; -P ?s or -P ?sa lists serial ones\n"
|
||||
" -r Reconnect to -P port after \"touching\" it; wait\n"
|
||||
" 400 ms for each -r; needed for some USB boards\n"
|
||||
" -F Override invalid signature or initial checks\n"
|
||||
" -e Perform a chip erase\n"
|
||||
" -e Perform a chip erase at the beginning\n"
|
||||
" -O Perform RC oscillator calibration (see AVR053)\n"
|
||||
" -t Run an interactive terminal when it is its turn\n"
|
||||
" -T <terminal cmd line> Run terminal line when it is its turn\n"
|
||||
@@ -249,7 +258,7 @@ static void usage(void)
|
||||
" -n Do not write to the device whilst processing -U\n"
|
||||
" -V Do not automatically verify during -U\n"
|
||||
" -E <exitsp>[,<exitsp>] List programmer exit specifications\n"
|
||||
" -x <extended_param> Pass <extended_param> to programmer, see -xhelp\n"
|
||||
" -x <extended_param> Pass <extended_param> to programmer, see -x help\n"
|
||||
" -v Verbose output; -v -v for more\n"
|
||||
" -q Quell progress output; -q -q for less\n"
|
||||
" -l logfile Use logfile rather than stderr for diagnostics\n"
|
||||
@@ -373,7 +382,7 @@ static void list_parts(FILE *f, const char *prefix, LISTID avrparts, int pm) {
|
||||
p = ldata(ln1);
|
||||
// List part if pm or prog_modes uninitialised or if they are compatible otherwise
|
||||
if(!pm || !p->prog_modes || (pm & p->prog_modes)) {
|
||||
if(verbose < 2 && p->id[0] == '.') // hide ids starting with '.'
|
||||
if(verbose < MSG_NOTICE2 && p->id[0] == '.') // hide ids starting with '.'
|
||||
continue;
|
||||
if((len = strlen(p->id)) > maxlen)
|
||||
maxlen = len;
|
||||
@@ -384,7 +393,7 @@ static void list_parts(FILE *f, const char *prefix, LISTID avrparts, int pm) {
|
||||
p = ldata(ln1);
|
||||
// List part if pm or prog_modes uninitialised or if they are compatible otherwise
|
||||
if(!pm || !p->prog_modes || (pm & p->prog_modes)) {
|
||||
if(verbose < 2 && p->id[0] == '.') // hide ids starting with '.'
|
||||
if(verbose < MSG_NOTICE2 && p->id[0] == '.') // hide ids starting with '.'
|
||||
continue;
|
||||
if(verbose > 0)
|
||||
fprintf(f, "%s%-*s = %-18s [%s:%d]", prefix, maxlen, p->id, p->desc, p->config_file, p->lineno);
|
||||
@@ -434,11 +443,11 @@ static void replace_backslashes(char *s)
|
||||
}
|
||||
}
|
||||
|
||||
// Return 2 if str is * or starts with */, 1 if str contains / but is not a valid part, 0 otherwise
|
||||
// Return whether a part/programmer string is a developer option and if so which type
|
||||
static int dev_opt(const char *str) {
|
||||
return
|
||||
!str? 0:
|
||||
str_eq(str, "*") || str_starts(str, "*/")? 2:
|
||||
str_eq(str, "*") || str_starts(str, "*/s")? 2: // Print PART DEFINITIONS comment as well
|
||||
strchr(str, '/') && !locate_part(part_list, str);
|
||||
}
|
||||
|
||||
@@ -512,7 +521,9 @@ static int suggest_programmers(const char *programmer, LISTID programmers) {
|
||||
return n;
|
||||
}
|
||||
|
||||
static void programmer_not_found(const char *programmer, PROGRAMMER *pgm, int pmode) {
|
||||
static void programmer_not_found(const char *programmer, const PROGRAMMER *pgm, const AVRPART *pt) {
|
||||
int pmode = pt? pt->prog_modes: ~0;
|
||||
|
||||
if(!programmer || !*programmer) {
|
||||
pmsg_error("no programmer has been specified on the command line or in the\n");
|
||||
imsg_error("config file(s); specify one using the -c option and try again\n");
|
||||
@@ -554,9 +565,15 @@ static void programmer_not_found(const char *programmer, PROGRAMMER *pgm, int pm
|
||||
}
|
||||
}
|
||||
} else if(!pgm || !pgm->id || !lsize(pgm->id)) {
|
||||
pmsg_error("cannot find programmer id %s\n", programmer);
|
||||
suggest_programmers(programmer, programmers);
|
||||
msg_info("use -c? to see all possible programmers\n");
|
||||
PROGRAMMER *pg = locate_programmer(programmers, programmer);
|
||||
if(!pgm && pt && pg && !(pg->prog_modes & pmode)) {
|
||||
pmsg_error("programmer %s and part %s have no programming modes in common\n", programmer, pt->desc);
|
||||
msg_info("use -c? -p %s to see all possible programmers for %s\n", pt->desc, pt->desc);
|
||||
} else {
|
||||
pmsg_error("cannot find programmer id %s\n", programmer);
|
||||
suggest_programmers(programmer, programmers);
|
||||
msg_info("use -c? to see all possible programmers\n");
|
||||
}
|
||||
} else
|
||||
pmsg_error("programmer %s lacks %s setting\n", programmer,
|
||||
!pgm->prog_modes? "prog_modes": !pgm->initpgm? "type": "some");
|
||||
@@ -610,7 +627,6 @@ int main(int argc, char * argv [])
|
||||
int exitrc; /* exit code for main() */
|
||||
int i; /* general loop counter */
|
||||
int ch; /* options flag */
|
||||
int len; /* length for various strings */
|
||||
struct avrpart * p; /* which avr part we are programming */
|
||||
AVRMEM * sig; /* signature data */
|
||||
struct stat sb;
|
||||
@@ -619,6 +635,7 @@ int main(int argc, char * argv [])
|
||||
|
||||
/* options / operating mode variables */
|
||||
int erase; /* 1=erase chip, 0=don't */
|
||||
int flashread; /* 1=flash is going to be read, 0=no flash reads */
|
||||
int calibrate; /* 1=calibrate RC oscillator, 0=don't */
|
||||
int no_avrduderc; /* 1=don't load personal conf file */
|
||||
char * port; /* device port (/dev/xxx) */
|
||||
@@ -642,6 +659,7 @@ int main(int argc, char * argv [])
|
||||
char * logfile; /* Use logfile rather than stderr for diagnostics */
|
||||
enum updateflags uflags = UF_AUTO_ERASE | UF_VERIFY; /* Flags for do_op() */
|
||||
|
||||
cx = mmt_malloc(sizeof *cx); // Allocate and initialise context structure
|
||||
(void) avr_ustimestamp(); // Base timestamps from program start
|
||||
|
||||
#ifdef _MSC_VER
|
||||
@@ -712,6 +730,7 @@ int main(int argc, char * argv [])
|
||||
partdesc = NULL;
|
||||
port = NULL;
|
||||
erase = 0;
|
||||
flashread = 0;
|
||||
calibrate = 0;
|
||||
no_avrduderc = 0;
|
||||
p = NULL;
|
||||
@@ -731,22 +750,14 @@ int main(int argc, char * argv [])
|
||||
ce_delayed = 0;
|
||||
logfile = NULL;
|
||||
|
||||
len = strlen(progname) + 2;
|
||||
for (i=0; i<len; i++)
|
||||
progbuf[i] = ' ';
|
||||
progbuf[i] = 0;
|
||||
|
||||
/*
|
||||
* check for no arguments
|
||||
*/
|
||||
if (argc == 1) {
|
||||
if(argc == 1) { // No arguments?
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Determine the location of personal configuration file
|
||||
#if defined(WIN32)
|
||||
win_usr_config_set(usr_config);
|
||||
win_set_path(usr_config, sizeof usr_config, USER_CONF_FILE);
|
||||
#else
|
||||
usr_config[0] = 0;
|
||||
if(!concatpath(usr_config, getenv("XDG_CONFIG_HOME"), XDG_USER_CONF_FILE, sizeof usr_config))
|
||||
@@ -759,7 +770,7 @@ int main(int argc, char * argv [])
|
||||
/*
|
||||
* process command line arguments
|
||||
*/
|
||||
while ((ch = getopt(argc,argv,"?Ab:B:c:C:DeE:Fi:l:nNp:OP:qrstT:U:uvVx:yY:")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "?Ab:B:c:C:DeE:Fi:l:nNp:OP:qrstT:U:uvVx:yY")) != -1) {
|
||||
|
||||
switch (ch) {
|
||||
case 'b': /* override default programmer baud rate */
|
||||
@@ -818,12 +829,12 @@ int main(int argc, char * argv [])
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D': /* disable auto erase */
|
||||
case 'D': /* disable auto-erase */
|
||||
uflags &= ~UF_AUTO_ERASE;
|
||||
/* fall through */
|
||||
|
||||
case 'A': /* explicit disabling of trailing-0xff removal */
|
||||
disable_trailing_ff_removal();
|
||||
cx->avr_disableffopt = 1;
|
||||
break;
|
||||
|
||||
case 'e': /* perform a chip erase */
|
||||
@@ -856,7 +867,7 @@ int main(int argc, char * argv [])
|
||||
calibrate = 1;
|
||||
break;
|
||||
|
||||
case 'p' : /* specify AVR part */
|
||||
case 'p': /* specify AVR part */
|
||||
partdesc = optarg;
|
||||
break;
|
||||
|
||||
@@ -864,7 +875,7 @@ int main(int argc, char * argv [])
|
||||
port = mmt_strdup(optarg);
|
||||
break;
|
||||
|
||||
case 'q' : /* Quell progress output */
|
||||
case 'q': /* Quell progress output */
|
||||
quell_progress++ ;
|
||||
break;
|
||||
|
||||
@@ -888,7 +899,7 @@ int main(int argc, char * argv [])
|
||||
case 'U':
|
||||
upd = parse_op(optarg);
|
||||
if (upd == NULL) {
|
||||
pmsg_error("unable to parse update operation '%s'\n", optarg);
|
||||
pmsg_error("unable to parse update operation %s\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
ladd(updates, upd);
|
||||
@@ -907,9 +918,6 @@ int main(int argc, char * argv [])
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
pmsg_error("erase cycle counter no longer supported\n");
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
pmsg_error("erase cycle counter no longer supported\n");
|
||||
break;
|
||||
@@ -928,6 +936,9 @@ int main(int argc, char * argv [])
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (logfile != NULL) {
|
||||
FILE *newstderr = freopen(logfile, "w", stderr);
|
||||
if (newstderr == NULL) {
|
||||
@@ -939,7 +950,7 @@ int main(int argc, char * argv [])
|
||||
|
||||
size_t ztest;
|
||||
if(1 != sscanf("42", "%zi", &ztest) || ztest != 42)
|
||||
pmsg_warning("Linked C library does not conform to C99; %s may not work as expected\n", progname);
|
||||
pmsg_warning("linked C library does not conform to C99; %s may not work as expected\n", progname);
|
||||
|
||||
/* search for system configuration file unless -C conffile was given */
|
||||
if (strlen(sys_config) == 0) {
|
||||
@@ -1020,7 +1031,7 @@ int main(int argc, char * argv [])
|
||||
if (!sys_config_found) {
|
||||
// 3. Check CONFIG_DIR/avrdude.conf
|
||||
#if defined(WIN32)
|
||||
win_sys_config_set(sys_config);
|
||||
win_set_path(sys_config, sizeof sys_config, SYSTEM_CONF_FILE);
|
||||
#else
|
||||
strcpy(sys_config, CONFIG_DIR);
|
||||
i = strlen(sys_config);
|
||||
@@ -1045,15 +1056,13 @@ int main(int argc, char * argv [])
|
||||
* Print out an identifying string so folks can tell what version
|
||||
* they are running
|
||||
*/
|
||||
msg_notice("\n");
|
||||
pmsg_notice("Version %s\n", AVRDUDE_FULL_VERSION);
|
||||
imsg_notice("Copyright the AVRDUDE authors;\n");
|
||||
imsg_notice("see https://github.com/avrdudes/avrdude/blob/main/AUTHORS\n\n");
|
||||
pmsg_notice("%s version %s\n", progname, AVRDUDE_FULL_VERSION);
|
||||
pmsg_notice("Copyright see https://github.com/avrdudes/avrdude/blob/main/AUTHORS\n\n");
|
||||
|
||||
if(*sys_config) {
|
||||
char *real_sys_config = realpath(sys_config, NULL);
|
||||
if(real_sys_config) {
|
||||
imsg_notice("System wide configuration file is %s\n", real_sys_config);
|
||||
pmsg_notice("system wide configuration file is %s\n", real_sys_config);
|
||||
} else
|
||||
pmsg_warning("cannot determine realpath() of config file %s: %s\n", sys_config, strerror(errno));
|
||||
|
||||
@@ -1066,12 +1075,11 @@ int main(int argc, char * argv [])
|
||||
}
|
||||
|
||||
if (usr_config[0] != 0 && !no_avrduderc) {
|
||||
imsg_notice("User configuration file is %s\n", usr_config);
|
||||
int ok = (rc = stat(usr_config, &sb)) >= 0 && (sb.st_mode & S_IFREG);
|
||||
pmsg_notice("user configuration file %s%s%s\n", ok? "is ": "", usr_config,
|
||||
rc<0? " does not exist": !(sb.st_mode & S_IFREG)? " is not a regular file, skipping": "");
|
||||
|
||||
rc = stat(usr_config, &sb);
|
||||
if ((rc < 0) || ((sb.st_mode & S_IFREG) == 0))
|
||||
imsg_notice("User configuration file does not exist or is not a regular file, skipping\n");
|
||||
else {
|
||||
if(ok) {
|
||||
rc = read_config(usr_config);
|
||||
if (rc) {
|
||||
pmsg_error("unable to process user configuration file %s\n", usr_config);
|
||||
@@ -1081,7 +1089,7 @@ int main(int argc, char * argv [])
|
||||
}
|
||||
|
||||
if(!str_eq(avrdude_conf_version, AVRDUDE_FULL_VERSION)) {
|
||||
pmsg_warning("System wide configuration file version (%s)\n", avrdude_conf_version);
|
||||
pmsg_warning("system wide configuration file version (%s)\n", avrdude_conf_version);
|
||||
imsg_warning("does not match Avrdude build version (%s)\n", AVRDUDE_FULL_VERSION);
|
||||
}
|
||||
|
||||
@@ -1091,7 +1099,7 @@ int main(int argc, char * argv [])
|
||||
|
||||
for (ln1=lfirst(additional_config_files); ln1; ln1=lnext(ln1)) {
|
||||
p = ldata(ln1);
|
||||
imsg_notice("additional configuration file is %s\n", p);
|
||||
pmsg_notice("additional configuration file is %s\n", p);
|
||||
|
||||
rc = read_config(p);
|
||||
if (rc) {
|
||||
@@ -1115,8 +1123,8 @@ int main(int argc, char * argv [])
|
||||
pgmid = cache_string(default_programmer);
|
||||
|
||||
// Developer options to print parts and/or programmer entries of avrdude.conf
|
||||
int dev_opt_c = dev_opt(pgmid); // -c <wildcard>/[sSArt]
|
||||
int dev_opt_p = dev_opt(partdesc); // -p <wildcard>/[dsSArcow*t]
|
||||
int dev_opt_c = dev_opt(pgmid); // -c <wildcard>/[dASsrtiBUPTIJWHQ]
|
||||
int dev_opt_p = dev_opt(partdesc); // -p <wildcard>/[cdoASsrw*tiBUPTIJWHQ]
|
||||
|
||||
if(dev_opt_c || dev_opt_p) { // See -c/h and or -p/h
|
||||
dev_output_pgm_part(dev_opt_c, pgmid, dev_opt_p, partdesc);
|
||||
@@ -1153,7 +1161,7 @@ int main(int argc, char * argv [])
|
||||
if(pgmid && *pgmid && explicit_c) {
|
||||
PROGRAMMER *pgm = locate_programmer_starts_set(programmers, pgmid, &pgmid, NULL);
|
||||
if(!pgm || !is_programmer(pgm)) {
|
||||
programmer_not_found(pgmid, pgm, ~0);
|
||||
programmer_not_found(pgmid, pgm, NULL);
|
||||
exit(1);
|
||||
}
|
||||
msg_error("\nValid parts for programmer %s are:\n", pgmid);
|
||||
@@ -1196,14 +1204,14 @@ int main(int argc, char * argv [])
|
||||
msg_notice("\n");
|
||||
|
||||
if(!pgmid || !*pgmid) {
|
||||
programmer_not_found(NULL, NULL, ~0);
|
||||
programmer_not_found(NULL, NULL, NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
p = partdesc && *partdesc? locate_part(part_list, partdesc): NULL;
|
||||
pgm = locate_programmer_starts_set(programmers, pgmid, &pgmid, p);
|
||||
if (pgm == NULL || !is_programmer(pgm)) {
|
||||
programmer_not_found(pgmid, pgm, p? p->prog_modes: ~0);
|
||||
programmer_not_found(pgmid, pgm, p);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1236,7 +1244,7 @@ int main(int argc, char * argv [])
|
||||
const char *extended_param = ldata(ln);
|
||||
if (str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -xhelp Show this help menu and exit\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
@@ -1247,7 +1255,7 @@ int main(int argc, char * argv [])
|
||||
if(rc == LIBAVRDUDE_EXIT)
|
||||
exit(0);
|
||||
if(rc < 0) {
|
||||
pmsg_error("unable to parse extended parameter list\n");
|
||||
pmsg_error("unable to parse list of -x parameters\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -1287,11 +1295,11 @@ int main(int argc, char * argv [])
|
||||
}
|
||||
}
|
||||
|
||||
int is_dryrun = str_eq(pgmid, "dryrun") || (dry && pgm->initpgm == dry->initpgm);
|
||||
int is_dryrun = str_eq(pgm->type, "dryrun") || (dry && pgm->initpgm == dry->initpgm);
|
||||
if((port[0] == 0 || str_eq(port, "unknown")) && !is_dryrun) {
|
||||
msg_error("\n");
|
||||
pmsg_error("no port has been specified on the command line or in the config file\n");
|
||||
imsg_error("specify a port using the -P option and try again\n\n");
|
||||
pmsg_error("no port has been specified on the command line or in the config file;\n");
|
||||
imsg_error("specify a port using the -P option and try again\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -1319,6 +1327,7 @@ int main(int argc, char * argv [])
|
||||
// Use libserialport to find the actual serial port
|
||||
ser = locate_programmer(programmers, port_tok[0]);
|
||||
if (is_serialadapter(ser)) {
|
||||
#ifdef HAVE_LIBSERIALPORT
|
||||
int rv = setport_from_serialadapter(&port, ser, port_tok[1]);
|
||||
if (rv == -1) {
|
||||
pmsg_warning("serial adapter %s", port_tok[0]);
|
||||
@@ -1332,6 +1341,7 @@ int main(int argc, char * argv [])
|
||||
print_ports = false;
|
||||
if(rv)
|
||||
ser = NULL;
|
||||
#endif
|
||||
} else if(str_eq(port_tok[0], DEFAULT_USB)) {
|
||||
// Port or usb:[vid]:[pid]
|
||||
int vid, pid;
|
||||
@@ -1357,37 +1367,37 @@ int main(int argc, char * argv [])
|
||||
// Open the programmer
|
||||
if (verbose > 0) {
|
||||
if(!is_dryrun)
|
||||
imsg_notice("Using port : %s\n", port);
|
||||
imsg_notice("Using programmer : %s\n", pgmid);
|
||||
pmsg_notice("using port : %s\n", port);
|
||||
pmsg_notice("using programmer : %s\n", pgmid);
|
||||
}
|
||||
|
||||
if (baudrate && !pgm->baudrate && !default_baudrate) { // none set
|
||||
imsg_notice("Setting baud rate : %d\n", baudrate);
|
||||
pmsg_notice("setting baud rate : %d\n", baudrate);
|
||||
pgm->baudrate = baudrate;
|
||||
}
|
||||
else if (baudrate && ((pgm->baudrate && pgm->baudrate != baudrate)
|
||||
|| (!pgm->baudrate && default_baudrate != baudrate))) {
|
||||
imsg_notice("Overriding baud rate : %d\n", baudrate);
|
||||
pmsg_notice("overriding baud rate : %d\n", baudrate);
|
||||
pgm->baudrate = baudrate;
|
||||
}
|
||||
else if (!pgm->baudrate && default_baudrate) {
|
||||
imsg_notice("Default baud rate : %d\n", default_baudrate);
|
||||
pmsg_notice("default baud rate : %d\n", default_baudrate);
|
||||
pgm->baudrate = default_baudrate;
|
||||
}
|
||||
else if (ser && ser->baudrate) {
|
||||
imsg_notice("Serial baud rate : %d\n", ser->baudrate);
|
||||
pmsg_notice("serial baud rate : %d\n", ser->baudrate);
|
||||
pgm->baudrate = ser->baudrate;
|
||||
}
|
||||
else if (pgm->baudrate != 0)
|
||||
imsg_notice("Programmer baud rate : %d\n", pgm->baudrate);
|
||||
pmsg_notice("programmer baud rate : %d\n", pgm->baudrate);
|
||||
|
||||
if (bitclock != 0.0) {
|
||||
imsg_notice("Setting bit clk period: %.1f us\n", bitclock);
|
||||
pmsg_notice("setting bit clk period: %.1f us\n", bitclock);
|
||||
pgm->bitclock = bitclock * 1e-6;
|
||||
}
|
||||
|
||||
if (ispdelay != 0) {
|
||||
imsg_notice("Setting ISP clk delay : %3i us\n", ispdelay);
|
||||
pmsg_notice("setting ISP clk delay : %3i us\n", ispdelay);
|
||||
pgm->ispdelay = ispdelay;
|
||||
}
|
||||
|
||||
@@ -1401,9 +1411,11 @@ int main(int argc, char * argv [])
|
||||
pmsg_error("unable to open port %s for programmer %s\n", port, pgmid);
|
||||
skipopen:
|
||||
if (print_ports && pgm->conntype == CONNTYPE_SERIAL) {
|
||||
#ifdef HAVE_LIBSERIALPORT
|
||||
list_available_serialports(programmers);
|
||||
if(touch_1200bps == 1)
|
||||
pmsg_info("alternatively, try -rr or -rrr for longer delays\n");
|
||||
#endif
|
||||
}
|
||||
exitrc = 1;
|
||||
pgm->ppidata = 0; /* clear all bits at exit */
|
||||
@@ -1428,11 +1440,14 @@ skipopen:
|
||||
if (pgm->parseexitspecs == NULL) {
|
||||
pmsg_warning("-E option not supported by this programmer type\n");
|
||||
exitspecs = NULL;
|
||||
}
|
||||
else if (pgm->parseexitspecs(pgm, exitspecs) < 0) {
|
||||
usage();
|
||||
exitrc = 1;
|
||||
goto main_exit;
|
||||
} else {
|
||||
int rc = pgm->parseexitspecs(pgm, exitspecs);
|
||||
if(rc == LIBAVRDUDE_EXIT)
|
||||
exit(0);
|
||||
if(rc < 0) {
|
||||
pmsg_error("unable to parse list of -E parameters\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1488,18 +1503,20 @@ skipopen:
|
||||
pmsg_error("programmer does not support RC oscillator calibration\n");
|
||||
exitrc = 1;
|
||||
} else {
|
||||
pmsg_info("performing RC oscillator calibration\n");
|
||||
pmsg_notice2("performing RC oscillator calibration\n");
|
||||
exitrc = pgm->perform_osccal(pgm);
|
||||
}
|
||||
if (exitrc == 0)
|
||||
pmsg_info("calibration value is now stored in EEPROM at address 0\n");
|
||||
if (exitrc)
|
||||
pmsg_error("RC calibration unsuccesful\n");
|
||||
else
|
||||
pmsg_notice("calibration value is now stored in EEPROM at address 0\n");
|
||||
|
||||
goto main_exit;
|
||||
}
|
||||
|
||||
if (verbose > 0 && quell_progress < 2) {
|
||||
avr_display(stderr, p, progbuf, verbose);
|
||||
if (verbose > 1)
|
||||
msg_notice("\n");
|
||||
msg_notice2("\n");
|
||||
programmer_display(pgm, progbuf);
|
||||
}
|
||||
|
||||
@@ -1524,19 +1541,19 @@ skipopen:
|
||||
exitrc = 0;
|
||||
goto main_exit;
|
||||
}
|
||||
pmsg_error("initialization failed, rc=%d\n", rc);
|
||||
pmsg_error("initialization failed (rc = %d)\n", rc);
|
||||
if (rc == -2)
|
||||
imsg_error("the programmer ISP clock is too fast for the target\n");
|
||||
imsg_error(" - the programmer ISP clock is too fast for the target\n");
|
||||
else
|
||||
imsg_error("- double check the connections and try again\n");
|
||||
imsg_error(" - double check the connections and try again\n");
|
||||
|
||||
if(str_eq(pgm->type, "serialupdi") || str_eq(pgm->type, "SERBB"))
|
||||
imsg_error("- use -b to set lower baud rate, e.g. -b %d\n", baudrate? baudrate/2: 57600);
|
||||
imsg_error(" - use -b to set lower baud rate, e.g. -b %d\n", baudrate? baudrate/2: 57600);
|
||||
else
|
||||
imsg_error("- use -B to set lower the bit clock frequency, e.g. -B 125kHz\n");
|
||||
imsg_error(" - use -B to set lower the bit clock frequency, e.g. -B 125kHz\n");
|
||||
|
||||
if (!ovsigck) {
|
||||
imsg_error("- use -F to override this check\n");
|
||||
imsg_error(" - use -F to override this check\n");
|
||||
exitrc = 1;
|
||||
goto main_exit;
|
||||
}
|
||||
@@ -1545,7 +1562,8 @@ skipopen:
|
||||
// Indicate programmer is ready
|
||||
led_set(pgm, LED_RDY);
|
||||
|
||||
pmsg_info("AVR device initialized and ready to accept instructions\n");
|
||||
msg_notice("\n");
|
||||
pmsg_notice("AVR device initialized and ready to accept instructions\n");
|
||||
|
||||
/*
|
||||
* Let's read the signature bytes to make sure there is at least a
|
||||
@@ -1573,16 +1591,18 @@ skipopen:
|
||||
char sib[AVR_SIBLEN + 1];
|
||||
pgm->read_sib(pgm, p, sib);
|
||||
pmsg_notice("System Information Block: %s\n", sib);
|
||||
pmsg_info("received FamilyID: \"%.*s\"\n", AVR_FAMILYIDLEN, sib);
|
||||
if (strncmp(p->family_id, sib, AVR_FAMILYIDLEN))
|
||||
pmsg_error("expected FamilyID: \"%s\"\n", p->family_id);
|
||||
if (strncmp(p->family_id, sib, AVR_FAMILYIDLEN)) {
|
||||
pmsg_warning("received FamilyID: \"%.*s\"\n", AVR_FAMILYIDLEN, sib);
|
||||
imsg_warning("expected FamilyID: \"%s\"\n", p->family_id);
|
||||
} else
|
||||
pmsg_notice("received FamilyID: \"%.*s\"\n", AVR_FAMILYIDLEN, sib);
|
||||
}
|
||||
if(erase) {
|
||||
erase = 0;
|
||||
if (uflags & UF_NOWRITE) {
|
||||
pmsg_warning("conflicting -e and -n options specified, NOT erasing chip\n");
|
||||
} else {
|
||||
pmsg_info("erasing chip\n");
|
||||
pmsg_notice("trying to unlock the chip\n");
|
||||
exitrc = avr_unlock(pgm, p);
|
||||
if(exitrc)
|
||||
goto main_exit;
|
||||
@@ -1590,12 +1610,12 @@ skipopen:
|
||||
}
|
||||
}
|
||||
if (!ovsigck) {
|
||||
imsg_error("double check chip or use -F to override this check\n");
|
||||
pmsg_error("double check chip or use -F to override this check\n");
|
||||
exitrc = 1;
|
||||
goto main_exit;
|
||||
}
|
||||
}
|
||||
pmsg_error("unable to read signature data, rc=%d\n", rc);
|
||||
pmsg_error("unable to read signature data (rc = %d)\n", rc);
|
||||
if(!ovsigck) {
|
||||
imsg_error("use -F to override this check\n");
|
||||
exitrc = 1;
|
||||
@@ -1607,60 +1627,71 @@ skipopen:
|
||||
sig = avr_locate_signature(p);
|
||||
if (sig == NULL)
|
||||
pmsg_warning("signature memory not defined for device %s\n", p->desc);
|
||||
else {
|
||||
const char *mculist = str_ccmcunames_signature(sig->buf, pgm->prog_modes);
|
||||
if(!*mculist) { // No matching signatures?
|
||||
if(p->prog_modes & PM_UPDI) { // UPDI parts have different(!) offsets for signature
|
||||
int k, n = 0; // Gather list of known different signature offsets
|
||||
unsigned myoff = sig->offset, offlist[10];
|
||||
for(LNODEID ln1 = lfirst(part_list); ln1; ln1 = lnext(ln1)) {
|
||||
AVRMEM *m = avr_locate_signature(ldata(ln1));
|
||||
if(m && m->offset != myoff) {
|
||||
for(k=0; k<n; k++)
|
||||
if(m->offset == offlist[k])
|
||||
break;
|
||||
if(k == n && k < (int) (sizeof offlist/sizeof*offlist))
|
||||
offlist[n++] = m->offset;
|
||||
}
|
||||
}
|
||||
// Now go through the list of other(!) sig offsets and try these
|
||||
for(k=0; k<n; k++) {
|
||||
sig->offset = offlist[k];
|
||||
if(avr_signature(pgm, p) >= 0)
|
||||
if(*(mculist = str_ccmcunames_signature(sig->buf, pgm->prog_modes)))
|
||||
break;
|
||||
}
|
||||
sig->offset = myoff;
|
||||
}
|
||||
}
|
||||
|
||||
if (sig != NULL) {
|
||||
int ff, zz;
|
||||
|
||||
pmsg_info("device signature = 0x");
|
||||
ff = zz = 1;
|
||||
int ff = 1, zz = 1;
|
||||
for (i=0; i<sig->size; i++) {
|
||||
msg_info("%02x", sig->buf[i]);
|
||||
if (sig->buf[i] != 0xff)
|
||||
ff = 0;
|
||||
if (sig->buf[i] != 0x00)
|
||||
zz = 0;
|
||||
}
|
||||
bool signature_matches = sig->size >= 3 && !memcmp(sig->buf, p->signature, 3);
|
||||
int showsig = !signature_matches || ff || zz || verbose > 0;
|
||||
if(showsig)
|
||||
pmsg_info("device signature =%s", str_cchex(sig->buf, sig->size, 1));
|
||||
if(*mculist && showsig)
|
||||
msg_info(" (%s)", is_dryrun? p->desc: mculist);
|
||||
|
||||
bool signature_matches =
|
||||
sig->size == 3 &&
|
||||
sig->buf[0] == p->signature[0] &&
|
||||
sig->buf[1] == p->signature[1] &&
|
||||
sig->buf[2] == p->signature[2];
|
||||
|
||||
if (quell_progress < 2) {
|
||||
AVRPART *part;
|
||||
if((part = locate_part_by_signature_pm(part_list, sig->buf, sig->size, pgm->prog_modes)) ||
|
||||
(part = locate_part_by_signature(part_list, sig->buf, sig->size)))
|
||||
msg_info(" (probably %s)", signature_matches? p->id: part->id);
|
||||
}
|
||||
if (ff || zz) {
|
||||
if (ff || zz) { // All three bytes are 0xff or all three bytes are 0x00
|
||||
if (++attempt < 3) {
|
||||
waittime *= 5;
|
||||
msg_info(" (retrying)\n");
|
||||
goto sig_again;
|
||||
}
|
||||
msg_info("\n");
|
||||
pmsg_error("Yikes! Invalid device signature.\n");
|
||||
pmsg_error("invalid device signature\n");
|
||||
if (!ovsigck) {
|
||||
pmsg_error("expected signature for %s is %02X %02X %02X\n", p->desc,
|
||||
p->signature[0], p->signature[1], p->signature[2]);
|
||||
imsg_error("Double check connections and try again, or use -F to override\n");
|
||||
imsg_error("this check.\n\n");
|
||||
pmsg_error("expected signature for %s is%s; double\n", p->desc, str_cchex(p->signature, 3, 1));
|
||||
imsg_error("check connections and try again, or use -F to carry on regardless\n");
|
||||
exitrc = 1;
|
||||
goto main_exit;
|
||||
}
|
||||
} else {
|
||||
} else if(showsig) {
|
||||
msg_info("\n");
|
||||
}
|
||||
|
||||
if (!signature_matches) {
|
||||
if (ovsigck) {
|
||||
pmsg_warning("expected signature for %s is %02X %02X %02X\n", p->desc,
|
||||
p->signature[0], p->signature[1], p->signature[2]);
|
||||
pmsg_warning("expected signature for %s is%s\n", p->desc, str_cchex(p->signature, 3, 1));
|
||||
} else {
|
||||
pmsg_error("expected signature for %s is %02X %02X %02X\n", p->desc,
|
||||
p->signature[0], p->signature[1], p->signature[2]);
|
||||
imsg_error("double check chip or use -F to override this check\n");
|
||||
pmsg_error("expected signature for %s is%s; double\n", p->desc, str_cchex(p->signature, 3, 1));
|
||||
imsg_error("check chip or use -F to carry on regardless\n");
|
||||
exitrc = 1;
|
||||
goto main_exit;
|
||||
}
|
||||
@@ -1669,26 +1700,37 @@ skipopen:
|
||||
}
|
||||
|
||||
if (uflags & UF_AUTO_ERASE) {
|
||||
if ((p->prog_modes & PM_PDI) && pgm->page_erase && lsize(updates) > 0) {
|
||||
pmsg_info("Note: programmer supports page erase for Xmega devices.\n");
|
||||
imsg_info("Each page will be erased before programming it, but no chip erase is performed.\n");
|
||||
imsg_info("To disable page erases, specify the -D option; for a chip-erase, use the -e option.\n");
|
||||
} else {
|
||||
AVRMEM * m;
|
||||
const char *memname = p->prog_modes & PM_PDI? "application": "flash";
|
||||
|
||||
uflags &= ~UF_AUTO_ERASE;
|
||||
for (ln=lfirst(updates); ln; ln=lnext(ln)) {
|
||||
if((p->prog_modes & (PM_PDI | PM_UPDI)) && pgm->page_erase && lsize(updates) > 0) {
|
||||
for(ln=lfirst(updates); ln; ln=lnext(ln)) {
|
||||
upd = ldata(ln);
|
||||
if(!upd->memstr)
|
||||
continue;
|
||||
m = avr_locate_mem(p, upd->memstr);
|
||||
if (m == NULL)
|
||||
continue;
|
||||
if(str_eq(m->desc, memname) && upd->op == DEVICE_WRITE) {
|
||||
erase = 1;
|
||||
pmsg_info("Note: %s memory has been specified, an erase cycle will be performed.\n", memname);
|
||||
imsg_info("To disable this feature, specify the -D option.\n");
|
||||
if(upd->memstr && upd->op == DEVICE_WRITE && memlist_contains_flash(upd->memstr, p)) {
|
||||
cx->avr_disableffopt = 1; // Must write full flash file including trailing 0xff
|
||||
pmsg_notice("NOT erasing chip as page erase will be used for new flash%s contents;\n",
|
||||
avr_locate_bootrow(p)? "/bootrow": "");
|
||||
imsg_notice("unprogrammed flash contents remains: use -e for an explicit chip-erase\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uflags &= ~UF_AUTO_ERASE;
|
||||
for(ln=lfirst(updates); ln; ln=lnext(ln)) {
|
||||
upd = ldata(ln);
|
||||
if(upd->cmdline && *str_ltrim(upd->cmdline) && str_starts("erase", str_ltrim(upd->cmdline)))
|
||||
break; // -T erase already erases the chip: no auto-erase needed
|
||||
|
||||
if(upd->cmdline || (upd->memstr && // Might be reading flash?
|
||||
(upd->op == DEVICE_READ || upd->op == DEVICE_VERIFY) &&
|
||||
memlist_contains_flash(upd->memstr, p)))
|
||||
flashread = 1;
|
||||
|
||||
if(upd->memstr && upd->op == DEVICE_WRITE && memlist_contains_flash(upd->memstr, p)) {
|
||||
if(flashread) {
|
||||
pmsg_info("NOT auto-erasing chip as flash might need reading before writing to it\n");
|
||||
} else {
|
||||
erase = 1;
|
||||
pmsg_notice("auto-erasing chip as flash memory needs programming (-U %s:w:...)\n", upd->memstr);
|
||||
imsg_notice("specify the -D option to disable this feature\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1701,16 +1743,21 @@ skipopen:
|
||||
* before the chip can accept new programming
|
||||
*/
|
||||
if (uflags & UF_NOWRITE) {
|
||||
pmsg_warning("%s-n specified, NOT erasing chip\n", explicit_e? "conflicting -e and ": "");
|
||||
if(explicit_e)
|
||||
pmsg_warning("conflicting -e and -n specified, NOT erasing chip\n");
|
||||
else
|
||||
pmsg_notice("-n specified, NOT erasing chip\n");
|
||||
} else {
|
||||
pmsg_info("erasing chip\n");
|
||||
exitrc = avr_chip_erase(pgm, p);
|
||||
if(exitrc == LIBAVRDUDE_SOFTFAIL) {
|
||||
imsg_info("delaying chip erase until first -U upload to flash\n");
|
||||
pmsg_notice("delaying chip erase until first -U upload to flash\n");
|
||||
ce_delayed = 1;
|
||||
exitrc = 0;
|
||||
} else if(exitrc)
|
||||
} else if(exitrc) {
|
||||
pmsg_error("chip erase failed\n");
|
||||
goto main_exit;
|
||||
} else
|
||||
pmsg_notice("erased chip\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1721,6 +1768,8 @@ skipopen:
|
||||
|
||||
|
||||
int wrmem = 0, terminal = 0;
|
||||
if(lsize(updates) <= 1)
|
||||
uflags |= UF_NOHEADING;
|
||||
for (ln=lfirst(updates); ln; ln=lnext(ln)) {
|
||||
const AVRMEM *m;
|
||||
upd = ldata(ln);
|
||||
@@ -1757,7 +1806,8 @@ main_exit:
|
||||
pgm->close(pgm);
|
||||
}
|
||||
|
||||
msg_info("\n%s done. Thank you.\n\n", progname);
|
||||
msg_info("\n");
|
||||
pmsg_info("%s done. Thank you.\n", progname);
|
||||
|
||||
return ce_delayed? 1: exitrc;
|
||||
}
|
||||
|
||||
@@ -75,12 +75,11 @@
|
||||
#define MICRONUCLEUS_DEFAULT_TIMEOUT 500
|
||||
#define MICRONUCLEUS_MAX_MAJOR_VERSION 2
|
||||
|
||||
#define PDATA(pgm) ((pdata_t*)(pgm->cookie))
|
||||
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef struct pdata
|
||||
{
|
||||
struct pdata {
|
||||
usb_dev_handle* usb_handle;
|
||||
// Extended parameters
|
||||
bool wait_until_device_present;
|
||||
@@ -102,7 +101,7 @@ typedef struct pdata
|
||||
uint16_t user_reset_vector; // reset vector of user program
|
||||
bool write_last_page; // last page already programmed
|
||||
bool start_program; // require start after flash
|
||||
} pdata_t;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -111,8 +110,7 @@ static void delay_ms(uint32_t duration)
|
||||
usleep(duration * 1000);
|
||||
}
|
||||
|
||||
static int micronucleus_check_connection(pdata_t* pdata)
|
||||
{
|
||||
static int micronucleus_check_connection(struct pdata *pdata) {
|
||||
if (pdata->major_version >= 2)
|
||||
{
|
||||
uint8_t buffer[6] = { 0 };
|
||||
@@ -139,8 +137,7 @@ static int micronucleus_check_connection(pdata_t* pdata)
|
||||
}
|
||||
}
|
||||
|
||||
static bool micronucleus_is_device_responsive(pdata_t* pdata, struct usb_device* device)
|
||||
{
|
||||
static bool micronucleus_is_device_responsive(struct pdata *pdata, struct usb_device *device) {
|
||||
pdata->usb_handle = usb_open(device);
|
||||
if (pdata->usb_handle == NULL)
|
||||
{
|
||||
@@ -155,8 +152,7 @@ static bool micronucleus_is_device_responsive(pdata_t* pdata, struct usb_device*
|
||||
return result >= 0;
|
||||
}
|
||||
|
||||
static int micronucleus_reconnect(pdata_t* pdata)
|
||||
{
|
||||
static int micronucleus_reconnect(struct pdata *pdata) {
|
||||
struct usb_device* device = usb_device(pdata->usb_handle);
|
||||
|
||||
usb_close(pdata->usb_handle);
|
||||
@@ -176,8 +172,7 @@ static int micronucleus_reconnect(pdata_t* pdata)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int micronucleus_get_bootloader_info_v1(pdata_t* pdata)
|
||||
{
|
||||
static int micronucleus_get_bootloader_info_v1(struct pdata *pdata) {
|
||||
uint8_t buffer[4] = { 0 };
|
||||
int result = usb_control_msg(
|
||||
pdata->usb_handle,
|
||||
@@ -243,8 +238,7 @@ static int micronucleus_get_bootloader_info_v1(pdata_t* pdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int micronucleus_get_bootloader_info_v2(pdata_t* pdata)
|
||||
{
|
||||
static int micronucleus_get_bootloader_info_v2(struct pdata *pdata) {
|
||||
uint8_t buffer[6] = { 0 };
|
||||
int result = usb_control_msg(
|
||||
pdata->usb_handle,
|
||||
@@ -284,8 +278,7 @@ static int micronucleus_get_bootloader_info_v2(pdata_t* pdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int micronucleus_get_bootloader_info(pdata_t* pdata)
|
||||
{
|
||||
static int micronucleus_get_bootloader_info(struct pdata *pdata) {
|
||||
if (pdata->major_version >= 2)
|
||||
{
|
||||
return micronucleus_get_bootloader_info_v2(pdata);
|
||||
@@ -296,8 +289,7 @@ static int micronucleus_get_bootloader_info(pdata_t* pdata)
|
||||
}
|
||||
}
|
||||
|
||||
static void micronucleus_dump_device_info(pdata_t* pdata)
|
||||
{
|
||||
static void micronucleus_dump_device_info(struct pdata *pdata) {
|
||||
pmsg_notice("Bootloader version: %d.%d\n", pdata->major_version, pdata->minor_version);
|
||||
imsg_notice("Available flash size: %u\n", pdata->flash_size);
|
||||
imsg_notice("Page size: %u\n", pdata->page_size);
|
||||
@@ -308,8 +300,7 @@ static void micronucleus_dump_device_info(pdata_t* pdata)
|
||||
imsg_notice("Signature2: 0x%02X\n", pdata->signature2);
|
||||
}
|
||||
|
||||
static int micronucleus_erase_device(pdata_t* pdata)
|
||||
{
|
||||
static int micronucleus_erase_device(struct pdata *pdata) {
|
||||
pmsg_debug("micronucleus_erase_device()\n");
|
||||
|
||||
int result = usb_control_msg(
|
||||
@@ -351,8 +342,7 @@ static int micronucleus_erase_device(pdata_t* pdata)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int micronucleus_patch_reset_vector(pdata_t* pdata, uint8_t* buffer)
|
||||
{
|
||||
static int micronucleus_patch_reset_vector(struct pdata *pdata, uint8_t *buffer) {
|
||||
// Save user reset vector.
|
||||
uint16_t word0 = (buffer[1] << 8) | buffer[0];
|
||||
uint16_t word1 = (buffer[3] << 8) | buffer[2];
|
||||
@@ -394,8 +384,7 @@ static int micronucleus_patch_reset_vector(pdata_t* pdata, uint8_t* buffer)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void micronucleus_patch_user_vector(pdata_t* pdata, uint8_t* buffer)
|
||||
{
|
||||
static void micronucleus_patch_user_vector(struct pdata *pdata, uint8_t *buffer) {
|
||||
uint16_t user_reset_addr = pdata->bootloader_start - 4;
|
||||
uint16_t address = pdata->bootloader_start - pdata->page_size;
|
||||
if (user_reset_addr > 0x2000)
|
||||
@@ -416,8 +405,7 @@ static void micronucleus_patch_user_vector(pdata_t* pdata, uint8_t* buffer)
|
||||
}
|
||||
}
|
||||
|
||||
static int micronucleus_write_page_v1(pdata_t* pdata, uint32_t address, uint8_t* buffer, uint32_t size)
|
||||
{
|
||||
static int micronucleus_write_page_v1(struct pdata *pdata, uint32_t address, uint8_t *buffer, uint32_t size) {
|
||||
int result = usb_control_msg(
|
||||
pdata->usb_handle,
|
||||
USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
@@ -434,8 +422,7 @@ static int micronucleus_write_page_v1(pdata_t* pdata, uint32_t address, uint8_t*
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int micronucleus_write_page_v2(pdata_t* pdata, uint32_t address, uint8_t* buffer, uint32_t size)
|
||||
{
|
||||
static int micronucleus_write_page_v2(struct pdata *pdata, uint32_t address, uint8_t *buffer, uint32_t size) {
|
||||
int result = usb_control_msg(
|
||||
pdata->usb_handle,
|
||||
USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
@@ -470,8 +457,7 @@ static int micronucleus_write_page_v2(pdata_t* pdata, uint32_t address, uint8_t*
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int micronucleus_write_page(pdata_t* pdata, uint32_t address, uint8_t* buffer, uint32_t size)
|
||||
{
|
||||
static int micronucleus_write_page(struct pdata *pdata, uint32_t address, uint8_t *buffer, uint32_t size) {
|
||||
pmsg_debug("micronucleus_write_page(address=0x%04X, size=%d)\n", address, size);
|
||||
|
||||
if (address == 0)
|
||||
@@ -522,8 +508,7 @@ static int micronucleus_write_page(pdata_t* pdata, uint32_t address, uint8_t* bu
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int micronucleus_start(pdata_t* pdata)
|
||||
{
|
||||
static int micronucleus_start(struct pdata *pdata) {
|
||||
pmsg_debug("micronucleus_start()\n");
|
||||
|
||||
int result = usb_control_msg(
|
||||
@@ -546,7 +531,7 @@ static int micronucleus_start(pdata_t* pdata)
|
||||
|
||||
static void micronucleus_setup(PROGRAMMER *pgm) {
|
||||
pmsg_debug("micronucleus_setup()\n");
|
||||
pgm->cookie = mmt_malloc(sizeof(pdata_t));
|
||||
pgm->cookie = mmt_malloc(sizeof(struct pdata));
|
||||
}
|
||||
|
||||
static void micronucleus_teardown(PROGRAMMER* pgm) {
|
||||
@@ -558,7 +543,7 @@ static void micronucleus_teardown(PROGRAMMER* pgm) {
|
||||
static int micronucleus_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
pmsg_debug("micronucleus_initialize()\n");
|
||||
|
||||
pdata_t* pdata = PDATA(pgm);
|
||||
struct pdata *pdata = PDATA(pgm);
|
||||
|
||||
int result = micronucleus_get_bootloader_info(pdata);
|
||||
if (result < 0)
|
||||
@@ -570,7 +555,7 @@ static int micronucleus_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
|
||||
static void micronucleus_display(const PROGRAMMER *pgm, const char *prefix) {
|
||||
pmsg_debug("micronucleus_display()\n");
|
||||
// pmsg_debug("micronucleus_display()\n");
|
||||
}
|
||||
|
||||
static void micronucleus_powerup(const PROGRAMMER *pgm) {
|
||||
@@ -580,7 +565,7 @@ static void micronucleus_powerup(const PROGRAMMER *pgm) {
|
||||
static void micronucleus_powerdown(const PROGRAMMER *pgm) {
|
||||
pmsg_debug("micronucleus_powerdown()\n");
|
||||
|
||||
pdata_t* pdata = PDATA(pgm);
|
||||
struct pdata *pdata = PDATA(pgm);
|
||||
if (pdata->write_last_page)
|
||||
{
|
||||
pdata->write_last_page = false;
|
||||
@@ -621,7 +606,7 @@ static int micronucleus_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdata_t* pdata = PDATA(pgm);
|
||||
struct pdata *pdata = PDATA(pgm);
|
||||
mem->buf[0] = 0x1E;
|
||||
mem->buf[1] = pdata->signature1;
|
||||
mem->buf[2] = pdata->signature2;
|
||||
@@ -631,14 +616,14 @@ static int micronucleus_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p,
|
||||
static int micronucleus_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
pmsg_debug("micronucleus_chip_erase()\n");
|
||||
|
||||
pdata_t* pdata = PDATA(pgm);
|
||||
struct pdata *pdata = PDATA(pgm);
|
||||
return micronucleus_erase_device(pdata);
|
||||
}
|
||||
|
||||
static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
|
||||
pmsg_debug("micronucleus_open(\"%s\")\n", port);
|
||||
|
||||
pdata_t* pdata = PDATA(pgm);
|
||||
struct pdata *pdata = PDATA(pgm);
|
||||
const char *bus_name = NULL;
|
||||
char* dev_name = NULL;
|
||||
|
||||
@@ -664,8 +649,7 @@ static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
|
||||
|
||||
if (port != NULL && dev_name == NULL)
|
||||
{
|
||||
pmsg_error("invalid -P value %s\n", port);
|
||||
imsg_error("use -P usb:bus:device\n");
|
||||
pmsg_error("invalid -P %s; use -P usb:bus:device\n", port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -790,7 +774,7 @@ static void micronucleus_close(PROGRAMMER* pgm)
|
||||
{
|
||||
pmsg_debug("micronucleus_close()\n");
|
||||
|
||||
pdata_t* pdata = PDATA(pgm);
|
||||
struct pdata *pdata = PDATA(pgm);
|
||||
if (pdata->usb_handle != NULL)
|
||||
{
|
||||
usb_close(pdata->usb_handle);
|
||||
@@ -838,7 +822,7 @@ static int micronucleus_paged_write(const PROGRAMMER *pgm, const AVRPART *p, con
|
||||
|
||||
if (mem_is_flash(mem))
|
||||
{
|
||||
pdata_t* pdata = PDATA(pgm);
|
||||
struct pdata *pdata = PDATA(pgm);
|
||||
|
||||
if (n_bytes > page_size)
|
||||
{
|
||||
@@ -884,39 +868,48 @@ static int micronucleus_paged_write(const PROGRAMMER *pgm, const AVRPART *p, con
|
||||
}
|
||||
|
||||
static int micronucleus_parseextparams(const PROGRAMMER *pgm, const LISTID xparams) {
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
pmsg_debug("micronucleus_parseextparams()\n");
|
||||
|
||||
pdata_t* pdata = PDATA(pgm);
|
||||
for (LNODEID node = lfirst(xparams); node != NULL; node = lnext(node))
|
||||
struct pdata *pdata = PDATA(pgm);
|
||||
for (LNODEID node = lfirst(xparams); node; node = lnext(node))
|
||||
{
|
||||
const char* param = ldata(node);
|
||||
const char* extended_param = ldata(node);
|
||||
|
||||
if (str_eq(param, "wait"))
|
||||
if (str_eq(extended_param, "wait"))
|
||||
{
|
||||
pdata->wait_until_device_present = true;
|
||||
pdata->wait_timout = -1;
|
||||
continue;
|
||||
}
|
||||
else if (str_starts(param, "wait="))
|
||||
|
||||
if (str_starts(extended_param, "wait="))
|
||||
{
|
||||
pdata->wait_until_device_present = true;
|
||||
pdata->wait_timout = atoi(param + 5);
|
||||
pdata->wait_timout = atoi(extended_param + 5);
|
||||
continue;
|
||||
}
|
||||
else if (str_eq(param, "help"))
|
||||
|
||||
if (str_eq(extended_param, "help"))
|
||||
{
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -xwait Wait for the device to be plugged in if not connected\n");
|
||||
msg_error(" -xwait=<arg> Wait <arg> [s] for the device to be plugged in if not connected\n");
|
||||
msg_error(" -xhelp Show this help menu and exit\n");
|
||||
return LIBAVRDUDE_EXIT;
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
else
|
||||
|
||||
if (!help)
|
||||
{
|
||||
pmsg_error("invalid extended parameter '%s'\n", param);
|
||||
return -1;
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x wait Wait for the device to be plugged in if not connected\n");
|
||||
msg_error(" -x wait=<n> Wait <n> s for the device to be plugged in if not connected\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void micronucleus_initpgm(PROGRAMMER *pgm) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* Copyright (C) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
|
||||
77
src/par.c
77
src/par.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2006 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2006 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -44,14 +42,14 @@
|
||||
|
||||
#if HAVE_PARPORT
|
||||
|
||||
struct ppipins_t {
|
||||
struct ppipins {
|
||||
int pin;
|
||||
int reg;
|
||||
int bit;
|
||||
int inverted;
|
||||
};
|
||||
|
||||
static const struct ppipins_t ppipins[] = {
|
||||
static const struct ppipins ppipins[] = {
|
||||
{ 1, PPICTRL, 0x01, 1 },
|
||||
{ 2, PPIDATA, 0x01, 0 },
|
||||
{ 3, PPIDATA, 0x02, 0 },
|
||||
@@ -71,7 +69,7 @@ static const struct ppipins_t ppipins[] = {
|
||||
{ 17, PPICTRL, 0x08, 1 }
|
||||
};
|
||||
|
||||
#define NPINS (sizeof(ppipins)/sizeof(struct ppipins_t))
|
||||
#define NPINS (sizeof(ppipins)/sizeof(struct ppipins))
|
||||
|
||||
static int par_setpin_internal(const PROGRAMMER *pgm, int pin, int value) {
|
||||
int inverted;
|
||||
@@ -335,36 +333,59 @@ static void par_close(PROGRAMMER *pgm) {
|
||||
*/
|
||||
static int par_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
|
||||
char *cp, *s, *str = mmt_strdup(sp);
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
s = str;
|
||||
while((cp = strtok(s, ","))) {
|
||||
if(str_eq(cp, "reset"))
|
||||
s = NULL;
|
||||
if(str_eq(cp, "reset")) {
|
||||
pgm->exit_reset = EXIT_RESET_ENABLED;
|
||||
|
||||
else if(str_eq(cp, "noreset"))
|
||||
pgm->exit_reset = EXIT_RESET_DISABLED;
|
||||
|
||||
else if(str_eq(cp, "vcc"))
|
||||
pgm->exit_vcc = EXIT_VCC_ENABLED;
|
||||
|
||||
else if(str_eq(cp, "novcc"))
|
||||
pgm->exit_vcc = EXIT_VCC_DISABLED;
|
||||
|
||||
else if(str_eq(cp, "d_high"))
|
||||
pgm->exit_datahigh = EXIT_DATAHIGH_ENABLED;
|
||||
|
||||
else if(str_eq(cp, "d_low"))
|
||||
pgm->exit_datahigh = EXIT_DATAHIGH_DISABLED;
|
||||
|
||||
else {
|
||||
mmt_free(str);
|
||||
return -1;
|
||||
continue;
|
||||
}
|
||||
s = NULL; // Only call strtok() once with the actual string
|
||||
if(str_eq(cp, "noreset")) {
|
||||
pgm->exit_reset = EXIT_RESET_DISABLED;
|
||||
continue;
|
||||
}
|
||||
if(str_eq(cp, "vcc")) {
|
||||
pgm->exit_vcc = EXIT_VCC_ENABLED;
|
||||
continue;
|
||||
}
|
||||
if(str_eq(cp, "novcc")) {
|
||||
pgm->exit_vcc = EXIT_VCC_DISABLED;
|
||||
continue;
|
||||
}
|
||||
if(str_eq(cp, "d_high")) {
|
||||
pgm->exit_datahigh = EXIT_DATAHIGH_ENABLED;
|
||||
continue;
|
||||
}
|
||||
if(str_eq(cp, "d_low")) {
|
||||
pgm->exit_datahigh = EXIT_DATAHIGH_DISABLED;
|
||||
continue;
|
||||
}
|
||||
if (str_eq(cp, "help")) {
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
if (!help) {
|
||||
pmsg_error("invalid exitspec parameter -E %s\n", cp);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s exitspec parameter options:\n", progname, pgmid);
|
||||
msg_error(" -E reset Programmer will keep the reset line low after programming session\n");
|
||||
msg_error(" -E noreset Programmer will not keep the reset line low after programming session\n");
|
||||
msg_error(" -E vcc Programmer VCC pin(s) remain active after programming session\n");
|
||||
msg_error(" -E novcc Programmer VCC pin(s) turned off after programming session\n");
|
||||
msg_error(" -E d_high Set all 8 programmer data pins high after programming session\n");
|
||||
msg_error(" -E d_low Set all 8 programmer data pins low after programming session\n");
|
||||
msg_error(" -E help Show this help menu and exit\n");
|
||||
mmt_free(str);
|
||||
return rv;
|
||||
}
|
||||
|
||||
mmt_free(str);
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
void par_initpgm(PROGRAMMER *pgm) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef par_h
|
||||
#define par_h
|
||||
|
||||
|
||||
47
src/pgm.c
47
src/pgm.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright 2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include <ac_cfg.h>
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -169,7 +167,7 @@ PROGRAMMER *pgm_new(void) {
|
||||
pin_clear_all(&(pgm->pin[i]));
|
||||
}
|
||||
|
||||
pgm->leds = mmt_malloc(sizeof(leds_t));
|
||||
pgm->leds = mmt_malloc(sizeof(Leds));
|
||||
|
||||
pgm_init_functions(pgm);
|
||||
|
||||
@@ -218,7 +216,7 @@ PROGRAMMER *pgm_dup(const PROGRAMMER *src) {
|
||||
if(pgm->cp_usersig)
|
||||
mmt_free(pgm->cp_usersig);
|
||||
|
||||
leds_t *ls = pgm->leds;
|
||||
Leds *ls = pgm->leds;
|
||||
memcpy(pgm, src, sizeof(*pgm));
|
||||
if(ls && src->leds)
|
||||
memcpy(ls, src->leds, sizeof *ls);
|
||||
@@ -284,7 +282,7 @@ static void pgm_default_setup_teardown(PROGRAMMER *pgm) {
|
||||
|
||||
|
||||
void programmer_display(PROGRAMMER *pgm, const char * p) {
|
||||
msg_info("%sProgrammer Type : %s\n", p, pgm->type);
|
||||
msg_info("%sProgrammer type : %s\n", p, pgm->type);
|
||||
msg_info("%sDescription : %s\n", p, pgm->desc);
|
||||
|
||||
pgm->display(pgm, p);
|
||||
@@ -292,34 +290,11 @@ void programmer_display(PROGRAMMER *pgm, const char * p) {
|
||||
|
||||
|
||||
void pgm_display_generic_mask(const PROGRAMMER *pgm, const char *p, unsigned int show) {
|
||||
if(show & (1<<PPI_AVR_VCC))
|
||||
msg_info("%s VCC = %s\n", p, pins_to_str(&pgm->pin[PPI_AVR_VCC]));
|
||||
if(show & (1<<PPI_AVR_BUFF))
|
||||
msg_info("%s BUFF = %s\n", p, pins_to_str(&pgm->pin[PPI_AVR_BUFF]));
|
||||
if(show & (1<<PIN_AVR_RESET))
|
||||
msg_info("%s RESET = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_RESET]));
|
||||
if(show & (1<<PIN_AVR_SCK))
|
||||
msg_info("%s SCK = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SCK]));
|
||||
if(show & (1<<PIN_AVR_SDO))
|
||||
msg_info("%s SDO = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SDO]));
|
||||
if(show & (1<<PIN_AVR_SDI))
|
||||
msg_info("%s SDI = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SDI]));
|
||||
if(show & (1<<PIN_JTAG_TCK))
|
||||
msg_info("%s TCK = %s\n", p, pins_to_str(&pgm->pin[PIN_JTAG_TCK]));
|
||||
if(show & (1<<PIN_JTAG_TDI))
|
||||
msg_info("%s TDI = %s\n", p, pins_to_str(&pgm->pin[PIN_JTAG_TDI]));
|
||||
if(show & (1<<PIN_JTAG_TDO))
|
||||
msg_info("%s TDO = %s\n", p, pins_to_str(&pgm->pin[PIN_JTAG_TDO]));
|
||||
if(show & (1<<PIN_JTAG_TMS))
|
||||
msg_info("%s TMS = %s\n", p, pins_to_str(&pgm->pin[PIN_JTAG_TMS]));
|
||||
if(show & (1<<PIN_LED_ERR))
|
||||
msg_info("%s ERR LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_ERR]));
|
||||
if(show & (1<<PIN_LED_RDY))
|
||||
msg_info("%s RDY LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_RDY]));
|
||||
if(show & (1<<PIN_LED_PGM))
|
||||
msg_info("%s PGM LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_PGM]));
|
||||
if(show & (1<<PIN_LED_VFY))
|
||||
msg_info("%s VFY LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_VFY]));
|
||||
for(int pbit = 1; pbit < N_PINS; pbit++)
|
||||
if(show & (1<<pbit)) {
|
||||
const char *pinstr = pins_to_str(pgm->pin + pbit);
|
||||
msg_info("%s %-6s = %s\n", p, avr_pin_name(pbit), *pinstr? pinstr: "(not used)");
|
||||
}
|
||||
}
|
||||
|
||||
void pgm_display_generic(const PROGRAMMER *pgm, const char *p) {
|
||||
@@ -435,7 +410,7 @@ void sort_programmers(LISTID programmers)
|
||||
}
|
||||
|
||||
|
||||
// Soft assignment: some struct programmer_t entries can be both programmers and serial adapters
|
||||
// Soft assignment: some PROGRAMMER entries can be both programmers and serial adapters
|
||||
int is_programmer(const PROGRAMMER *p) {
|
||||
return p && p->id && lsize(p->id) && p->prog_modes && p->initpgm;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright 2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "ppi.h"
|
||||
#include "serbb.h"
|
||||
#include "serialupdi.h"
|
||||
#include "serprog.h"
|
||||
#include "stk500.h"
|
||||
#include "stk500generic.h"
|
||||
#include "stk500v2.h"
|
||||
@@ -100,6 +101,7 @@ const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call th
|
||||
{"pickit2", pickit2_initpgm, pickit2_desc}, // "pickit2"
|
||||
{"serbb", serbb_initpgm, serbb_desc}, // "SERBB"
|
||||
{"serialupdi", serialupdi_initpgm, serialupdi_desc}, // "serialupdi"
|
||||
{"serprog", serprog_initpgm, serprog_desc}, // "serprog"
|
||||
{"stk500", stk500_initpgm, stk500_desc}, // "STK500"
|
||||
{"stk500generic", stk500generic_initpgm, stk500generic_desc}, // "STK500GENERIC"
|
||||
{"stk500v2", stk500v2_initpgm, stk500v2_desc}, // "STK500V2"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Copyright (C) 2005 Erik Walthinsen
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2006 David Moore
|
||||
* Copyright (C) 2006,2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2006, 2007 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -249,7 +249,7 @@ static int pickit2_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
//memset(report, 0, sizeof(report));
|
||||
if ((errorCode = pickit2_read_report(pgm, report)) >= 4)
|
||||
{
|
||||
pmsg_notice("%s firmware version %d.%d.%d\n", pgm->desc, (int)report[1], (int)report[2], (int)report[3]);
|
||||
pmsg_notice2("%s firmware version %d.%d.%d\n", pgm->desc, report[1], report[2], report[3]);
|
||||
|
||||
// set the pins, apply reset,
|
||||
// TO DO: apply vtarget (if requested though -x option)
|
||||
@@ -408,7 +408,7 @@ static int pickit2_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
|
||||
{
|
||||
int i;
|
||||
msg_debug("program_enable(): sending command. Resp = ");
|
||||
msg_debug("%s(): sending command. Resp = ", __func__);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
@@ -1105,7 +1105,7 @@ static int usb_open_device(PROGRAMMER *pgm, struct usb_dev_handle **device, int
|
||||
// return with opened device handle
|
||||
else
|
||||
{
|
||||
msg_notice("device %p seemed to open OK\n", handle);
|
||||
msg_notice2("device %p seemed to open OK\n", handle);
|
||||
|
||||
if ((errorCode = usb_set_configuration(handle, 1)) < 0)
|
||||
{
|
||||
@@ -1144,30 +1144,28 @@ static int pickit2_read_report(const PROGRAMMER *pgm, unsigned char report[65])
|
||||
#endif // WIN32
|
||||
|
||||
static int pickit2_parseextparams(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln))
|
||||
for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln))
|
||||
{
|
||||
extended_param = ldata(ln);
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
if (str_starts(extended_param, "clockrate="))
|
||||
{
|
||||
int clock_rate;
|
||||
if (sscanf(extended_param, "clockrate=%i", &clock_rate) != 1 || clock_rate <= 0)
|
||||
{
|
||||
pmsg_error("invalid clockrate '%s'\n", extended_param);
|
||||
pmsg_error("invalid clock rate in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
int clock_period = MIN(1000000 / clock_rate, 255); // max period is 255
|
||||
clock_rate = (int)(1000000 / (clock_period + 5e-7)); // assume highest speed is 2MHz - should probably check this
|
||||
|
||||
pmsg_notice2("pickit2_parseextparms(): clockrate set to 0x%02x\n", clock_rate);
|
||||
pmsg_notice2("%s(): effective clock rate set to 0x%02x\n", __func__, clock_rate);
|
||||
PDATA(pgm)->clock_period = clock_period;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1176,26 +1174,32 @@ static int pickit2_parseextparams(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
int timeout;
|
||||
if (sscanf(extended_param, "timeout=%i", &timeout) != 1 || timeout <= 0)
|
||||
{
|
||||
pmsg_error("invalid timeout '%s'\n", extended_param);
|
||||
pmsg_error("invalid timeout in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
pmsg_notice2("pickit2_parseextparms(): usb timeout set to 0x%02x\n", timeout);
|
||||
pmsg_notice2("%s(): usb timeout set to 0x%02x\n", __func__, timeout);
|
||||
PDATA(pgm)->transaction_timeout = timeout;
|
||||
|
||||
continue;
|
||||
}
|
||||
if (str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -xclockrate=<arg> Set the SPI clocking rate in <arg> [Hz]\n");
|
||||
msg_error(" -xtimeout=<arg> Set the timeout for USB read/write to <arg> [ms]\n");
|
||||
msg_error(" -xhelp Show this help menu and exit\n");
|
||||
return LIBAVRDUDE_EXIT;;
|
||||
|
||||
if (str_eq(extended_param, "help"))
|
||||
{
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
pmsg_error("invalid extended parameter '%s'\n", extended_param);
|
||||
rv = -1;
|
||||
if (!help)
|
||||
{
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x clockrate=<n> Set the SPI clock rate to <n> Hz\n");
|
||||
msg_error(" -x timeout=<n> Set the timeout for USB read/write to <n> ms\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2006 Thomas Fischl
|
||||
* Copyright (C) 2006 Thomas Fischl
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
100
src/pindefs.c
100
src/pindefs.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -34,7 +34,7 @@
|
||||
* @param[in] pin number of pin [0..PIN_MAX]
|
||||
* @param[in] inverse inverse (true) or normal (false) pin
|
||||
*/
|
||||
void pin_set_value(struct pindef_t * const pindef, const int pin, const bool inverse) {
|
||||
void pin_set_value(struct pindef * const pindef, const int pin, const bool inverse) {
|
||||
|
||||
pindef->mask[pin / PIN_FIELD_ELEMENT_SIZE] |= 1 << (pin % PIN_FIELD_ELEMENT_SIZE);
|
||||
if(inverse) {
|
||||
@@ -49,8 +49,8 @@ void pin_set_value(struct pindef_t * const pindef, const int pin, const bool inv
|
||||
*
|
||||
* @param[out] pindef pin definition to clear
|
||||
*/
|
||||
void pin_clear_all(struct pindef_t * const pindef) {
|
||||
memset(pindef, 0, sizeof(struct pindef_t));
|
||||
void pin_clear_all(struct pindef * const pindef) {
|
||||
memset(pindef, 0, sizeof(struct pindef));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,7 +59,7 @@ void pin_clear_all(struct pindef_t * const pindef) {
|
||||
* @param[in] pindef new pin definition structure
|
||||
* @param[out] pinno old pin definition integer
|
||||
*/
|
||||
static int pin_fill_old_pinno(const struct pindef_t * const pindef, unsigned int * const pinno) {
|
||||
static int pin_fill_old_pinno(const struct pindef * const pindef, unsigned int * const pinno) {
|
||||
bool found = false;
|
||||
int i;
|
||||
for(i = 0; i <= PIN_MAX; i++) {
|
||||
@@ -84,7 +84,7 @@ static int pin_fill_old_pinno(const struct pindef_t * const pindef, unsigned int
|
||||
* @param[in] pindef new pin definition structure
|
||||
* @param[out] pinno old pin definition integer
|
||||
*/
|
||||
static int pin_fill_old_pinlist(const struct pindef_t * const pindef, unsigned int * const pinno) {
|
||||
static int pin_fill_old_pinlist(const struct pindef * const pindef, unsigned int * const pinno) {
|
||||
for(size_t i = 0; i < PIN_FIELD_SIZE; i++) {
|
||||
if(i == 0) {
|
||||
if((pindef->mask[i] & ~PIN_MASK) != 0) {
|
||||
@@ -152,19 +152,17 @@ int pgm_fill_old_pins(PROGRAMMER * const pgm) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns a string representation of pins in the mask eg. 1,3,5-7,9,12
|
||||
* Another execution of this function will overwrite the previous result in the static buffer.
|
||||
* Consecutive pin number are represented as start-end.
|
||||
* This function returns a string representation of pins in the mask eg. 1, 3, 5-7, 9, 12
|
||||
* Consecutive pin numbers are represented as start-end.
|
||||
*
|
||||
* @param[in] pinmask the pin mask for which we want the string representation
|
||||
* @returns pointer to a static string.
|
||||
* @returns a temporary string that lives in closed-circuit space
|
||||
*/
|
||||
const char * pinmask_to_str(const pinmask_t * const pinmask) {
|
||||
static char buf[(PIN_MAX + 1) * 5]; // should be enough for PIN_MAX=255
|
||||
const char *pinmask_to_str(const Pinmask * const pinmask) {
|
||||
char buf[6 * (PIN_MAX + 1)];
|
||||
char *p = buf;
|
||||
int n;
|
||||
int pin;
|
||||
const char * fmt;
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
|
||||
@@ -189,11 +187,8 @@ const char * pinmask_to_str(const pinmask_t * const pinmask) {
|
||||
start = pin;
|
||||
end = start;
|
||||
}
|
||||
if(output) {
|
||||
fmt = (buf[0] == 0) ? "%d" : ",%d";
|
||||
n = sprintf(p, fmt, pin);
|
||||
p += n;
|
||||
}
|
||||
if(output)
|
||||
p += n = sprintf(p, *buf? ", %d": "%d", pin);
|
||||
}
|
||||
}
|
||||
if(start != end) {
|
||||
@@ -201,10 +196,7 @@ const char * pinmask_to_str(const pinmask_t * const pinmask) {
|
||||
p += n;
|
||||
}
|
||||
|
||||
if(buf[0] == 0)
|
||||
return "(no pins)";
|
||||
|
||||
return buf;
|
||||
return str_ccstrdup(*buf? buf: "(no pins)");
|
||||
}
|
||||
|
||||
|
||||
@@ -216,20 +208,20 @@ const char * pinmask_to_str(const pinmask_t * const pinmask) {
|
||||
* @li any pins are used by more than one function
|
||||
* @li any mandatory pin is not set all.
|
||||
*
|
||||
* In case of any error it report the wrong function and the pin numbers.
|
||||
* For verbose >= 2 it also reports the possible correct values.
|
||||
* For verbose >=3 it shows also which pins were ok.
|
||||
* In case of any error it report the wrong function and the pin numbers
|
||||
* For verbose >= MSG_NOTICE2 it also reports the possible correct values
|
||||
* For verbose >= MSG_DEBUG it shows also which pins were ok
|
||||
*
|
||||
* @param[in] pgm the programmer to check
|
||||
* @param[in] checklist the constraint for the pins
|
||||
* @param[in] size the number of entries in checklist
|
||||
* @returns 0 if all pin definitions are valid, -1 otherwise
|
||||
*/
|
||||
int pins_check(const PROGRAMMER *const pgm, const struct pin_checklist_t *const checklist, const int size, const bool output) {
|
||||
static const struct pindef_t no_valid_pins = {{0}, {0}}; // default value if check list does not contain anything else
|
||||
int pins_check(const PROGRAMMER *const pgm, const Pin_checklist *const checklist, const int size, const bool output) {
|
||||
static const struct pindef no_valid_pins = {{0}, {0}}; // default value if check list does not contain anything else
|
||||
int rv = 0; // return value
|
||||
int pinname; // loop counter through pinnames
|
||||
pinmask_t already_used_all[PIN_FIELD_SIZE] = {0}; // collect pin definitions of all pin names for check of double use
|
||||
Pinmask already_used_all[PIN_FIELD_SIZE] = {0}; // collect pin definitions of all pin names for check of double use
|
||||
// loop over all possible pinnames
|
||||
for(pinname = 0; pinname < N_PINS; pinname++) {
|
||||
bool used = false;
|
||||
@@ -237,10 +229,10 @@ int pins_check(const PROGRAMMER *const pgm, const struct pin_checklist_t *const
|
||||
bool inverse = false;
|
||||
int index;
|
||||
bool mandatory_used = false;
|
||||
pinmask_t invalid_used[PIN_FIELD_SIZE] = {0};
|
||||
pinmask_t inverse_used[PIN_FIELD_SIZE] = {0};
|
||||
pinmask_t already_used[PIN_FIELD_SIZE] = {0};
|
||||
const struct pindef_t * valid_pins = &no_valid_pins;
|
||||
Pinmask invalid_used[PIN_FIELD_SIZE] = {0};
|
||||
Pinmask inverse_used[PIN_FIELD_SIZE] = {0};
|
||||
Pinmask already_used[PIN_FIELD_SIZE] = {0};
|
||||
const struct pindef * valid_pins = &no_valid_pins;
|
||||
bool is_mandatory = false;
|
||||
bool is_ok = true;
|
||||
//find corresponding check pattern
|
||||
@@ -279,7 +271,7 @@ int pins_check(const PROGRAMMER *const pgm, const struct pin_checklist_t *const
|
||||
if(output) {
|
||||
pmsg_error("%s: these pins are not valid pins for this function: %s\n",
|
||||
avr_pin_name(pinname), pinmask_to_str(invalid_used));
|
||||
pmsg_notice("%s: valid pins for this function are: %s\n",
|
||||
imsg_error("%s: valid pins for this function are: %s\n",
|
||||
avr_pin_name(pinname), pinmask_to_str(valid_pins->mask));
|
||||
}
|
||||
is_ok = false;
|
||||
@@ -288,7 +280,7 @@ int pins_check(const PROGRAMMER *const pgm, const struct pin_checklist_t *const
|
||||
if(output) {
|
||||
pmsg_error("%s: these pins are not usable as inverse pins for this function: %s\n",
|
||||
avr_pin_name(pinname), pinmask_to_str(inverse_used));
|
||||
pmsg_notice("%s: valid inverse pins for this function are: %s\n",
|
||||
imsg_error("%s: valid inverse pins for this function are: %s\n",
|
||||
avr_pin_name(pinname), pinmask_to_str(valid_pins->inverse));
|
||||
}
|
||||
is_ok = false;
|
||||
@@ -315,48 +307,14 @@ int pins_check(const PROGRAMMER *const pgm, const struct pin_checklist_t *const
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns a string of defined pins, eg, ~1,2,~4,~5,7 or " (not used)"
|
||||
* Another execution of this function will overwrite the previous result in the static buffer.
|
||||
*
|
||||
* @param[in] pindef the pin definition for which we want the string representation
|
||||
* @returns pointer to a static string.
|
||||
*/
|
||||
const char * pins_to_str(const struct pindef_t * const pindef) {
|
||||
static char buf[(PIN_MAX + 1) * 5]; // should be enough for PIN_MAX=255
|
||||
char *p = buf;
|
||||
int n;
|
||||
int pin;
|
||||
const char * fmt;
|
||||
|
||||
buf[0] = 0;
|
||||
for(pin = PIN_MIN; pin <= PIN_MAX; pin++) {
|
||||
int index = pin / PIN_FIELD_ELEMENT_SIZE;
|
||||
int bit = pin % PIN_FIELD_ELEMENT_SIZE;
|
||||
if(pindef->mask[index] & (1 << bit)) {
|
||||
if(pindef->inverse[index] & (1 << bit)) {
|
||||
fmt = (buf[0] == 0) ? "~%d" : ",~%d";
|
||||
} else {
|
||||
fmt = (buf[0] == 0) ? " %d" : ",%d";
|
||||
}
|
||||
n = sprintf(p, fmt, pin);
|
||||
p += n;
|
||||
}
|
||||
}
|
||||
|
||||
if(buf[0] == 0)
|
||||
return " (not used)";
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or ""
|
||||
*
|
||||
* @param[in] pindef the pin definition for which we want the string representation
|
||||
* @returns a pointer to a string, which was created by mmt_strdup()
|
||||
* @returns a temporary string that lives in closed-circuit space
|
||||
*/
|
||||
char *pins_to_strdup(const struct pindef_t * const pindef) {
|
||||
const char *pins_to_str(const struct pindef * const pindef) {
|
||||
char buf[6*(PIN_MAX+1)], *p = buf;
|
||||
|
||||
*buf = 0;
|
||||
@@ -369,7 +327,7 @@ char *pins_to_strdup(const struct pindef_t * const pindef) {
|
||||
}
|
||||
}
|
||||
|
||||
return mmt_strdup(buf);
|
||||
return str_ccstrdup(buf);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
11
src/ppi.c
11
src/ppi.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
|
||||
#if !defined(WIN32)
|
||||
|
||||
@@ -54,7 +52,6 @@ enum {
|
||||
static int ppi_shadow_access(const union filedescriptor *fdp, int reg,
|
||||
unsigned char *v, unsigned char action)
|
||||
{
|
||||
static unsigned char shadow[3];
|
||||
int shadow_num;
|
||||
|
||||
switch (reg) {
|
||||
@@ -75,14 +72,14 @@ static int ppi_shadow_access(const union filedescriptor *fdp, int reg,
|
||||
|
||||
switch (action) {
|
||||
case PPI_SHADOWREAD:
|
||||
*v = shadow[shadow_num];
|
||||
*v = cx->ppi_shadow[shadow_num];
|
||||
break;
|
||||
case PPI_READ:
|
||||
DO_PPI_READ(fdp->ifd, reg, v);
|
||||
shadow[shadow_num]=*v;
|
||||
cx->ppi_shadow[shadow_num]=*v;
|
||||
break;
|
||||
case PPI_WRITE:
|
||||
shadow[shadow_num]=*v;
|
||||
cx->ppi_shadow[shadow_num]=*v;
|
||||
DO_PPI_WRITE(fdp->ifd, reg, v);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef ppi_h
|
||||
#define ppi_h
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003, 2004, 2006
|
||||
* Eric B. Weddington <eweddington@cso.atmel.com>
|
||||
* Copyright 2008, Joerg Wunsch
|
||||
* Copyright (C) 2003, 2004, 2006 Eric B. Weddington <eweddington@cso.atmel.com>
|
||||
* Copyright (C) 2008 Joerg Wunsch
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
This is the parallel port interface for Windows built using Cygwin.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2006 Christian Starkjohann
|
||||
*
|
||||
@@ -18,8 +18,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Serial Interface emulation for USB programmer "AVR-Doper" in HID mode.
|
||||
*/
|
||||
@@ -57,10 +55,6 @@
|
||||
|
||||
static const int reportDataSizes[4] = {13, 29, 61, 125};
|
||||
|
||||
static unsigned char avrdoperRxBuffer[280]; /* buffer for receive data */
|
||||
static int avrdoperRxLength = 0; /* amount of valid bytes in rx buffer */
|
||||
static int avrdoperRxPosition = 0; /* amount of bytes already consumed in rx buffer */
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -189,19 +183,18 @@ static void dumpBlock(const char *prefix, const unsigned char *buf, int len)
|
||||
}
|
||||
}
|
||||
|
||||
static char *usbErrorText(int usbErrno)
|
||||
{
|
||||
static char buffer[32];
|
||||
|
||||
static const char *usbErrorText(int usbErrno) {
|
||||
switch(usbErrno){
|
||||
case USB_ERROR_NONE: return "Success";
|
||||
case USB_ERROR_ACCESS: return "Access denied";
|
||||
case USB_ERROR_NOTFOUND:return "Device not found";
|
||||
case USB_ERROR_BUSY: return "Device is busy";
|
||||
case USB_ERROR_NONE: return "success";
|
||||
case USB_ERROR_ACCESS: return "access denied";
|
||||
case USB_ERROR_NOTFOUND:return "device not found";
|
||||
case USB_ERROR_BUSY: return "device is busy";
|
||||
case USB_ERROR_IO: return "I/O Error";
|
||||
default:
|
||||
sprintf(buffer, "Unknown error %d", usbErrno);
|
||||
default: {
|
||||
char *buffer = avr_cc_buffer(32);
|
||||
sprintf(buffer, "unknown error %d", usbErrno);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,7 +208,7 @@ static int avrdoper_open(const char *port, union pinfo pinfo, union filedescript
|
||||
|
||||
rval = usbOpenDevice(fdp, USB_VENDOR_ID, vname, USB_PRODUCT_ID, devname, 1);
|
||||
if(rval != 0){
|
||||
pmsg_ext_error("%s\n", usbErrorText(rval));
|
||||
pmsg_ext_error("USB %s\n", usbErrorText(rval));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
@@ -247,7 +240,7 @@ static int avrdoper_send(const union filedescriptor *fdp, const unsigned char *b
|
||||
pmsg_error("%s() called with too large buflen = %lu\n", __func__, (unsigned long) buflen);
|
||||
return -1;
|
||||
}
|
||||
if(verbose > 3)
|
||||
if(verbose >= MSG_TRACE)
|
||||
dumpBlock("Send", buf, buflen);
|
||||
while(buflen > 0){
|
||||
unsigned char buffer[256];
|
||||
@@ -261,7 +254,7 @@ static int avrdoper_send(const union filedescriptor *fdp, const unsigned char *b
|
||||
rval = usbSetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, (char *)buffer,
|
||||
reportDataSizes[lenIndex] + 2);
|
||||
if(rval != 0){
|
||||
pmsg_error("%s\n", usbErrorText(rval));
|
||||
pmsg_error("USB %s\n", usbErrorText(rval));
|
||||
return -1;
|
||||
}
|
||||
buflen -= thisLen;
|
||||
@@ -275,18 +268,18 @@ static int avrdoper_send(const union filedescriptor *fdp, const unsigned char *b
|
||||
static int avrdoperFillBuffer(const union filedescriptor *fdp) {
|
||||
int bytesPending = reportDataSizes[1]; /* guess how much data is buffered in device */
|
||||
|
||||
avrdoperRxPosition = avrdoperRxLength = 0;
|
||||
cx->sad_avrdoperRxPosition = cx->sad_avrdoperRxLength = 0;
|
||||
while(bytesPending > 0){
|
||||
int len, usbErr, lenIndex = chooseDataSize(bytesPending);
|
||||
unsigned char buffer[128];
|
||||
len = sizeof(avrdoperRxBuffer) - avrdoperRxLength; /* bytes remaining */
|
||||
len = sizeof(cx->sad_avrdoperRxBuffer) - cx->sad_avrdoperRxLength; /* bytes remaining */
|
||||
if(reportDataSizes[lenIndex] + 2 > len) /* requested data would not fit into buffer */
|
||||
break;
|
||||
len = reportDataSizes[lenIndex] + 2;
|
||||
usbErr = usbGetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, lenIndex + 1,
|
||||
(char *)buffer, &len);
|
||||
if(usbErr != 0){
|
||||
pmsg_error("%s\n", usbErrorText(usbErr));
|
||||
pmsg_error("USB %s\n", usbErrorText(usbErr));
|
||||
return -1;
|
||||
}
|
||||
msg_trace("Received %d bytes data chunk of total %d\n", len - 2, buffer[1]);
|
||||
@@ -294,12 +287,12 @@ static int avrdoperFillBuffer(const union filedescriptor *fdp) {
|
||||
bytesPending = buffer[1] - len; /* amount still buffered */
|
||||
if(len > buffer[1]) /* cut away padding */
|
||||
len = buffer[1];
|
||||
if(avrdoperRxLength + len > (int) sizeof(avrdoperRxBuffer)){
|
||||
if(cx->sad_avrdoperRxLength + len > (int) sizeof(cx->sad_avrdoperRxBuffer)){
|
||||
pmsg_error("buffer overflow\n");
|
||||
return -1;
|
||||
}
|
||||
memcpy(avrdoperRxBuffer + avrdoperRxLength, buffer + 2, len);
|
||||
avrdoperRxLength += len;
|
||||
memcpy(cx->sad_avrdoperRxBuffer + cx->sad_avrdoperRxLength, buffer + 2, len);
|
||||
cx->sad_avrdoperRxLength += len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -310,19 +303,19 @@ static int avrdoper_recv(const union filedescriptor *fdp, unsigned char *buf, si
|
||||
int remaining = buflen;
|
||||
|
||||
while(remaining > 0){
|
||||
int len, available = avrdoperRxLength - avrdoperRxPosition;
|
||||
int len, available = cx->sad_avrdoperRxLength - cx->sad_avrdoperRxPosition;
|
||||
if(available <= 0){ /* buffer is empty */
|
||||
if (avrdoperFillBuffer(fdp) < 0)
|
||||
return -1;
|
||||
continue;
|
||||
}
|
||||
len = remaining < available ? remaining : available;
|
||||
memcpy(p, avrdoperRxBuffer + avrdoperRxPosition, len);
|
||||
memcpy(p, cx->sad_avrdoperRxBuffer + cx->sad_avrdoperRxPosition, len);
|
||||
p += len;
|
||||
remaining -= len;
|
||||
avrdoperRxPosition += len;
|
||||
cx->sad_avrdoperRxPosition += len;
|
||||
}
|
||||
if(verbose > 3)
|
||||
if(verbose >= MSG_TRACE)
|
||||
dumpBlock("Receive", buf, buflen);
|
||||
return 0;
|
||||
}
|
||||
@@ -334,7 +327,7 @@ static int avrdoper_drain(const union filedescriptor *fdp, int display)
|
||||
do{
|
||||
if (avrdoperFillBuffer(fdp) < 0)
|
||||
return -1;
|
||||
}while(avrdoperRxLength > 0);
|
||||
}while(cx->sad_avrdoperRxLength > 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
|
||||
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Posix serial interface for avrdude.
|
||||
*/
|
||||
@@ -59,9 +57,7 @@ struct baud_mapping {
|
||||
speed_t speed;
|
||||
};
|
||||
|
||||
/* There are a lot more baud rates we could handle, but what's the point? */
|
||||
|
||||
static struct baud_mapping baud_lookup_table [] = {
|
||||
static const struct baud_mapping baud_lookup_table [] = {
|
||||
{ 300, B300 },
|
||||
{ 600, B600 },
|
||||
{ 1200, B1200 },
|
||||
@@ -121,28 +117,17 @@ static struct baud_mapping baud_lookup_table [] = {
|
||||
{ 0, 0 } /* Terminator. */
|
||||
};
|
||||
|
||||
static struct termios original_termios;
|
||||
static int saved_original_termios;
|
||||
|
||||
static speed_t serial_baud_lookup(long baud, bool *nonstandard) {
|
||||
struct baud_mapping *map = baud_lookup_table;
|
||||
|
||||
*nonstandard = false;
|
||||
|
||||
while (map->baud) {
|
||||
for(const struct baud_mapping *map = baud_lookup_table; map->baud; map++)
|
||||
if (map->baud == baud)
|
||||
return map->speed;
|
||||
map++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a non-standard BAUD rate is used, issue
|
||||
* a warning (if we are verbose) and return the raw rate
|
||||
*/
|
||||
pmsg_notice2("serial_baud_lookup(): using non-standard baud rate: %ld\n", baud);
|
||||
// Return the raw rate when asked for non-standard baud rate
|
||||
pmsg_notice2("%s(): using non-standard baud rate: %ld\n", __func__, baud);
|
||||
|
||||
*nonstandard = true;
|
||||
|
||||
return baud;
|
||||
}
|
||||
|
||||
@@ -168,9 +153,8 @@ static int ser_setparams(const union filedescriptor *fd, long baud, unsigned lon
|
||||
/*
|
||||
* copy termios for ser_close if we haven't already
|
||||
*/
|
||||
if (! saved_original_termios++) {
|
||||
original_termios = termios;
|
||||
}
|
||||
if(!cx->ser_saved_original_termios++)
|
||||
cx->ser_original_termios = termios;
|
||||
|
||||
if (cflags & SERIAL_CREAD) {
|
||||
termios.c_cflag |= CREAD;
|
||||
@@ -413,15 +397,12 @@ static int ser_open(const char *port, union pinfo pinfo, union filedescriptor *f
|
||||
}
|
||||
|
||||
static void ser_close(union filedescriptor *fd) {
|
||||
/*
|
||||
* restore original termios settings from ser_open
|
||||
*/
|
||||
if (saved_original_termios) {
|
||||
int rc = tcsetattr(fd->ifd, TCSANOW | TCSADRAIN, &original_termios);
|
||||
if (rc) {
|
||||
// Restore original termios settings from ser_open
|
||||
if(cx->ser_saved_original_termios) {
|
||||
int rc = tcsetattr(fd->ifd, TCSANOW | TCSADRAIN, &cx->ser_original_termios);
|
||||
if(rc)
|
||||
pmsg_ext_error("cannot reset attributes for device: %s\n", strerror(errno));
|
||||
}
|
||||
saved_original_termios = 0;
|
||||
cx->ser_saved_original_termios = 0;
|
||||
}
|
||||
|
||||
close(fd->ifd);
|
||||
@@ -429,14 +410,14 @@ static void ser_close(union filedescriptor *fd) {
|
||||
|
||||
// Close but don't restore attributes
|
||||
static void ser_rawclose(union filedescriptor *fd) {
|
||||
saved_original_termios = 0;
|
||||
cx->ser_saved_original_termios = 0;
|
||||
close(fd->ifd);
|
||||
}
|
||||
|
||||
static int ser_send(const union filedescriptor *fd, const unsigned char *buf, size_t len) {
|
||||
int rc;
|
||||
|
||||
if(verbose > 3)
|
||||
if(verbose >= MSG_TRACE)
|
||||
trace_buffer(__func__, buf, len);
|
||||
|
||||
while(len) {
|
||||
@@ -472,7 +453,7 @@ static int ser_recv(const union filedescriptor *fd, unsigned char *buf, size_t b
|
||||
|
||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
||||
if (nfds == 0) {
|
||||
pmsg_notice2("ser_recv(): programmer is not responding\n");
|
||||
pmsg_notice2("%s(): programmer is not responding\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (nfds == -1) {
|
||||
@@ -495,7 +476,7 @@ static int ser_recv(const union filedescriptor *fd, unsigned char *buf, size_t b
|
||||
len += rc;
|
||||
}
|
||||
|
||||
if(verbose > 3)
|
||||
if(verbose >= MSG_TRACE)
|
||||
trace_buffer(__func__, buf, len);
|
||||
|
||||
return 0;
|
||||
|
||||
170
src/ser_win32.c
170
src/ser_win32.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003, 2004 Martin J. Thomas <mthomas@rhrk.uni-kl.de>
|
||||
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
* Copyright (C) 2003, 2004 Martin J. Thomas <mthomas@rhrk.uni-kl.de>
|
||||
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -46,11 +46,9 @@ struct baud_mapping {
|
||||
DWORD speed;
|
||||
};
|
||||
|
||||
static unsigned char serial_over_ethernet = 0;
|
||||
|
||||
/* HANDLE hComPort=INVALID_HANDLE_VALUE; */
|
||||
|
||||
static struct baud_mapping baud_lookup_table [] = {
|
||||
static const struct baud_mapping baud_lookup_table [] = {
|
||||
{ 300, CBR_300 },
|
||||
{ 600, CBR_600 },
|
||||
{ 1200, CBR_1200 },
|
||||
@@ -64,21 +62,13 @@ static struct baud_mapping baud_lookup_table [] = {
|
||||
{ 0, 0 } /* Terminator. */
|
||||
};
|
||||
|
||||
static DWORD serial_baud_lookup(long baud)
|
||||
{
|
||||
struct baud_mapping *map = baud_lookup_table;
|
||||
|
||||
while (map->baud) {
|
||||
static DWORD serial_baud_lookup(long baud) {
|
||||
for(const struct baud_mapping *map = baud_lookup_table; map->baud; map++)
|
||||
if (map->baud == baud)
|
||||
return map->speed;
|
||||
map++;
|
||||
}
|
||||
|
||||
/*
|
||||
* If a non-standard BAUD rate is used, issue
|
||||
* a warning (if we are verbose) and return the raw rate
|
||||
*/
|
||||
pmsg_notice2("serial_baud_lookup(): using non-standard baud rate: %ld", baud);
|
||||
// Return the raw rate when asked for non-standard baud rate
|
||||
pmsg_notice2("%s(): using non-standard baud rate: %ld", __func__, baud);
|
||||
|
||||
return baud;
|
||||
}
|
||||
@@ -96,57 +86,55 @@ static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms
|
||||
}
|
||||
|
||||
static int ser_setparams(const union filedescriptor *fd, long baud, unsigned long cflags) {
|
||||
if (serial_over_ethernet) {
|
||||
if(cx->ser_serial_over_ethernet)
|
||||
return -ENOTTY;
|
||||
} else {
|
||||
DCB dcb;
|
||||
HANDLE hComPort = (HANDLE)fd->pfd;
|
||||
|
||||
ZeroMemory (&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
dcb.BaudRate = serial_baud_lookup (baud);
|
||||
dcb.fBinary = 1;
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
switch ((cflags & (SERIAL_CS5 | SERIAL_CS6 | SERIAL_CS7 | SERIAL_CS8))) {
|
||||
case SERIAL_CS5:
|
||||
dcb.ByteSize = 5;
|
||||
break;
|
||||
case SERIAL_CS6:
|
||||
dcb.ByteSize = 6;
|
||||
break;
|
||||
case SERIAL_CS7:
|
||||
dcb.ByteSize = 7;
|
||||
break;
|
||||
case SERIAL_CS8:
|
||||
dcb.ByteSize = 8;
|
||||
break;
|
||||
}
|
||||
switch ((cflags & (SERIAL_NO_PARITY | SERIAL_PARENB | SERIAL_PARODD))) {
|
||||
case SERIAL_NO_PARITY:
|
||||
dcb.Parity = NOPARITY;
|
||||
break;
|
||||
case SERIAL_PARENB:
|
||||
dcb.Parity = EVENPARITY;
|
||||
break;
|
||||
case SERIAL_PARODD:
|
||||
dcb.Parity = ODDPARITY;
|
||||
break;
|
||||
}
|
||||
switch ((cflags & (SERIAL_NO_CSTOPB | SERIAL_CSTOPB))) {
|
||||
case SERIAL_NO_CSTOPB:
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
break;
|
||||
case SERIAL_CSTOPB:
|
||||
dcb.StopBits = TWOSTOPBITS;
|
||||
break;
|
||||
}
|
||||
DCB dcb;
|
||||
HANDLE hComPort = (HANDLE)fd->pfd;
|
||||
|
||||
if (!SetCommState(hComPort, &dcb))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
ZeroMemory (&dcb, sizeof(DCB));
|
||||
dcb.DCBlength = sizeof(DCB);
|
||||
dcb.BaudRate = serial_baud_lookup (baud);
|
||||
dcb.fBinary = 1;
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
switch ((cflags & (SERIAL_CS5 | SERIAL_CS6 | SERIAL_CS7 | SERIAL_CS8))) {
|
||||
case SERIAL_CS5:
|
||||
dcb.ByteSize = 5;
|
||||
break;
|
||||
case SERIAL_CS6:
|
||||
dcb.ByteSize = 6;
|
||||
break;
|
||||
case SERIAL_CS7:
|
||||
dcb.ByteSize = 7;
|
||||
break;
|
||||
case SERIAL_CS8:
|
||||
dcb.ByteSize = 8;
|
||||
break;
|
||||
}
|
||||
switch ((cflags & (SERIAL_NO_PARITY | SERIAL_PARENB | SERIAL_PARODD))) {
|
||||
case SERIAL_NO_PARITY:
|
||||
dcb.Parity = NOPARITY;
|
||||
break;
|
||||
case SERIAL_PARENB:
|
||||
dcb.Parity = EVENPARITY;
|
||||
break;
|
||||
case SERIAL_PARODD:
|
||||
dcb.Parity = ODDPARITY;
|
||||
break;
|
||||
}
|
||||
switch ((cflags & (SERIAL_NO_CSTOPB | SERIAL_CSTOPB))) {
|
||||
case SERIAL_NO_CSTOPB:
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
break;
|
||||
case SERIAL_CSTOPB:
|
||||
dcb.StopBits = TWOSTOPBITS;
|
||||
break;
|
||||
}
|
||||
if (!SetCommState(hComPort, &dcb))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_open(const char *port, union filedescriptor *fdp) {
|
||||
@@ -231,7 +219,7 @@ static int net_open(const char *port, union filedescriptor *fdp) {
|
||||
|
||||
fdp->ifd = fd;
|
||||
|
||||
serial_over_ethernet = 1;
|
||||
cx->ser_serial_over_ethernet = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -308,7 +296,7 @@ static int ser_open(const char *port, union pinfo pinfo, union filedescriptor *f
|
||||
|
||||
|
||||
static void ser_close(union filedescriptor *fd) {
|
||||
if (serial_over_ethernet) {
|
||||
if (cx->ser_serial_over_ethernet) {
|
||||
closesocket(fd->ifd);
|
||||
WSACleanup();
|
||||
} else {
|
||||
@@ -321,20 +309,15 @@ static void ser_close(union filedescriptor *fd) {
|
||||
}
|
||||
|
||||
static int ser_set_dtr_rts(const union filedescriptor *fd, int is_on) {
|
||||
if (serial_over_ethernet) {
|
||||
if(cx->ser_serial_over_ethernet)
|
||||
return 0;
|
||||
} else {
|
||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||
|
||||
if (is_on) {
|
||||
EscapeCommFunction(hComPort, SETDTR);
|
||||
EscapeCommFunction(hComPort, SETRTS);
|
||||
} else {
|
||||
EscapeCommFunction(hComPort, CLRDTR);
|
||||
EscapeCommFunction(hComPort, CLRRTS);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||
|
||||
EscapeCommFunction(hComPort, is_on? SETDTR: CLRDTR);
|
||||
EscapeCommFunction(hComPort, is_on? SETRTS: CLRRTS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int net_send(const union filedescriptor *fd, const unsigned char *buf, size_t len) {
|
||||
@@ -342,14 +325,14 @@ static int net_send(const union filedescriptor *fd, const unsigned char *buf, si
|
||||
int rc;
|
||||
|
||||
if (fd->ifd < 0) {
|
||||
pmsg_notice("net_send(): connection not open\n");
|
||||
pmsg_notice("%s(): connection not open\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (verbose > 3)
|
||||
if (verbose >= MSG_TRACE)
|
||||
trace_buffer(__func__, buf, len);
|
||||
|
||||
while (len) {
|
||||
@@ -378,7 +361,7 @@ static int net_send(const union filedescriptor *fd, const unsigned char *buf, si
|
||||
|
||||
|
||||
static int ser_send(const union filedescriptor *fd, const unsigned char *buf, size_t len) {
|
||||
if (serial_over_ethernet)
|
||||
if(cx->ser_serial_over_ethernet)
|
||||
return net_send(fd, buf, len);
|
||||
|
||||
DWORD written;
|
||||
@@ -393,7 +376,7 @@ static int ser_send(const union filedescriptor *fd, const unsigned char *buf, si
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (verbose > 3)
|
||||
if (verbose >= MSG_TRACE)
|
||||
trace_buffer(__func__, buf, len);
|
||||
|
||||
serial_w32SetTimeOut(hComPort,500);
|
||||
@@ -437,13 +420,11 @@ reselect:
|
||||
|
||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
||||
if (nfds == 0) {
|
||||
if (verbose > 1) {
|
||||
pmsg_notice("net_recv(): programmer is not responding\n");
|
||||
}
|
||||
pmsg_notice2("%s(): programmer is not responding\n", __func__);
|
||||
return -1;
|
||||
} else if (nfds == -1) {
|
||||
if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS) {
|
||||
pmsg_notice("net_recv(): programmer is not responding, reselecting\n");
|
||||
pmsg_notice("%s(): programmer is not responding, reselecting\n", __func__);
|
||||
goto reselect;
|
||||
} else {
|
||||
FormatMessage(
|
||||
@@ -456,7 +437,7 @@ reselect:
|
||||
(LPTSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
pmsg_error("select(): %s\n", (char *) lpMsgBuf);
|
||||
pmsg_error("%s(): %s\n", __func__, (char *) lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
return -1;
|
||||
}
|
||||
@@ -482,14 +463,14 @@ reselect:
|
||||
len += rc;
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
if (verbose >= MSG_TRACE)
|
||||
trace_buffer(__func__, buf, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ser_recv(const union filedescriptor *fd, unsigned char *buf, size_t buflen) {
|
||||
if (serial_over_ethernet)
|
||||
if(cx->ser_serial_over_ethernet)
|
||||
return net_recv(fd, buf, buflen);
|
||||
|
||||
DWORD read;
|
||||
@@ -522,11 +503,11 @@ static int ser_recv(const union filedescriptor *fd, unsigned char *buf, size_t b
|
||||
|
||||
/* time out detected */
|
||||
if (read < buflen) {
|
||||
pmsg_notice2("ser_recv(): programmer is not responding\n");
|
||||
pmsg_notice2("%s(): programmer is not responding\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (verbose > 3)
|
||||
if (verbose >= MSG_TRACE)
|
||||
trace_buffer(__func__, buf, read);
|
||||
|
||||
return 0;
|
||||
@@ -566,7 +547,7 @@ static int net_drain(const union filedescriptor *fd, int display) {
|
||||
}
|
||||
else if (nfds == -1) {
|
||||
if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS) {
|
||||
pmsg_notice("ser_drain(): programmer is not responding, reselecting\n");
|
||||
pmsg_notice("%s(): programmer is not responding, reselecting\n", __func__);
|
||||
goto reselect;
|
||||
} else {
|
||||
FormatMessage(
|
||||
@@ -579,7 +560,7 @@ static int net_drain(const union filedescriptor *fd, int display) {
|
||||
(LPTSTR)&lpMsgBuf,
|
||||
0,
|
||||
NULL);
|
||||
pmsg_error("select(): %s\n", (char *) lpMsgBuf);
|
||||
pmsg_error("%s(): %s\n", __func__, (char *) lpMsgBuf);
|
||||
LocalFree(lpMsgBuf);
|
||||
return -1;
|
||||
}
|
||||
@@ -611,9 +592,8 @@ static int net_drain(const union filedescriptor *fd, int display) {
|
||||
}
|
||||
|
||||
static int ser_drain(const union filedescriptor *fd, int display) {
|
||||
if (serial_over_ethernet) {
|
||||
if(cx->ser_serial_over_ethernet)
|
||||
return net_drain(fd, display);
|
||||
}
|
||||
|
||||
// int rc;
|
||||
unsigned char buf[10];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@@ -16,7 +16,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef serbb_h
|
||||
#define serbb_h
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
|
||||
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
@@ -17,7 +17,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Posix serial bitbanging interface for avrdude.
|
||||
@@ -44,7 +43,13 @@
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
static struct termios oldmode;
|
||||
struct pdata {
|
||||
struct termios oldmode;
|
||||
};
|
||||
|
||||
// Use private programmer data as if they were a global structure my
|
||||
#define my (*(struct pdata *)(pgm->cookie))
|
||||
|
||||
|
||||
/*
|
||||
serial port/pin mapping
|
||||
@@ -62,11 +67,11 @@ static struct termios oldmode;
|
||||
|
||||
#define DB9PINS 9
|
||||
|
||||
static int serregbits[DB9PINS + 1] =
|
||||
static const int serregbits[DB9PINS + 1] =
|
||||
{ 0, TIOCM_CD, 0, 0, TIOCM_DTR, 0, TIOCM_DSR, TIOCM_RTS, TIOCM_CTS, TIOCM_RI };
|
||||
|
||||
#ifdef DEBUG
|
||||
static char *serpins[DB9PINS + 1] =
|
||||
static const char * const serpins[DB9PINS + 1] =
|
||||
{ "NONE", "CD", "RXD", "TXD", "DTR", "GND", "DSR", "RTS", "CTS", "RI" };
|
||||
#endif
|
||||
|
||||
@@ -89,7 +94,7 @@ static int serbb_setpin(const PROGRAMMER *pgm, int pinfunc, int value) {
|
||||
return -1;
|
||||
|
||||
#ifdef DEBUG
|
||||
msg_info("%s to %d\n", serpins[pin], value);
|
||||
msg_notice("%s to %d\n", serpins[pin], value);
|
||||
#endif
|
||||
|
||||
switch ( pin )
|
||||
@@ -167,14 +172,14 @@ static int serbb_getpin(const PROGRAMMER *pgm, int pinfunc) {
|
||||
if ( !invert )
|
||||
{
|
||||
#ifdef DEBUG
|
||||
msg_info("%s is %d\n", serpins[pin], ctl & serregbits[pin]? 1: 0);
|
||||
msg_notice("%s is %d\n", serpins[pin], ctl & serregbits[pin]? 1: 0);
|
||||
#endif
|
||||
return ctl & serregbits[pin]? 1: 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG
|
||||
msg_info("%s is %d (~)\n", serpins[pin], ctl & serregbits[pin]? 0: 1);
|
||||
msg_notice("%s is %d (~)\n", serpins[pin], ctl & serregbits[pin]? 0: 1);
|
||||
#endif
|
||||
return ctl & serregbits[pin]? 0: 1;
|
||||
}
|
||||
@@ -243,7 +248,7 @@ static int serbb_open(PROGRAMMER *pgm, const char *port) {
|
||||
pmsg_ext_error("%s, tcgetattr(): %s\n", port, strerror(errno));
|
||||
return(-1);
|
||||
}
|
||||
oldmode = mode;
|
||||
my.oldmode = mode;
|
||||
|
||||
mode.c_iflag = IGNBRK | IGNPAR;
|
||||
mode.c_oflag = 0;
|
||||
@@ -277,13 +282,22 @@ static int serbb_open(PROGRAMMER *pgm, const char *port) {
|
||||
static void serbb_close(PROGRAMMER *pgm) {
|
||||
if (pgm->fd.ifd != -1)
|
||||
{
|
||||
(void)tcsetattr(pgm->fd.ifd, TCSANOW, &oldmode);
|
||||
(void) tcsetattr(pgm->fd.ifd, TCSANOW, &my.oldmode);
|
||||
pgm->setpin(pgm, PIN_AVR_RESET, 1);
|
||||
close(pgm->fd.ifd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void serbb_setup(PROGRAMMER *pgm) {
|
||||
pgm->cookie = mmt_malloc(sizeof(struct pdata));
|
||||
}
|
||||
|
||||
static void serbb_teardown(PROGRAMMER *pgm) {
|
||||
mmt_free(pgm->cookie);
|
||||
pgm->cookie = NULL;
|
||||
}
|
||||
|
||||
const char serbb_desc[] = "Serial port bitbanging";
|
||||
|
||||
void serbb_initpgm(PROGRAMMER *pgm) {
|
||||
@@ -291,6 +305,8 @@ void serbb_initpgm(PROGRAMMER *pgm) {
|
||||
|
||||
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
||||
|
||||
pgm->setup = serbb_setup;
|
||||
pgm->teardown = serbb_teardown;
|
||||
pgm->rdy_led = bitbang_rdy_led;
|
||||
pgm->err_led = bitbang_err_led;
|
||||
pgm->pgm_led = bitbang_pgm_led;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2003, 2004 Martin J. Thomas <mthomas@rhrk.uni-kl.de>
|
||||
* Copyright (C) 2003, 2004 Martin J. Thomas <mthomas@rhrk.uni-kl.de>
|
||||
* Copyright (C) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
|
||||
* Copyright (C) 2005, 2006 Joerg Wunsch <j@uriah.heep.sax.de>
|
||||
*
|
||||
@@ -17,7 +17,6 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Win32 serial bitbanging interface for avrdude.
|
||||
@@ -40,8 +39,12 @@
|
||||
#include "bitbang.h"
|
||||
#include "serbb.h"
|
||||
|
||||
/* cached status lines */
|
||||
static int dtr, rts, txd;
|
||||
struct pdata {
|
||||
int dtr, rts, txd; // Cached status lines
|
||||
};
|
||||
|
||||
// Use private programmer data as if they were a global structure my
|
||||
#define my (*(struct pdata *)(pgm->cookie))
|
||||
|
||||
#define W32SERBUFSIZE 1024
|
||||
|
||||
@@ -85,25 +88,26 @@ static int serbb_setpin(const PROGRAMMER *pgm, int pinfunc, int value) {
|
||||
case 3: /* txd */
|
||||
dwFunc = value? SETBREAK: CLRBREAK;
|
||||
name = value? "SETBREAK": "CLRBREAK";
|
||||
txd = value;
|
||||
my.txd = value;
|
||||
break;
|
||||
|
||||
case 4: /* dtr */
|
||||
dwFunc = value? SETDTR: CLRDTR;
|
||||
name = value? "SETDTR": "CLRDTR";
|
||||
dtr = value;
|
||||
my.dtr = value;
|
||||
break;
|
||||
|
||||
case 7: /* rts */
|
||||
dwFunc = value? SETRTS: CLRRTS;
|
||||
name = value? "SETRTS": "CLRRTS";
|
||||
my.rts = value;
|
||||
break;
|
||||
|
||||
default:
|
||||
pmsg_notice("serbb_setpin(): unknown pin %d\n", pin + 1);
|
||||
pmsg_warning("%s(): unknown pin %d\n", __func__, pin + 1);
|
||||
return -1;
|
||||
}
|
||||
pmsg_trace2("serbb_setpin(): EscapeCommFunction(%s)\n", name);
|
||||
pmsg_trace2("%s(): EscapeCommFunction(%s)\n", __func__, name);
|
||||
if (!EscapeCommFunction(hComPort, dwFunc))
|
||||
{
|
||||
FormatMessage(
|
||||
@@ -168,7 +172,7 @@ static int serbb_getpin(const PROGRAMMER *pgm, int pinfunc) {
|
||||
LocalFree(lpMsgBuf);
|
||||
return -1;
|
||||
}
|
||||
pmsg_trace2("serbb_getpin(): GetCommState() => 0x%lx\n", modemstate);
|
||||
pmsg_trace2("%s(): GetCommState() => 0x%lx\n", __func__, modemstate);
|
||||
switch (pin)
|
||||
{
|
||||
case 1:
|
||||
@@ -191,22 +195,22 @@ static int serbb_getpin(const PROGRAMMER *pgm, int pinfunc) {
|
||||
switch (pin)
|
||||
{
|
||||
case 3: /* txd */
|
||||
rv = txd;
|
||||
rv = my.txd;
|
||||
name = "TXD";
|
||||
break;
|
||||
case 4: /* dtr */
|
||||
rv = dtr;
|
||||
rv = my.dtr;
|
||||
name = "DTR";
|
||||
break;
|
||||
case 7: /* rts */
|
||||
rv = rts;
|
||||
rv = my.rts;
|
||||
name = "RTS";
|
||||
break;
|
||||
default:
|
||||
pmsg_notice("serbb_getpin(): unknown pin %d\n", pin + 1);
|
||||
pmsg_warning("%s(): unknown pin %d\n", __func__, pin + 1);
|
||||
return -1;
|
||||
}
|
||||
pmsg_trace2("serbb_getpin(): return cached state for %s\n", name);
|
||||
pmsg_trace2("%s(): return cached state for %s\n", __func__, name);
|
||||
if (invert)
|
||||
rv = !rv;
|
||||
|
||||
@@ -299,11 +303,11 @@ static int serbb_open(PROGRAMMER *pgm, const char *port) {
|
||||
pmsg_error("cannot set com-state for %s\n", port);
|
||||
return -1;
|
||||
}
|
||||
pmsg_debug("ser_open(): opened comm port %s, handle 0x%lx\n", port, (long) (INT_PTR) hComPort);
|
||||
pmsg_debug("%s(): opened comm port %s, handle 0x%lx\n", __func__, port, (long) (INT_PTR) hComPort);
|
||||
|
||||
pgm->fd.pfd = (void *)hComPort;
|
||||
|
||||
dtr = rts = txd = 0;
|
||||
my.dtr = my.rts = my.txd = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -315,11 +319,20 @@ static void serbb_close(PROGRAMMER *pgm) {
|
||||
pgm->setpin(pgm, PIN_AVR_RESET, 1);
|
||||
CloseHandle (hComPort);
|
||||
}
|
||||
pmsg_debug("ser_close(): closed comm port handle 0x%lx\n", (long) (INT_PTR) hComPort);
|
||||
pmsg_debug("%s(): closed comm port handle 0x%lx\n", __func__, (long) (INT_PTR) hComPort);
|
||||
|
||||
hComPort = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
static void serbb_setup(PROGRAMMER *pgm) {
|
||||
pgm->cookie = mmt_malloc(sizeof(struct pdata));
|
||||
}
|
||||
|
||||
static void serbb_teardown(PROGRAMMER *pgm) {
|
||||
mmt_free(pgm->cookie);
|
||||
pgm->cookie = NULL;
|
||||
}
|
||||
|
||||
const char serbb_desc[] = "Serial port bitbanging";
|
||||
|
||||
void serbb_initpgm(PROGRAMMER *pgm) {
|
||||
@@ -327,6 +340,8 @@ void serbb_initpgm(PROGRAMMER *pgm) {
|
||||
|
||||
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
||||
|
||||
pgm->setup = serbb_setup;
|
||||
pgm->teardown = serbb_teardown;
|
||||
pgm->rdy_led = bitbang_rdy_led;
|
||||
pgm->err_led = bitbang_err_led;
|
||||
pgm->pgm_led = bitbang_pgm_led;
|
||||
|
||||
@@ -217,7 +217,7 @@ static char **sa_list_specs(const SERPORT *sp, int n, int i) {
|
||||
if(sa_unique_by_sea(sea, "", sp, n, i))
|
||||
Plist[Pi++] = mmt_strdup(id);
|
||||
else if(*sn && sa_unique_by_sea(sea, sn, sp, n, i))
|
||||
Plist[Pi++] = str_sprintf("%s:%s", id, sn);
|
||||
Plist[Pi++] = mmt_sprintf("%s:%s", id, sn);
|
||||
else if(!via && sa_num_matches_by_sea(sea, "", sp+i, 1))
|
||||
via = id;
|
||||
|
||||
@@ -232,11 +232,11 @@ static char **sa_list_specs(const SERPORT *sp, int n, int i) {
|
||||
|
||||
if(Pi == 0 && sp[i].vid) { // No unique serial adapter, so maybe vid:pid[:sn] works?
|
||||
if(sa_unique_by_ids(sp[i].vid, sp[i].pid, "", sp, n, i))
|
||||
Plist[Pi++] = str_sprintf("usb:%04x:%04x", sp[i].vid, sp[i].pid);
|
||||
Plist[Pi++] = mmt_sprintf("usb:%04x:%04x", sp[i].vid, sp[i].pid);
|
||||
else if(*sn && sa_unique_by_ids(sp[i].vid, sp[i].pid, sn, sp, n, i))
|
||||
Plist[Pi++] = str_sprintf("usb:%04x:%04x:%s", sp[i].vid, sp[i].pid, sn);
|
||||
Plist[Pi++] = mmt_sprintf("usb:%04x:%04x:%s", sp[i].vid, sp[i].pid, sn);
|
||||
else if(via && Pi == 0)
|
||||
Plist[Pi++] = str_sprintf("(via %s serial adapter)", via);
|
||||
Plist[Pi++] = mmt_sprintf("(via %s serial adapter)", via);
|
||||
}
|
||||
|
||||
Plist[Pi] = NULL;
|
||||
@@ -315,7 +315,7 @@ int touch_serialport(char **portp, int baudrate, int nwaits) {
|
||||
if(!sp1 || n1 <= 0 || !portp)
|
||||
return -1;
|
||||
|
||||
pmsg_info("touching serial port %s at %d baud\n", *portp, baudrate);
|
||||
pmsg_notice("touching serial port %s at %d baud\n", *portp, baudrate);
|
||||
|
||||
union pinfo pinfo;
|
||||
union filedescriptor fd;
|
||||
@@ -334,18 +334,18 @@ int touch_serialport(char **portp, int baudrate, int nwaits) {
|
||||
#if (defined(__arm__) || defined(__aarch64__)) && !defined(__APPLE__)
|
||||
nwaits += 2;
|
||||
#endif
|
||||
pmsg_info("waiting for new port...");
|
||||
pmsg_notice("waiting for new port...");
|
||||
usleep(400*1000*nwaits);
|
||||
for(i = nloops; i > 0; i--) {
|
||||
usleep(nap*1000);
|
||||
if((sp2 = get_libserialport_data(&n2))) {
|
||||
diff = sa_spa_not_spb(sp2, n2, sp1, n1);
|
||||
if(*diff && diff[0]->port && !diff[1]) { // Exactly one new port sprung up
|
||||
pmsg_notice("new port %s discovered\n", (*diff)->port);
|
||||
pmsg_notice2("new port %s discovered\n", (*diff)->port);
|
||||
if(*portp)
|
||||
mmt_free(*portp);
|
||||
*portp = mmt_strdup((*diff)->port);
|
||||
msg_info(" %d ms:", (nloops-i+1)*nap + nwaits*400);
|
||||
msg_notice(" %d ms:", (nloops-i+1)*nap + nwaits*400);
|
||||
i = -1; // Leave loop
|
||||
}
|
||||
mmt_free(diff);
|
||||
@@ -353,7 +353,7 @@ int touch_serialport(char **portp, int baudrate, int nwaits) {
|
||||
}
|
||||
}
|
||||
free_libserialport_data(sp1, n1);
|
||||
msg_info(" using %s port %s\n", i<0? "new": "same", *portp);
|
||||
msg_notice(" using %s port %s\n", i<0? "new": "same", *portp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2021 Dawid Buchwald
|
||||
* Copyright (C) 2021 Dawid Buchwald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,8 +17,6 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Interface to the SerialUPDI programmer.
|
||||
*
|
||||
@@ -186,7 +184,7 @@ static void serialupdi_close(PROGRAMMER * pgm)
|
||||
pmsg_error("unable to leave NVM programming mode\n");
|
||||
}
|
||||
if (updi_get_rts_mode(pgm) != RTS_MODE_DEFAULT) {
|
||||
pmsg_info("releasing DTR/RTS handshake lines\n");
|
||||
pmsg_notice("releasing DTR/RTS handshake lines\n");
|
||||
}
|
||||
|
||||
updi_link_close(pgm);
|
||||
@@ -604,7 +602,7 @@ static int serialupdi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
pmsg_notice2("UPDI link initialization OK\n");
|
||||
|
||||
if (updi_get_rts_mode(pgm) != RTS_MODE_DEFAULT) {
|
||||
pmsg_info("forcing serial DTR/RTS handshake lines %s\n", updi_get_rts_mode(pgm) == RTS_MODE_LOW ? "LOW" : "HIGH");
|
||||
pmsg_notice("forcing serial DTR/RTS handshake lines %s\n", updi_get_rts_mode(pgm) == RTS_MODE_LOW ? "LOW" : "HIGH");
|
||||
}
|
||||
|
||||
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
|
||||
@@ -677,11 +675,11 @@ static int serialupdi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
if (serialupdi_enter_progmode(pgm) == 0) {
|
||||
/* If successful, you can run silicon check */
|
||||
if (updi_read_data(pgm, p->syscfg_base+1, &value, 1) < 0) {
|
||||
pmsg_error("Reading chip silicon revision failed\n");
|
||||
pmsg_error("reading chip silicon revision failed\n");
|
||||
return -1;
|
||||
} else {
|
||||
pmsg_debug("Received chip silicon revision 0x%02x\n", value);
|
||||
pmsg_notice("Chip silicon revision: %x.%x\n", value >> 4, value & 0x0f);
|
||||
pmsg_debug("received chip silicon revision 0x%02x\n", value);
|
||||
pmsg_notice("chip silicon revision: %x.%x\n", value >> 4, value & 0x0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,6 +767,11 @@ static int serialupdi_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const
|
||||
buffer[0]=value;
|
||||
return updi_nvm_write_flash(pgm, p, mem->offset + addr, buffer, 1);
|
||||
}
|
||||
if (mem_is_bootrow(mem)) {
|
||||
unsigned char buffer[1];
|
||||
buffer[0]=value;
|
||||
return updi_nvm_write_boot_row(pgm, p, mem->offset + addr, buffer, 1);
|
||||
}
|
||||
// Read-only memories
|
||||
if(mem_is_readonly(mem)) {
|
||||
unsigned char is;
|
||||
@@ -841,6 +844,9 @@ static int serialupdi_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const
|
||||
} else if (mem_is_userrow(m)) {
|
||||
rc = serialupdi_write_userrow(pgm, p, m, page_size, write_offset,
|
||||
remaining_bytes > m->page_size ? m->page_size : remaining_bytes);
|
||||
} else if (mem_is_bootrow(m)) {
|
||||
rc = updi_nvm_write_boot_row(pgm, p, m->offset + write_offset, m->buf + write_offset,
|
||||
remaining_bytes > m->page_size ? m->page_size : remaining_bytes);
|
||||
} else if (mem_is_fuses(m)) {
|
||||
pmsg_debug("page write operation requested for fuses, falling back to byte-level write\n");
|
||||
return -1;
|
||||
@@ -866,6 +872,8 @@ static int serialupdi_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const
|
||||
rc = updi_nvm_write_flash(pgm, p, m->offset+addr, m->buf+addr, n_bytes);
|
||||
} else if (mem_is_userrow(m)) {
|
||||
rc = serialupdi_write_userrow(pgm, p, m, page_size, addr, n_bytes);
|
||||
} else if (mem_is_bootrow(m)) {
|
||||
rc = updi_nvm_write_boot_row(pgm, p, m->offset+addr, m->buf+addr, n_bytes);
|
||||
} else if (mem_is_fuses(m)) {
|
||||
pmsg_debug("page write operation requested for fuses, falling back to byte-level write\n");
|
||||
rc = -1;
|
||||
@@ -1004,13 +1012,12 @@ static int serialupdi_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *si
|
||||
}
|
||||
|
||||
static int serialupdi_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
char rts_mode[5];
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
if (sscanf(extended_param, "rtsdtr=%4s", rts_mode) == 1) {
|
||||
if (str_caseeq(rts_mode, "low")) {
|
||||
@@ -1018,20 +1025,26 @@ static int serialupdi_parseextparms(const PROGRAMMER *pgm, const LISTID extparms
|
||||
} else if (str_caseeq(rts_mode, "high")) {
|
||||
updi_set_rts_mode(pgm, RTS_MODE_HIGH);
|
||||
} else {
|
||||
pmsg_error("RTS/DTR mode must be LOW or HIGH\n");
|
||||
return -1;
|
||||
pmsg_error("-x rtsdtr=<mode>: RTS/DTR mode must be LOW or HIGH\n");
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -xrtsdtr=low,high Force RTS/DTR lines low or high state during programming\n");
|
||||
msg_error(" -xhelp Show this help menu and exit\n");
|
||||
return LIBAVRDUDE_EXIT;;
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
pmsg_error("invalid extended parameter '%s'\n", extended_param);
|
||||
rv = -1;
|
||||
if (!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x rtsdtr=[low|high] Set RTS/DTR lines low/high during programming\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2021 Dawid Buchwald
|
||||
* Copyright (C) 2021 Dawid Buchwald
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,8 +17,6 @@
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* Based on pymcuprog
|
||||
* See https://github.com/microchip-pic-avr-tools/pymcuprog
|
||||
|
||||
523
src/serprog.c
Normal file
523
src/serprog.c
Normal file
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Support for using serprog programmers to program over ISP.
|
||||
* For information on serprog see:
|
||||
* https://flashrom.org/supported_hw/supported_prog/serprog/index.html
|
||||
*
|
||||
* Copyright (C) 2024 Sydney Louisa Wilke <git@funkeleinhorn.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Known limitations:
|
||||
* - performance is suboptimal
|
||||
* - connecting over TCP/IP to programmers is not implemented yet
|
||||
*/
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
|
||||
#include "serprog.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
const char serprog_desc[] = "Program via the Serprog protocol from Flashrom";
|
||||
|
||||
// Private data for this programmer
|
||||
struct pdata {
|
||||
unsigned char cmd_bitmap[32];
|
||||
unsigned int cs;
|
||||
uint32_t actual_frequency;
|
||||
};
|
||||
|
||||
#define my (*(struct pdata *)(pgm->cookie))
|
||||
|
||||
// Serprog protocol specification
|
||||
|
||||
// According to Serial Flasher Protocol Specification - version 1
|
||||
#define S_ACK 0x06
|
||||
#define S_NAK 0x15
|
||||
#define S_CMD_NOP 0x00 // No operation
|
||||
#define S_CMD_Q_IFACE 0x01 // Query interface version
|
||||
#define S_CMD_Q_CMDMAP 0x02 // Query supported commands bitmap
|
||||
#define S_CMD_Q_PGMNAME 0x03 // Query programmer name
|
||||
#define S_CMD_Q_SERBUF 0x04 // Query Serial Buffer Size
|
||||
#define S_CMD_Q_BUSTYPE 0x05 // Query supported bustypes
|
||||
#define S_CMD_Q_CHIPSIZE 0x06 // Query supported chipsize (2^n format)
|
||||
#define S_CMD_Q_OPBUF 0x07 // Query operation buffer size
|
||||
#define S_CMD_Q_WRNMAXLEN 0x08 // Query Write to opbuf: Write-N maximum length
|
||||
#define S_CMD_R_BYTE 0x09 // Read a single byte
|
||||
#define S_CMD_R_NBYTES 0x0A // Read n bytes
|
||||
#define S_CMD_O_INIT 0x0B // Initialize operation buffer
|
||||
#define S_CMD_O_WRITEB 0x0C // Write opbuf: Write byte with address
|
||||
#define S_CMD_O_WRITEN 0x0D // Write to opbuf: Write-N
|
||||
#define S_CMD_O_DELAY 0x0E // Write opbuf: udelay
|
||||
#define S_CMD_O_EXEC 0x0F // Execute operation buffer
|
||||
#define S_CMD_SYNCNOP 0x10 // Special no-operation that returns NAK+ACK
|
||||
#define S_CMD_Q_RDNMAXLEN 0x11 // Query read-n maximum length
|
||||
#define S_CMD_S_BUSTYPE 0x12 // Set used bustype(s).
|
||||
#define S_CMD_O_SPIOP 0x13 // Perform SPI operation.
|
||||
#define S_CMD_S_SPI_FREQ 0x14 // Set SPI clock frequency
|
||||
#define S_CMD_S_PIN_STATE 0x15 // Enable/disable output drivers
|
||||
#define S_CMD_S_SPI_CS 0x16 // Set SPI chip select to use
|
||||
#define S_CMD_S_SPI_MODE 0x17 // Sets the SPI mode used by S_CMD_O_SPIOP
|
||||
#define S_CMD_S_CS_MODE 0x18 // Sets the way the CS is controlled
|
||||
|
||||
enum spi_mode {
|
||||
SPI_MODE_HALF_DUPLEX = 0,
|
||||
SPI_MODE_FULL_DUPLEX = 1,
|
||||
SPI_MODE_MAX = SPI_MODE_FULL_DUPLEX,
|
||||
};
|
||||
|
||||
enum cs_mode {
|
||||
CS_MODE_AUTO = 0,
|
||||
CS_MODE_SELECTED = 1,
|
||||
CS_MODE_DESELECTED = 2,
|
||||
CS_MODE_MAX = CS_MODE_DESELECTED,
|
||||
};
|
||||
|
||||
// Little endian helper functions
|
||||
|
||||
static uint16_t read_le16(const unsigned char *buf) {
|
||||
return buf[0] | (buf[1] << 8);
|
||||
}
|
||||
|
||||
static uint32_t read_le32(const unsigned char *buf) {
|
||||
return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
|
||||
}
|
||||
|
||||
static void write_le24(unsigned char *buf, uint32_t val) {
|
||||
buf[0] = val;
|
||||
buf[1] = val >> 8;
|
||||
buf[2] = val >> 16;
|
||||
}
|
||||
|
||||
static void write_le32(unsigned char *buf, uint32_t val) {
|
||||
buf[0] = val;
|
||||
buf[1] = val >> 8;
|
||||
buf[2] = val >> 16;
|
||||
buf[3] = val >> 24;
|
||||
}
|
||||
|
||||
// Serprog communication functions
|
||||
|
||||
static int perform_serprog_cmd_full(const PROGRAMMER *pgm, uint8_t cmd,
|
||||
const unsigned char *params, int params_len,
|
||||
const unsigned char *send_buf, int send_len, unsigned char *recv_buf, int recv_len) {
|
||||
|
||||
unsigned char resp_status_code = 0;
|
||||
|
||||
if(serial_send(&pgm->fd, &cmd, 1) < 0)
|
||||
return -1;
|
||||
if(params_len > 0)
|
||||
if(serial_send(&pgm->fd, params, params_len) < 0)
|
||||
return -1;
|
||||
if(send_len > 0)
|
||||
if(serial_send(&pgm->fd, send_buf, send_len) < 0)
|
||||
return -1;
|
||||
|
||||
if(serial_recv(&pgm->fd, &resp_status_code, 1) < 0 || serial_recv(&pgm->fd, recv_buf, recv_len) < 0)
|
||||
return -1;
|
||||
|
||||
return resp_status_code == S_ACK? 0: resp_status_code == S_NAK? 1: -1;
|
||||
}
|
||||
|
||||
static int perform_serprog_cmd(const PROGRAMMER *pgm, uint8_t cmd,
|
||||
const unsigned char *params, int params_len, unsigned char *recv_buf, int recv_len) {
|
||||
return perform_serprog_cmd_full(pgm, cmd, params, params_len, NULL, 0, recv_buf, recv_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends/receives a message to the AVR in full duplex mode
|
||||
* @return -1 on failure, otherwise number of bytes sent/received
|
||||
*/
|
||||
static int serprog_spi_duplex(const PROGRAMMER *pgm, const unsigned char *tx, unsigned char *rx, int len) {
|
||||
unsigned char params[6];
|
||||
|
||||
write_le24(params, len);
|
||||
write_le24(params + 3, len);
|
||||
if(perform_serprog_cmd_full(pgm, S_CMD_O_SPIOP, params, sizeof params, tx, len, rx, len) != 0)
|
||||
return -1;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool is_serprog_cmd_supported(const unsigned char *cmd_bitmap, unsigned char cmd) {
|
||||
return (cmd_bitmap[cmd / 8] >> (cmd % 8)) & 1;
|
||||
}
|
||||
|
||||
// Programmer lifecycle handlers
|
||||
|
||||
static int serprog_open(PROGRAMMER *pgm, const char *port) {
|
||||
union pinfo pinfo;
|
||||
|
||||
pgm->port = port;
|
||||
pinfo.serialinfo.baud = pgm->baudrate? pgm->baudrate: 115200;
|
||||
pinfo.serialinfo.cflags = SERIAL_8N1;
|
||||
if(serial_open(port, pinfo, &pgm->fd) == -1)
|
||||
return -1;
|
||||
|
||||
unsigned char buf[32];
|
||||
|
||||
// Sync
|
||||
memset(buf, 0, sizeof buf);
|
||||
if(perform_serprog_cmd(pgm, S_CMD_SYNCNOP, NULL, 0, buf, 1) != 1 || buf[0] != S_ACK) {
|
||||
pmsg_error("cannot sync; is this a serprog programmer?\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get command bitmap
|
||||
memset(my.cmd_bitmap, 0, sizeof my.cmd_bitmap);
|
||||
if(perform_serprog_cmd(pgm, S_CMD_Q_CMDMAP, NULL, 0, my.cmd_bitmap, 32) != 0) {
|
||||
pmsg_error("cannot get list of supported serprog commands\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get protocol version
|
||||
memset(buf, 0, sizeof buf);
|
||||
if(!is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_Q_IFACE)
|
||||
|| perform_serprog_cmd(pgm, S_CMD_Q_IFACE, NULL, 0, buf, 2) != 0) {
|
||||
pmsg_error("cannot get serprog protocol version\n");
|
||||
return -1;
|
||||
}
|
||||
if(read_le16(buf) != 0x01) {
|
||||
pmsg_error("unsupported serprog protocol version: %d\n", read_le16(buf));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pmsg_info("serprog protocol version: %d\n", read_le16(buf));
|
||||
|
||||
// Get programmer name
|
||||
if(is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_Q_PGMNAME)) {
|
||||
memset(buf, 0, sizeof buf);
|
||||
if(perform_serprog_cmd(pgm, S_CMD_Q_PGMNAME, NULL, 0, buf, 16) != 0) {
|
||||
pmsg_error("cannot get programmer name\n");
|
||||
return -1;
|
||||
}
|
||||
pmsg_info("programmer name: %s\n", buf);
|
||||
}
|
||||
|
||||
// Check if required commands are supported
|
||||
if(!is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_O_SPIOP)) {
|
||||
pmsg_error("the %s programmer does not support SPI operations\n", pgmid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_S_CS_MODE)) {
|
||||
pmsg_error("the %s programmer does not support setting the CS mode\n", pgmid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_S_SPI_MODE)) {
|
||||
pmsg_error("the %s programmer does not support setting the SPI mode\n", pgmid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(my.cs > 0 && !is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_S_SPI_CS)) {
|
||||
pmsg_error("the %s programmer does not support changing the CS\n", pgmid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void serprog_disable(const PROGRAMMER *pgm) {
|
||||
unsigned char buf[32];
|
||||
|
||||
// Switch CS to auto
|
||||
const unsigned char cs_mode = CS_MODE_AUTO;
|
||||
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_CS_MODE, &cs_mode, 1, NULL, 0) != 0) {
|
||||
pmsg_error("cannot reset the CS mode to auto\n");
|
||||
}
|
||||
// Disable output
|
||||
if(is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_S_PIN_STATE)) {
|
||||
memset(buf, 0, sizeof buf);
|
||||
buf[0] = 0; // Pin state disable
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_PIN_STATE, buf, 1, NULL, 0) != 0) {
|
||||
pmsg_error("cannot disable pin state\n");
|
||||
}
|
||||
}
|
||||
// Restore half duplex
|
||||
memset(buf, 0, sizeof buf);
|
||||
buf[0] = SPI_MODE_HALF_DUPLEX;
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_SPI_MODE, buf, 1, NULL, 0) != 0)
|
||||
pmsg_error("cannot reset SPI half duplex mode\n");
|
||||
|
||||
// Reset CS to CS_0
|
||||
if(is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_S_SPI_CS)) {
|
||||
memset(buf, 0, sizeof buf);
|
||||
buf[0] = 0;
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_SPI_CS, buf, 1, NULL, 0) != 0)
|
||||
pmsg_error("cannot reset CS to CS_0\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void serprog_close(PROGRAMMER *pgm) {
|
||||
serial_close(&pgm->fd);
|
||||
}
|
||||
|
||||
static int serprog_cmd(const PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res) {
|
||||
return serprog_spi_duplex(pgm, cmd, res, 4);
|
||||
}
|
||||
|
||||
static int serprog_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||
if(part->prog_modes & PM_TPI) {
|
||||
// We do not support TPI; this is a dedicated SPI thing
|
||||
pmsg_error("the %s programmer does not support TPI\n", pgmid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned char buf[32];
|
||||
|
||||
// Set SPI clock frequency
|
||||
if(is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_S_SPI_FREQ)) {
|
||||
memset(buf, 0, sizeof buf);
|
||||
uint32_t frequency =
|
||||
pgm->bitclock > 0? 1/pgm->bitclock:
|
||||
part->factory_fcpu > 0? part->factory_fcpu/4:
|
||||
250000;
|
||||
write_le32(buf, frequency);
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_SPI_FREQ, buf, 4, buf, 4) != 0) {
|
||||
pmsg_error("cannot set SPI frequency %u Hz\n", (unsigned) frequency);
|
||||
return -1;
|
||||
}
|
||||
my.actual_frequency = read_le32(buf);
|
||||
}
|
||||
|
||||
// Set active chip select
|
||||
if(is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_S_SPI_CS)) {
|
||||
memset(buf, 0, sizeof buf);
|
||||
buf[0] = my.cs;
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_SPI_CS, buf, 1, NULL, 0) != 0) {
|
||||
pmsg_error("cannot change CS\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Set full duplex
|
||||
memset(buf, 0, sizeof buf);
|
||||
buf[0] = SPI_MODE_FULL_DUPLEX;
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_SPI_MODE, buf, 1, NULL, 0) != 0) {
|
||||
pmsg_error("cannot set SPI full duplex mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set output
|
||||
if(is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_S_PIN_STATE)) {
|
||||
memset(buf, 0, sizeof buf);
|
||||
buf[0] = 1; // Pin state enable
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_PIN_STATE, buf, 1, NULL, 0) != 0) {
|
||||
pmsg_error("cannot enable pin state\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the CS/reset pin
|
||||
const unsigned char cs_mode = CS_MODE_SELECTED;
|
||||
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_CS_MODE, &cs_mode, 1, NULL, 0) != 0) {
|
||||
pmsg_error("cannot enable the reset pin\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tries, ret;
|
||||
|
||||
// Enable programming on the part
|
||||
tries = 0;
|
||||
do {
|
||||
ret = pgm->program_enable(pgm, part);
|
||||
if(ret == 0 || ret == -1)
|
||||
break;
|
||||
} while(tries++ < 65);
|
||||
|
||||
if(ret)
|
||||
pmsg_error("AVR device not responding\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* used linuxspi.c as a template:
|
||||
* Copyright (C) 2013 Kevin Cuzner <kevin@kevincuzner.com>
|
||||
* Copyright (C) 2018 Ralf Ramsauer <ralf@vmexit.de>
|
||||
*/
|
||||
static int serprog_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
unsigned char cmd[4], res[4];
|
||||
|
||||
if(!p->op[AVR_OP_PGM_ENABLE]) {
|
||||
pmsg_error("program enable instruction not defined for part %s\n", p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(cmd, 0, sizeof cmd);
|
||||
avr_set_bits(p->op[AVR_OP_PGM_ENABLE], cmd); // Set the cmd
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
|
||||
if(res[2] != cmd[1]) {
|
||||
|
||||
/** From ATtiny441 datasheet:
|
||||
*
|
||||
* In some systems, the programmer cannot guarantee that SCK is held low
|
||||
* during power-up. In this case, RESET must be given a positive pulse after
|
||||
* SCK has been set to '0'. The duration of the pulse must be at least t RST
|
||||
* plus two CPU clock cycles. See Table 25-5 on page 240 for definition of
|
||||
* minimum pulse width on RESET pin, t RST
|
||||
* 2. Wait for at least 20 ms and then enable serial programming by sending
|
||||
* the Programming Enable serial instruction to the SDO pin
|
||||
* 3. The serial programming instructions will not work if the communication
|
||||
* is out of synchronization. When in sync, the second byte (0x53) will echo
|
||||
* back when issuing the third byte of the Programming Enable instruction
|
||||
* ...
|
||||
* If the 0x53 did not echo back, give RESET a positive pulse and issue a
|
||||
* new Programming Enable command
|
||||
*/
|
||||
|
||||
unsigned char cs_mode = CS_MODE_DESELECTED;
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_CS_MODE, &cs_mode, 1, NULL, 0) != 0)
|
||||
return -1;
|
||||
|
||||
usleep(5);
|
||||
cs_mode = CS_MODE_SELECTED;
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_CS_MODE, &cs_mode, 1, NULL, 0) != 0)
|
||||
return -1;
|
||||
|
||||
usleep(20000);
|
||||
|
||||
return -2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serprog_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
unsigned char cmd[4], res[4];
|
||||
|
||||
if(!p->op[AVR_OP_CHIP_ERASE]) {
|
||||
pmsg_error("chip erase instruction not defined for part %s\n", p->desc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(cmd, 0, sizeof cmd);
|
||||
avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
|
||||
pgm->cmd(pgm, cmd, res);
|
||||
usleep(p->chip_erase_delay);
|
||||
pgm->initialize(pgm, p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void serprog_display(const PROGRAMMER *pgm, const char *p) {
|
||||
}
|
||||
|
||||
static void serprog_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
|
||||
static void serprog_setup(PROGRAMMER *pgm) {
|
||||
pgm->cookie = mmt_malloc(sizeof(struct pdata));
|
||||
}
|
||||
|
||||
static void serprog_teardown(PROGRAMMER *pgm) {
|
||||
mmt_free(pgm->cookie);
|
||||
pgm->cookie = NULL;
|
||||
}
|
||||
|
||||
static int serprog_set_sck_period(const PROGRAMMER *pgm, double v) {
|
||||
if(!is_serprog_cmd_supported(my.cmd_bitmap, S_CMD_S_SPI_FREQ))
|
||||
return -1;
|
||||
|
||||
unsigned char buf[8];
|
||||
|
||||
memset(buf, 0, sizeof buf);
|
||||
write_le32(buf, v);
|
||||
if(perform_serprog_cmd(pgm, S_CMD_S_SPI_FREQ, buf, 4, buf, 4) != 0) {
|
||||
pmsg_error("cannot set SPI frequency\n");
|
||||
return -1;
|
||||
}
|
||||
my.actual_frequency = read_le32(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serprog_get_sck_period(const PROGRAMMER *pgm, double *v) {
|
||||
*v = my.actual_frequency;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serprog_parseextparams(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
for(LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
if(str_starts(extended_param, "cs=")) {
|
||||
unsigned int cs;
|
||||
|
||||
if(sscanf(extended_param, "cs=%u", &cs) != 1) {
|
||||
pmsg_error("invalid chip select in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
my.cs = cs;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(str_eq(extended_param, "help")) {
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
if(!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x cs=<n> Sets the chip select line to CS<n> for supported programmers\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void serprog_initpgm(PROGRAMMER *pgm) {
|
||||
strcpy(pgm->type, "serprog");
|
||||
|
||||
// Required fields
|
||||
pgm->initialize = serprog_initialize;
|
||||
pgm->display = serprog_display;
|
||||
pgm->enable = serprog_enable;
|
||||
pgm->disable = serprog_disable;
|
||||
pgm->program_enable = serprog_program_enable;
|
||||
pgm->chip_erase = serprog_chip_erase;
|
||||
pgm->cmd = serprog_cmd;
|
||||
pgm->open = serprog_open;
|
||||
pgm->close = serprog_close;
|
||||
pgm->read_byte = avr_read_byte_default;
|
||||
pgm->write_byte = avr_write_byte_default;
|
||||
|
||||
// Optional fields
|
||||
pgm->setup = serprog_setup;
|
||||
pgm->teardown = serprog_teardown;
|
||||
pgm->parseextparams = serprog_parseextparams;
|
||||
pgm->get_sck_period = serprog_get_sck_period;
|
||||
pgm->set_sck_period = serprog_set_sck_period;
|
||||
}
|
||||
35
src/serprog.h
Normal file
35
src/serprog.h
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
*
|
||||
* Copyright (C) 2024 Sydney Louisa Wilke <git@funkeleinhorn.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef serprog_h
|
||||
#define serprog_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char serprog_desc[];
|
||||
void serprog_initpgm(PROGRAMMER *pgm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // serprog_h
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef solaris_ecpp_h
|
||||
#define solaris_ecpp_h
|
||||
|
||||
|
||||
113
src/stk500.c
113
src/stk500.c
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2008,2014 Joerg Wunsch
|
||||
* Copyright (C) 2008, 2014 Joerg Wunsch
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,8 +17,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* avrdude interface for Atmel STK500 programmer
|
||||
*
|
||||
@@ -116,7 +114,7 @@ int stk500_getsync(const PROGRAMMER *pgm) {
|
||||
|
||||
for (attempt = 0; attempt < max_sync_attempts; attempt++) {
|
||||
// Restart Arduino bootloader for every sync attempt
|
||||
if (str_eq(pgm->type, "Arduino") && attempt > 0) {
|
||||
if(str_eq(pgm->type, "Arduino") && PDATA(pgm)->autoreset && attempt > 0) {
|
||||
// This code assumes a negative-logic USB to TTL serial adapter
|
||||
// Pull the RTS/DTR line low to reset AVR: it is still high from open()/last attempt
|
||||
serial_set_dtr_rts(&pgm->fd, 1);
|
||||
@@ -202,8 +200,7 @@ static int stk500_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
unsigned char res[4];
|
||||
|
||||
if (pgm->cmd == NULL) {
|
||||
pmsg_error("%s programmer uses stk500_chip_erase() but does not\n", pgm->type);
|
||||
imsg_error("provide a cmd() method\n");
|
||||
pmsg_error("%s programmer uses %s() without providing a cmd() method\n", pgm->type, __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -450,7 +447,7 @@ static int stk500_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
}
|
||||
|
||||
#if 0
|
||||
pmsg_info("stk500_initialize(): n_extparms = %d\n", n_extparms);
|
||||
pmsg_notice("%s(): n_extparms = %d\n", __func__, n_extparms);
|
||||
#endif
|
||||
|
||||
buf[5] = 1; /* polling supported - XXX need this in config file */
|
||||
@@ -640,30 +637,28 @@ static int stk500_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||
return pgm->program_enable(pgm, p);
|
||||
}
|
||||
|
||||
static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
{
|
||||
LNODEID ln;
|
||||
const char *extended_param;
|
||||
int attempts;
|
||||
int rv = 0;
|
||||
static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||
int attempts;
|
||||
int rv = 0;
|
||||
bool help = false;
|
||||
|
||||
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
extended_param = ldata(ln);
|
||||
for (LNODEID ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||
const char *extended_param = ldata(ln);
|
||||
|
||||
if (sscanf(extended_param, "attempts=%2d", &attempts) == 1) {
|
||||
if (sscanf(extended_param, "attempts=%i", &attempts) == 1) {
|
||||
PDATA(pgm)->retry_attempts = attempts;
|
||||
pmsg_info("setting number of retry attempts to %d\n", attempts);
|
||||
continue;
|
||||
}
|
||||
|
||||
else if (str_starts(extended_param, "vtarg")) {
|
||||
if (str_starts(extended_param, "vtarg")) {
|
||||
if ((pgm->extra_features & HAS_VTARG_ADJ) && (str_starts(extended_param, "vtarg="))) {
|
||||
// Set target voltage
|
||||
double vtarg_set_val = -1; // default = invlid value
|
||||
int sscanf_success = sscanf(extended_param, "vtarg=%lf", &vtarg_set_val);
|
||||
PDATA(pgm)->vtarg_data = (double)((int)(vtarg_set_val * 100 + .5)) / 100;
|
||||
if (sscanf_success < 1 || vtarg_set_val < 0) {
|
||||
pmsg_error("invalid vtarg value %s\n", extended_param);
|
||||
pmsg_error("invalid target voltage in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
@@ -699,7 +694,7 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
if (PDATA(pgm)->varef_set) {
|
||||
PDATA(pgm)->varef_data = (double)((int)(varef_set_val * 100 + .5)) / 100;
|
||||
if (sscanf_success < 1 || varef_set_val < 0) {
|
||||
pmsg_error("invalid varef value %s\n", extended_param);
|
||||
pmsg_error("invalid value in -x %s\n", extended_param);
|
||||
PDATA(pgm)->varef_set = false;
|
||||
rv = -1;
|
||||
break;
|
||||
@@ -717,7 +712,7 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
// allow spaces in fosc_str
|
||||
int sscanf_success = sscanf(extended_param, "fosc=%15[0-9.eE MmKkHhZzof]", fosc_str);
|
||||
if (sscanf_success < 1) {
|
||||
pmsg_error("invalid fosc value %s\n", extended_param);
|
||||
pmsg_error("invalid value in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
@@ -726,13 +721,12 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
if (endp == fosc_str){ // no number
|
||||
while ( *endp == ' ' ) // remove leading spaces
|
||||
++endp;
|
||||
if (str_starts(endp, "off"))
|
||||
PDATA(pgm)->fosc_data = 0.0;
|
||||
else {
|
||||
pmsg_error("invalid fosc value %s\n", fosc_str);
|
||||
if (!str_eq(endp, "off")) {
|
||||
pmsg_error("invalid -x fosc=%s value\n", fosc_str);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
PDATA(pgm)->fosc_data = 0.0;
|
||||
}
|
||||
while ( *endp == ' ' ) // remove leading spaces before unit
|
||||
++endp;
|
||||
@@ -759,14 +753,14 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
char xtal_str[16] = {0};
|
||||
int sscanf_success = sscanf(extended_param, "xtal=%15[0-9.eE MmKkHhZz]", xtal_str);
|
||||
if (sscanf_success < 1) {
|
||||
pmsg_error("invalid xtal value %s\n", extended_param);
|
||||
pmsg_error("invalid value in -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
char *endp;
|
||||
double v = strtod(xtal_str, &endp);
|
||||
if (endp == xtal_str){
|
||||
pmsg_error("invalid xtal value %s\n", xtal_str);
|
||||
pmsg_error("invalid -x xtal=%s value\n", xtal_str);
|
||||
rv = -1;
|
||||
break;
|
||||
}
|
||||
@@ -783,33 +777,38 @@ static int stk500_parseextparms(const PROGRAMMER *pgm, const LISTID extparms)
|
||||
}
|
||||
|
||||
else if (str_eq(extended_param, "help")) {
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -xattempts=<arg> Specify no. connection retry attempts\n");
|
||||
if (pgm->extra_features & HAS_VTARG_READ) {
|
||||
msg_error(" -xvtarg Read target supply voltage\n");
|
||||
}
|
||||
if (pgm->extra_features & HAS_VTARG_ADJ) {
|
||||
msg_error(" -xvtarg=<arg> Set target supply voltage\n");
|
||||
}
|
||||
if (pgm->extra_features & HAS_VAREF_ADJ) {
|
||||
msg_error(" -xvaref Read analog reference voltage\n");
|
||||
msg_error(" -xvaref=<arg> Set analog reference voltage\n");
|
||||
}
|
||||
if (pgm->extra_features & HAS_FOSC_ADJ) {
|
||||
msg_error(" -xfosc Read oscillator clock frequency\n");
|
||||
msg_error(" -xfosc=<arg>[M|k]|off Set oscillator clock frequency\n");
|
||||
}
|
||||
msg_error(" -xxtal=<arg>[M|k] Set programmer xtal frequency\n");
|
||||
msg_error(" -xhelp Show this help menu and exit\n");
|
||||
return LIBAVRDUDE_EXIT;;
|
||||
help = true;
|
||||
rv = LIBAVRDUDE_EXIT;
|
||||
}
|
||||
|
||||
pmsg_error("invalid extended parameter %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
if (!help) {
|
||||
pmsg_error("invalid extended parameter -x %s\n", extended_param);
|
||||
rv = -1;
|
||||
}
|
||||
msg_error("%s -c %s extended options:\n", progname, pgmid);
|
||||
msg_error(" -x attempts=<n> Specify the number <n> of connection retry attempts\n");
|
||||
if (pgm->extra_features & HAS_VTARG_READ) {
|
||||
msg_error(" -x vtarg Read target supply voltage\n");
|
||||
}
|
||||
if (pgm->extra_features & HAS_VTARG_ADJ) {
|
||||
msg_error(" -x vtarg=<dbl> Set target supply voltage to <dbl> V\n");
|
||||
}
|
||||
if (pgm->extra_features & HAS_VAREF_ADJ) {
|
||||
msg_error(" -x varef Read analog reference voltage\n");
|
||||
msg_error(" -x varef=<dbl> Set analog reference voltage to <dbl> V\n");
|
||||
}
|
||||
if (pgm->extra_features & HAS_FOSC_ADJ) {
|
||||
msg_error(" -x fosc Read oscillator clock frequency\n");
|
||||
msg_error(" -x fosc=<n>[unit] Set oscillator clock frequency to <n> Hz (or kHz/MHz)\n");
|
||||
msg_error(" -x fosc=off Switch the oscillator clock off\n");
|
||||
}
|
||||
msg_error(" -x xtal=<n>[unit] Set programmer xtal frequency to <n> Hz (or kHz/MHz)\n");
|
||||
msg_error(" -x help Show this help menu and exit\n");
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void stk500_disable(const PROGRAMMER *pgm) {
|
||||
unsigned char buf[16];
|
||||
@@ -894,8 +893,7 @@ static int stk500_open(PROGRAMMER *pgm, const char *port) {
|
||||
}
|
||||
|
||||
|
||||
static void stk500_close(PROGRAMMER * pgm)
|
||||
{
|
||||
static void stk500_close(PROGRAMMER *pgm) {
|
||||
// MIB510 close
|
||||
if (str_eq(pgmid, "mib510"))
|
||||
(void)mib510_isp(pgm, 0);
|
||||
@@ -1006,9 +1004,9 @@ static int set_memchr_a_div(const PROGRAMMER *pgm, const AVRPART *p, const AVRME
|
||||
|
||||
if(mem_is_eeprom(m)) {
|
||||
*memchrp = 'E';
|
||||
// Word addr for bootloaders or Arduino as ISP if part is a "classic" part, byte addr otherwise
|
||||
// Word addr for bootloaders or Arduino as ISP if part is a classic part; byte addr otherwise
|
||||
*a_divp = ((pgm->prog_modes & PM_SPM) || str_caseeq(pgmid, "arduino_as_isp")) \
|
||||
&& !(p->prog_modes & (PM_UPDI | PM_PDI))? 2: 1;
|
||||
&& (p->prog_modes & PM_Classic)? 2: 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1569,7 +1567,7 @@ static void stk500_print_parms(const PROGRAMMER *pgm, FILE *fp) {
|
||||
stk500_print_parms1(pgm, "", fp);
|
||||
}
|
||||
|
||||
static void stk500_setup(PROGRAMMER * pgm) {
|
||||
static void stk500_setup(PROGRAMMER *pgm) {
|
||||
pgm->cookie = mmt_malloc(sizeof(struct pdata));
|
||||
PDATA(pgm)->ext_addr_byte = 0xff;
|
||||
PDATA(pgm)->xbeeResetPin = XBEE_DEFAULT_RESET_PIN;
|
||||
@@ -1578,9 +1576,12 @@ static void stk500_setup(PROGRAMMER * pgm) {
|
||||
PDATA(pgm)->xtal = 16000000U;
|
||||
else
|
||||
PDATA(pgm)->xtal = STK500_XTAL;
|
||||
// The -c arduino programmer has auto-reset enabled be default
|
||||
if (str_eq(pgm->type, "Arduino"))
|
||||
PDATA(pgm)->autoreset = true;
|
||||
}
|
||||
|
||||
static void stk500_teardown(PROGRAMMER * pgm) {
|
||||
static void stk500_teardown(PROGRAMMER *pgm) {
|
||||
mmt_free(pgm->cookie);
|
||||
pgm->cookie = NULL;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
* Copyright (C) 2002-2004 Brian S. Dean <bsd@bdmicro.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef stk500_h
|
||||
#define stk500_h
|
||||
|
||||
@@ -60,6 +58,9 @@ struct pdata {
|
||||
double fosc_data;
|
||||
|
||||
unsigned xtal; // Set STK500 XTAL frequency
|
||||
|
||||
// Flag to enable/disable autoreset for the arduino programmer
|
||||
bool autoreset;
|
||||
};
|
||||
|
||||
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
/*
|
||||
* avrdude interface for Atmel STK500 programmer
|
||||
*
|
||||
@@ -47,8 +45,8 @@ static int stk500generic_open(PROGRAMMER *pgm, const char *port) {
|
||||
if(pgm->setup)
|
||||
pgm->setup(pgm);
|
||||
if(pgm->open(pgm, port) >= 0) {
|
||||
pmsg_info("successfully opened stk500v2 device\n");
|
||||
imsg_info("in future, please use -c stk500v2, so -x parameters are available\n");
|
||||
pmsg_info("successfully opened stk500v2 device; in future\n");
|
||||
imsg_info("please use -c stk500v2, so -x parameters are available\n");
|
||||
return 0;
|
||||
}
|
||||
if(pgm->teardown)
|
||||
@@ -59,8 +57,8 @@ static int stk500generic_open(PROGRAMMER *pgm, const char *port) {
|
||||
if(pgm->setup)
|
||||
pgm->setup(pgm);
|
||||
if(pgm->open(pgm, port) >= 0) {
|
||||
pmsg_info("successfully opened stk500v1 device\n");
|
||||
imsg_info("in future, please use -c stk500v1, so -x parameters are available\n");
|
||||
pmsg_info("successfully opened stk500v1 device; in future\n");
|
||||
imsg_info("please use -c stk500v1, so -x parameters are available\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user