1 Commits
v6.4 ... v6.2

Author SHA1 Message Date
Joerg Wunsch
595c92288d This is AVRDUDE 6.2.
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/tags/RELEASE_6_2@1363 81a1dc3b-b13d-400b-aceb-764788c761c2
2015-11-16 22:43:18 +00:00
62 changed files with 892 additions and 8428 deletions

View File

@@ -10,7 +10,7 @@ Contributors:
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>
Michael Holzt <kju-avr@fqdn.org>
Colin O'Flynn <coflynn@newae.com>
Thomas Fischl <tfischl@gmx.de>
David Hoerl <dhoerl@mac.com>
@@ -23,9 +23,6 @@ Contributors:
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>
David Sainty
For minor contributions, please see the ChangeLog files.

331
ChangeLog
View File

@@ -1,320 +1,39 @@
2021-12-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
2015-11-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* configure.ac (AC_INIT): Bump version to 6.4
* main.c: Remove unmaintained year numbers from Copyright
* configure.ac: Released version 6.2.
2021-12-06 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #57338: if safemode has to change fuses avrdude should exit with non-zero exit code
* main.c (main): drop unused variable `fuses_specified'
2021-12-06 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Dmitrii Chernukhin:
bug #58994: VPP PWM still enabled at the end of programming process
* pickit2.c (pickit2_disable): turn off VPP before shutting down
2021-12-05 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* configure.ac (AC_INIT): Bump version date
* configure.ac (enabled_parport): Default to "no"
2021-12-03 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Alex Sverdlin:
patch #10153: linuxspi: Support "-E reset" and "-E noreset"
* linuxspi.c (linuxspi_parseexitspecs): New function
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #58440: linuxgpio PIN limit too low
* libavrdude.h (PIN_MAX): bump (for HAVE_LINUXGPIO) to 400
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang:
patch #8923: Enable TPI for linuxgpio
* linuxgpio.c (linuxgpio_initpgm): add cmd_tpi entry
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by: Milan Kupcevic <milan@debian.org>
patch #8996: Remove lock byte read mask (bug#21954, bug#46759)
* avrdude.conf.in (ATmega48, ATmega88, ATmega168, ATmega328)
(ATmega32U4, ATmega640, ATmega1280, ATmega1281, ATmega2560)
(ATmega2561, ATmega8, ATtiny13, ATmega64, ATmega128, ATmega16)
(AT90CAN32, AT90CAN64, AT90CAN128, ATmega324, ATmega644)
(ATmega1284, ATmega161, ATmega162, ATmega163, ATmega169, ATmega32)
(ATmega329, ATmega649, ATmega8515, ATmega8535, ATtiny2313, ATtiny4313)
(AT90PWM2, AT90USB646, AT90USB1286, AT90USB162, AT90USB82, ATmega32U2)
(ATmega16U2, ATmega8U2, ATmega325, ATmega645, ATtiny1634): Remove
lock byte read mask (bug#46759).
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Christopher Cooper:
patch #9304: [Bug #48767] Implemented WinSock variation of "ser_drain(...)" functionality
* ser_win32.c (ser_drain): Implement a network drain
function.
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Lars Ollén:
* linux_spi.c (linuxspi_open): ensure correct SPI mode is
set (submitted in the audit trail of patch #9816).
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* linuxspi.c: Use -B <bitclock> rather than -b <baudrate>
to specify the clock rate
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Improve defaults and documentation of linuxspi
* avrdude.conf.in: use @HAVE_LINUXGPIO_BEGIN/END@ and
@HAVE_LINUXSPI_BEGIN/END@ brackets around respective config
snippets; values were already set in configure.ac.
* linuxspi.c (linuxspi_open): Provide a reasonable (for the
Raspberry Pi) default for the -P option
* avrdude.1: Extend linuxspi documentation
* doc/avrdude.texi: (Dito.)
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Alex Sverdlin:
patch #10031: linuxspi: Support GPIO uAPI v2
* linuxspi.c (linuxspi_reset_mcu, linuxspi_open): Since Linux
v5.10 GPIO ABI Version 1 is optional and depends on
CONFIG_GPIO_CDEV_V1.
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Alex Sverdlin:
patch #10030: linuxspi: Support inverted GPIO pin
* linuxspi.c (linuxspi_open): Clear the inversion mask on request
and set default state to avoid short glitches on the GPIO line.
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Alex Sverdlin:
patch #10029: linuxspi: Report GPIO_GET_LINEHANDLE_IOCTL errors
* linuxspi.c (linuxspi_open): Report ioctl error
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Alex Sverdlin:
patch #10028: linuxspi: close() only when necessary
* linuxspi.c: unify descriptor closing
2021-11-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Alex Sverdlin:
patch #10027: linuxspi: Add reset pulse, according to AVR programming algorithm
* linuxspi.c (linuxspi_open, linuxspi_program_enable):
movw out reset code into linuxspi_reset_mcu()
2021-11-25 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang:
patch #9328: ft245r.c: add TPI support (patches 5-7)
* ft245r.c (ft245r_set_bitclock): add workaround for
FT245 hardware bugs in bitclock setting
2021-11-25 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang:
patch #9328: ft245r.c: add TPI support (patches 5-7)
* ft245r.c: Remove the reader thread (also removes
patch #9079)
2021-11-24 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang:
patch #9327: ft245r.c: add TPI support (patches 1-4)
* ft245r.c (set_pin, ft245r_open): use
ft245r_send_and_discard() so ft245r_in can go away
2021-11-24 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang:
patch #9327: ft245r.c: add TPI support (patches 1-4)
* ft245r.c (ft245r_recv): Optimize TPI programming
speed by reducing number of USB reads.
2021-11-24 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang:
patch #9327: ft245r.c: add TPI support (patches 1-4)
* ft245r.c (ft245r_open): add call to
ftdi_set_latency_timer() to improve timing
2021-11-24 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang:
patch #9327: ft245r.c: add TPI support (patches 1-4)
* ft245r.c: add TPI support
* avrdude.conf.in (tc2030): New programmer
2021-11-24 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* ft245r.c (ft245r_open): allow for picking a default
device if none has been provided by -P
2021-11-24 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* jtag3.c (jtag3_edbg_recv_frame): Better handling for
fragment_info == 0x00 (no response available)
2021-11-23 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* jtag3.c: Use matches() instead of strncmp()
2021-11-23 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
patch #9757: Fix ATtiny817 Xplained Mini programmer
* jtag3.c (jtag3_getsync, jtag3_close): correctly extract
programmer name from list of names
2021-11-22 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Sainty:
patch #8719: Support Over-the-Air bootloading with XBeeBoot
* xbee.c: New programmer
* xbee.h: (Dito.)
* pgm_type.c: Add xbee.h
* avrdude.conf.in (xbee): New programmer
* Makefile.am (libavrdude_a_SOURCES): add xbee.c, xbee.h
* avrdude.1: document the new programmer
* doc/avrdude.texi: (Dito.)
2021-11-14 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Ivan Frederiks:
patch #9079: Fix ftdi_syncbb teardown (supersedes #9893)
patch #9122: Fixed MISO sampling in ftdi_syncbb
patch #9123: ftdi_syncbb: use FT245R_CYCLES in ft245r_set_bitclock()
* ft245r.c: Various fixes for FT245-bitbang programmers
2021-11-14 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang:
patch #9320: fix TPI RESET in bitbang.c
* bitbang.c (bitbang_initialize): wait for 128 ms after deasserting
/RESET (per datasheet), and keep /RESET low during MOSI/MISO link check
2021-11-12 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jon Thacker:
patch #9253: Fix for giving terminal_mode commands more than 20 arguments
* term.c (tokenize): fix realloc usage, pointer returned not necessarily
the same as pointer passed
2021-11-12 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
2015-10-31 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Martino Facchin:
patch #9110: Let reserved fuse bits to be read as *don't care*
* avr.c (compare_memory_masked): New function
* libavrdude.h: declare compare_memory_masked(); also, insist on C99
so <stdint.h> is required now
* main.c: Use compare_memory_masked() in safemode comparisons
bug #45727: Wrong atmega8u2 flash parameters
* avrdude.conf.in (ATmega8U2): correct page and block size
2021-11-11 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
2015-10-31 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Joseph Coffland:
patch #8957: Allow reading prodsig memory from stk500v2 on xmega devices
* stk500v2.c (stk600_xprog_read_byte, stk600_xprog_paged_load):
treat "prodsig" memory space as equivalent to "calibration"
Submitted by Pasquale Cocchini:
bug #46020: Add TIAO TUMPA to the conf file.
* avrdude.conf.in (tumpa): New entry.
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
2015-10-31 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Martin Thierer:
patch #10017: uspasp / tpi: Automatically clear configuration byte (fuse) before writing it
* usbasp.c (usbasp_tpi_paged_write): clear fuse region before writing it
Submitted by Pasquale Cocchini:
bug #46021: Please add read in the memory lock section of ATtiny85
* avrdude.conf.in (ATtiny25/45/85): add read pattern for lock bits
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
2015-10-31 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Michael Petersen:
patch #9697: Add iseavrprog support
* avrdude.conf.in (iseavrprog): New programmer
* Makefile.am (libavrdude_a_SOURCES): reflect recent changes
(pgm.h is gone, config.h is new).
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
2015-04-09 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #50630: Erase Cycle Counter options ( -y -Y n ) should be removed from usage Message
* main.c (usage): remove -y / -Y descriptions
bug #44717: avrdude creates empty flash dump
* update.c (do_op): When about to write an empty flash dump file,
warn about this to avoid surprises.
* avrdude.1: Document the truncation of trailing 0xFF bytes for
flash memory areas.
* doc/avrdude.texi: (Dito.)
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
2015-04-09 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* avrdude.conf.in (ATmega8A): new device (alias for ATmega8)
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #50517: Reading fails if "immediate mode" for output file format is selected - fileio: invalid operation=1
* update.c (do_op): refuse to write to "immediate format" argument
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Martin Thierer:
bug #60863: avrftdi programming error probably caused by multiple, consecutive empty pages
* avrftdi.c (avrftdi_flash_write): Skip empty pages
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Matwey V. Kornilov:
bug #58495: Add atmega324pb support to avrdude.conf.in
* avrdude.conf.in (ATmega324PB): new entry
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #55734: USBtiny programming of ATmega328p broken by Patch #9278
* usbtiny.c (usbtiny_initialize): undo change from patch #9728
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #55009: no efuses for m164a/pa
* avrdude.conf.in (ATmega164P): derive from ATmega324P
2021-11-07 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by evan Venn:
bug #59227: Add new part. How does one get a part added to the CONF file?
* avrdude.conf.in (LGT8FX88P, LGT8FX168P, LGT8FX328P): new parts
2021-11-06 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Britton Kerin:
bug #57453: [PATCH] fix reference to nonexistant -m option by changing to -U
* avrdude.1: replace -m option by -U
2021-11-06 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Andrew D'Addesio:
bug #58078: [PATCH] buspirate: remove compound literals (fixes GCC>=9)
* buspirate.c (buspirate_start_mode_bin):
avoid propagating local scope compound literals
2021-11-06 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud:
patch #10000: Add support for extended UPDI device context
* avrdude.conf.in (pickit4_updi, snap_updi, pkobn_updi):
new programmers
* avrdude.conf.in (ATmega808, ATmega809, ATmega1608, ATmega1609)
(AVR DA, AVR DB): new devices
* jtag3.c: Add support for extended UPDI device context
* jtag3_private.h: (Dito.)
* tools/atdf-to-avrdude.xslt: Bug fixes
* usbdevs.h: Bump USBDEV_MAX_XFER_3 to 912
* doc/avrdude.texi: Document changes
* avrdude.1: (Dito)
2021-06-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #60753: Patch #1436 breaks multiple programmer/device combinations on MacOS BigSur
* avr.c: compare page_size > 1 instead of != 0
* stk500v2.c: (Ditto.)
2021-06-27 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by gerardoallende:
bug #59525: Bogus error message because Copy/Paste typo in stk500.c
* stk500.c (stk500_getparm): Fix bogus ID in error message
Annual ChangeLog rotation.

View File

@@ -1080,7 +1080,7 @@
2005-09-18 Joerg Wunsch <j@uriah.heep.sax.de>
Add the serial bit-bang driver, contributed by Juliane Holzt.
Add the serial bit-bang driver, contributed by Michael Holzt.
* bitbang.h: New file.
* bitbang.c: New file.
* serbb.h: New file.

View File

@@ -1,54 +0,0 @@
2015-12-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* avrdude.1 (-C): Do not suggest users might change the
default config file. It will be overwritten by updates.
2015-12-09 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #46610: Floating point exception (core dumped) arch linux rpi2
bug #46483: version 6.2. ser_open(): can't set attributes for device
* ser_posix.c: Back out change from patch #8380
2015-11-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* configure.ac: Bump for post-release 6.2.
2015-11-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* configure.ac: Released version 6.2.
2015-10-31 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Martino Facchin:
bug #45727: Wrong atmega8u2 flash parameters
* avrdude.conf.in (ATmega8U2): correct page and block size
2015-10-31 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Pasquale Cocchini:
bug #46020: Add TIAO TUMPA to the conf file.
* avrdude.conf.in (tumpa): New entry.
2015-10-31 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Pasquale Cocchini:
bug #46021: Please add read in the memory lock section of ATtiny85
* avrdude.conf.in (ATtiny25/45/85): add read pattern for lock bits
2015-10-31 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* Makefile.am (libavrdude_a_SOURCES): reflect recent changes
(pgm.h is gone, config.h is new).
2015-04-09 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #44717: avrdude creates empty flash dump
* update.c (do_op): When about to write an empty flash dump file,
warn about this to avoid surprises.
* avrdude.1: Document the truncation of trailing 0xFF bytes for
flash memory areas.
* doc/avrdude.texi: (Dito.)
2015-04-09 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Annual ChangeLog rotation.

View File

@@ -1,95 +0,0 @@
2016-09-14 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* stk500v2.c (DEBUG, DEBUGRECV): define these unconditionally,
as MSG_TRACE2 messages.
2016-05-10 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Hannes Jochriem:
* avrdude.conf.in (ehajo-isp): New programmer.
2016-04-20 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* configure.ac (libftdi1): Rather than hardcoding the library
providing the libusb-1.0 API, use the result from the previous
probe. This helps detecting libftdi1 on FreeBSD where the
libusb-1.0 API is provided by the system's libusb.
2016-04-18 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* usb_hidapi.c (usbhid_open): Correctly calculate the
offset for serial number matching
2016-03-28 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #47550: Linux GPIO broken
* linuxgpio.c: Replace %ud by %u in snprintf calls.
2016-03-02 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* usb_hidapi.c (usbhid_recv): Bump read timeout to 300 ms.
2016-02-20 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* jtag3.c: add support for libhidapi as (optional) transport for
CMSIS-DAP compliant debuggers (JTAGICE3 with firmware 3+,
AtmelICE, EDBG, mEDBG)
* usb_hidapi.c: (New file)
* libavrdude.h: Mention usbhid_serdev
* configure.ac: Bump version date
2016-02-18 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
(Obtained from patch #8717: pattch for mcprog and libhidapi support)
* configure.ac: Probe for libhidapi
* Makefile.am: Add @LIBHIDAPI@
2016-02-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* doc/avrdude.texi: Bump copyright year.
2016-02-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* configure.ac: Bump for post-release 6.3.
2016-02-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* configure.ac: Released version 6.3.
2016-02-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
patch #8894: Spelling in 6.2 doc
* doc/avrdude.texi: Various spelling fixes.
2016-02-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
patch #8895: Spelling in 6.2 code
* avrftdi.c (avrftdi_open): Spell fix.
2016-02-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
patch #8896: Silence cppcheck warnings in 6.2 code
* linuxgpio.c: Use %ud to print GPIO values.
2016-02-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
patch #8735: ATtiny28 support in avrdude.conf
* avrdude.conf.in (ATtiny28): New device.
2016-02-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* avrdude.conf.in (ATmega48PB, ATmega88PB, ATmega168PB): New
devices.
2016-02-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
patch #8435: Implementing mEDBG CMSIS-DAP protocol
* usb_libusb.c: Add endpoint IDs for Xplained Mini, correctly
transfer trailing ZLP when needed
* avrdude.conf.in (xplainedmini, xplainedmini_dw): New entries.
* jtag3.c (jtag3_edbg_send, jtag3_edbg_recv_frame): Implement
fragmentation needed for the 64-byte EP size of the Xplained Mini
* avrdude.1: Document the change
* doc/avrdude.texi: (Dito.)

View File

@@ -1,56 +0,0 @@
2017-12-30 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud <janegil.ruud@microchip.com>
patch #9507: Fix UPDI chip erase
* jtag3.c (jtag3_chip_erase_updi): New function
* jtag3_private.h: More constants
2017-12-30 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud <janegil.ruud@microchip.com>
patch #9508: Add PowerDebugger and XPlained Mini in UPDI mode
* avrdude.conf.in (xplainedmini_updi, powerdebugger,
powerdebugger_pdi, powerdebugger_updi, powerdebugger_dw,
powerdebugger_isp): New programmers
2017-12-29 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* bootstrap: Detect whether libtoolize is named
`glibtoolize' (MacOS)
2017-11-30 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* configure.ac: Bump version date, due to UPDI addition
2017-11-29 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud <janegil.ruud@microchip.com>
patch #9482: Add support for UPDI and AVR8X
* avrdude.conf.in (xplainedpro_updi): New programmer
* avrdude.conf.in (.avr8x, ATtiny1617, ATtiny817): New device
family and devices
* config_gram.y: add K_OCD_BASE and K_HAS_UPDI
* lexer.l: (Ditto.)
* doc/avrdude.texi: Document "has_updi" flag
* jtag3.c: Implement UPDI
* jtag3.h: (Ditto.)
* jtag3_private.h: (Ditto.)
* libavrdude.h: Add ocd_base value and AVRPART_HAS_UPDI flag
* pgm_type.c: Add jtagice3_updi
2017-11-29 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud <janegil.ruud@microchip.com>
* avrdude.conf.in (ATmega328PB): New part
2017-11-13 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #48084: Avoid compiled-in timestamp for reproducible release builds
* main.c: Remove "compiled on/at" string
2017-03-05 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
bug #47718: "lfuse reads as" not displayed in verbose mode - SOLUTION
Reported by Roger A. Krupski:
* safemode.c: Display lfuse at correct MSG level

View File

@@ -1,148 +0,0 @@
2018-01-21 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
patch #8444: Proposal for modifications in -B and -U command options managment
* update.c (parse_op): Default -U filename to RBIN for output
files
2018-01-18 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Simone:
patch #8128: Added new option to configure.ac script
* configure.ac (disable-libusb_1_0): New option
2018-01-18 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud:
patch #9542: Correct "usersig" on avr8x devices
* avrdude.conf.in (.avr8x_tiny, .avr8x_mega): rename "userrow" to
"usersig", and fix its page size for .avr8x_mega
* jtag3.c: Remove all "userrow" handling
2018-01-17 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Reinhard Max
patch #8311: Add IPv6 support to the -Pnet:host:port option
* ser_posix.c (net_open): Rewrite to use getaddrinfo()
rather than gethostbyname()
* avrdude.1: Document IPv6 feature
* doc/avrdude.texi: (Dito)
2018-01-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Maciej:
patch #9185: Add extended_param to usbasp.c - erasing
configuration section in ATtiny 4...40 (TPI)
* usbasp.c: Implement extended parameter parsing, and modify
usbasp_tpi_chip_erase() appropriately
* avrdude.1: Document USBasp extended parameters
* doc/avrdude.texi: (Dito)
2018-01-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Tom Carney:
patch #8219: Fix boot_start for xmega devices on jtagmkII
* jtagmkII.c (jtagmkII_initialize): Determine boarder between
application and boot area correctly.
2018-01-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud <janegil.ruud@microchip.com>
patch #9507: Fix UPDI chip erase
* libavrdude.h (PROGRAMMER): add unlock method
* avr.c (avr_unlock): Generic unlock function
* jtag3.c: Implement unlock feature; avoid calling
jtag3_edbg_prepare() and jtag3_edbg_signoff() on XplainedMini
boards to work around a bug in early firmware versions;
implement "userrow" memory region
* main.c: Call avr_unlock() rather than avr_chip_erase() when
encountering a locked UPDI chip
2018-01-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Nicolas BRULEZ
patch #8910: ATxmega32c4 and ATxmega16c4 have wrong signatures
bug #41388: ATxmega32c4 and ATxmega16c4 have wrong signatures
* avrdude.conf.in (ATxmega16C4, ATxmega32C4): Fix signatures
2018-01-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Dennis Reimers:
patch #8580: FT245r support to select device by serial number
* ft245r.c (ft245r_open): Add serial number parsing.
2018-01-15 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Axel Simon:
patch #9033: avrdoper backend uses libhidapi instead of libusb
* ser_avrdoper: Add libhidapi implementation
* stk500v2.c: Adapt #ifdefs for LIBHIDAPI
* avrdude.1: Document change
* doc/avrdude.texi: (Dito)
2018-01-13 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by David Mosberger-Tang
patch #8924: Enable TPI for usbtiny
* usbtiny.c: Extend to handle TPI targets
* configure.ac: Probe for <netinet/in.h>
2018-01-12 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Yegor Yefremov:
patch #9222: Enable silent build
* configure.ac: Add AM_SILENT_RULES
* Makefile.am: Document how to run "make" to get verbose
build messages
2018-01-12 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by: Kjetil Kjeka:
patch #9317: Support atmega64m1 as part
* avrdue.conf.in (ATmega64M1): New entry.
2018-01-12 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Submitted David Griffith:
patch #9530: Update URL to Ladyada's USBtinyISP page.
* avrdude.conf.in (usbtiny): Update URL
2018-01-12 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Milan Kupcevic:
patch #9423: Support ATtiny841 and ATtiny441
bug #47376: ATtiny841 description missing in configuration file
bug #49455: support for tiny441
* avrdude.conf.in (ATtiny841, ATtiny441): New entries
2018-01-10 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Morten Engelhardt Olsen
patch #9506: Script to create device configuration stub from Atmel ATDF files
* tools/atdf-to-avrdude.xslt: New script
2018-01-10 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud <janegil.ruud@microchip.com>
patch #9507: Fix UPDI chip erase
* lexer.l (family_id): New keyword.
* config_gram.y: (Ditto)
* doc/avrdude.texi: Document new keyword
* avrdude.conf.in: Add family_id for avr8x devices
* avr.c: Pass error code up.
* jtag3.c: Pass error code from memory read up; implement
jtag3_read_sib()
* libavrdude.h: Add new items.
* main.c: Implement different chip erase handling required
for UPDI devices.
2018-01-10 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Jan Egil Ruud <janegil.ruud@microchip.com>
patch #9506: Script to create device configuration stub from Atmel ATDF files
* avrdude.conf.in (ATtiny202, ATtiny204, ATtiny402, ATtiny404)
(ATtiny406, ATtiny804, ATtiny806, ATtiny807, ATtiny1604)
(ATtiny1606, ATtiny1607, ATtiny212, ATtiny214, ATtiny412)
(ATTiny414, ATtiny416, ATtiny417, ATtiny814, ATtiny816)
(ATtiny1614, ATtiny1616, ATtiny3214, ATtiny3216, ATtiny3217)
(ATmega3208, ATmega3209, ATmega4808, ATmega4809): New devices

View File

@@ -1,20 +0,0 @@
2019-12-17 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Britton Kerin:
bug #57428: [PATCH] document when 'arduino' or 'wiring' should be used, and -D requirement of latter
* avrdude.1: Clarify
* doc/avrdude.texi: (dito)
2019-01-05 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Milan Kupcevic:
patch #9735: spelling error fix: psuedo -> pseudo
* avrpart.c (avr_display): Spelling fix
2019-01-05 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Martino Facchin:
patch #9728: Fix UsbTiny programmer
* usbtiny.c (usbtiny_initialize): Only consider
pgm->program_enable successful if returning 0

View File

@@ -1,104 +0,0 @@
2020-09-22 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Reported by Hannes Wallnöfer:
* avrdude.conf.in (m32m1): add "size" parameter in "efuse"
section
2020-09-20 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Björn Mellström
patch #9744: Patch for ATMega324A support
* avrdude.conf.in (m324a): New entry.
2020-09-20 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Ronald Sutherland
patch #9811: ATmega328pb has efuse bit 3
* avrdude.conf.in (m328pb): Add own efuse definition
2020-09-19 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Ralf Ramsauer
patch #9816: Implement new programmer type: linuxspi
* linuxspi.c: (New file.)
* linuxspi.h: (New file.)
* Makefile.am: Add new files
* configure.ac: Add "linuxspi" --enable option
* avrdude.conf.in: Add "linuxspi" programmer template
* pgm_type.c: Include linuxspi programmer
* doc/avrdude.texi: Document new programmer
* avrdude.1: (Dito.)
2020-09-18 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Marcin Miskiewic
patch #9963: UsbAsp 3 MHz patch for UsbAsp-flash firmware
* usbasp.c: Implement 3 MHz clock option including capability check
* usbasp.h: (Dito.)
2020-09-18 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Sven Schwermer:
patch #9966: Add JTAGICE3 in UPDI mode
* avrdude.conf (jtag3updi): New entry.
2020-09-18 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Joel Ray Holveck
patch #9732: usbtiny_paged_load overflows buffer e.g. when reading EEPROM
* usbtiny.c (usbtiny_paged_load, usbtiny_paged_write): ensure chunk
does not overflow memory area
2020-09-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Adrian Klieber:
patch #9818: correct typos in SVN rev 1429
* buspirate.c: Fix typos.
* fileio.c: Fix typos.
* jtagmkII.c: Fix typos.
* main.c: Fix typos.
* term.c: Fix typos.
* usbasp.c: Fix typos.
* usbtiny.h: Fix typos.
2020-09-16 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Adrian Klieber:
patch #9820: Fix some out-of-bounds/uninitialized issues
* stk500v2.c (stk500v2_display): fix uninitialized variables
* stk500v2.c (stk500v2_set_sck_period_mk2): fix loop limits
* pickit2.c (pickit2_open): Use pgm->desc to store description (WIN32 only)
* config_gram.y (K_PAGE_SIZE): ensure page_size is > 0
* avrpart.c (avr_new_memtype): initialize page_size to 1
2020-09-10 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* config_gram.y (K_DESC): Enforce correct length in strncpy()
* config_gram.y (K_MEMORY): (Dito.)
2020-09-10 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
* avrpart.c (avr_new_memtype): ensure page_size is at least 1
* config_gram.y (K_PAGE_SIZE): (Dito.)
2020-03-14 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by Adrian Klieber:
patch #9819: Address several leaks in SVN rev 1429
* config.c: Fix potential memory leak
* jtagmkII.c: (Dito.)
* stk500v2.c: (Dito.)
* update.c: (Dito.)
* windows/loaddrv.c: Fix file descriptor leak.
2020-03-11 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Submitted by: kautism
patch #9893: [PATCH] Reader reads ftdi handle after main thread close it
* ft245r.c: Wait until reader thread has been stopped before closing FTDI
2020-03-11 Joerg Wunsch <j.gnu@uriah.heep.sax.de>
Fix compiler warnings
* avr.c: misleading indentation after spin loop
* fileio.c: EM_AVR32 might be defined in system <libelf.h>

57
INSTALL
View File

@@ -1,57 +0,0 @@
Installation Instructions
*************************
Use `./configure; make all; sudo make install' for Unix-like systems.
Depending on your requirements, the following prerequisites are
needed:
* libelf including header files (for directly reading ELF files)
* libusb 0.1 or 1.0 (or compatible), including header files
* libftdi or libftdi1 (for direct access to FTDI devices)
* libhidapi or libhid (for access to recent Atmel/Microchip dongles)
If the header and/or library files for one of those are found in
non-default locations, you can add them to configure, e.g.
`./configure CPPFLAGS=-I/opt/local/include LDFLAGS=-L/opt/local/lib'
as an example for MacOS using Macports. MacOS Brew requires
`./configure CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/Cellar'
instead. (LDFLAGS and CPPFLAGS can also be supplied as environment
variables to configure.)
At the end of the configure script, a configuration summary is issued,
like this:
Configuration summary:
----------------------
DO HAVE libelf
DO HAVE libusb
DO HAVE libusb_1_0
DO HAVE libftdi1
DON'T HAVE libftdi
DON'T HAVE libhid
DO HAVE libhidapi
DO HAVE pthread
DISABLED doc
DISABLED parport
DISABLED linuxgpio
DISABLED linuxspi
Make sure all the features you are interested in have been found.
For BSD-like systems, using GNU make (gmake) is not mandatory but
appears to cause less troubles with the quite complex dependency graph
that might be produced by autoconf/automake.
For Windows, right now, a toolset like MinGW is required to compile
AVRDUDE.
Obviously, a working C compiler is needed. Tested compilers so far
include GCC (in various versions) and Clang. The compiler needs to
support (at least) C99 language level. For MacOS, either Xcode or the
(smaller) Xcode Command Line tools are needed, for Windows, some port
of GCC that supports generating native Windows executables.

View File

@@ -16,15 +16,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# In order to get verbose build messages rather than a summary line
# only, either use
#
# ./configure --disable-silent-rules
#
# or run make like
#
# make V=1
#
# $Id$
#
@@ -42,10 +33,6 @@ EXTRA_DIST = \
ChangeLog-2011 \
ChangeLog-2012 \
ChangeLog-2013 \
ChangeLog-2014 \
ChangeLog-2015 \
ChangeLog-2016 \
ChangeLog-2017 \
avrdude.1 \
avrdude.spec \
bootstrap
@@ -79,7 +66,7 @@ avrdude_CFLAGS = @ENABLE_WARNINGS@
libavrdude_a_CFLAGS = @ENABLE_WARNINGS@
libavrdude_la_CFLAGS = $(libavrdude_a_CFLAGS)
avrdude_LDADD = $(top_builddir)/$(noinst_LIBRARIES) @LIBUSB_1_0@ @LIBHIDAPI@ @LIBUSB@ @LIBFTDI1@ @LIBFTDI@ @LIBHID@ @LIBELF@ @LIBPTHREAD@ -lm
avrdude_LDADD = $(top_builddir)/$(noinst_LIBRARIES) @LIBUSB_1_0@ @LIBUSB@ @LIBFTDI1@ @LIBFTDI@ @LIBHID@ @LIBELF@ @LIBPTHREAD@ -lm
bin_PROGRAMS = avrdude
@@ -149,8 +136,6 @@ libavrdude_a_SOURCES = \
libavrdude.h \
linuxgpio.c \
linuxgpio.h \
linuxspi.c \
linuxspi.h \
linux_ppdev.h \
lists.c \
my_ddk_hidsdi.h \
@@ -184,15 +169,12 @@ libavrdude_a_SOURCES = \
usbasp.c \
usbasp.h \
usbdevs.h \
usb_hidapi.c \
usb_libusb.c \
usbtiny.h \
usbtiny.c \
update.c \
wiring.h \
wiring.c \
xbee.h \
xbee.c
wiring.c
libavrdude_la_SOURCES = $(libavrdude_a_SOURCES)
libavrdude_la_LDFLAGS = -version-info 1:0

171
NEWS
View File

@@ -5,176 +5,6 @@ Approximate change log for AVRDUDE by version.
(For more detailed changes, see the ChangeLog file.)
----------------------------------------------------------------------
Version 6.4:
* Major changes compared to the previous version:
- libhidapi support (part of patch #8717)
- use libhidapi as (optional) transport for CMSIS-DAP compliant
debuggers (JTAGICE3 with firmware 3+, AtmelICE, EDBG, mEDBG)
- UPDI support added (AVR8X family)
- TPI support for USBtinyISP
- TPI support for ft245r
- TPI support for linuxgpio
- AVR Doper uses libhidapi rather than raw libusb (patch #9033)
- -P net:host:port can use IPv6 now (Posix systems only)
- New configure option: -disable-libusb_1_0
- extended UPDI device context (> 64 Ki flash)
- major overhaul of ft245r driver (patch #9327/#9328)
- some improvements in linuxspi driver
- Use -B <bitclock> rather than -b <baudrate> for linuxspi driver
- unused lock byte bits are not masked on read anymore
- parport support disabled by default; configure with
--enable-parport to explicitly enable it
* New devices supported:
- ATmega328PB
- AVR8X family, ATtiny1617, ATtiny817, ATtiny202, ATtiny204,
ATtiny402, ATtiny404, ATtiny406, ATtiny804, ATtiny806,
ATtiny807, ATtiny1604, ATtiny1606, ATtiny1607, ATtiny212,
ATtiny214, ATtiny412, ATTiny414, ATtiny416, ATtiny417,
ATtiny814, ATtiny816, ATtiny1614, ATtiny1616, ATtiny3214,
ATtiny3216, ATtiny3217, ATmega3208, ATmega3209, ATmega4808,
ATmega4809
- ATtiny841, ATtiny441
- ATmega64M1
- ATmega324A
- ATmega808, ATmega809, ATmega1608, ATmega1609, AVR DA, AVR DB
- LGT8FX88P, LGT8FX168P, LGT8FX328P
- ATmega324PB
- ATmega8A
* New programmers supported:
- ehajo-isp (commercial version of USBtiny)
- XplainedPro in UPDI mode
- XplainedMini in UPDI mode
- JTAGICE3 in UPDI mode
- Atmel Powerdebugger in all modes (JTAG, PDI, UPDI, debugWIRE, ISP)
- linuxspi (direct SPI bus e.g. on Raspberry Pi devices)
- PICkit4, Snap, PKoB
- iseavrprog
- XBeeBoot
* Bugfixes:
bug #47550: Linux GPIO broken
bug #47718: "lfuse reads as" not displayed in verbose mode - SOLUTION
bug #48084: Avoid compiled-in timestamp for reproducible release builds
bug #47376: ATtiny841 description missing in configuration file
bug #49455: support for tiny441
bug #57428: document when 'arduino' or 'wiring' should be used, and -D requirement of latter
bug #58095: error setting efuse on atmega328pb variant
bug #51409: Can't program EFUSE on ATmega32M1
bug #60753: Patch #1436 breaks multiple programmer/device combinations on MacOS BigSur
bug #59525: Bogus error message because Copy/Paste typo in stk500.c
bug #58078: [PATCH] buspirate: remove compound literals (fixes GCC>=9)
bug #57453: [PATCH] fix reference to nonexistant -m option by changing to -U
bug #59227: Add new part. How does one get a part added to the CONF file?
bug #55009: no efuses for m164a/pa
bug #55734: USBtiny programming of ATmega328p broken by Patch #9278
bug #58495: Add atmega324pb support to avrdude.conf.in
bug #60863: avrftdi programming error probably caused by multiple, consecutive empty pages
bug #50517: Reading fails if "immediate mode" for output file format is selected - fileio: invalid operation=1
bug #50630: Erase Cycle Counter options ( -y -Y n ) should be removed from usage Message
bug #48767: ser_drain() for TCP on Windows doesn't work
bug #46759: avrdude 6.1 -> 6.2 regression: lock byte verification error
bug #58440: linuxgpio PIN limit too low
bug #55462: wrong programmer id check in jtag3_getsync() and jtag3_close()
bug #58994: VPP PWM still enabled at the end of programming process
bug #57338: if safemode has to change fuses avrdude should exit with non-zero exit code
bug #60575: Permission denied on macOS Big Sur
* Patches:
patch #9482: Add support for UPDI and AVR8X
patch #9508: Add PowerDebugger and XPlained Mini in UPDI mode
patch #9507: Fix UPDI chip erase
patch #9506: Script to create device configuration stub from Atmel
ATDF files
patch #9423: Support ATtiny841 and ATtiny441
patch #9530: Update URL to Ladyada's USBtinyISP page.
patch #9317: Support atmega64m1 as part
patch #9222: Enable silent build
patch #8924: Enable TPI for usbtiny
patch #9033: avrdoper backend uses libhidapi instead of libusb
patch #8580: FT245r support to select device by serial number
patch #8910: ATxmega32c4 and ATxmega16c4 have wrong signatures
patch #8219: Fix boot_start for xmega devices on jtagmkII
patch #9185: Add extended_param to usbasp.c - erasing
patch #8311: Add IPv6 support to the -Pnet:host:port option
patch #9542: Correct "usersig" on avr8x devices
patch #8128: Added new option to configure.ac script
patch #8444: Proposal for modifications in -B and -U command options managment (partially)
patch #9735: spelling error fix: psuedo -> pseudo
patch #9893: [PATCH] Reader reads ftdi handle after main thread close it
patch #9819: Address several leaks in SVN rev 1429
patch #9820: Fix some out-of-bounds/uninitialized issues
patch #9818: correct typos in SVN rev 1429
patch #9732: usbtiny_paged_load overflows buffer e.g. when reading EEPROM
patch #9966: Add JTAGICE3 in UPDI mode
patch #9963: UsbAsp 3 MHz patch for UsbAsp-flash firmware
patch #9816: Implement new programmer type: linuxspi
patch #9811: ATmega328pb has efuse bit 3
patch #9744: Patch for ATMega324A support
patch #10000: Add support for extended UPDI device context
patch #9697: Add iseavrprog support
patch #10017: uspasp / tpi: Automatically clear configuration byte (fuse) before writing it
patch #8957: Allow reading prodsig memory from stk500v2 on xmega devices
patch #9110: Let reserved fuse bits to be read as *don't care*
patch #9253: Fix for giving terminal_mode commands more than 20 arguments
patch #9320: fix TPI RESET in bitbang.c
patch #9079: Fix ftdi_syncbb teardown (supersedes #9893, superseded by #9328)
patch #9122: Fixed MISO sampling in ftdi_syncbb
patch #9123: ftdi_syncbb: use FT245R_CYCLES in ft245r_set_bitclock()
patch #8719: Support Over-the-Air bootloading with XBeeBoot
patch #9757: Fix ATtiny817 Xplained Mini programmer
patch #9327: ft245r.c: add TPI support (patches 1-4)
patch #9328: ft245r.c: add TPI support (patches 5-7)
patch #10027: linuxspi: Add reset pulse, according to AVR programming algorithm
patch #10028: linuxspi: close() only when necessary
patch #10029: linuxspi: Report GPIO_GET_LINEHANDLE_IOCTL errors
patch #10030: linuxspi: Support inverted GPIO pin
patch #10031: linuxspi: Support GPIO uAPI v2
(no-id): Improve documentation of linuxspi driver, provide portname default
(no-id): Use -B <bitclock> rather than -b <baudrate> for linuxspi driver
patch #9304: [Bug #48767] Implemented WinSock variation of "ser_drain(...)" functionality
patch #8996: Remove lock byte read mask (bug#21954, bug#46759)
patch #8923: Enable TPI for linuxgpio
patch #10153: linuxspi: Support "-E reset" and "-E noreset"
* Internals:
- New avrdude.conf keyword "family_id", used to verify SIB attributes
on AVR8X architecture if device is locked.
Version 6.3:
* Major changes compared to the previous version:
- Backout of
patch #8380: adds 500k 1M 2M baud to ser_posix.c
It broke the functionality in too many situations
(bug #46610/46483)
* New devices supported:
- ATmega48PB, ATmega88PB, ATmega168PB
- ATtiny28 (HVPP-only device)
* New programmers supported:
- Atmel mEDBG: xplainedmini, xplainedmini_dw
* Bugfixes
- bug #46610: Floating point exception (core dumped) arch linux rpi2
- bug #46483: version 6.2. ser_open(): can't set attributes for device
- patch #8435: Implementing mEDBG CMSIS-DAP protocol
- patch #8735: ATtiny28 support in avrdude.conf
- patch #8896: Silence cppcheck warnings in 6.2 code
- patch #8895: Spelling in 6.2 code
Version 6.2:
* Major changes compared to the previous version:
@@ -233,6 +63,7 @@ Version 6.2:
- bug #40870: config nitpick: ATtiny25/45/85 have 1 calibration byte not 2
- bug #42908: no external reset at JTAGICE3
- patch #8437: [PATCH] Serial-over-ethernet for Win32
- patch #8380: adds 500k 1M 2M baud to ser_posix.c
- bug #44717: avrdude creates empty flash dump
* Internals:

94
avr.c
View File

@@ -80,12 +80,11 @@ int avr_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
0xFF
};
while (avr_tpi_poll_nvmbsy(pgm))
;
while (avr_tpi_poll_nvmbsy(pgm));
err = pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);
if(err)
return err;
err = pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);
if(err)
return err;
while (avr_tpi_poll_nvmbsy(pgm));
@@ -330,7 +329,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype,
memset(mem->buf, 0xff, mem->size);
/* supports "paged load" thru post-increment */
if ((p->flags & AVRPART_HAS_TPI) && mem->page_size > 1 &&
if ((p->flags & AVRPART_HAS_TPI) && mem->page_size != 0 &&
pgm->cmd_tpi != NULL) {
while (avr_tpi_poll_nvmbsy(pgm));
@@ -361,7 +360,7 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype,
return avr_mem_hiaddr(mem);
}
if (pgm->paged_load != NULL && mem->page_size > 1) {
if (pgm->paged_load != NULL && mem->page_size != 0) {
/*
* the programmer supports a paged mode read
*/
@@ -439,15 +438,11 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype,
{
rc = pgm->read_byte(pgm, p, mem, i, mem->buf + i);
if (rc != 0) {
avrdude_message(MSG_INFO, "avr_read(): error reading address 0x%04lx\n", i);
if (rc == -1) {
avrdude_message(MSG_INFO, " read operation not supported for memory \"%s\"\n",
avrdude_message(MSG_INFO, "avr_read(): error reading address 0x%04lx\n", i);
if (rc == -1)
avrdude_message(MSG_INFO, " read operation not supported for memory \"%s\"\n",
memtype);
return -2;
}
avrdude_message(MSG_INFO, " read operation failed for memory \"%s\"\n",
memtype);
return rc;
return -2;
}
}
report_progress(i, mem->size, NULL);
@@ -863,7 +858,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
}
if ((p->flags & AVRPART_HAS_TPI) && m->page_size > 1 &&
if ((p->flags & AVRPART_HAS_TPI) && m->page_size != 0 &&
pgm->cmd_tpi != NULL) {
while (avr_tpi_poll_nvmbsy(pgm));
@@ -903,7 +898,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
return i;
}
if (pgm->paged_write != NULL && m->page_size > 1) {
if (pgm->paged_write != NULL && m->page_size != 0) {
/*
* the programmer supports a paged mode write
*/
@@ -1056,37 +1051,13 @@ int avr_signature(PROGRAMMER * pgm, AVRPART * p)
if (rc < 0) {
avrdude_message(MSG_INFO, "%s: error reading signature data for part \"%s\", rc=%d\n",
progname, p->desc, rc);
return rc;
return -1;
}
report_progress (1,1,NULL);
return 0;
}
static uint8_t get_fuse_bitmask(AVRMEM * m) {
uint8_t bitmask_r = 0;
uint8_t bitmask_w = 0;
int i;
if (!m || m->size > 1) {
// not a fuse, compare bytes directly
return 0xFF;
}
// For fuses, only compare bytes that are actually written *and* read.
for (i = 0; i < 32; i++) {
if (m->op[AVR_OP_WRITE]->bit[i].type == AVR_CMDBIT_INPUT)
bitmask_w |= (1 << m->op[AVR_OP_WRITE]->bit[i].bitno);
if (m->op[AVR_OP_READ]->bit[i].type == AVR_CMDBIT_OUTPUT)
bitmask_r |= (1 << m->op[AVR_OP_READ]->bit[i].bitno);
}
return bitmask_r & bitmask_w;
}
int compare_memory_masked(AVRMEM * m, uint8_t b1, uint8_t b2) {
uint8_t bitmask = get_fuse_bitmask(m);
return (b1 & bitmask) != (b2 & bitmask);
}
/*
* Verify the memory buffer of p with that of v. The byte range of v,
@@ -1133,30 +1104,11 @@ int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size)
for (i=0; i<size; i++) {
if ((b->tags[i] & TAG_ALLOCATED) != 0 &&
buf1[i] != buf2[i]) {
uint8_t bitmask = get_fuse_bitmask(a);
if((buf1[i] & bitmask) != (buf2[i] & bitmask)) {
// Mismatch is not just in unused bits
avrdude_message(MSG_INFO, "%s: verification error, first mismatch at byte 0x%04x\n"
"%s0x%02x != 0x%02x\n",
progname, i,
progbuf, buf1[i], buf2[i]);
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
avrdude_message(MSG_INFO, "%s: WARNING: ignoring mismatch in unused bits of \"%s\"\n"
"%s(0x%02x != 0x%02x). To prevent this warning fix the part\n"
"%sor programmer definition in the config file.\n",
progname, memtype, progbuf, buf1[i], buf2[i], progbuf);
} else {
// Programmer returned unused bits as 1, must be the user
avrdude_message(MSG_INFO, "%s: WARNING: ignoring mismatch in unused bits of \"%s\"\n"
"%s(0x%02x != 0x%02x). To prevent this warning set unused bits\n"
"%sto 1 when writing (double check with your datasheet first).\n",
progname, memtype, progbuf, buf1[i], buf2[i], progbuf);
}
}
avrdude_message(MSG_INFO, "%s: verification error, first mismatch at byte 0x%04x\n"
"%s0x%02x != 0x%02x\n",
progname, i,
progbuf, buf1[i], buf2[i]);
return -1;
}
}
@@ -1239,16 +1191,6 @@ int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p)
return rc;
}
int avr_unlock(PROGRAMMER * pgm, AVRPART * p)
{
int rc = -1;
if (pgm->unlock)
rc = pgm->unlock(pgm, p);
return rc;
}
/*
* Report the progress of a read or write operation from/to the
* device.

109
avrdude.1
View File

@@ -1,6 +1,6 @@
.\"
.\" avrdude - A Downloader/Uploader for AVR device programmers
.\" Copyright (C) 2001, 2002, 2003, 2005 - 2020 Joerg Wunsch
.\" Copyright (C) 2001, 2002, 2003, 2005 - 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
@@ -18,7 +18,7 @@
.\"
.\" $Id$
.\"
.Dd DATE November 22, 2021
.Dd DATE November 23, 2014
.Os
.Dt AVRDUDE 1
.Sh NAME
@@ -109,31 +109,6 @@ some resistors in series or better yet use a 3-state buffer driver like
the 74HC244. Have a look at http://kolev.info/avrdude-linuxgpio for a more
detailed tutorial about using this programmer type.
.Pp
Under a Linux installation with direct access to the SPI bus and GPIO
pins, such as would be found on a Raspberry Pi, the ``linuxspi''
programmer type can be used to directly connect to and program a chip
using the built in interfaces on the computer. The requirements to use
this type are that an SPI interface is exposed along with one GPIO
pin. The GPIO serves as the reset output since the Linux SPI drivers
do not hold slave select down when a transfer is not occuring and thus
it cannot be used as the reset pin. A readily available level
translator should be used between the SPI bus/reset GPIO and the chip
to avoid potentially damaging the computer's SPI controller in the
event that the chip is running at 5V and the SPI runs at 3.3V. The
GPIO chosen for reset can be configured in the avrdude configuration
file using the
.Li reset
entry under the linuxspi programmer, or
directly in the port specification. An external pull-up resistor
should be connected between the AVR's reset pin and Vcc. If Vcc is not
the same as the SPI voltage, this should be done on the AVR side of
the level translator to protect the hardware from damage.
.Pp
The
.Fl P Ar portname
option for this programmer defaults to
.Li /dev/spidev0.0:/dev/gpiochip0 .
.Pp
Atmel's STK500 programmer is also supported and connects to a serial
port.
Both, firmware versions 1.x and 2.x can be handled, but require a
@@ -142,15 +117,12 @@ Using firmware version 2, high-voltage programming is also supported,
both parallel and serial
(programmer types stk500pp and stk500hvsp).
.Pp
Wiring boards (e.g. Arduino Mega 2560 Rev3) are supported, utilizing STK500
V2.x protocol, but a simple DTR/RTS toggle is used to set the boards into
programming mode. The programmer type is ``wiring''. Note that the -D option
will likely be required in this case, because the bootloader will rewrite the
program memory, but no true chip erase can be performed.
Wiring boards are supported, utilizing STK500 V2.x protocol, but
a simple DTR/RTS toggle is used to set the boards into programming mode.
The programmer type is ``wiring''.
.Pp
The Arduino (which is very similar to the STK500 1.x) is supported via
its own programmer type specification ``arduino''. This programmer works for
the Arduino Uno Rev3.
its own programmer type specification ``arduino''.
.Pp
The BusPirate is a versatile tool that can also be used as an AVR programmer.
A single BusPirate can be connected to up to 3 independent AVRs. See
@@ -184,9 +156,6 @@ ISP).
Atmel's XplainedPro boards, using the EDBG protocol (CMSIS-DAP compatible),
are supported using the "jtag3" programmer type.
.Pp
Atmel's XplainedMini boards, using the mEDBG protocol,
are also supported using the "jtag3" programmer type.
.Pp
The AVR Dragon is supported in all modes (ISP, JTAG, HVSP, PP, debugWire).
When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
JTAG ICE mkII, so all device-specific comments for that device
@@ -216,12 +185,6 @@ The Atmel DFU bootloader is supported in both, FLIP protocol version 1
(AT90USB* and ATmega*U* devices), as well as version 2 (Xmega devices).
See below for some hints about FLIP version 1 protocol behaviour.
.Pp
The MPLAB(R) PICkit 4, MPLAB(R) SNAP, and Curiosity Nano boards are
supported in UPDI mode. The Curiosity Nano board is dubbed
.Dq PICkit on Board ,
thus the name
.Pa pkobn_updi .
.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
@@ -247,7 +210,7 @@ lock bits can be programmed as well. These are implemented within
.Nm
as separate memory types and can be programmed using data from a file
(see the
.Fl U
.Fl m
option) or from terminal mode (see the
.Ar dump
and
@@ -326,8 +289,11 @@ by using ? as programmer-id.
Use the specified config file to load configuration data. This file
contains all programmer and part definitions that
.Nm avrdude
knows about.
See the config file, located at
knows about. If you have a programmer or part that
.Nm avrdude
does not know about, you can add it to the config file (be sure and
submit a patch back to the author so that it can be incorporated for
the next version). See the config file, located at
.Pa ${PREFIX}/etc/avrdude.conf ,
which contains a description of the format.
.Pp
@@ -519,7 +485,7 @@ same method of specifying the port is required there.
For the USB programmer "AVR-Doper" running in HID mode, the port must
be specified as
.Ar avrdoper.
Libhidapi support is required on Unix and Mac OS but not on Windows. For more
Libusb support is required on Unix but not on Windows. For more
information about AVR-Doper see http://www.obdev.at/avrusb/avrdoper.html.
.Pp
For the USBtinyISP, which is a simplicistic device not implementing
@@ -528,22 +494,6 @@ location in the USB hierarchy. See the the respective
.Em Troubleshooting
entry in the detailed documentation for examples.
.Pp
For the XBee programmer the target MCU is to be programmed wirelessly over a
ZigBee mesh using the XBeeBoot bootloader. The ZigBee 64-bit address for the
target MCU's own XBee device must be supplied as a 16-character hexadecimal
value as a
.Ar port
prefix, followed by the
.Ql @
character, and the serial device to connect to a second directly contactable
XBee device associated with the same mesh (with a default baud rate of 9600).
This may look similar to:
.Pa 0013a20000000001@/dev/tty.serial .
.Pp
For diagnostic purposes, if the target MCU with an XBeeBoot bootloader is
connected directly to the serial port, the 64-bit address field can be
omitted. In this mode the default baud rate will be 19200.
.Pp
For programmers that attach to a serial port using some kind of
higher level protocol (as opposed to bit-bang style programmers),
.Ar port
@@ -555,19 +505,12 @@ network connection to (TCP)
on
.Ar host
is established.
Square brackets may be placed around
.Ar host
to improve readability, for numeric IPv6 addresses (e.g.
.Li net:[2001:db8::42]:1337 ) .
The remote endpoint is assumed to be a terminal or console server
that connects the network stream to a local serial port where the
actual programmer has been attached to.
The port is assumed to be properly configured, for example using a
transparent 8-bit data connection without parity at 115200 Baud
for a STK500.
.Pp
Note: The ability to handle IPv6 hostnames and addresses is limited to
Posix systems (by now).
.It Fl q
Disable (or quell) output of the progress bar while reading or writing
to the device. Specify it a second time for even quieter operation.
@@ -1104,32 +1047,6 @@ Sets the SPI clocking rate in Hz (default is 100kHz). Alternately the -B or -i o
.It Ar timeout=<usb-transaction-timeout>
Sets the timeout for USB reads and writes in milliseconds (default is 1500 ms).
.El
.It Ar USBasp
Extended parameters:
.Bl -tag -offset indent -width indent
.It Ar section_config
Programmer will erase configuration section with option
.Fl e
(chip erase), rather than entire chip.
Only applicable to TPI devices (ATtiny 4/5/9/10/20/40).
.El
.It Ar xbee
Extended parameters:
.Bl -tag -offset indent -width indent
.It Ar xbeeresetpin=<1..7>
Select the XBee pin DIO<1..7> that is connected to the MCU's
.Ql /RESET
line. The programmer needs to know which DIO pin to use to reset into the
bootloader. The default (3) is the DIO3 pin (XBee pin 17), but some
commercial products use a different XBee pin.
.Pp
The remaining two necessary XBee-to-MCU connections are not selectable - the
XBee DOUT pin (pin 2) must be connected to the MCU's
.Ql RXD
line, and the XBee DIN pin (pin 3) must be connected to the MCU's
.Ql TXD
line.
.El
.El
.Sh FILES
.Bl -tag -offset indent -width /dev/ppi0XXX

File diff suppressed because it is too large Load Diff

View File

@@ -703,7 +703,7 @@ static int avrftdi_open(PROGRAMMER * pgm, char *port)
err = ftdi_usb_open_desc_index(pdata->ftdic, vid, pid, desc, serial, index);
if(err) {
log_err("Error %d occurred: %s\n", err, ftdi_get_error_string(pdata->ftdic));
log_err("Error %d occured: %s\n", err, ftdi_get_error_string(pdata->ftdic));
//stupid hack, because avrdude calls pgm->close() even when pgm->open() fails
//and usb_dev is intialized to the last usb device from probing
pdata->ftdic->usb_dev = NULL;
@@ -1045,6 +1045,16 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
bufptr += 4;
}
buf_size = bufptr - buf;
if(verbose > TRACE)
buf_dump(buf, buf_size, "command buffer", 0, 16*2);
log_info("Transmitting buffer of size: %d\n", buf_size);
if (0 > avrftdi_transmit(pgm, MPSSE_DO_WRITE, buf, buf, buf_size))
return -1;
bufptr = buf;
/* find a poll byte. we cannot poll a value of 0xff, so look
* for a value != 0xff
*/
@@ -1054,17 +1064,6 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
if((poll_index < addr + len) && m->buf[poll_index] != 0xff)
{
buf_size = bufptr - buf;
if(verbose > TRACE)
buf_dump(buf, buf_size, "command buffer", 0, 16*2);
log_info("Transmitting buffer of size: %d\n", buf_size);
if (0 > avrftdi_transmit(pgm, MPSSE_DO_WRITE, buf, buf, buf_size))
return -1;
bufptr = buf;
log_info("Using m->buf[%d] = 0x%02x as polling value ", poll_index,
m->buf[poll_index]);
/* poll page write ready */
@@ -1078,7 +1077,9 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
}
else
{
log_warn("Skipping empty page (containing only 0xff bytes)\n");
log_warn("No suitable byte (!=0xff) for polling found.\n");
log_warn("Trying to sleep instead, but programming errors may occur.\n");
log_warn("Be sure to verify programmed memory (no -V option)\n");
/* TODO sync write */
/* sleep */
usleep((m->max_write_delay));

View File

@@ -254,7 +254,6 @@ AVRMEM * avr_new_memtype(void)
}
memset(m, 0, sizeof(*m));
m->page_size = 1; // ensure not 0
return m;
}
@@ -646,7 +645,7 @@ void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose)
prefix, avr_pin_name(p->retry_pulse),
prefix, (p->flags & AVRPART_SERIALOK) ? "yes" : "no",
prefix, (p->flags & AVRPART_PARALLELOK) ?
((p->flags & AVRPART_PSEUDOPARALLEL) ? "pseudo" : "yes") : "no",
((p->flags & AVRPART_PSEUDOPARALLEL) ? "psuedo" : "yes") : "no",
prefix, p->timeout,
prefix, p->stabdelay,
prefix, p->cmdexedelay,

View File

@@ -1,7 +1,7 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bsdhome.com>
* Copyright (C) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.org>
* Copyright (C) 2011 Darell Tan <darell.tan@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -542,10 +542,7 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
/* bring RESET high first */
pgm->setpin(pgm, PIN_AVR_RESET, 1);
usleep(128000); /* wait t_TOUT (32-128ms) */
/* RESET must be LOW in case the existing code is driving the TPI pins: */
pgm->setpin(pgm, PIN_AVR_RESET, 0);
usleep(1000);
avrdude_message(MSG_NOTICE2, "doing MOSI-MISO link check\n");

View File

@@ -1,7 +1,7 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bsdhome.com>
* Copyright (C) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.org>
* Copyright (C) 2011 Darell Tan <darell.tan@gmail.com>
*
* This program is free software; you can redistribute it and/or modify

View File

@@ -13,11 +13,7 @@ set -x
rm -rf autom4te.cache
# MacOS calls it "glibtoolize", everyone else "libtoolize"
# probe for that
LIBTOOLIZE=libtoolize
glibtoolize --version > /dev/null 2>&1 && LIBTOOLIZE=glibtoolize
${LIBTOOLIZE}
libtoolize
${ACLOCAL}
${AUTOHEADER}

View File

@@ -493,31 +493,35 @@ static void buspirate_reset_from_binmode(struct programmer_t *pgm)
static int buspirate_start_mode_bin(struct programmer_t *pgm)
{
struct submode {
const struct submode {
const char *name; /* Name of mode for user messages */
char enter; /* Command to enter from base binary mode */
const char *entered_format; /* Response, for "scanf" */
char config; /* Command to setup submode parameters */
} submode;
} *submode;
if (pgm->flag & BP_FLAG_XPARM_RAWFREQ) {
submode.name = "Raw-wire";
submode.enter = 0x05;
submode.entered_format = "RAW%1d";
submode.config = 0x8C;
submode = &(const struct submode){
.name = "Raw-wire",
.enter = 0x05,
.entered_format = "RAW%1d",
.config = 0x8C,
};
pgm->flag |= BP_FLAG_NOPAGEDWRITE;
pgm->flag |= BP_FLAG_NOPAGEDREAD;
} else {
submode.name = "SPI";
submode.enter = 0x01;
submode.entered_format = "SPI%1d";
/* 1000wxyz - SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample
* we want: 3.3V(1), idle low(0), data change on
* trailing edge (1), sample in the middle
* of the pulse (0)
* => 0b10001010 = 0x8a */
submode.config = 0x8A;
submode = &(const struct submode){
.name = "SPI",
.enter = 0x01,
.entered_format = "SPI%1d",
/* 1000wxyz - SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample
* we want: 3.3V(1), idle low(0), data change on
* trailing edge (1), sample in the middle
* of the pulse (0)
* => 0b10001010 = 0x8a */
.config = 0x8A,
};
}
unsigned char buf[20] = { '\0' };
@@ -562,18 +566,18 @@ static int buspirate_start_mode_bin(struct programmer_t *pgm)
}
/* == Set protocol sub-mode of binary mode == */
buf[0] = submode.enter;
buf[0] = submode->enter;
buspirate_send_bin(pgm, buf, 1);
memset(buf, 0, sizeof(buf));
buspirate_recv_bin(pgm, buf, 4);
if (sscanf((const char*)buf, submode.entered_format, &PDATA(pgm)->submode_version) != 1) {
if (sscanf((const char*)buf, submode->entered_format, &PDATA(pgm)->submode_version) != 1) {
avrdude_message(MSG_INFO, "%s mode not confirmed: '%s'\n",
submode.name, buf);
submode->name, buf);
buspirate_reset_from_binmode(pgm);
return -1;
}
avrdude_message(MSG_NOTICE, "BusPirate %s version: %d\n",
submode.name, PDATA(pgm)->submode_version);
submode->name, PDATA(pgm)->submode_version);
if (pgm->flag & BP_FLAG_NOPAGEDWRITE) {
avrdude_message(MSG_NOTICE, "%s: Paged flash write disabled.\n", progname);
@@ -614,7 +618,7 @@ static int buspirate_start_mode_bin(struct programmer_t *pgm)
return -1;
/* Submode config */
if (buspirate_expect_bin_byte(pgm, submode.config, 0x01) < 0)
if (buspirate_expect_bin_byte(pgm, submode->config, 0x01) < 0)
return -1;
/* AVR Extended Commands - test for existence */
@@ -797,7 +801,7 @@ static void buspirate_powerup(struct programmer_t *pgm)
char buf[25];
int ok = 0;
snprintf(buf, sizeof(buf), "%d\n", PDATA(pgm)->cpufreq);
if (buspirate_expect(pgm, "g\n", "Frequency in kHz", 1)) {
if (buspirate_expect(pgm, "g\n", "Frequency in KHz", 1)) {
if (buspirate_expect(pgm, buf, "Duty cycle in %", 1)) {
if (buspirate_expect(pgm, "50\n", "PWM active", 1)) {
ok = 1;

View File

@@ -217,7 +217,6 @@ TOKEN * hexnumber(char * text)
tkn->value.number = strtoul(text, &e, 16);
if ((e == text) || (*e != 0)) {
yyerror("can't scan hex number \"%s\"", text);
free_token(tkn);
return NULL;
}
@@ -245,7 +244,6 @@ TOKEN * string(char * text)
tkn->value.string = (char *) malloc(len+1);
if (tkn->value.string == NULL) {
yyerror("string(): out of memory");
free_token(tkn);
return NULL;
}
strcpy(tkn->value.string, text);

View File

@@ -80,7 +80,6 @@ static int pin_name;
%token K_DEFAULT_SAFEMODE
%token K_DEFAULT_SERIAL
%token K_DESC
%token K_FAMILY_ID
%token K_DEVICECODE
%token K_STK500_DEVCODE
%token K_AVR910_DEVCODE
@@ -97,7 +96,6 @@ static int pin_name;
%token K_MOSI
%token K_NUM_PAGES
%token K_NVM_BASE
%token K_OCD_BASE
%token K_OCDREV
%token K_OFFSET
%token K_PAGEL
@@ -185,7 +183,6 @@ static int pin_name;
%token K_HAS_JTAG /* MCU has JTAG i/f. */
%token K_HAS_DW /* MCU has debugWire i/f. */
%token K_HAS_PDI /* MCU has PDI i/f rather than ISP (ATxmega). */
%token K_HAS_UPDI /* MCU has UPDI i/f (AVR8X). */
%token K_HAS_TPI /* MCU has TPI i/f rather than ISP (ATtiny4/5/9/10). */
%token K_IDR /* address of OCD register in IO space */
%token K_IS_AT90S1200 /* chip is an AT90S1200 (needs special treatment) */
@@ -672,18 +669,11 @@ part_parm :
K_DESC TKN_EQUAL TKN_STRING
{
strncpy(current_part->desc, $3->value.string, AVR_DESCLEN - 1);
strncpy(current_part->desc, $3->value.string, AVR_DESCLEN);
current_part->desc[AVR_DESCLEN-1] = 0;
free_token($3);
} |
K_FAMILY_ID TKN_EQUAL TKN_STRING
{
strncpy(current_part->family_id, $3->value.string, AVR_FAMILYIDLEN);
current_part->family_id[AVR_FAMILYIDLEN] = 0;
free_token($3);
} |
K_DEVICECODE TKN_EQUAL TKN_NUMBER {
{
yyerror("devicecode is deprecated, use "
@@ -1072,16 +1062,6 @@ part_parm :
free_token($3);
} |
K_HAS_UPDI TKN_EQUAL yesno
{
if ($3->primary == K_YES)
current_part->flags |= AVRPART_HAS_UPDI;
else if ($3->primary == K_NO)
current_part->flags &= ~AVRPART_HAS_UPDI;
free_token($3);
} |
K_HAS_TPI TKN_EQUAL yesno
{
if ($3->primary == K_YES)
@@ -1168,12 +1148,6 @@ part_parm :
free_token($3);
} |
K_OCD_BASE TKN_EQUAL TKN_NUMBER
{
current_part->ocd_base = $3->value.number;
free_token($3);
} |
K_OCDREV TKN_EQUAL TKN_NUMBER
{
current_part->ocdrev = $3->value.number;
@@ -1240,7 +1214,7 @@ part_parm :
free_token($2);
YYABORT;
}
strncpy(current_mem->desc, $2->value.string, AVR_MEMDESCLEN - 1);
strncpy(current_mem->desc, $2->value.string, AVR_MEMDESCLEN);
current_mem->desc[AVR_MEMDESCLEN-1] = 0;
free_token($2);
}
@@ -1310,13 +1284,7 @@ mem_spec :
K_PAGE_SIZE TKN_EQUAL TKN_NUMBER
{
int ps = $3->value.number;
if (ps <= 0)
avrdude_message(MSG_INFO,
"%s, line %d: invalid page size %d, ignored\n",
infile, lineno, ps);
else
current_mem->page_size = ps;
current_mem->page_size = $3->value.number;
free_token($3);
} |

View File

@@ -23,7 +23,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.60)
AC_INIT(avrdude, 6.4, avrdude-dev@nongnu.org)
AC_INIT(avrdude, 6.2, avrdude-dev@nongnu.org)
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
@@ -36,8 +36,6 @@ AC_CONFIG_MACRO_DIR([m4])
LT_INIT()
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
@@ -115,22 +113,10 @@ if test x$have_libusb = xyes; then
fi
AC_SUBST(LIBUSB, $LIBUSB)
AC_ARG_ENABLE(
[libusb_1_0],
AC_HELP_STRING(
[--disable-libusb_1_0],
[Allow to build with libusb instead of libusb_1_0 if both are present]),
[case "${enableval}" in
yes) enabled_libusb_1_0=yes ;;
no) enabled_libusb_1_0=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for enable-libusb_1_0 option) ;;
esac],
[enabled_libusb_1_0=yes])
AH_TEMPLATE([HAVE_LIBUSB_1_0],
[Define if USB support is enabled via libusb 1.0])
AC_CHECK_LIB([usb-1.0], [libusb_init], [have_libusb_1_0=yes])
if test x$have_libusb_1_0 = xyes && test x$enabled_libusb_1_0 = xyes; then
if test x$have_libusb_1_0 = xyes; then
case $target in
*-*-darwin*)
LIBUSB_1_0="-lusb-1.0 -framework CoreFoundation -framework IOKit"
@@ -146,7 +132,7 @@ fi
AH_TEMPLATE([HAVE_LIBUSB_1_0],
[Define if USB support is enabled via a libusb-1.0 compatible libusb])
AC_CHECK_LIB([usb], [libusb_init], [have_libusb_1_0=yes])
if test x$have_libusb_1_0 = xyes && test x$enabled_libusb_1_0 = xyes; then
if test x$have_libusb_1_0 = xyes; then
case $target in
*-*-freebsd*)
# FreeBSD 8+ has a native libusb-1.0 API compatible
@@ -164,32 +150,13 @@ if test x$have_libusb_1_0 = xyes && test x$enabled_libusb_1_0 = xyes; then
AC_CHECK_HEADERS([libusb.h])
fi
AC_SUBST(LIBUSB_1_0, $LIBUSB_1_0)
AH_TEMPLATE([HAVE_LIBHIDAPI],
[Define if HID support is enabled via libhidapi])
AC_SEARCH_LIBS([hid_init], [hidapi hidapi-libusb hidapi-hidraw], [have_libhidapi=yes])
if test x$have_libhidapi = xyes; then
case $target in
*-*-darwin*)
LIBHIDAPI="-lhidapi -iframework CoreFoundation -framework IOKit"
;;
*)
LIBHIDAPI="$ac_cv_lib_hid_init"
;;
esac
AC_DEFINE([HAVE_LIBHIDAPI])
AC_CHECK_HEADERS([hidapi/hidapi.h])
fi
AC_SUBST(LIBHIDAPI, $LIBHIDAPI)
AH_TEMPLATE([HAVE_LIBFTDI1],
[Define if FTDI support is enabled via libftdi1])
AH_TEMPLATE([HAVE_LIBFTDI],
[Define if FTDI support is enabled via libftdi])
AH_TEMPLATE([HAVE_LIBFTDI_TYPE_232H],
[Define if libftdi supports FT232H, libftdi version >= 0.20])
AC_CHECK_LIB([ftdi1], [ftdi_new], [have_libftdi1=yes], [], [$LIBUSB_1_0])
AC_CHECK_LIB([ftdi1], [ftdi_new], [have_libftdi1=yes], [], [-lusb-1.0])
AC_CHECK_LIB([ftdi], [ftdi_usb_get_strings], [have_libftdi=yes], [], [-lusb])
if test x$have_libftdi1 = xyes; then
LIBFTDI1="-lftdi1"
@@ -224,13 +191,11 @@ AC_CHECK_HEADERS([ddk/hidsdi.h],,,[#include <windows.h>
AC_C_CONST
AC_HEADER_TIME
AC_CHECK_HEADERS([netinet/in.h])
# WinSock2
AC_CHECK_LIB([ws2_32], [puts])
# Checks for library functions.
AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul gettimeofday usleep getaddrinfo])
AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul gettimeofday usleep])
AC_MSG_CHECKING([for a Win32 HID libray])
SAVED_LIBS="${LIBS}"
@@ -322,7 +287,7 @@ AC_ARG_ENABLE(
no) enabled_parport=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for enable-parport option) ;;
esac],
[enabled_parport=no])
[enabled_parport=yes])
AC_ARG_ENABLE(
[linuxgpio],
@@ -336,18 +301,6 @@ AC_ARG_ENABLE(
esac],
[enabled_linuxgpio=no])
AC_ARG_ENABLE(
[linuxspi],
AC_HELP_STRING(
[--enable-linuxspi],
[Enable the Linux SPIDEV interface programmer type]),
[case "${enableval}" in
yes) enabled_linuxspi=yes ;;
no) enabled_linuxspi=no ;;
*) AC_MSG_ERROR(bad value ${enableval} for enable-linuxspi option) ;;
esac],
[enabled_linuxspi=no])
DIST_SUBDIRS_AC='doc windows'
if test "$enabled_doc" = "yes"; then
@@ -425,14 +378,6 @@ else
fi
if test "$enabled_linuxspi" = "yes"; then
AC_DEFINE(HAVE_LINUXSPI, 1, [Linux SPI support enabled])
confsubst="$confsubst -e /^@HAVE_LINUXSPI_/d"
else
confsubst="$confsubst -e /^@HAVE_LINUXSPI_BEGIN@/,/^@HAVE_LINUXSPI_END@/d"
fi
# If we are compiling with gcc, enable all warning and make warnings errors.
if test "$GCC" = yes; then
ENABLE_WARNINGS="-Wall"
@@ -549,11 +494,7 @@ else
fi
if test x$have_libusb_1_0 = xyes; then
if test x$enabled_libusb_1_0 = xyes; then
echo "DO HAVE libusb_1_0"
else
echo "DISABLED libusb_1_0"
fi
echo "DO HAVE libusb_1_0"
else
echo "DON'T HAVE libusb_1_0"
fi
@@ -580,12 +521,6 @@ else
echo "DON'T HAVE libhid"
fi
if test x$have_libhidapi = xyes; then
echo "DO HAVE libhidapi"
else
echo "DON'T HAVE libhidapi"
fi
if test x$have_pthread = xyes; then
echo "DO HAVE pthread"
else
@@ -610,9 +545,3 @@ else
echo "DISABLED linuxgpio"
fi
if test x$enabled_linuxspi = xyes; then
echo "ENABLED linuxspi"
else
echo "DISABLED linuxspi"
fi

View File

@@ -30,7 +30,7 @@ For avrdude version @value{VERSION}, @value{UPDATED}.
Copyright @copyright{} 2003, 2005 Brian Dean
Copyright @copyright{} 2006 - 2021 J@"org Wunsch
Copyright @copyright{} 2006 - 2011 J@"org Wunsch
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
@@ -154,7 +154,7 @@ serial bit-bang adapters,
and the PPI (parallel port interface). PPI represents a class
of simple programmers where the programming lines are directly
connected to the PC parallel port. Several pin configurations exist
for several variations of the PPI programmers, and AVRDUDE can be
for several variations of the PPI programmers, and AVRDUDE can be be
configured to work with them by either specifying the appropriate
programmer on the command line or by creating a new entry in its
configuration file. All that's usually required for a new entry is to
@@ -173,58 +173,15 @@ available (like almost all embedded Linux boards) you can do without
any additional hardware - just connect them to the MOSI, MISO, RESET
and SCK pins on the AVR and use the linuxgpio programmer type. It bitbangs
the lines using the Linux sysfs GPIO interface. Of course, care should
be taken about voltage level compatibility. Also, although not strictly
be taken about voltage level compatibility. Also, although not strictrly
required, it is strongly advisable to protect the GPIO pins from
overcurrent situations in some way. The simplest would be to just put
some resistors in series or better yet use a 3-state buffer driver like
the 74HC244. Have a look at http://kolev.info/avrdude-linuxgpio for a more
detailed tutorial about using this programmer type.
Under a Linux installation with direct access to the SPI bus and GPIO
pins, such as would be found on a Raspberry Pi, the ``linuxspi''
programmer type can be used to directly connect to and program a chip
using the built in interfaces on the computer. The requirements to use
this type are that an SPI interface is exposed along with one GPIO
pin. The GPIO serves as the reset output since the Linux SPI drivers
do not hold slave select down when a transfer is not occuring and thus
it cannot be used as the reset pin. A readily available level
translator should be used between the SPI bus/reset GPIO and the chip
to avoid potentially damaging the computer's SPI controller in the
event that the chip is running at 5V and the SPI runs at 3.3V. The
GPIO chosen for reset can be configured in the avrdude configuration
file using the @code{reset} entry under the linuxspi programmer, or
directly in the port specification. An external pull-up resistor
should be connected between the AVR's reset pin and Vcc. If Vcc is not
the same as the SPI voltage, this should be done on the AVR side of
the level translator to protect the hardware from damage.
On a Raspberry Pi, header J8 provides access to the SPI and GPIO
lines.
Typically, pins 19, 21, and 23 are SPI MOSI, MISO, and SCK, while
pins 24 and 26 would serve as CE outputs. So, close to these pins
is pin 22 as GPIO25 which can be used as /RESET, and pin 25 can
be used as GND.
A typical programming cable would then look like:
@multitable @columnfractions .15 .15 .3
@item @code{J8 pin} @tab @code{ISP pin} @tab @code{Name}
@item @code{21} @tab @code{1} @tab @code{MISO}
@item @code{-} @tab @code{2} @tab @code{Vcc - leave open}
@item @code{23} @tab @code{3} @tab @code{SCK}
@item @code{19} @tab @code{4} @tab @code{MOSI}
@item @code{22} @tab @code{5} @tab @code{/RESET}
@item @code{25} @tab @code{6} @tab @code{GND}
@end multitable
(Mind the 3.3 V voltage level of the Raspberry Pi!)
The @code{-P @var{portname}} option defaults to
@code{/dev/spidev0.0:/dev/gpiochip0} for this programmer.
The STK500, JTAG ICE, avr910, and avr109/butterfly use the serial port to communicate with the PC.
The STK600, JTAG ICE mkII/3, AVRISP mkII, USBasp, avrftdi (and derivatives), and USBtinyISP
The STK600, JTAG ICE mkII/3, AVRISP mkII, USBasp, avrftdi (and derivitives), and USBtinyISP
programmers communicate through the USB, using @code{libusb} as a
platform abstraction layer.
The avrftdi adds support for the FT2232C/D, FT2232H, and FT4232H devices. These all use
@@ -259,10 +216,7 @@ has a revision 1 hardware and firmware version of at least 5.37 (decimal).
The Atmel-ICE (ARM/AVR) is supported (JTAG, PDI for Xmega, debugWIRE, ISP modes).
Atmel's XplainedPro boards, using EDBG protocol (CMSIS-DAP compliant), are
supported by the ``jtag3'' programmer type.
Atmel's XplainedMini boards, using mEDBG protocol, are also
supported by the ``jtag3'' programmer type.
supported by teh ``jtag3'' programmer type.
The AVR Dragon is supported in all modes (ISP, JTAG, PDI, HVSP, PP, debugWire).
When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
@@ -277,16 +231,12 @@ option might be required to achieve a stable ISP communication.
For ATxmega devices, the AVR Dragon is supported in PDI mode, provided it
has a firmware version of at least 6.11 (decimal).
Wiring boards (e.g. Arduino Mega 2560 Rev3) are supported, utilizing
STK500 V2.x protocol, but a simple DTR/RTS toggle to set the boards
into programming mode. The programmer type is ``wiring''. Note that
the -D option will likely be required in this case, because the
bootloader will rewrite the program memory, but no true chip erase can
be performed.
Wiring boards are supported, utilizing STK500 V2.x protocol, but
a simple DTR/RTS toggle to set the boards into programming mode.
The programmer type is ``wiring''.
The Arduino (which is very similar to the STK500 1.x) is supported via
its own programmer type specification ``arduino''. This programmer works for
the Arduino Uno Rev3.
its own programmer type specification ``arduino''.
The BusPirate is a versatile tool that can also be used as an AVR programmer.
A single BusPirate can be connected to up to 3 independent AVRs. See
@@ -303,10 +253,6 @@ The Atmel DFU bootloader is supported in both, FLIP protocol version 1
(AT90USB* and ATmega*U* devices), as well as version 2 (Xmega devices).
See below for some hints about FLIP version 1 protocol behaviour.
The MPLAB(R) PICkit 4, MPLAB(R) SNAP, and Curiosity Nano boards are
supported in UPDI mode. The Curiosity Nano board is dubbed ``PICkit on
Board'', thus the name @code{pkobn_updi}.
@menu
* History::
@@ -593,29 +539,14 @@ As the AVRISP mkII device can only be talked to over USB, the very
same method of specifying the port is required there.
For the USB programmer "AVR-Doper" running in HID mode, the port must
be specified as @var{avrdoper}. Libhidapi support is required on Unix
and Mac OS but not on Windows. For more information about AVR-Doper see
be specified as @var{avrdoper}. Libusb support is required on Unix
but not on Windows. For more information about AVR-Doper see
@url{http://www.obdev.at/avrusb/avrdoper.html}.
For the USBtinyISP, which is a simplistic device not implementing
For the USBtinyISP, which is a simplicistic device not implementing
serial numbers, multiple devices can be distinguished by their
location in the USB hierarchy.
See the respective
@xref{Troubleshooting} entry for examples.
For the XBee programmer the target MCU is to be programmed wirelessly
over a ZigBee mesh using the XBeeBoot bootloader. The ZigBee 64-bit
address for the target MCU's own XBee device must be supplied as a
16-character hexadecimal value as a port prefix, followed by the
@code{@@} character, and the serial device to connect to a second
directly contactable XBee device associated with the same mesh (with
a default baud rate of 9600). This may look similar to:
@code{0013a20000000001@/dev/tty.serial}.
For diagnostic purposes, if the target MCU with an XBeeBoot
bootloader is connected directly to the serial port, the
64-bit address field can be omitted. In this mode the
default baud rate will be 19200.
@xref{Troubleshooting}, for examples.
For programmers that attach to a serial port using some kind of
higher level protocol (as opposed to bit-bang style programmers),
@@ -623,9 +554,6 @@ higher level protocol (as opposed to bit-bang style programmers),
In this case, instead of trying to open a local device, a TCP
network connection to (TCP) @var{port} on @var{host}
is established.
Square brackets may be placed around @var{host} to improve
readability for numeric IPv6 addresses (e.g.
@code{net:[2001:db8::42]:1337}).
The remote endpoint is assumed to be a terminal or console server
that connects the network stream to a local serial port where the
actual programmer has been attached to.
@@ -633,8 +561,6 @@ The port is assumed to be properly configured, for example using a
transparent 8-bit data connection without parity at 115200 Baud
for a STK500.
Note: The ability to handle IPv6 hostnames and addresses is limited to
Posix systems (by now).
@item -q
Disable (or quell) output of the progress bar while reading or writing
@@ -972,7 +898,7 @@ Connection to the PICkit2 programmer:
@item @code{OSI} @tab @code{AUX (6) }
@end multitable
Extended command line parameters:
Extended commandline parameters:
@table @code
@item @samp{clockrate=@var{rate}}
Sets the SPI clocking rate in Hz (default is 100kHz). Alternately the -B or -i options can be used to set the period.
@@ -980,32 +906,6 @@ Sets the SPI clocking rate in Hz (default is 100kHz). Alternately the -B or -i o
Sets the timeout for USB reads and writes in milliseconds (default is 1500 ms).
@end table
@item USBasp
Extended parameters:
@table @code
@item @samp{section_config}
Programmer will erase
configuration section with option '-e' (chip erase),
rather than entire chip.
Only applicable to TPI devices (ATtiny 4/5/9/10/20/40).
@end table
@item xbee
Extended parameters:
@table @code
@item @samp{xbeeresetpin=@var{1..7}}
Select the XBee pin @code{DIO<1..7>} that is connected to the MCU's
/RESET line. The programmer needs to know which DIO pin to use to
reset into the bootloader. The default (3) is the @code{DIO3} pin
(XBee pin 17), but some commercial products use a different XBee
pin.
The remaining two necessary XBee-to-MCU connections are not selectable
- the XBee @code{DOUT} pin (pin 2) must be connected to the MCU's
RXD line, and the XBee @code{DIN} pin (pin 3) must be connected to
the MCU's TXD line.
@end table
@end table
@page
@@ -1250,7 +1150,7 @@ Return to programming mode (from direct SPI mode).
Change (when @var{level} is provided), or display the verbosity
level.
The initial verbosity level is controlled by the number of @code{-v} options
given on the command line.
given on the commandline.
@item ?
@itemx help
@@ -1429,7 +1329,7 @@ programmer work with AVRDUDE.
AVRDUDE first looks for a system wide configuration file in a platform
dependent location. On Unix, this is usually
@code{/usr/local/etc/avrdude.conf}, while on Windows it is usually in the
@code{/usr/local/etc/avrdude.conf}, while on Windows it is usally in the
same location as the executable file. The name of this file can be
changed using the @option{-C} command line option. After the system wide
configuration file is parsed, AVRDUDE looks for a per-user configuration
@@ -1534,11 +1434,9 @@ Following programmer types are currently implemented:
part
id = <id> ; # quoted string
desc = <description> ; # quoted string
family_id = <description> ; # quoted string
has_jtag = <yes/no> ; # part has JTAG i/f
has_debugwire = <yes/no> ; # part has debugWire i/f
has_pdi = <yes/no> ; # part has PDI i/f
has_updi = <yes/no> ; # part has UPDI i/f
has_tpi = <yes/no> ; # part has TPI i/f
devicecode = <num> ; # numeric
stk500_devcode = <num> ; # numeric
@@ -1759,7 +1657,7 @@ flash pages of the application section.
Reading fuse and lock bits is fully supported.
Note that due to the inability to write the fuse bits, the safemode
Note that due to the unability to write the fuse bits, the safemode
functionality does not make sense for these boot loaders.
@end itemize
@@ -1944,7 +1842,7 @@ The default location of the install is into @code{/usr/local} so you
will need to be sure that @code{/usr/local/bin} is in your @code{PATH}
environment variable.
If you do not have root access to your system, you can do the
If you do not have root access to your system, you can do the the
following instead:
@example
@@ -1994,7 +1892,7 @@ obtained.
@subsubsection Linux Installation
@noindent
On rpm based Linux systems (such as RedHat, SUSE, Mandrake, etc.), you
On rpm based Linux systems (such as RedHat, SUSE, Mandrake, etc), you
can build and install the rpm binaries directly from the tarball:
@example
@@ -2488,7 +2386,7 @@ be added to the @var{-P usb} option, similar to adding a serial number
on other USB-based programmers.
The actual naming convention for the bus and device names is
operating-system dependent; AVRDUDE will print out what it found
operating-system dependant; AVRDUDE will print out what it found
on the bus when running it with (at least) one @var{-v} option.
By specifying a string that cannot match any existing device
(for example, @var{-P usb:xxx}), the scan will list all possible

View File

@@ -34,9 +34,7 @@
#elif defined(HAVE_LIBELF_LIBELF_H)
#include <libelf/libelf.h>
#endif
#ifndef EM_AVR32
# define EM_AVR32 0x18ad /* inofficial */
#endif
#define EM_AVR32 0x18ad /* inofficial */
#endif
#include "avrdude.h"
@@ -1172,7 +1170,7 @@ static int fileio_ihex(struct fioparms * fio,
break;
default:
avrdude_message(MSG_INFO, "%s: invalid Intel Hex file I/O operation=%d\n",
avrdude_message(MSG_INFO, "%s: invalid Intex Hex file I/O operation=%d\n",
progname, fio->op);
return -1;
break;

583
ft245r.c
View File

@@ -59,7 +59,6 @@
#include <sys/time.h>
#include <unistd.h>
#include <stdint.h>
#include <math.h>
#include "avrdude.h"
#include "libavrdude.h"
@@ -68,11 +67,6 @@
#include "ft245r.h"
#include "usbdevs.h"
#include "tpi.h"
#define TPIPCR_GT_0b 0x07
#define TPI_STOP_BITS 0x03
#if defined(_WIN32)
#include <windows.h>
#endif
@@ -92,7 +86,25 @@
#define DO_NOT_BUILD_FT245R
#endif
#if defined(DO_NOT_BUILD_FT245R)
#ifndef HAVE_PTHREAD_H
static int ft245r_nopthread_open (struct programmer_t *pgm, char * name) {
avrdude_message(MSG_INFO, "%s: error: no pthread support. Please compile again with pthread installed."
#if defined(_WIN32)
" See http://sourceware.org/pthreads-win32/."
#endif
"\n",
progname);
return -1;
}
void ft245r_initpgm(PROGRAMMER * pgm) {
strcpy(pgm->type, "ftdi_syncbb");
pgm->open = ft245r_nopthread_open;
}
#elif defined(DO_NOT_BUILD_FT245R)
static int ft245r_noftdi_open (struct programmer_t *pgm, char * name) {
avrdude_message(MSG_INFO, "%s: error: no libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.\n",
@@ -108,183 +120,102 @@ void ft245r_initpgm(PROGRAMMER * pgm) {
#else
#include <pthread.h>
#ifdef __APPLE__
/* Mac OS X defines sem_init but actually does not implement them */
#include <dispatch/dispatch.h>
typedef dispatch_semaphore_t sem_t;
#define sem_init(psem,x,val) *psem = dispatch_semaphore_create(val)
#define sem_post(psem) dispatch_semaphore_signal(*psem)
#define sem_wait(psem) dispatch_semaphore_wait(*psem, DISPATCH_TIME_FOREVER)
#else
#include <semaphore.h>
#endif
#define FT245R_CYCLES 2
#define FT245R_FRAGMENT_SIZE 512
#define REQ_OUTSTANDINGS 10
//#define USE_INLINE_WRITE_PAGE
#define FT245R_DEBUG 0
/*
Some revisions of the FTDI chips mess up the timing in bitbang mode
unless the bitclock is set to the max (3MHz). For example, see:
http://www.ftdichip.com/Support/Documents/TechnicalNotes/TN_120_FT232R%20Errata%20Technical%20Note.pdf
To work around this problem, set the macro below to 1 to always set
the bitclock to 3MHz and then issue the same byte repeatedly to get
the desired timing.
*/
#define FT245R_BITBANG_VARIABLE_PULSE_WIDTH_WORKAROUND 0
static struct ftdi_context *handle;
#if FT245R_BITBANG_VARIABLE_PULSE_WIDTH_WORKAROUND
static unsigned int baud_multiplier;
#else
# define baud_multiplier 1 // this let's C compiler optimize
#endif
static unsigned char ft245r_ddr;
static unsigned char ft245r_out;
static unsigned char ft245r_in;
#define FT245R_BUFSIZE 0x2000 // receive buffer size
#define FT245R_MIN_FIFO_SIZE 128 // min of FTDI RX/TX FIFO size
#define BUFSIZE 0x2000
static struct {
int len; // # of bytes in transmit buffer
uint8_t buf[FT245R_MIN_FIFO_SIZE]; // transmit buffer
} tx;
// libftdi / libftd2xx compatibility functions.
static struct {
int discard; // # of bytes to discard during read
int pending; // # of bytes that have been written since last read
int wr; // write pointer
int rd; // read pointer
uint8_t buf[FT245R_BUFSIZE]; // receive ring buffer
} rx;
static pthread_t readerthread;
static sem_t buf_data, buf_space;
static unsigned char buffer[BUFSIZE];
static int head, tail;
static int ft245r_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
unsigned char *res);
static int ft245r_tpi_tx(PROGRAMMER * pgm, uint8_t byte);
static int ft245r_tpi_rx(PROGRAMMER * pgm, uint8_t *bytep);
static void add_to_buf (unsigned char c) {
int nh;
// Discard all data from the receive buffer.
static void ft245r_rx_buf_purge(PROGRAMMER * pgm) {
rx.rd = rx.wr = 0;
}
sem_wait (&buf_space);
if (head == (BUFSIZE -1)) nh = 0;
else nh = head + 1;
static void ft245r_rx_buf_put(PROGRAMMER * pgm, uint8_t byte) {
rx.buf[rx.wr++] = byte;
if (rx.wr >= sizeof(rx.buf))
rx.wr = 0;
}
static uint8_t ft245r_rx_buf_get(PROGRAMMER * pgm) {
uint8_t byte = rx.buf[rx.rd++];
if (rx.rd >= sizeof(rx.buf))
rx.rd = 0;
return byte;
}
/* Fill receive buffer with data from the FTDI receive FIFO. */
static int ft245r_fill(PROGRAMMER * pgm) {
uint8_t raw[FT245R_MIN_FIFO_SIZE];
int i, nread;
nread = ftdi_read_data(handle, raw, rx.pending);
if (nread < 0)
return -1;
rx.pending -= nread;
#if FT245R_DEBUG
avrdude_message(MSG_INFO, "%s: read %d bytes (pending=%d)\n",
__func__, nread, rx.pending);
#endif
for (i = 0; i < nread; ++i)
ft245r_rx_buf_put(pgm, raw[i]);
return nread;
}
/* Flush pending TX data to the FTDI send FIFO. */
static int ft245r_flush(PROGRAMMER * pgm) {
int rv, len = tx.len, avail;
uint8_t *src = tx.buf;
if (!len)
return 0;
while (len > 0) {
avail = FT245R_MIN_FIFO_SIZE - rx.pending;
if (avail <= 0) {
avail = ft245r_fill(pgm);
if (avail < 0) {
avrdude_message(MSG_INFO,
"%s: fill returned %d: %s\n",
__func__, avail, ftdi_get_error_string(handle));
return -1;
}
}
if (avail > len)
avail = len;
#if FT245R_DEBUG
avrdude_message(MSG_INFO, "%s: writing %d bytes\n", __func__, avail);
#endif
rv = ftdi_write_data(handle, src, avail);
if (rv != avail) {
avrdude_message(MSG_INFO,
"%s: write returned %d (expected %d): %s\n",
__func__, rv, avail, ftdi_get_error_string(handle));
return -1;
}
src += avail;
len -= avail;
rx.pending += avail;
if (nh == tail) {
avrdude_message(MSG_INFO, "buffer overflow. Cannot happen!\n");
}
tx.len = 0;
return 0;
buffer[head] = c;
head = nh;
sem_post (&buf_data);
}
static int ft245r_send2(PROGRAMMER * pgm, unsigned char * buf, size_t len,
bool discard_rx_data) {
int i, j;
static void *reader (void *arg) {
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL);
struct ftdi_context *handle = (struct ftdi_context *)(arg);
unsigned char buf[0x1000];
int br, i;
for (i = 0; i < len; ++i) {
for (j = 0; j < baud_multiplier; ++j) {
if (discard_rx_data)
++rx.discard;
tx.buf[tx.len++] = buf[i];
if (tx.len >= FT245R_MIN_FIFO_SIZE)
ft245r_flush(pgm);
}
while (1) {
pthread_testcancel();
br = ftdi_read_data (handle, buf, sizeof(buf));
for (i=0; i<br; i++)
add_to_buf (buf[i]);
}
return 0;
return NULL;
}
static int ft245r_send(PROGRAMMER * pgm, unsigned char * buf, size_t len) {
return ft245r_send2(pgm, buf, len, false);
}
int rv;
static int ft245r_send_and_discard(PROGRAMMER * pgm, unsigned char * buf,
size_t len) {
return ft245r_send2(pgm, buf, len, true);
rv = ftdi_write_data(handle, buf, len);
if (len != rv) return -1;
return 0;
}
static int ft245r_recv(PROGRAMMER * pgm, unsigned char * buf, size_t len) {
int i, j;
int i;
ft245r_flush(pgm);
ft245r_fill(pgm);
#if FT245R_DEBUG
avrdude_message(MSG_INFO, "%s: discarding %d, consuming %zu bytes\n",
__func__, rx.discard, len);
#endif
while (rx.discard > 0) {
ft245r_rx_buf_get(pgm);
--rx.discard;
// Copy over data from the circular buffer..
// XXX This should timeout, and return error if there isn't enough
// data.
for (i=0; i<len; i++) {
sem_wait (&buf_data);
buf[i] = buffer[tail];
if (tail == (BUFSIZE -1)) tail = 0;
else tail++;
sem_post (&buf_space);
}
for (i = 0; i < len; ++i) {
buf[i] = ft245r_rx_buf_get(pgm);
for (j = 1; j < baud_multiplier; ++j)
ft245r_rx_buf_get(pgm);
}
return 0;
}
static int ft245r_drain(PROGRAMMER * pgm, int display) {
int r;
unsigned char t;
// flush the buffer in the chip by changing the mode.....
r = ftdi_set_bitmode(handle, 0, BITMODE_RESET); // reset
@@ -293,25 +224,17 @@ static int ft245r_drain(PROGRAMMER * pgm, int display) {
if (r) return -1;
// drain our buffer.
ft245r_rx_buf_purge(pgm);
while (head != tail) {
ft245r_recv (pgm, &t, 1);
}
return 0;
}
/* Ensure any pending writes are sent to the FTDI chip before sleeping. */
static void ft245r_usleep(PROGRAMMER * pgm, useconds_t usec) {
ft245r_flush(pgm);
usleep(usec);
}
static int ft245r_chip_erase(PROGRAMMER * pgm, AVRPART * p) {
unsigned char cmd[4] = {0,0,0,0};
unsigned char res[4];
if (p->flags & AVRPART_HAS_TPI)
return avr_tpi_chip_erase(pgm, p);
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
avrdude_message(MSG_INFO, "chip erase instruction not defined for part \"%s\"\n",
p->desc);
@@ -320,38 +243,29 @@ static int ft245r_chip_erase(PROGRAMMER * pgm, AVRPART * p) {
avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
pgm->cmd(pgm, cmd, res);
ft245r_usleep(pgm, p->chip_erase_delay);
usleep(p->chip_erase_delay);
return pgm->initialize(pgm, p);
}
static int ft245r_set_bitclock(PROGRAMMER * pgm) {
// libftdi1 multiplies bitbang baudrate by 4:
int r, rate = 0, ftdi_rate = 3000000 / 4;
int r;
int rate = 0;
/* bitclock is second. 1us = 0.000001. Max rate for ft232r 750000 */
if(pgm->bitclock) {
rate = (uint32_t)(1.0/pgm->bitclock);
rate = (uint32_t)(1.0/pgm->bitclock) * 2;
} else if (pgm->baudrate) {
rate = pgm->baudrate;
rate = pgm->baudrate * 2;
} else {
rate = 150000; /* should work for all ftdi chips and the avr default internal clock of 1MHz */
}
#if FT245R_BITBANG_VARIABLE_PULSE_WIDTH_WORKAROUND
if (rate > 0 && rate < ftdi_rate)
baud_multiplier = round((ftdi_rate + rate - 1) / rate);
else
baud_multiplier = 1;
#else
ftdi_rate = rate;
#endif
avrdude_message(MSG_NOTICE2,
"%s: bitclk %d -> FTDI rate %d, baud multiplier %d\n",
__func__, rate, ftdi_rate, baud_multiplier);
r = ftdi_set_baudrate(handle, ftdi_rate);
if (FT245R_DEBUG) {
avrdude_message(MSG_NOTICE2, " ft245r: spi bitclk %d -> ft baudrate %d\n",
rate / 2, rate);
}
r = ftdi_set_baudrate(handle, rate);
if (r) {
avrdude_message(MSG_INFO, "Set baudrate (%d) failed with error '%s'.\n",
rate, ftdi_get_error_string (handle));
@@ -360,18 +274,6 @@ static int ft245r_set_bitclock(PROGRAMMER * pgm) {
return 0;
}
static int get_pin(PROGRAMMER *pgm, int pinname) {
uint8_t byte;
ft245r_flush(pgm);
if (ftdi_read_pins(handle, &byte) != 0)
return -1;
if (FT245R_DEBUG)
avrdude_message(MSG_INFO, "%s: in 0x%02x\n", __func__, byte);
return GET_BITS_0(byte, pgm, pinname) != 0;
}
static int set_pin(PROGRAMMER * pgm, int pinname, int val) {
unsigned char buf[1];
@@ -383,7 +285,10 @@ static int set_pin(PROGRAMMER * pgm, int pinname, int val) {
ft245r_out = SET_BITS_0(ft245r_out,pgm,pinname,val);
buf[0] = ft245r_out;
ft245r_send_and_discard(pgm, buf, 1);
ft245r_send (pgm, buf, 1);
ft245r_recv (pgm, buf, 1);
ft245r_in = buf[0];
return 0;
}
@@ -428,7 +333,7 @@ static int set_led_vfy(struct programmer_t * pgm, int value) {
static void ft245r_powerup(PROGRAMMER * pgm)
{
set_vcc(pgm, ON); /* power up */
ft245r_usleep(pgm, 100);
usleep(100);
}
@@ -458,10 +363,12 @@ static void ft245r_enable(PROGRAMMER * pgm) {
* and not via the buffer chip.
*/
set_reset(pgm, OFF);
ft245r_usleep(pgm, 1);
usleep(1);
set_buff(pgm, ON);
}
static int ft245r_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
unsigned char *res);
/*
* issue the 'program enable' command to the AVR device
*/
@@ -470,9 +377,6 @@ static int ft245r_program_enable(PROGRAMMER * pgm, AVRPART * p) {
unsigned char res[4];
int i;
if (p->flags & AVRPART_HAS_TPI)
return avr_tpi_program_enable(pgm, p, TPIPCR_GT_0b);
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
avrdude_message(MSG_INFO, "%s: AVR_OP_PGM_ENABLE command not defined for %s\n",
progname, p->desc);
@@ -493,12 +397,12 @@ static int ft245r_program_enable(PROGRAMMER * pgm, AVRPART * p) {
fflush(stderr);
}
set_pin(pgm, PIN_AVR_RESET, ON);
ft245r_usleep(pgm, 20);
usleep(20);
set_pin(pgm, PIN_AVR_RESET, OFF);
if (i == 3) {
ft245r_drain(pgm, 0);
ft245r_rx_buf_purge(pgm);
tail = head;
}
}
@@ -523,83 +427,35 @@ static int ft245r_initialize(PROGRAMMER * pgm, AVRPART * p) {
ft245r_powerup(pgm);
set_reset(pgm, OFF);
ft245r_usleep(pgm, 5000); // 5ms
usleep(5000); // 5ms
set_reset(pgm, ON);
ft245r_usleep(pgm, 5000); // 5ms
usleep(5000); // 5ms
set_reset(pgm, OFF);
/* Wait for at least 20 ms and enable serial programming by sending the Programming
* Enable serial instruction to pin MOSI.
*/
ft245r_usleep(pgm, 20000); // 20ms
usleep(20000); // 20ms
if (p->flags & AVRPART_HAS_TPI) {
bool io_link_ok = true;
uint8_t byte;
int i;
/* Since there is a single TPIDATA line, MOSI and MISO must be
linked together through a 1kOhm resistor. Verify that
everything we send on MOSI gets mirrored back on MISO. */
set_pin(pgm, PIN_AVR_MOSI, 0);
if (get_pin(pgm, PIN_AVR_MISO) != 0) {
io_link_ok = false;
avrdude_message(MSG_INFO, "MOSI->MISO 0 failed\n");
if (!ovsigck)
return -1;
}
set_pin(pgm, PIN_AVR_MOSI, 1);
if (get_pin(pgm, PIN_AVR_MISO) != 1) {
io_link_ok = false;
avrdude_message(MSG_INFO, "MOSI->MISO 1 failed\n");
if (!ovsigck)
return -1;
}
if (io_link_ok)
avrdude_message(MSG_NOTICE2, "MOSI-MISO link present\n");
/* keep TPIDATA high for 16 clock cycles */
set_pin(pgm, PIN_AVR_MOSI, 1);
for (i = 0; i < 16; i++) {
set_sck(pgm, 1);
set_sck(pgm, 0);
}
/* remove extra guard timing bits */
ft245r_tpi_tx(pgm, TPI_CMD_SSTCS | TPI_REG_TPIPCR);
ft245r_tpi_tx(pgm, 0x7);
/* read TPI ident reg */
ft245r_tpi_tx(pgm, TPI_CMD_SLDCS | TPI_REG_TPIIR);
ft245r_tpi_rx(pgm, &byte);
if (byte != 0x80) {
avrdude_message(MSG_INFO, "TPIIR 0x%02x not correct\n", byte);
return -1;
}
}
return ft245r_program_enable(pgm, p);
}
static inline void add_bit(PROGRAMMER * pgm, unsigned char *buf, int *buf_pos,
uint8_t bit) {
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_MOSI, bit);
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0);
buf[*buf_pos] = ft245r_out;
(*buf_pos)++;
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,1);
buf[*buf_pos] = ft245r_out;
(*buf_pos)++;
}
static inline int set_data(PROGRAMMER * pgm, unsigned char *buf, unsigned char data) {
int j;
int buf_pos = 0;
unsigned char bit = 0x80;
for (j=0; j<8; j++) {
add_bit(pgm, buf, &buf_pos, (data & bit) != 0);
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_MOSI,data & bit);
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0);
buf[buf_pos] = ft245r_out;
buf_pos++;
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,1);
buf[buf_pos] = ft245r_out;
buf_pos++;
bit >>= 1;
}
return buf_pos;
@@ -607,8 +463,7 @@ static inline int set_data(PROGRAMMER * pgm, unsigned char *buf, unsigned char d
static inline unsigned char extract_data(PROGRAMMER * pgm, unsigned char *buf, int offset) {
int j;
int buf_pos = FT245R_CYCLES; /* MISO data is valid AFTER rising SCK edge,
i.e. in next clock cycle */
int buf_pos = 1;
unsigned char bit = 0x80;
unsigned char r = 0;
@@ -624,7 +479,6 @@ static inline unsigned char extract_data(PROGRAMMER * pgm, unsigned char *buf, i
}
/* to check data */
#if 0
static inline unsigned char extract_data_out(PROGRAMMER * pgm, unsigned char *buf, int offset) {
int j;
int buf_pos = 1;
@@ -641,7 +495,6 @@ static inline unsigned char extract_data_out(PROGRAMMER * pgm, unsigned char *bu
}
return r;
}
#endif
/*
@@ -670,122 +523,6 @@ static int ft245r_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
return 0;
}
static inline uint8_t extract_tpi_data(PROGRAMMER * pgm, unsigned char *buf,
int *buf_pos) {
uint8_t bit = 0x1, byte = 0;
int j;
for (j = 0; j < 8; j++) {
(*buf_pos)++; // skip over falling clock edge
if (GET_BITS_0(buf[(*buf_pos)++], pgm, PIN_AVR_MISO))
byte |= bit;
bit <<= 1;
}
return byte;
}
static inline int set_tpi_data(PROGRAMMER * pgm, unsigned char *buf,
uint8_t byte) {
uint8_t bit = 0x1, parity = 0;
int j, buf_pos = 0;
// start bit:
add_bit(pgm, buf, &buf_pos, 0);
// 8 data bits:
for (j = 0; j < 8; j++) {
add_bit(pgm, buf, &buf_pos, (byte & bit) != 0);
parity ^= (byte & bit) != 0;
bit <<= 1;
}
// parity bit:
add_bit(pgm, buf, &buf_pos, parity);
// stop bits:
add_bit(pgm, buf, &buf_pos, 1);
add_bit(pgm, buf, &buf_pos, 1);
return buf_pos;
}
static int ft245r_tpi_tx(PROGRAMMER * pgm, uint8_t byte) {
uint8_t buf[128];
int len;
len = set_tpi_data(pgm, buf, byte);
ft245r_send_and_discard(pgm, buf, len);
return 0;
}
static int ft245r_tpi_rx(PROGRAMMER * pgm, uint8_t *bytep) {
uint8_t buf[128], bit, parity;
int i, buf_pos = 0, len = 0;
uint32_t res, m, byte;
/* Allow for up to 4 bits before we must see start bit; during
that time, we must keep the MOSI line high. */
for (i = 0; i < 2; ++i)
len += set_data(pgm, &buf[len], 0xff);
ft245r_send(pgm, buf, len);
ft245r_recv(pgm, buf, len);
res = (extract_tpi_data(pgm, buf, &buf_pos)
| ((uint32_t) extract_tpi_data(pgm, buf, &buf_pos) << 8));
/* Look for start bit: */
m = 0x1;
while (m & res)
m <<= 1;
if (m >= 0x10) {
avrdude_message(MSG_INFO, "%s: start bit missing (res=0x%04x)\n",
__func__, res);
return -1;
}
byte = parity = 0;
for (i = 0; i < 8; ++i) {
m <<= 1;
bit = (res & m) != 0;
parity ^= bit;
byte |= bit << i;
}
m <<= 1;
if (((res & m) != 0) != parity) {
avrdude_message(MSG_INFO, "%s: parity bit wrong\n", __func__);
return -1;
}
if (((res & (m << 1)) == 0) || ((res & (m << 2))) == 0) {
avrdude_message(MSG_INFO, "%s: stop bits wrong\n", __func__);
return -1;
}
*bytep = (uint8_t) byte;
return 0;
}
static int ft245r_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd,
int cmd_len, unsigned char *res, int res_len) {
int i, ret = 0;
pgm->pgm_led(pgm, ON);
for (i = 0; i < cmd_len; ++i)
ft245r_tpi_tx(pgm, cmd[i]);
for (i = 0; i < res_len; ++i)
if ((ret = ft245r_tpi_rx(pgm, &res[i])) < 0)
break;
if (verbose >= 2) {
avrdude_message(MSG_NOTICE2, "%s: [ ", __func__);
for (i = 0; i < cmd_len; i++)
avrdude_message(MSG_NOTICE2, "%02X ", cmd[i]);
avrdude_message(MSG_NOTICE2, "] [ ");
for(i = 0; i < res_len; i++)
avrdude_message(MSG_NOTICE2, "%02X ", res[i]);
avrdude_message(MSG_NOTICE2, "]\n");
}
pgm->pgm_led(pgm, OFF);
return ret;
}
/* lower 8 pins are accepted, they might be also inverted */
static const struct pindef_t valid_pins = {{0xff},{0xff}} ;
@@ -800,10 +537,8 @@ static const struct pin_checklist_t pin_checklist[] = {
static int ft245r_open(PROGRAMMER * pgm, char * port) {
int rv;
int devnum = -1;
char device[9] = "";
rv = pins_check(pgm,pin_checklist,sizeof(pin_checklist)/sizeof(pin_checklist[0]), true);
if(rv) {
pgm->display(pgm, progbuf);
return rv;
@@ -811,47 +546,22 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) {
strcpy(pgm->port, port);
// read device string cut after 8 chars (max. length of serial number)
if ((sscanf(port, "usb:%8s", device) != 1)) {
avrdude_message(MSG_NOTICE,
"%s: ft245r_open(): no device identifier in portname, using default\n",
progname);
pgm->usbsn[0] = 0;
devnum = 0;
if (strcmp(port,DEFAULT_USB) != 0) {
if (strncasecmp("ft", port, 2) == 0) {
char *startptr = port + 2;
char *endptr = NULL;
devnum = strtol(startptr,&endptr,10);
if ((startptr==endptr) || (*endptr != '\0')) {
devnum = -1;
}
}
if (devnum < 0) {
avrdude_message(MSG_INFO, "%s: invalid portname '%s': use 'ft[0-9]+'\n",
progname,port);
return -1;
}
} else {
if (strlen(device) == 8 ){ // serial number
if (verbose >= 2) {
avrdude_message(MSG_INFO,
"%s: ft245r_open(): serial number parsed as: "
"%s\n",
progname,
device);
}
// copy serial number to pgm struct
strcpy(pgm->usbsn, device);
// and use first device with matching serial (should be unique)
devnum = 0;
}
else if (strncmp("ft", device, 2) || strlen(device) <= 8) { // classic device number
char *startptr = device + 2;
char *endptr = NULL;
devnum = strtol(startptr,&endptr,10);
if ((startptr==endptr) || (*endptr != '\0')) {
devnum = -1;
}
avrdude_message(MSG_INFO,
"%s: ft245r_open(): device number parsed as: "
"%d\n",
progname,
devnum);
}
}
// if something went wrong before abort with helpful message
if (devnum < 0) {
avrdude_message(MSG_INFO, "%s: ft245r_open(): invalid portname '%s': use^ 'ft[0-9]+' or serial number\n",
progname,port);
return -1;
}
handle = malloc (sizeof (struct ftdi_context));
@@ -873,8 +583,7 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) {
pgm->usbsn[0]?pgm->usbsn:NULL,
devnum);
if (rv) {
avrdude_message(MSG_INFO, "%s: can't open ftdi device: %s\n",
progname, ftdi_get_error_string(handle));
avrdude_message(MSG_INFO, "can't open ftdi device %d. (%s)\n", devnum, ftdi_get_error_string(handle));
goto cleanup_no_usb;
}
@@ -902,13 +611,6 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) {
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_VFY,0);
rv = ftdi_set_latency_timer(handle, 1);
if (rv) {
avrdude_message(MSG_INFO, "%s: unable to set latency timer to 1 (%s)\n",
progname, ftdi_get_error_string(handle));
goto cleanup;
}
rv = ftdi_set_bitmode(handle, ft245r_ddr, BITMODE_SYNCBB); // set Synchronous BitBang
if (rv) {
avrdude_message(MSG_INFO, "%s: Synchronous BitBangMode is not supported (%s)\n",
@@ -921,12 +623,22 @@ static int ft245r_open(PROGRAMMER * pgm, char * port) {
goto cleanup;
}
/* We start a new thread to read the output from the FTDI. This is
* necessary because otherwise we'll deadlock. We cannot finish
* writing because the ftdi cannot send the results because we
* haven't provided a read buffer yet. */
sem_init (&buf_data, 0, 0);
sem_init (&buf_space, 0, BUFSIZE);
pthread_create (&readerthread, NULL, reader, handle);
/*
* drain any extraneous input
*/
ft245r_drain (pgm, 0);
ft245r_send_and_discard(pgm, &ft245r_out, 1);
ft245r_send (pgm, &ft245r_out, 1);
ft245r_recv (pgm, &ft245r_in, 1);
return 0;
@@ -947,6 +659,8 @@ static void ft245r_close(PROGRAMMER * pgm) {
ftdi_set_bitmode(handle, 0, BITMODE_RESET); // disable Synchronous BitBang
ftdi_usb_close(handle);
ftdi_deinit (handle);
pthread_cancel(readerthread);
pthread_join(readerthread, NULL);
free(handle);
handle = NULL;
}
@@ -1096,11 +810,6 @@ static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down
buf[buf_pos++] = ft245r_out;
}
else {
/* stretch sequence to allow correct readout, see extract_data() */
buf[buf_pos] = buf[buf_pos - 1];
buf_pos++;
}
ft245r_send(pgm, buf, buf_pos);
put_request(addr_save, buf_pos, 0);
//ft245r_sync(pgm);
@@ -1118,7 +827,7 @@ static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
#if defined(USE_INLINE_WRITE_PAGE)
while (do_request(pgm, m))
;
ft245r_usleep(pgm, m->max_write_delay);
usleep(m->max_write_delay);
#else
int addr_wk = addr_save - (addr_save % m->page_size);
int rc;
@@ -1190,11 +899,6 @@ static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down
buf[buf_pos++] = ft245r_out;
}
else {
/* stretch sequence to allow correct readout, see extract_data() */
buf[buf_pos] = buf[buf_pos - 1];
buf_pos++;
}
n = j;
ft245r_send(pgm, buf, buf_pos);
put_request(addr_save, buf_pos, n);
@@ -1233,7 +937,6 @@ void ft245r_initpgm(PROGRAMMER * pgm) {
pgm->program_enable = ft245r_program_enable;
pgm->chip_erase = ft245r_chip_erase;
pgm->cmd = ft245r_cmd;
pgm->cmd_tpi = ft245r_cmd_tpi;
pgm->open = ft245r_open;
pgm->close = ft245r_close;
pgm->read_byte = avr_read_byte_default;

625
jtag3.c
View File

@@ -30,7 +30,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
@@ -85,7 +84,6 @@ struct pdata
#define PGM_FL_IS_PDI (0x0002)
#define PGM_FL_IS_JTAG (0x0004)
#define PGM_FL_IS_EDBG (0x0008)
#define PGM_FL_IS_UPDI (0x0010)
static int jtag3_open(PROGRAMMER * pgm, char * port);
static int jtag3_edbg_prepare(PROGRAMMER * pgm);
@@ -162,11 +160,6 @@ u16_to_b2(unsigned char *b, unsigned short l)
b[1] = (l >> 8) & 0xff;
}
static bool matches(const char *s, const char *pat)
{
return strncmp(s, pat, strlen(pat)) == 0;
}
static void jtag3_print_data(unsigned char *b, size_t s)
{
int i;
@@ -453,66 +446,39 @@ static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
avrdude_message(MSG_DEBUG, "\n%s: jtag3_edbg_send(): sending %lu bytes\n",
progname, (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)
if (len + 8 > USBDEV_MAX_XFER_3)
{
avrdude_message(MSG_DEBUG, "%s: jtag3_edbg_send(): fragmenting into %d packets\n",
progname, nfragments);
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Fragmentation not (yet) implemented!\n",
progname);
return -1;
}
int frag;
for (frag = 0; frag < nfragments; frag++)
buf[0] = EDBG_VENDOR_AVR_CMD;
buf[1] = (1 << 4) | 1; /* first out of a total of 1 fragments */
buf[2] = (len + 4) >> 8;
buf[3] = (len + 4) & 0xff;
buf[4] = TOKEN;
buf[5] = 0; /* dummy */
u16_to_b2(buf + 6, PDATA(pgm)->command_sequence);
memcpy(buf + 8, data, len);
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): failed to send command to serial port\n",
progname);
return -1;
}
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
if (rv < 0) {
/* timeout in receive */
avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_send(): Timeout receiving packet\n",
progname);
return -1;
}
if (status[0] != EDBG_VENDOR_AVR_CMD || status[1] != 0x01)
{
int this_len;
/* All fragments have the (CMSIS-DAP layer) CMD, the fragment
* identifier, and the length field. */
buf[0] = EDBG_VENDOR_AVR_CMD;
buf[1] = ((frag + 1) << 4) | nfragments;
if (frag == 0)
{
/* Only first fragment has TOKEN and seq#, thus four bytes
* less payload than subsequent fragments. */
this_len = len < max_xfer - 8? len: max_xfer - 8;
buf[2] = (this_len + 4) >> 8;
buf[3] = (this_len + 4) & 0xff;
buf[4] = TOKEN;
buf[5] = 0; /* dummy */
u16_to_b2(buf + 6, PDATA(pgm)->command_sequence);
memcpy(buf + 8, data, this_len);
}
else
{
this_len = len < max_xfer - 4? len: max_xfer - 4;
buf[2] = (this_len) >> 8;
buf[3] = (this_len) & 0xff;
memcpy(buf + 4, data, this_len);
}
if (serial_send(&pgm->fd, buf, max_xfer) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): failed to send command to serial port\n",
progname);
return -1;
}
rv = serial_recv(&pgm->fd, status, max_xfer);
if (rv < 0) {
/* timeout in receive */
avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_send(): Timeout receiving packet\n",
progname);
return -1;
}
if (status[0] != EDBG_VENDOR_AVR_CMD ||
(frag == nfragments - 1 && status[1] != 0x01))
{
/* what to do in this case? */
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n",
progname, status[0], status[1]);
}
data += this_len;
len -= this_len;
/* what to do in this case? */
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n",
progname, status[0], status[1]);
}
return 0;
@@ -535,13 +501,13 @@ static int jtag3_edbg_prepare(PROGRAMMER * pgm)
buf[0] = CMSISDAP_CMD_CONNECT;
buf[1] = CMSISDAP_CONN_SWD;
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to send command to serial port\n",
progname);
return -1;
}
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) {
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
if (rv != USBDEV_MAX_XFER_3) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to read from serial port (%d)\n",
progname, rv);
return -1;
@@ -556,13 +522,13 @@ static int jtag3_edbg_prepare(PROGRAMMER * pgm)
buf[0] = CMSISDAP_CMD_LED;
buf[1] = CMSISDAP_LED_CONNECT;
buf[2] = 1;
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to send command to serial port\n",
progname);
return -1;
}
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) {
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
if (rv != USBDEV_MAX_XFER_3) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_prepare(): failed to read from serial port (%d)\n",
progname, rv);
return -1;
@@ -594,13 +560,13 @@ static int jtag3_edbg_signoff(PROGRAMMER * pgm)
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) {
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
progname);
return -1;
}
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) {
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
if (rv != USBDEV_MAX_XFER_3) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
progname, rv);
return -1;
@@ -611,13 +577,13 @@ static int jtag3_edbg_signoff(PROGRAMMER * pgm)
progname, status[0], status[1]);
buf[0] = CMSISDAP_CMD_DISCONNECT;
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
progname);
return -1;
}
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) {
rv = serial_recv(&pgm->fd, status, USBDEV_MAX_XFER_3);
if (rv != USBDEV_MAX_XFER_3) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
progname, rv);
return -1;
@@ -678,9 +644,8 @@ static int jtag3_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
}
static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
int rv, len = 0;
int rv, len;
unsigned char *buf = NULL;
unsigned char *request;
avrdude_message(MSG_TRACE, "%s: jtag3_edbg_recv():\n", progname);
@@ -689,105 +654,42 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
progname);
return -1;
}
if ((request = malloc(pgm->fd.usb.max_xfer)) == NULL) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): out of memory\n",
progname);
buf[0] = EDBG_VENDOR_AVR_RSP;
if (serial_send(&pgm->fd, buf, USBDEV_MAX_XFER_3) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n",
progname);
return -1;
}
rv = serial_recv(&pgm->fd, buf, USBDEV_MAX_XFER_3);
if (rv < 0) {
/* timeout in receive */
avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_recv(): Timeout receiving packet\n",
progname);
free(buf);
return -1;
}
if (buf[0] != EDBG_VENDOR_AVR_RSP ||
buf[1] != ((1 << 4) | 1)) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected response 0x%02x, 0x%02x\n",
progname, buf[0], buf[1]);
return -1;
}
/* calculate length from response; CMSIS-DAP response might be larger */
len = (buf[2] << 8) | buf[3];
if (len > rv + 4) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected length value (%d > %d)\n",
progname, len, rv + 4);
len = rv + 4;
}
memmove(buf, buf + 4, len);
*msg = buf;
int nfrags = 0;
int thisfrag = 0;
do {
request[0] = EDBG_VENDOR_AVR_RSP;
if (serial_send(&pgm->fd, request, pgm->fd.usb.max_xfer) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n",
progname);
free(request);
free(*msg);
return -1;
}
rv = serial_recv(&pgm->fd, buf, pgm->fd.usb.max_xfer);
if (rv < 0) {
/* timeout in receive */
avrdude_message(MSG_NOTICE2, "%s: jtag3_edbg_recv(): Timeout receiving packet\n",
progname);
free(*msg);
free(request);
return -1;
}
if (buf[0] != EDBG_VENDOR_AVR_RSP) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected response 0x%02x\n",
progname, buf[0]);
free(*msg);
free(request);
return -1;
}
if (buf[1] == 0) {
// Documentation says:
// "FragmentInfo 0x00 indicates that no response data is
// available, and the rest of the packet is ignored."
avrdude_message(MSG_INFO,
"%s: jtag3_edbg_recv(): "
"No response available\n",
progname);
free(*msg);
free(request);
return -1;
}
/* calculate fragment information */
if (thisfrag == 0) {
/* first fragment */
nfrags = buf[1] & 0x0F;
thisfrag = 1;
} else {
if (nfrags != (buf[1] & 0x0F)) {
avrdude_message(MSG_INFO,
"%s: jtag3_edbg_recv(): "
"Inconsistent # of fragments; had %d, now %d\n",
progname, nfrags, (buf[1] & 0x0F));
free(*msg);
free(request);
return -1;
}
}
if (thisfrag != ((buf[1] >> 4) & 0x0F)) {
avrdude_message(MSG_INFO,
"%s: jtag3_edbg_recv(): "
"Inconsistent fragment number; expect %d, got %d\n",
progname, thisfrag, ((buf[1] >> 4) & 0x0F));
free(*msg);
free(request);
return -1;
}
int thislen = (buf[2] << 8) | buf[3];
if (thislen > rv + 4) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected length value (%d > %d)\n",
progname, thislen, rv + 4);
thislen = rv + 4;
}
if (len + thislen > USBDEV_MAX_XFER_3) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Length exceeds max size (%d > %d)\n",
progname, len + thislen, USBDEV_MAX_XFER_3);
thislen = USBDEV_MAX_XFER_3 - len;
}
memmove(buf, buf + 4, thislen);
thisfrag++;
len += thislen;
buf += thislen;
} while (thisfrag <= nfrags);
free(request);
return len;
}
@@ -859,18 +761,11 @@ int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) {
c = (*resp)[1];
if ((c & RSP3_STATUS_MASK) != RSP3_OK) {
if ((c == RSP3_FAILED) && ((*resp)[3] == RSP3_FAIL_OCD_LOCKED)) {
avrdude_message(MSG_INFO,
"%s: Device is locked! Chip erase required to unlock.\n",
progname);
} else {
avrdude_message(MSG_INFO, "%s: bad response to %s command: 0x%02x\n",
progname, descr, c);
}
status = (*resp)[3];
avrdude_message(MSG_INFO, "%s: bad response to %s command: 0x%02x\n",
progname, descr, c);
free(*resp);
resp = 0;
return -status;
return -1;
}
return status;
@@ -883,13 +778,9 @@ int jtag3_getsync(PROGRAMMER * pgm, int mode) {
avrdude_message(MSG_DEBUG, "%s: jtag3_getsync()\n", progname);
/* XplainedMini boards do not need this, and early revisions had a
* firmware bug where they complained about it. */
if ((pgm->flag & PGM_FL_IS_EDBG) &&
!matches(ldata(lfirst(pgm->id)), "xplainedmini")) {
if (jtag3_edbg_prepare(pgm) < 0) {
return -1;
}
if (pgm->flag & PGM_FL_IS_EDBG) {
if (jtag3_edbg_prepare(pgm) < 0)
return -1;
}
/* Get the sign-on information. */
@@ -925,34 +816,6 @@ static int jtag3_chip_erase(PROGRAMMER * pgm, AVRPART * p)
return 0;
}
/*
* UPDI 'unlock' -> 'enter progmode' with chip erase key
*/
static int jtag3_unlock_erase_key(PROGRAMMER * pgm, AVRPART * p)
{
unsigned char buf[8], *resp;
buf[0] = 1; /* Enable */
if (jtag3_setparm(pgm, SCOPE_AVR, SET_GET_CTXT_OPTIONS, PARM3_OPT_CHIP_ERASE_TO_ENTER, buf, 1) < 0)
return -1;
buf[0] = SCOPE_AVR;
buf[1] = CMD3_ENTER_PROGMODE;
buf[2] = 0;
if (jtag3_command(pgm, buf, 3, &resp, "enter progmode") < 0)
return -1;
PDATA(pgm)->prog_enabled = 1;
buf[0] = 0; /* Disable */
if (jtag3_setparm(pgm, SCOPE_AVR, SET_GET_CTXT_OPTIONS, PARM3_OPT_CHIP_ERASE_TO_ENTER, buf, 1) < 0)
return -1;
free(resp);
return 0;
}
/*
* There is no chip erase functionality in debugWire mode.
*/
@@ -973,7 +836,6 @@ static int jtag3_program_enable_dummy(PROGRAMMER * pgm, AVRPART * p)
static int jtag3_program_enable(PROGRAMMER * pgm)
{
unsigned char buf[3], *resp;
int status;
if (PDATA(pgm)->prog_enabled)
return 0;
@@ -982,14 +844,14 @@ static int jtag3_program_enable(PROGRAMMER * pgm)
buf[1] = CMD3_ENTER_PROGMODE;
buf[2] = 0;
if ((status = jtag3_command(pgm, buf, 3, &resp, "enter progmode")) >= 0) {
if (jtag3_command(pgm, buf, 3, &resp, "enter progmode") >= 0) {
free(resp);
PDATA(pgm)->prog_enabled = 1;
return 0;
}
return status;
return -1;
}
static int jtag3_program_disable(PROGRAMMER * pgm)
@@ -1074,10 +936,6 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
ifname = "PDI";
if (p->flags & AVRPART_HAS_PDI)
conn = PARM3_CONN_PDI;
} else if (pgm->flag & PGM_FL_IS_UPDI) {
ifname = "UPDI";
if (p->flags & AVRPART_HAS_UPDI)
conn = PARM3_CONN_UPDI;
} else {
ifname = "JTAG";
if (p->flags & AVRPART_HAS_JTAG)
@@ -1092,8 +950,6 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
if (p->flags & AVRPART_HAS_PDI)
parm[0] = PARM3_ARCH_XMEGA;
else if (p->flags & AVRPART_HAS_UPDI)
parm[0] = PARM3_ARCH_UPDI;
else if (p->flags & AVRPART_HAS_DW)
parm[0] = PARM3_ARCH_TINY;
else
@@ -1109,7 +965,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
if (jtag3_setparm(pgm, SCOPE_AVR, 1, PARM3_CONNECTION, parm, 1) < 0)
return -1;
if (conn == PARM3_CONN_PDI || conn == PARM3_CONN_UPDI)
if (conn == PARM3_CONN_PDI)
PDATA(pgm)->set_sck = jtag3_set_sck_xmega_pdi;
else if (conn == PARM3_CONN_JTAG) {
if (p->flags & AVRPART_HAS_PDI)
@@ -1171,7 +1027,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
u32_to_b4(xd.nvm_boot_offset, m->offset);
} else if (strcmp(m->desc, "fuse1") == 0) {
u32_to_b4(xd.nvm_fuse_offset, m->offset & ~7);
} else if (matches(m->desc, "lock")) {
} else if (strncmp(m->desc, "lock", 4) == 0) {
u32_to_b4(xd.nvm_lock_offset, m->offset);
} else if (strcmp(m->desc, "usersig") == 0) {
u32_to_b4(xd.nvm_user_sig_offset, m->offset);
@@ -1185,99 +1041,6 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0)
return -1;
}
else if ((p->flags & AVRPART_HAS_UPDI))
{
struct updi_device_desc xd;
LNODEID ln;
AVRMEM *m;
u16_to_b2(xd.nvm_base_addr, p->nvm_base);
u16_to_b2(xd.ocd_base_addr, p->ocd_base);
for (ln = lfirst(p->mem); ln; ln = lnext(ln))
{
m = ldata(ln);
if (strcmp(m->desc, "flash") == 0)
{
u16_to_b2(xd.prog_base, m->offset&0xFFFF);
xd.prog_base_msb = m->offset>>16;
if (m->readsize != 0 && m->readsize < m->page_size)
PDATA(pgm)->flash_pagesize = m->readsize;
else
PDATA(pgm)->flash_pagesize = m->page_size;
xd.flash_page_size = m->page_size & 0xFF;
xd.flash_page_size_msb = (m->page_size)>>8;
u32_to_b4(xd.flash_bytes, m->size);
if (m->offset > 0xFFFF)
xd.address_mode = UPDI_ADDRESS_MODE_24BIT;
else
xd.address_mode = UPDI_ADDRESS_MODE_16BIT;
}
else if (strcmp(m->desc, "eeprom") == 0)
{
PDATA(pgm)->eeprom_pagesize = m->page_size;
xd.eeprom_page_size = m->page_size;
u16_to_b2(xd.eeprom_bytes, m->size);
u16_to_b2(xd.eeprom_base, m->offset);
}
else if (strcmp(m->desc, "usersig") == 0)
{
u16_to_b2(xd.user_sig_bytes, m->size);
u16_to_b2(xd.user_sig_base, m->offset);
}
else if (strcmp(m->desc, "signature") == 0)
{
u16_to_b2(xd.signature_base, m->offset);
xd.device_id[0] = p->signature[1];
xd.device_id[1] = p->signature[2];
}
else if (strcmp(m->desc, "fuses") == 0)
{
xd.fuses_bytes = m->size;
u16_to_b2(xd.fuses_base, m->offset);
}
else if (strcmp(m->desc, "lock") == 0)
{
u16_to_b2(xd.lockbits_base, m->offset);
}
}
u16_to_b2(xd.default_min_div1_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV1_VOLTAGE_MV);
u16_to_b2(xd.default_min_div2_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV2_VOLTAGE_MV);
u16_to_b2(xd.default_min_div4_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV4_VOLTAGE_MV);
u16_to_b2(xd.default_min_div8_voltage, DEFAULT_MINIMUM_CHARACTERISED_DIV8_VOLTAGE_MV);
u16_to_b2(xd.pdi_pad_fmax, MAX_FREQUENCY_SHARED_UPDI_PIN);
xd.syscfg_offset = FUSES_SYSCFG0_OFFSET;
xd.syscfg_write_mask_and = 0xFF;
xd.syscfg_write_mask_or = 0x00;
xd.syscfg_erase_mask_and = 0xFF;
xd.syscfg_erase_mask_or = 0x00;
avrdude_message(MSG_NOTICE2, "UPDI SET: \n\t"
"xd->prog_base_msb=%x\n\t"
"xd->prog_base=%x %x\n\t"
"xd->flash_page_size_msb=%x\n\t"
"xd->flash_page_size=%x\n\t"
"xd->eeprom_page_size=%x\n\t"
"xd->nvmctrl=%x %x\n\t"
"xd->ocd=%x %x\n\t",
"xd->address_mode=%x\n",
xd.prog_base_msb,
xd.prog_base[0], xd.prog_base[1],
xd.flash_page_size_msb,
xd.flash_page_size,
xd.eeprom_page_size,
xd.nvm_base_addr[0], xd.nvm_base_addr[1],
xd.ocd_base_addr[0], xd.ocd_base_addr[1],
xd.address_mode);
if (jtag3_setparm(pgm, SCOPE_AVR, 2, PARM3_DEVICEDESC, (unsigned char *)&xd, sizeof xd) < 0)
return -1;
}
else
{
struct mega_device_desc md;
@@ -1360,28 +1123,17 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
}
/*
* Depending on the target connection, there are three different
* Depending on the target connection, there are two different
* possible replies of the ICE. For a JTAG connection, the reply
* format is RSP3_DATA, followed by 4 bytes of the JTAG ID read from
* the device (followed by a trailing 0).
* For a UPDI connection the reply format is RSP3_DATA, followed by
* 4 bytes of the SIB Family_ID read from the device (followed by a
* trailing 0).
* For all other connections
* the device (followed by a trailing 0). For all other connections
* (except ISP which is handled completely differently, but that
* doesn't apply here anyway), the response is just RSP_OK.
*/
if (resp[1] == RSP3_DATA && status >= 7) {
if (p->flags & AVRPART_HAS_UPDI) {
/* Partial Family_ID has been returned */
avrdude_message(MSG_NOTICE, "%s: Partial Family_ID returned: \"%c%c%c%c\"\n",
progname, resp[3], resp[4], resp[5], resp[6]);
}
else
/* JTAG ID has been returned */
avrdude_message(MSG_NOTICE, "%s: JTAG ID returned: 0x%02x 0x%02x 0x%02x 0x%02x\n",
progname, resp[3], resp[4], resp[5], resp[6]);
}
if (resp[1] == RSP3_DATA && status >= 7)
/* JTAG ID has been returned */
avrdude_message(MSG_NOTICE, "%s: JTAG ID returned: 0x%02x 0x%02x 0x%02x 0x%02x\n",
progname, resp[3], resp[4], resp[5], resp[6]);
free(resp);
@@ -1449,7 +1201,7 @@ static int jtag3_parseextparms(PROGRAMMER * pgm, LISTID extparms)
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
extended_param = ldata(ln);
if (matches(extended_param, "jtagchain=")) {
if (strncmp(extended_param, "jtagchain=", strlen("jtagchain=")) == 0) {
unsigned int ub, ua, bb, ba;
if (sscanf(extended_param, "jtagchain=%u,%u,%u,%u", &ub, &ua, &bb, &ba)
!= 4) {
@@ -1484,17 +1236,18 @@ int jtag3_open_common(PROGRAMMER * pgm, char * port)
LNODEID usbpid;
int rv = -1;
#if !defined(HAVE_LIBUSB) && !defined(HAVE_LIBHIDAPI)
avrdude_message(MSG_INFO, "avrdude was compiled without USB or HIDAPI support.\n");
#if !defined(HAVE_LIBUSB)
avrdude_message(MSG_INFO, "avrdude was compiled without usb support.\n");
return -1;
#endif
if (!matches(port, "usb")) {
if (strncmp(port, "usb", 3) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_open_common(): JTAGICE3/EDBG port names must start with \"usb\"\n",
progname);
return -1;
}
serdev = &usb_serdev_frame;
if (pgm->usbvid)
pinfo.usbinfo.vid = pgm->usbvid;
else
@@ -1504,42 +1257,17 @@ int jtag3_open_common(PROGRAMMER * pgm, char * port)
if (lfirst(pgm->usbpid) == NULL)
ladd(pgm->usbpid, (void *)USB_DEVICE_JTAGICE3);
#if defined(HAVE_LIBHIDAPI)
/*
* Try HIDAPI first. LibUSB is more generic, but might then cause
* troubles for HID-class devices in some OSes (like Windows).
*/
serdev = &usbhid_serdev;
for (usbpid = lfirst(pgm->usbpid); rv < 0 && usbpid != NULL; usbpid = lnext(usbpid)) {
pinfo.usbinfo.flags = PINFO_FL_SILENT;
pinfo.usbinfo.pid = *(int *)(ldata(usbpid));
pgm->fd.usb.max_xfer = USBDEV_MAX_XFER_3;
pgm->fd.usb.rep = USBDEV_BULK_EP_READ_3;
pgm->fd.usb.wep = USBDEV_BULK_EP_WRITE_3;
pgm->fd.usb.eep = 0;
pgm->fd.usb.eep = USBDEV_EVT_EP_READ_3;
strcpy(pgm->port, port);
rv = serial_open(port, pinfo, &pgm->fd);
}
if (rv < 0) {
#endif /* HAVE_LIBHIDAPI */
#if defined(HAVE_LIBUSB)
serdev = &usb_serdev_frame;
for (usbpid = lfirst(pgm->usbpid); rv < 0 && usbpid != NULL; usbpid = lnext(usbpid)) {
pinfo.usbinfo.flags = PINFO_FL_SILENT;
pinfo.usbinfo.pid = *(int *)(ldata(usbpid));
pgm->fd.usb.max_xfer = USBDEV_MAX_XFER_3;
pgm->fd.usb.rep = USBDEV_BULK_EP_READ_3;
pgm->fd.usb.wep = USBDEV_BULK_EP_WRITE_3;
pgm->fd.usb.eep = USBDEV_EVT_EP_READ_3;
strcpy(pgm->port, port);
rv = serial_open(port, pinfo, &pgm->fd);
}
#endif /* HAVE_LIBUSB */
#if defined(HAVE_LIBHIDAPI)
}
#endif
if (rv < 0) {
avrdude_message(MSG_INFO, "%s: jtag3_open_common(): Did not find any device matching VID 0x%04x and PID list: ",
progname, (unsigned)pinfo.usbinfo.vid);
@@ -1613,18 +1341,6 @@ static int jtag3_open_pdi(PROGRAMMER * pgm, char * port)
return 0;
}
static int jtag3_open_updi(PROGRAMMER * pgm, char * port)
{
avrdude_message(MSG_NOTICE2, "%s: jtag3_open_updi()\n", progname);
if (jtag3_open_common(pgm, port) < 0)
return -1;
if (jtag3_getsync(pgm, PARM3_CONN_UPDI) < 0)
return -1;
return 0;
}
void jtag3_close(PROGRAMMER * pgm)
{
@@ -1645,12 +1361,8 @@ void jtag3_close(PROGRAMMER * pgm)
if (jtag3_command(pgm, buf, 4, &resp, "sign-off") >= 0)
free(resp);
/* XplainedMini boards do not need this, and early revisions had a
* firmware bug where they complained about it. */
if ((pgm->flag & PGM_FL_IS_EDBG) &&
!matches(ldata(lfirst(pgm->id)), "xplainedmini")) {
jtag3_edbg_signoff(pgm);
}
if (pgm->flag & PGM_FL_IS_EDBG)
jtag3_edbg_signoff(pgm);
serial_close(&pgm->fd);
pgm->fd.ifd = -1;
@@ -1712,13 +1424,8 @@ static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int status, dynamic_memtype = 0;
long otimeout = serial_recv_timeout;
avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(.., %s, %d, 0x%lx, %d)\n",
progname, m->desc, page_size, addr, n_bytes);
block_size = jtag3_memaddr(pgm, p, m, addr);
if(block_size != addr)
avrdude_message(MSG_NOTICE2, " mapped to address: 0x%lx\n", block_size);
block_size = 0;
avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_write(.., %s, %d, %d)\n",
progname, m->desc, page_size, n_bytes);
if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
return -1;
@@ -1762,7 +1469,7 @@ static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[3] = MTYPE_USERSIG;
} else if ( ( strcmp(m->desc, "boot") == 0 ) ) {
cmd[3] = MTYPE_BOOT_FLASH;
} else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
} else if ( p->flags & AVRPART_HAS_PDI ) {
cmd[3] = MTYPE_FLASH;
} else {
cmd[3] = MTYPE_SPM;
@@ -1821,13 +1528,8 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
int status, dynamic_memtype = 0;
long otimeout = serial_recv_timeout;
avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_load(.., %s, %d, 0x%lx, %d)\n",
progname, m->desc, page_size, addr, n_bytes);
block_size = jtag3_memaddr(pgm, p, m, addr);
if(block_size != addr)
avrdude_message(MSG_NOTICE2, " mapped to address: 0x%lx\n", block_size);
block_size = 0;
avrdude_message(MSG_NOTICE2, "%s: jtag3_paged_load(.., %s, %d, %d)\n",
progname, m->desc, page_size, n_bytes);
if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
return -1;
@@ -1844,7 +1546,7 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
/* dynamically decide between flash/boot memtype */
dynamic_memtype = 1;
} else if (strcmp(m->desc, "eeprom") == 0) {
cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
if (pgm->flag & PGM_FL_IS_DW)
return -1;
} else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) {
@@ -1855,8 +1557,6 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[3] = MTYPE_BOOT_FLASH;
} else if ( p->flags & AVRPART_HAS_PDI ) {
cmd[3] = MTYPE_FLASH;
} else if ( p->flags & AVRPART_HAS_UPDI ) {
cmd[3] = MTYPE_SRAM;
} else {
cmd[3] = MTYPE_SPM;
}
@@ -1907,20 +1607,14 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
avrdude_message(MSG_NOTICE2, "%s: jtag3_read_byte(.., %s, 0x%lx, ...)\n",
progname, mem->desc, addr);
paddr = jtag3_memaddr(pgm, p, mem, addr);
if(paddr != addr)
avrdude_message(MSG_NOTICE2, " mapped to address: 0x%lx\n", paddr);
paddr = 0;
if (!(pgm->flag & PGM_FL_IS_DW))
if ((status = jtag3_program_enable(pgm)) < 0)
return status;
if (!(pgm->flag & PGM_FL_IS_DW) && jtag3_program_enable(pgm) < 0)
return -1;
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_READ_MEMORY;
cmd[2] = 0;
cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE;
cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_FLASH_PAGE;
if (strcmp(mem->desc, "flash") == 0 ||
strcmp(mem->desc, "application") == 0 ||
strcmp(mem->desc, "apptable") == 0 ||
@@ -1931,7 +1625,7 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
paddr_ptr = &PDATA(pgm)->flash_pageaddr;
cache_ptr = PDATA(pgm)->flash_pagecache;
} else if (strcmp(mem->desc, "eeprom") == 0) {
if ( (pgm->flag & PGM_FL_IS_DW) || ( p->flags & AVRPART_HAS_PDI ) || ( p->flags & AVRPART_HAS_UPDI ) ) {
if ( (pgm->flag & PGM_FL_IS_DW) || ( p->flags & AVRPART_HAS_PDI ) ) {
cmd[3] = MTYPE_EEPROM;
} else {
cmd[3] = MTYPE_EEPROM_PAGE;
@@ -1955,14 +1649,13 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
addr = 2;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (matches(mem->desc, "lock")) {
} else if (strncmp(mem->desc, "lock", 4) == 0) {
cmd[3] = MTYPE_LOCK_BITS;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (matches(mem->desc, "fuse")) {
} else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) {
cmd[3] = MTYPE_FUSE_BITS;
if (!(p->flags & AVRPART_HAS_UPDI))
addr = mem->offset & 7;
addr = mem->offset & 7;
} else if (strcmp(mem->desc, "usersig") == 0) {
cmd[3] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) {
@@ -1983,11 +1676,11 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
* harm for other connection types either.
*/
u32_to_b4(cmd + 8, 3);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
u32_to_b4(cmd + 4, 0);
if (addr == 0) {
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
return status;
return -1;
signature_cache[0] = resp[4];
signature_cache[1] = resp[5];
@@ -2029,15 +1722,14 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
if (pagesize) {
u32_to_b4(cmd + 8, pagesize);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, paddr));
u32_to_b4(cmd + 4, paddr);
} else {
u32_to_b4(cmd + 8, 1);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
u32_to_b4(cmd + 4, addr);
}
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read memory")) < 0)
return status;
return -1;
if (resp[1] != RSP3_DATA ||
status < (pagesize? pagesize: 1) + 4) {
@@ -2066,19 +1758,14 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned char *cache_ptr = 0;
int status, unsupp = 0;
unsigned int pagesize = 0;
unsigned long mapped_addr;
avrdude_message(MSG_NOTICE2, "%s: jtag3_write_byte(.., %s, 0x%lx, ...)\n",
progname, mem->desc, addr);
mapped_addr = jtag3_memaddr(pgm, p, mem, addr);
if(mapped_addr != addr)
avrdude_message(MSG_NOTICE2, " mapped to address: 0x%lx\n", mapped_addr);
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_WRITE_MEMORY;
cmd[2] = 0;
cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_FLASH : MTYPE_SPM;
cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_FLASH : MTYPE_SPM;
if (strcmp(mem->desc, "flash") == 0) {
cache_ptr = PDATA(pgm)->flash_pagecache;
pagesize = PDATA(pgm)->flash_pagesize;
@@ -2108,15 +1795,14 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
addr = 2;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
} else if (matches(mem->desc, "fuse")) {
} else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) {
cmd[3] = MTYPE_FUSE_BITS;
if (!(p->flags & AVRPART_HAS_UPDI))
addr = mem->offset & 7;
addr = mem->offset & 7;
} else if (strcmp(mem->desc, "usersig") == 0) {
cmd[3] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) {
cmd[3] = MTYPE_PRODSIG;
} else if (matches(mem->desc, "lock")) {
} else if (strncmp(mem->desc, "lock", 4) == 0) {
cmd[3] = MTYPE_LOCK_BITS;
if (pgm->flag & PGM_FL_IS_DW)
unsupp = 1;
@@ -2159,12 +1845,12 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
return -1;
u32_to_b4(cmd + 8, 1);
u32_to_b4(cmd + 4, jtag3_memaddr(pgm, p, mem, addr));
u32_to_b4(cmd + 4, addr);
cmd[12] = 0;
cmd[13] = data;
if ((status = jtag3_command(pgm, cmd, 14, &resp, "write memory")) < 0)
return status;
return -1;
free(resp);
@@ -2281,28 +1967,6 @@ int jtag3_setparm(PROGRAMMER * pgm, unsigned char scope,
return status;
}
int jtag3_read_sib(PROGRAMMER * pgm, AVRPART * p, char * sib)
{
int status;
unsigned char cmd[12];
unsigned char *resp = NULL;
cmd[0] = SCOPE_AVR;
cmd[1] = CMD3_READ_MEMORY;
cmd[2] = 0;
cmd[3] = MTYPE_SIB;
u32_to_b4(cmd + 4, 0);
u32_to_b4(cmd + 8, AVR_SIBLEN);
if ((status = jtag3_command(pgm, cmd, 12, &resp, "read SIB")) < 0)
return status;
memcpy(sib, resp+3, AVR_SIBLEN);
sib[AVR_SIBLEN] = 0; // Zero terminate string
avrdude_message(MSG_DEBUG, "%s: jtag3_read_sib(): Received SIB: \"%s\"\n", progname, sib);
free(resp);
return 0;
}
static void jtag3_display(PROGRAMMER * pgm, const char * p)
{
@@ -2413,17 +2077,6 @@ static unsigned int jtag3_memaddr(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, uns
/*
* Non-Xmega device.
*/
if (p->flags & AVRPART_HAS_UPDI) {
if (strcmp(m->desc, "fuses") == 0) {
addr += m->offset;
}
else if (matches(m->desc, "fuse")) {
addr = m->offset;
}
else if (strcmp(m->desc, "flash") != 0) {
addr += m->offset;
}
}
return addr;
}
@@ -2529,39 +2182,3 @@ void jtag3_pdi_initpgm(PROGRAMMER * pgm)
pgm->flag = PGM_FL_IS_PDI;
}
const char jtag3_updi_desc[] = "Atmel JTAGICE3 in UPDI mode";
void jtag3_updi_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "JTAGICE3_UPDI");
/*
* mandatory functions
*/
pgm->initialize = jtag3_initialize;
pgm->display = jtag3_display;
pgm->enable = jtag3_enable;
pgm->disable = jtag3_disable;
pgm->program_enable = jtag3_program_enable_dummy;
pgm->chip_erase = jtag3_chip_erase;
pgm->open = jtag3_open_updi;
pgm->close = jtag3_close;
pgm->read_byte = jtag3_read_byte;
pgm->write_byte = jtag3_write_byte;
/*
* optional functions
*/
pgm->paged_write = jtag3_paged_write;
pgm->paged_load = jtag3_paged_load;
pgm->page_erase = jtag3_page_erase;
pgm->print_parms = jtag3_print_parms;
pgm->set_sck_period = jtag3_set_sck_period;
pgm->setup = jtag3_setup;
pgm->teardown = jtag3_teardown;
pgm->page_size = 256;
pgm->flag = PGM_FL_IS_UPDI;
pgm->unlock = jtag3_unlock_erase_key;
pgm->read_sib = jtag3_read_sib;
}

View File

@@ -41,11 +41,9 @@ int jtag3_command(PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
extern const char jtag3_desc[];
extern const char jtag3_dw_desc[];
extern const char jtag3_pdi_desc[];
extern const char jtag3_updi_desc[];
void jtag3_initpgm (PROGRAMMER * pgm);
void jtag3_dw_initpgm (PROGRAMMER * pgm);
void jtag3_pdi_initpgm (PROGRAMMER * pgm);
void jtag3_updi_initpgm (PROGRAMMER * pgm);
/*
* These functions are referenced from stk500v2.c for JTAGICE3 in

View File

@@ -109,7 +109,6 @@
#define CMD3_GET_PARAMETER 0x02
#define CMD3_SIGN_ON 0x10
#define CMD3_SIGN_OFF 0x11 /* takes one parameter? */
#define CMD3_GET_ID 0x12
#define CMD3_START_DW_DEBUG 0x13
#define CMD3_MONCON_DISABLE 0x17
@@ -144,7 +143,6 @@
# define RSP3_FAIL_WRONG_MODE 0x32 /* progmode vs. non-prog */
# define RSP3_FAIL_UNSUPP_MEMORY 0x34 /* unsupported memory type */
# define RSP3_FAIL_WRONG_LENGTH 0x35 /* wrong lenth for mem access */
# define RSP3_FAIL_OCD_LOCKED 0x44 /* device is locked */
# define RSP3_FAIL_NOT_UNDERSTOOD 0x91
/* ICE events */
@@ -167,16 +165,6 @@
#define MTYPE_EEPROM_XMEGA 0xc4 /* xmega EEPROM in debug mode - undocumented in AVR067 */
#define MTYPE_USERSIG 0xc5 /* xmega user signature - undocumented in AVR067 */
#define MTYPE_PRODSIG 0xc6 /* xmega production signature - undocumented in AVR067 */
#define MTYPE_SIB 0xD3 /* AVR8X System Information Block */
/*
* SET and GET context definitions
*/
#define SET_GET_CTXT_CONFIG 0x00 /* Configuration */
#define SET_GET_CTXT_PHYSICAL 0x01 /* Physical interface related */
#define SET_GET_CTXT_DEVICE 0x02 /* Device specific settings */
#define SET_GET_CTXT_OPTIONS 0x03 /* Option-related settings */
#define SET_GET_CTXT_SESSION 0x04 /* Session-related settings */
/*
* Parameters are divided into sections, where the section number
@@ -201,7 +189,6 @@
# define PARM3_ARCH_TINY 1 /* also small megaAVR with ISP/DW only */
# define PARM3_ARCH_MEGA 2
# define PARM3_ARCH_XMEGA 3
# define PARM3_ARCH_UPDI 5 /* AVR devices with UPDI i/f */
#define PARM3_SESS_PURPOSE 0x01 /* section 0, AVR scope, 1 byte */
# define PARM3_SESS_PROGRAMMING 1
@@ -212,26 +199,18 @@
# define PARM3_CONN_JTAG 4
# define PARM3_CONN_DW 5
# define PARM3_CONN_PDI 6
# define PARM3_CONN_UPDI 8
#define PARM3_JTAGCHAIN 0x01 /* JTAG chain info, AVR scope (units
* before/after, bits before/after), 4
* bytes */
/*
* Physical context parameters
*/
#define PARM3_CLK_MEGA_PROG 0x20 /* section 1, AVR scope, 2 bytes (kHz) */
#define PARM3_CLK_MEGA_DEBUG 0x21 /* section 1, AVR scope, 2 bytes (kHz) */
#define PARM3_CLK_XMEGA_JTAG 0x30 /* section 1, AVR scope, 2 bytes (kHz) */
#define PARM3_CLK_XMEGA_PDI 0x31 /* section 1, AVR scope, 2 bytes (kHz) */
/*
* Options context parameters
*/
#define PARM3_OPT_12V_UPDI_ENABLE 0x06
#define PARM3_OPT_CHIP_ERASE_TO_ENTER 0x07
/* Xmega erase memory types, for CMND_XMEGA_ERASE */
#define XMEGA_ERASE_CHIP 0x00
@@ -284,16 +263,6 @@
#define CMSISDAP_CMD_SWD_CONFIGURE 0x13 /* configure SWD protocol; (byte) */
#define DEFAULT_MINIMUM_CHARACTERISED_DIV1_VOLTAGE_MV 4500 // Default minimum voltage for 32M => 4.5V
#define DEFAULT_MINIMUM_CHARACTERISED_DIV2_VOLTAGE_MV 2700 // Default minimum voltage for 16M => 2.7V
#define DEFAULT_MINIMUM_CHARACTERISED_DIV4_VOLTAGE_MV 2200 // Default minimum voltage for 8M => 2.2V
#define DEFAULT_MINIMUM_CHARACTERISED_DIV8_VOLTAGE_MV 1500 // Default minimum voltage for 4M => 1.5V
#define MAX_FREQUENCY_DEDICATED_UPDI_PIN 1500
#define MAX_FREQUENCY_SHARED_UPDI_PIN 750
#define UPDI_ADDRESS_MODE_16BIT 0
#define UPDI_ADDRESS_MODE_24BIT 1
#define FUSES_SYSCFG0_OFFSET 5
#if !defined(JTAG3_PRIVATE_EXPORTED)
struct mega_device_desc {
@@ -347,47 +316,4 @@ struct xmega_device_desc {
unsigned char nvm_base_addr[2]; // IO space base address of NVM controller
unsigned char mcu_base_addr[2]; // IO space base address of MCU control
};
/* UPDI device descriptor */
struct updi_device_desc {
unsigned char prog_base[2];
unsigned char flash_page_size;
unsigned char eeprom_page_size;
unsigned char nvm_base_addr[2];
unsigned char ocd_base_addr[2];
// Configuration below, except for "Extended memory support", is only used by kits with
// embedded debuggers (XPlained, Curiosity, ...).
unsigned char default_min_div1_voltage[2]; // Default minimum voltage for 32M => 4.5V -> 4500
unsigned char default_min_div2_voltage[2]; // Default minimum voltage for 16M => 2.7V -> 2700
unsigned char default_min_div4_voltage[2]; // Default minimum voltage for 8M => 2.2V -> 2200
unsigned char default_min_div8_voltage[2]; // Default minimum voltage for 4M => 1.5V -> 1500
unsigned char pdi_pad_fmax[2]; // 750
unsigned char flash_bytes[4]; // Flash size in bytes
unsigned char eeprom_bytes[2]; // EEPROM size in bytes
unsigned char user_sig_bytes[2]; // UserSignture size in bytes
unsigned char fuses_bytes; // Fuses size in bytes
unsigned char syscfg_offset; // Offset of SYSCFG0 within FUSE space
unsigned char syscfg_write_mask_and; // AND mask to apply to SYSCFG0 when writing
unsigned char syscfg_write_mask_or; // OR mask to apply to SYSCFG0 when writing
unsigned char syscfg_erase_mask_and; // AND mask to apply to SYSCFG0 after erase
unsigned char syscfg_erase_mask_or; // OR mask to apply to SYSCFG0 after erase
unsigned char eeprom_base[2]; // Base address for EEPROM memory
unsigned char user_sig_base[2]; // Base address for UserSignature memory
unsigned char signature_base[2]; // Base address for Signature memory
unsigned char fuses_base[2]; // Base address for Fuses memory
unsigned char lockbits_base[2]; // Base address for Lockbits memory
unsigned char device_id[2]; // Two last bytes of the device ID
// Extended memory support. Needed for flash >= 64kb
unsigned char prog_base_msb; // Extends prog_base, used in 24-bit mode
unsigned char flash_page_size_msb; // Extends flash_page_size, used in 24-bit mode
unsigned char address_mode; // 0x00 = 16-bit mode, 0x01 = 24-bit mode
};
#endif /* JTAG3_PRIVATE_EXPORTED */

View File

@@ -604,7 +604,6 @@ static int jtagmkII_recv_frame(PROGRAMMER * pgm, unsigned char **msg,
if (tnow - tstart > timeoutval) {
avrdude_message(MSG_INFO, "%s: jtagmkII_recv_frame(): timeout\n",
progname);
free(buf);
return -1;
}
@@ -742,7 +741,6 @@ int jtagmkII_getsync(PROGRAMMER * pgm, int mode) {
avrdude_message(MSG_NOTICE, "Device ID: %s\n",
resp + 16);
}
free(resp);
break;
}
free(resp);
@@ -1348,7 +1346,12 @@ static int jtagmkII_initialize(PROGRAMMER * pgm, AVRPART * p)
jtagmkII_set_devdescr(pgm, p);
PDATA(pgm)->boot_start = ULONG_MAX;
if ((p->flags & AVRPART_HAS_PDI)) {
/*
* If this is an ATxmega device in JTAG mode, change the emulator
* mode from JTAG to JTAG_XMEGA.
*/
if ((pgm->flag & PGM_FL_IS_JTAG) &&
(p->flags & AVRPART_HAS_PDI)) {
/*
* Find out where the border between application and boot area
* is.
@@ -1916,7 +1919,7 @@ static int jtagmkII_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
retry:
avrdude_message(MSG_NOTICE2, "%s: jtagmkII_page_erase(): "
"Sending Xmega erase command: ",
"Sending xmega erase command: ",
progname);
jtagmkII_send(pgm, cmd, sizeof cmd);
@@ -3636,12 +3639,12 @@ static int jtagmkII_paged_write32(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
status = jtagmkII_flash_write_page32(pgm, pageNum);
if(status < 0) {lineno = __LINE__; goto eRR;}
}
free(cmd);
serial_recv_timeout = otimeout;
status = jtagmkII_reset32(pgm, AVR32_SET4RUNNING); // AVR32_SET4RUNNING | AVR32_RELEASE_JTAG
if(status < 0) {lineno = __LINE__; goto eRR;}
free(cmd);
return addr;
eRR:

View File

@@ -140,7 +140,6 @@ default_safemode { yylval=NULL; return K_DEFAULT_SAFEMODE; }
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
delay { yylval=NULL; return K_DELAY; }
desc { yylval=NULL; return K_DESC; }
family_id { yylval=NULL; return K_FAMILY_ID; }
devicecode { yylval=NULL; return K_DEVICECODE; }
eecr { yylval=NULL; return K_EECR; }
eeprom { yylval=NULL; return K_EEPROM; }
@@ -153,7 +152,6 @@ has_debugwire { yylval=NULL; return K_HAS_DW; }
has_jtag { yylval=NULL; return K_HAS_JTAG; }
has_pdi { yylval=NULL; return K_HAS_PDI; }
has_tpi { yylval=NULL; return K_HAS_TPI; }
has_updi { yylval=NULL; return K_HAS_UPDI; }
hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; }
hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; }
hvsp_controlstack { yylval=NULL; return K_HVSP_CONTROLSTACK; }
@@ -178,7 +176,6 @@ no { yylval=new_token(K_NO); return K_NO; }
num_banks { yylval=NULL; return K_NUM_PAGES; }
num_pages { yylval=NULL; return K_NUM_PAGES; }
nvm_base { yylval=NULL; return K_NVM_BASE; }
ocd_base { yylval=NULL; return K_OCD_BASE; }
ocdrev { yylval=NULL; return K_OCDREV; }
offset { yylval=NULL; return K_OFFSET; }
page_size { yylval=NULL; return K_PAGE_SIZE; }

View File

@@ -33,7 +33,11 @@
#include <stdint.h>
typedef uint32_t pinmask_t;
#else
#error Need a C99 capable compiler
#if UINT_MAX >= 0xFFFFFFFF
typedef unsigned int pinmask_t;
#else
typedef unsigned long pinmask_t;
#endif
#endif
@@ -195,12 +199,9 @@ typedef struct opcode {
#define AVRPART_WRITE 0x0400 /* at least one write operation specified */
#define AVRPART_HAS_TPI 0x0800 /* part has TPI i/f rather than ISP (ATtiny4/5/9/10) */
#define AVRPART_IS_AT90S1200 0x1000 /* part is an AT90S1200 (needs special treatment) */
#define AVRPART_HAS_UPDI 0x2000 /* part has UPDI i/f (AVR8X) */
#define AVR_DESCLEN 64
#define AVR_IDLEN 32
#define AVR_FAMILYIDLEN 7
#define AVR_SIBLEN 16
#define CTL_STACK_SIZE 32
#define FLASH_INSTR_SIZE 3
#define EEPROM_INSTR_SIZE 20
@@ -210,7 +211,6 @@ typedef struct opcode {
typedef struct avrpart {
char desc[AVR_DESCLEN]; /* long part name */
char id[AVR_IDLEN]; /* short part name */
char family_id[AVR_FAMILYIDLEN+1]; /* family id in the SIB (avr8x) */
int stk500_devcode; /* stk500 device code */
int avr910_devcode; /* avr910 device code */
int chip_erase_delay; /* microseconds */
@@ -264,7 +264,6 @@ typedef struct avrpart {
unsigned short eecr; /* JTAC ICE mkII XML file parameter */
unsigned int mcu_base; /* Base address of MCU control block in ATxmega devices */
unsigned int nvm_base; /* Base address of NVM controller in ATxmega devices */
unsigned int ocd_base; /* Base address of OCD module in AVR8X/UPDI devices */
int ocdrev; /* OCD revision (JTAGICE3 parameter, from AS6 XML files) */
OPCODE * op[AVR_OP_MAX]; /* opcodes */
@@ -338,9 +337,6 @@ typedef void (*walk_avrparts_cb)(const char *name, const char *desc,
void *cookie);
void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie);
void sort_avrparts(LISTID avrparts);
int compare_memory_masked(AVRMEM * m, uint8_t buf1, uint8_t buf2);
#ifdef __cplusplus
}
#endif
@@ -369,7 +365,7 @@ enum {
#ifdef HAVE_LINUXGPIO
/* Embedded systems might have a lot more gpio than only 0-31 */
#undef PIN_MAX
#define PIN_MAX 400 /* largest allowed pin number */
#define PIN_MAX 255 /* largest allowed pin number */
#endif
/** Number of pins in each element of the bitfield */
@@ -567,7 +563,6 @@ extern struct serial_device serial_serdev;
extern struct serial_device usb_serdev;
extern struct serial_device usb_serdev_frame;
extern struct serial_device avrdoper_serdev;
extern struct serial_device usbhid_serdev;
#define serial_open (serdev->open)
#define serial_setspeed (serdev->setspeed)
@@ -646,7 +641,6 @@ typedef struct programmer_t {
void (*powerdown) (struct programmer_t * pgm);
int (*program_enable) (struct programmer_t * pgm, AVRPART * p);
int (*chip_erase) (struct programmer_t * pgm, AVRPART * p);
int (*unlock) (struct programmer_t * pgm, AVRPART * p);
int (*cmd) (struct programmer_t * pgm, const unsigned char *cmd,
unsigned char *res);
int (*cmd_tpi) (struct programmer_t * pgm, const unsigned char *cmd,
@@ -669,7 +663,6 @@ typedef struct programmer_t {
int (*read_byte) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char * value);
int (*read_sig_bytes) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m);
int (*read_sib) (struct programmer_t * pgm, AVRPART * p, char *sib);
void (*print_parms) (struct programmer_t * pgm);
int (*set_vtarget) (struct programmer_t * pgm, double v);
int (*set_varef) (struct programmer_t * pgm, unsigned int chan, double v);
@@ -764,8 +757,6 @@ int avr_mem_hiaddr(AVRMEM * mem);
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p);
int avr_unlock(PROGRAMMER * pgm, AVRPART * p);
void report_progress (int completed, int total, char *hdr);
#ifdef __cplusplus

View File

@@ -66,7 +66,7 @@ static int linuxgpio_export(unsigned int gpio)
return fd;
}
len = snprintf(buf, sizeof(buf), "%u", gpio);
len = snprintf(buf, sizeof(buf), "%d", gpio);
r = write(fd, buf, len);
close(fd);
@@ -84,7 +84,7 @@ static int linuxgpio_unexport(unsigned int gpio)
return fd;
}
len = snprintf(buf, sizeof(buf), "%u", gpio);
len = snprintf(buf, sizeof(buf), "%d", gpio);
r = write(fd, buf, len);
close(fd);
@@ -95,7 +95,7 @@ static int linuxgpio_openfd(unsigned int gpio)
{
char filepath[60];
snprintf(filepath, sizeof(filepath), "/sys/class/gpio/gpio%u/value", gpio);
snprintf(filepath, sizeof(filepath), "/sys/class/gpio/gpio%d/value", gpio);
return (open(filepath, O_RDWR));
}
@@ -104,7 +104,7 @@ static int linuxgpio_dir(unsigned int gpio, unsigned int dir)
int fd, r;
char buf[60];
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%u/direction", gpio);
snprintf(buf, sizeof(buf), "/sys/class/gpio/gpio%d/direction", gpio);
fd = open(buf, O_WRONLY);
if (fd < 0) {
@@ -330,7 +330,6 @@ void linuxgpio_initpgm(PROGRAMMER *pgm)
pgm->program_enable = bitbang_program_enable;
pgm->chip_erase = bitbang_chip_erase;
pgm->cmd = bitbang_cmd;
pgm->cmd_tpi = bitbang_cmd_tpi;
pgm->open = linuxgpio_open;
pgm->close = linuxgpio_close;
pgm->setpin = linuxgpio_setpin;

View File

@@ -1,427 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Support for using spidev userspace drivers to communicate directly over SPI
*
* Copyright (C) 2013 Kevin Cuzner <kevin@kevincuzner.com>
* Copyright (C) 2018 Ralf Ramsauer <ralf@vmexit.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
* 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
*
* Support for inversion of reset pin, Tim Chilton 02/05/2014
* Review code, rebase to latest trunk, add linux/gpio.h support, Ralf Ramsauer 2018-09-07
*/
#include "ac_cfg.h"
#include "avrdude.h"
#include "libavrdude.h"
#include "linuxspi.h"
#if HAVE_LINUXSPI
/**
* Linux Kernel SPI Drivers
*
* Copyright (C) 2006 SWAPP
* Andrea Paterniani <a.paterniani@swapp-eng.it>
* Copyright (C) 2007 David Brownell (simplification, cleanup)
*
* 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.
*/
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <linux/gpio.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define LINUXSPI "linuxspi"
static int fd_spidev, fd_gpiochip, fd_linehandle;
/**
* @brief Sends/receives a message in full duplex mode
* @return -1 on failure, otherwise number of bytes sent/recieved
*/
static int linuxspi_spi_duplex(PROGRAMMER *pgm, const unsigned char *tx, unsigned char *rx, int len)
{
struct spi_ioc_transfer tr;
int ret;
tr = (struct spi_ioc_transfer) {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = len,
.delay_usecs = 1,
.speed_hz = 1.0 / pgm->bitclock, // seconds to Hz
.bits_per_word = 8,
};
ret = ioctl(fd_spidev, SPI_IOC_MESSAGE(1), &tr);
if (ret != len)
avrdude_message(MSG_INFO, "\n%s: error: Unable to send SPI message\n", progname);
return (ret == -1) ? -1 : 0;
}
static void linuxspi_setup(PROGRAMMER *pgm)
{
}
static void linuxspi_teardown(PROGRAMMER* pgm)
{
}
static int linuxspi_reset_mcu(PROGRAMMER *pgm, bool active)
{
struct gpiohandle_data data;
int ret;
/*
* Set the reset state and keep it. The pin will be released and set back to
* its initial value, once the fd_gpiochip is closed.
*/
data.values[0] = active ^ !(pgm->pinno[PIN_AVR_RESET] & PIN_INVERSE);
ret = ioctl(fd_linehandle, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
#ifdef GPIO_V2_LINE_SET_VALUES_IOCTL
if (ret == -1) {
struct gpio_v2_line_values val;
val.mask = 1;
val.bits = active ^ !(pgm->pinno[PIN_AVR_RESET] & PIN_INVERSE);
ret = ioctl(fd_linehandle, GPIO_V2_LINE_SET_VALUES_IOCTL, &val);
}
#endif
if (ret == -1) {
ret = -errno;
avrdude_message(MSG_INFO, "%s error: Unable to set GPIO line %d value\n",
progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE);
return ret;
}
return 0;
}
static int linuxspi_open(PROGRAMMER *pgm, char *port)
{
const char *port_error =
"%s: error: Unknown port specification. "
"Please use the format /dev/spidev:/dev/gpiochip[:resetno]\n";
char port_default[] = "/dev/spidev0.0:/dev/gpiochip0";
char *spidev, *gpiochip, *reset_pin;
struct gpiohandle_request req;
int ret;
if (!strcmp(port, "unknown")) {
port = port_default;
}
spidev = strtok(port, ":");
if (!spidev) {
avrdude_message(MSG_INFO, port_error, progname);
return -1;
}
gpiochip = strtok(NULL, ":");
if (!gpiochip) {
avrdude_message(MSG_INFO, port_error, progname);
return -1;
}
/* optional: override reset pin in configuration */
reset_pin = strtok(NULL, ":");
if (reset_pin)
pgm->pinno[PIN_AVR_RESET] = strtoul(reset_pin, NULL, 0);
strcpy(pgm->port, port);
fd_spidev = open(pgm->port, O_RDWR);
if (fd_spidev < 0) {
avrdude_message(MSG_INFO, "\n%s: error: Unable to open the spidev device %s", progname, pgm->port);
return -1;
}
uint32_t mode = SPI_MODE_0 | SPI_NO_CS;
ret = ioctl(fd_spidev, SPI_IOC_WR_MODE32, &mode);
if (ret == -1) {
avrdude_message(MSG_INFO, "%s: error: Unable to set SPI mode %0X on %s\n",
progname, mode, spidev);
goto close_spidev;
}
fd_gpiochip = open(gpiochip, 0);
if (fd_gpiochip < 0) {
avrdude_message(MSG_INFO, "\n%s error: Unable to open the gpiochip %s", progname, gpiochip);
ret = -1;
goto close_spidev;
}
strcpy(req.consumer_label, progname);
req.lines = 1;
req.lineoffsets[0] = pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE;
req.default_values[0] = !!(pgm->pinno[PIN_AVR_RESET] & PIN_INVERSE);
req.flags = GPIOHANDLE_REQUEST_OUTPUT;
ret = ioctl(fd_gpiochip, GPIO_GET_LINEHANDLE_IOCTL, &req);
if (ret != -1)
fd_linehandle = req.fd;
#ifdef GPIO_V2_GET_LINE_IOCTL
if (ret == -1) {
struct gpio_v2_line_request reqv2;
memset(&reqv2, 0, sizeof(reqv2));
reqv2.offsets[0] = pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE;
strncpy(reqv2.consumer, progname, sizeof(reqv2.consumer) - 1);
reqv2.config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
reqv2.config.num_attrs = 1;
reqv2.config.attrs[0].attr.id = GPIO_V2_LINE_ATTR_ID_OUTPUT_VALUES;
reqv2.config.attrs[0].attr.values = !!(pgm->pinno[PIN_AVR_RESET] & PIN_INVERSE);
reqv2.config.attrs[0].mask = 1;
reqv2.num_lines = 1;
ret = ioctl(fd_gpiochip, GPIO_V2_GET_LINE_IOCTL, &reqv2);
if (ret != -1)
fd_linehandle = reqv2.fd;
}
#endif
if (ret == -1) {
ret = -errno;
avrdude_message(MSG_INFO, "%s error: Unable to get GPIO line %d\n",
progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE);
goto close_gpiochip;
}
ret = linuxspi_reset_mcu(pgm, true);
if (ret)
goto close_out;
if (pgm->baudrate != 0) {
avrdude_message(MSG_INFO,
"%s: obsolete use of -b <clock> option for bit clock; use -B <clock>\n",
progname);
pgm->bitclock = 1E6 / pgm->baudrate;
}
if (pgm->bitclock == 0) {
avrdude_message(MSG_NOTICE,
"%s: defaulting bit clock to 200 kHz\n",
progname);
pgm->bitclock = 5E-6; // 200 kHz - 5 µs
}
return 0;
close_out:
close(fd_linehandle);
close_gpiochip:
close(fd_gpiochip);
close_spidev:
close(fd_spidev);
return ret;
}
static void linuxspi_close(PROGRAMMER *pgm)
{
switch (pgm->exit_reset) {
case EXIT_RESET_ENABLED:
linuxspi_reset_mcu(pgm, true);
break;
case EXIT_RESET_DISABLED:
linuxspi_reset_mcu(pgm, false);
break;
default:
break;
}
close(fd_linehandle);
close(fd_spidev);
close(fd_gpiochip);
}
static void linuxspi_disable(PROGRAMMER* pgm)
{
}
static void linuxspi_enable(PROGRAMMER* pgm)
{
}
static void linuxspi_display(PROGRAMMER* pgm, const char* p)
{
}
static int linuxspi_initialize(PROGRAMMER *pgm, AVRPART *p)
{
int tries, ret;
if (p->flags & AVRPART_HAS_TPI) {
/* We do not support tpi. This is a dedicated SPI thing */
avrdude_message(MSG_INFO, "%s: error: Programmer " LINUXSPI " does not support TPI\n", progname);
return -1;
}
//enable programming on the part
tries = 0;
do
{
ret = pgm->program_enable(pgm, p);
if (ret == 0 || ret == -1)
break;
} while(tries++ < 65);
if (ret)
avrdude_message(MSG_INFO, "%s: error: AVR device not responding\n", progname);
return ret;
}
static int linuxspi_cmd(PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res)
{
return linuxspi_spi_duplex(pgm, cmd, res, 4);
}
static int linuxspi_program_enable(PROGRAMMER *pgm, AVRPART *p)
{
unsigned char cmd[4], res[4];
if (!p->op[AVR_OP_PGM_ENABLE]) {
avrdude_message(MSG_INFO, "%s: error: program enable instruction not defined for part \"%s\"\n", progname, 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 can not 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 MOSI 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
*/
if (linuxspi_reset_mcu(pgm, false))
return -1;
usleep(5);
if (linuxspi_reset_mcu(pgm, true))
return -1;
usleep(20000);
return -2;
}
return 0;
}
static int linuxspi_chip_erase(PROGRAMMER *pgm, AVRPART *p)
{
unsigned char cmd[4], res[4];
if (!p->op[AVR_OP_CHIP_ERASE]) {
avrdude_message(MSG_INFO, "%s: error: chip erase instruction not defined for part \"%s\"\n", progname, 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 int linuxspi_parseexitspecs(PROGRAMMER *pgm, char *s)
{
char *cp;
while ((cp = strtok(s, ","))) {
s = 0;
if (!strcmp(cp, "reset")) {
pgm->exit_reset = EXIT_RESET_ENABLED;
continue;
}
if (!strcmp(cp, "noreset")) {
pgm->exit_reset = EXIT_RESET_DISABLED;
continue;
}
return -1;
}
return 0;
}
void linuxspi_initpgm(PROGRAMMER *pgm)
{
strcpy(pgm->type, LINUXSPI);
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
/* mandatory functions */
pgm->initialize = linuxspi_initialize;
pgm->display = linuxspi_display;
pgm->enable = linuxspi_enable;
pgm->disable = linuxspi_disable;
pgm->program_enable = linuxspi_program_enable;
pgm->chip_erase = linuxspi_chip_erase;
pgm->cmd = linuxspi_cmd;
pgm->open = linuxspi_open;
pgm->close = linuxspi_close;
pgm->read_byte = avr_read_byte_default;
pgm->write_byte = avr_write_byte_default;
/* optional functions */
pgm->setup = linuxspi_setup;
pgm->teardown = linuxspi_teardown;
pgm->parseexitspecs = linuxspi_parseexitspecs;
}
const char linuxspi_desc[] = "SPI using Linux spidev driver";
#else /* !HAVE_LINUXSPI */
void linuxspi_initpgm(PROGRAMMER * pgm)
{
avrdude_message(MSG_INFO, "%s: Linux SPI driver not available in this configuration\n",
progname);
}
const char linuxspi_desc[] = "SPI using Linux spidev driver (not available)";
#endif /* HAVE_LINUXSPI */

View File

@@ -1,35 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2013 Kevin Cuzner <kevin@kevincuner.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 linuxspi_h
#define linuxspi_h
#ifdef __cplusplus
extern "C" {
#endif
extern const char linuxspi_desc[];
void linuxspi_initpgm (PROGRAMMER * pgm);
#ifdef __cplusplus
}
#endif
#endif //linuxspi_h

73
main.c
View File

@@ -1,7 +1,7 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2000-2005 Brian S. Dean <bsd@bsdhome.com>
* Copyright Joerg Wunsch <j@uriah.heep.sax.de>
* Copyright 2007-2014 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
@@ -127,6 +127,8 @@ static void usage(void)
" -t Enter terminal mode.\n"
" -E <exitspec>[,<exitspec>] List programmer exit specifications.\n"
" -x <extended_param> Pass <extended_param> to programmer.\n"
" -y Count # erase cycles in EEPROM.\n"
" -Y <number> Initialize erase cycle # in EEPROM.\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"
@@ -345,6 +347,7 @@ int main(int argc, char * argv [])
unsigned char safemode_fuse = 0xff;
char * safemode_response;
int fuses_specified = 0;
int fuses_updated = 0;
#if !defined(WIN32NATIVE)
char * homedir;
@@ -676,10 +679,10 @@ int main(int argc, char * argv [])
* Print out an identifying string so folks can tell what version
* they are running
*/
avrdude_message(MSG_NOTICE, "\n%s: Version %s\n"
"%sCopyright (c) Brian Dean, http://www.bdmicro.com/\n"
"%sCopyright (c) Joerg Wunsch\n\n",
progname, version, progbuf, progbuf);
avrdude_message(MSG_NOTICE, "\n%s: Version %s, compiled on %s at %s\n"
"%sCopyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/\n"
"%sCopyright (c) 2007-2014 Joerg Wunsch\n\n",
progname, version, __DATE__, __TIME__, progbuf, progbuf);
avrdude_message(MSG_NOTICE, "%sSystem wide configuration file is \"%s\"\n",
progbuf, sys_config);
@@ -918,7 +921,7 @@ int main(int argc, char * argv [])
*/
if (port[0] == 0) {
avrdude_message(MSG_INFO, "\n%s: no port has been specified on the command line "
"or in the config file\n",
"or the config file\n",
progname);
avrdude_message(MSG_INFO, "%sSpecify a port using the -P option and try again\n\n",
progbuf);
@@ -1042,44 +1045,6 @@ int main(int argc, char * argv [])
if (init_ok) {
rc = avr_signature(pgm, p);
if (rc != 0) {
// -68 == -(0x44) == -(RSP3_FAIL_OCD_LOCKED)
if ((rc == -68) && (p->flags & AVRPART_HAS_UPDI) && (attempt < 1)) {
attempt++;
if (pgm->read_sib) {
// Read SIB and compare FamilyID
char sib[AVR_SIBLEN + 1];
pgm->read_sib(pgm, p, sib);
avrdude_message(MSG_NOTICE, "%s: System Information Block: \"%s\"\n",
progname, sib);
if (quell_progress < 2) {
avrdude_message(MSG_INFO, "%s: Received FamilyID: \"%.*s\"\n", progname, AVR_FAMILYIDLEN, sib);
}
if (strncmp(p->family_id, sib, AVR_FAMILYIDLEN)) {
avrdude_message(MSG_INFO, "%s: Expected FamilyID: \"%s\"\n", progname, p->family_id);
if (!ovsigck) {
avrdude_message(MSG_INFO, "%sDouble check chip, "
"or use -F to override this check.\n",
progbuf);
exitrc = 1;
goto main_exit;
}
}
}
if(erase) {
erase = 0;
if (uflags & UF_NOWRITE) {
avrdude_message(MSG_INFO, "%s: conflicting -e and -n options specified, NOT erasing chip\n",
progname);
} else {
if (quell_progress < 2) {
avrdude_message(MSG_INFO, "%s: erasing chip\n", progname);
}
exitrc = avr_unlock(pgm, p);
if(exitrc) goto main_exit;
goto sig_again;
}
}
}
avrdude_message(MSG_INFO, "%s: error reading signature data, rc=%d\n",
progname, rc);
exitrc = 1;
@@ -1173,7 +1138,7 @@ int main(int argc, char * argv [])
//Check if the programmer just doesn't support reading
if (rc == -5)
{
avrdude_message(MSG_NOTICE, "%s: safemode: Fuse reading not supported by programmer.\n"
avrdude_message(MSG_NOTICE, "%s: safemode: Fuse reading not support by programmer.\n"
" Safemode disabled.\n", progname);
}
else
@@ -1299,11 +1264,8 @@ int main(int argc, char * argv [])
}
}
AVRMEM * m;
/* Now check what fuses are against what they should be */
m = avr_locate_mem(p, "fuse");
if (compare_memory_masked(m, safemodeafter_fuse, safemode_fuse)) {
if (safemodeafter_fuse != safemode_fuse) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: fuse changed! Was %x, and is now %x\n",
progname, safemode_fuse, safemodeafter_fuse);
@@ -1331,8 +1293,7 @@ int main(int argc, char * argv [])
}
/* Now check what fuses are against what they should be */
m = avr_locate_mem(p, "lfuse");
if (compare_memory_masked(m, safemodeafter_lfuse, safemode_lfuse)) {
if (safemodeafter_lfuse != safemode_lfuse) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: lfuse changed! Was %x, and is now %x\n",
progname, safemode_lfuse, safemodeafter_lfuse);
@@ -1360,8 +1321,7 @@ int main(int argc, char * argv [])
}
/* Now check what fuses are against what they should be */
m = avr_locate_mem(p, "hfuse");
if (compare_memory_masked(m, safemodeafter_hfuse, safemode_hfuse)) {
if (safemodeafter_hfuse != safemode_hfuse) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: hfuse changed! Was %x, and is now %x\n",
progname, safemode_hfuse, safemodeafter_hfuse);
@@ -1386,8 +1346,7 @@ int main(int argc, char * argv [])
}
/* Now check what fuses are against what they should be */
m = avr_locate_mem(p, "efuse");
if (compare_memory_masked(m, safemodeafter_efuse, safemode_efuse)) {
if (safemodeafter_efuse != safemode_efuse) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: efuse changed! Was %x, and is now %x\n",
progname, safemode_efuse, safemodeafter_efuse);
@@ -1415,14 +1374,14 @@ int main(int argc, char * argv [])
avrdude_message(MSG_INFO, "%s: safemode: ", progname);
if (failures == 0) {
avrdude_message(MSG_INFO, "Fuses OK (E:%02X, H:%02X, L:%02X)\n",
safemodeafter_efuse, safemodeafter_hfuse, safemodeafter_lfuse);
safemode_efuse, safemode_hfuse, safemode_lfuse);
}
else {
avrdude_message(MSG_INFO, "Fuses not recovered, sorry\n");
}
}
if (fuses_updated) {
if (fuses_updated && fuses_specified) {
exitrc = 1;
}

View File

@@ -40,7 +40,6 @@
#include "jtagmkII.h"
#include "jtag3.h"
#include "linuxgpio.h"
#include "linuxspi.h"
#include "par.h"
#include "pickit2.h"
#include "ppi.h"
@@ -51,7 +50,6 @@
#include "usbasp.h"
#include "usbtiny.h"
#include "wiring.h"
#include "xbee.h"
const PROGRAMMER_TYPE programmers_types[] = {
@@ -79,11 +77,9 @@ const PROGRAMMER_TYPE programmers_types[] = {
{"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc},
{"jtagice3", jtag3_initpgm, jtag3_desc},
{"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc},
{"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc},
{"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc},
{"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc},
{"linuxgpio", linuxgpio_initpgm, linuxgpio_desc},
{"linuxspi", linuxspi_initpgm, linuxspi_desc},
{"par", par_initpgm, par_desc},
{"pickit2", pickit2_initpgm, pickit2_desc},
{"serbb", serbb_initpgm, serbb_desc},
@@ -98,7 +94,6 @@ const PROGRAMMER_TYPE programmers_types[] = {
{"usbasp", usbasp_initpgm, usbasp_desc},
{"usbtiny", usbtiny_initpgm, usbtiny_desc},
{"wiring", wiring_initpgm, wiring_desc},
{"xbee", xbee_initpgm, xbee_desc},
};
const PROGRAMMER_TYPE * locate_programmer_type(const char * id)

View File

@@ -202,10 +202,10 @@ static int pickit2_open(PROGRAMMER * pgm, char * port)
HidD_GetProductString(PDATA(pgm)->usb_handle, buff, PGM_DESCLEN-1);
// convert from wide chars, but do not overwrite trailing '\0'
memset(&(pgm->desc), 0, PGM_DESCLEN);
memset(&(pgm->type), 0, PGM_DESCLEN);
for (i = 0; i < (PGM_DESCLEN-1) && buff[i]; i++)
{
pgm->desc[i] = (char)buff[i]; // TODO what about little/big endian???
pgm->type[i] = (char)buff[i]; // TODO what about little/big endian???
}
}
#else
@@ -330,8 +330,6 @@ static void pickit2_disable(PROGRAMMER * pgm)
SCR_MCLR_GND_OFF,
SCR_VPP_OFF,
SCR_VDD_OFF,
SCR_VPP_PWM_OFF,
SCR_DELAY_2(.01),
SCR_BUSY_LED_OFF,
CMD_END_OF_BUFFER
};

View File

@@ -180,7 +180,7 @@ int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse,
return -1;
}
else if (fusegood == 1) {
avrdude_message(MSG_NOTICE, "%s: safemode: lfuse reads as %X\n", progname, safemode_lfuse);
avrdude_message(MSG_DEBUG, "%s: safemode: lfuse reads as %X\n", progname, safemode_lfuse);
}
/* Read hfuse three times */

View File

@@ -26,7 +26,7 @@
#include "ac_cfg.h"
#if defined(HAVE_LIBHIDAPI) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID))
#if defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID))
#include <stdio.h>
#include <string.h>
@@ -64,102 +64,7 @@ static int avrdoperRxPosition = 0; /* amount of bytes already consu
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#if defined(HAVE_LIBHIDAPI)
#include <hidapi/hidapi.h>
/* ------------------------------------------------------------------------- */
static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName,
int product, char *productName, int doReportIDs)
{
hid_device *dev;
dev = hid_open(vendor, product, NULL);
if (dev == NULL)
{
avrdude_message(MSG_INFO, "%s: usbOpenDevice(): No device found\n",
progname);
return USB_ERROR_NOTFOUND;
}
fdp->usb.handle = dev;
return USB_ERROR_NONE;
}
/* ------------------------------------------------------------------------- */
static void usbCloseDevice(union filedescriptor *fdp)
{
hid_device *udev = (hid_device *)fdp->usb.handle;
fdp->usb.handle = NULL;
if (udev == NULL)
return;
hid_close(udev);
}
/* ------------------------------------------------------------------------- */
static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len)
{
hid_device *udev = (hid_device *)fdp->usb.handle;
int bytesSent = -1;
switch(reportType){
case USB_HID_REPORT_TYPE_INPUT:
break;
case USB_HID_REPORT_TYPE_OUTPUT:
bytesSent = hid_write(udev, (unsigned char*) buffer, len);
break;
case USB_HID_REPORT_TYPE_FEATURE:
bytesSent = hid_send_feature_report(udev, (unsigned char*) buffer, len);
break;
}
if(bytesSent != len){
if(bytesSent < 0)
avrdude_message(MSG_INFO, "Error sending message: %s\n", hid_error(udev));
return USB_ERROR_IO;
}
return USB_ERROR_NONE;
}
/* ------------------------------------------------------------------------- */
static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber,
char *buffer, int *len)
{
hid_device *udev = (hid_device *)fdp->usb.handle;
int bytesReceived = -1;
switch(reportType){
case USB_HID_REPORT_TYPE_INPUT:
bytesReceived = hid_read_timeout(udev, (unsigned char*) buffer, *len, 300);
break;
case USB_HID_REPORT_TYPE_OUTPUT:
break;
case USB_HID_REPORT_TYPE_FEATURE:
bytesReceived = hid_get_feature_report(udev, (unsigned char*) buffer, *len);
break;
}
if(bytesReceived < 0){
avrdude_message(MSG_INFO, "Error sending message: %s\n", hid_error(udev));
return USB_ERROR_IO;
}
*len = bytesReceived;
return USB_ERROR_NONE;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#else /* !defined(HAVE_LIBHIDAPI) */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#if defined(WIN32NATIVE) && defined(HAVE_LIBHID)
#include <windows.h>
#include <setupapi.h>
@@ -332,6 +237,204 @@ static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNum
return rval == 0 ? USB_ERROR_IO : 0;
}
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#else /* !(WIN32NATIVE && HAVE_LIBHID) */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#if defined(HAVE_USB_H)
# include <usb.h>
#elif defined(HAVE_LUSB0_USB_H)
# include <lusb0_usb.h>
#else
# error "libusb needs either <usb.h> or <lusb0_usb.h>"
#endif
/* ------------------------------------------------------------------------- */
#define USBRQ_HID_GET_REPORT 0x01
#define USBRQ_HID_SET_REPORT 0x09
static int usesReportIDs;
/* ------------------------------------------------------------------------- */
static int usbGetStringAscii(usb_dev_handle *dev, int index, int langid, char *buf, int buflen)
{
char buffer[256];
int rval, i;
if((rval = usb_control_msg(dev, USB_ENDPOINT_IN, USB_REQ_GET_DESCRIPTOR,
(USB_DT_STRING << 8) + index, langid, buffer,
sizeof(buffer), 1000)) < 0)
return rval;
if(buffer[1] != USB_DT_STRING)
return 0;
if((unsigned char)buffer[0] < rval)
rval = (unsigned char)buffer[0];
rval /= 2;
/* lossy conversion to ISO Latin1 */
for(i=1;i<rval;i++){
if(i > buflen) /* destination buffer overflow */
break;
buf[i-1] = buffer[2 * i];
if(buffer[2 * i + 1] != 0) /* outside of ISO Latin1 range */
buf[i-1] = '?';
}
buf[i-1] = 0;
return i-1;
}
static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName,
int product, char *productName, int doReportIDs)
{
struct usb_bus *bus;
struct usb_device *dev;
usb_dev_handle *handle = NULL;
int errorCode = USB_ERROR_NOTFOUND;
static int didUsbInit = 0;
if(!didUsbInit){
usb_init();
didUsbInit = 1;
}
usb_find_busses();
usb_find_devices();
for(bus=usb_get_busses(); bus; bus=bus->next){
for(dev=bus->devices; dev; dev=dev->next){
if(dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product){
char string[256];
int len;
handle = usb_open(dev); /* we need to open the device in order to query strings */
if(!handle){
errorCode = USB_ERROR_ACCESS;
avrdude_message(MSG_INFO, "Warning: cannot open USB device: %s\n",
usb_strerror());
continue;
}
if(vendorName == NULL && productName == NULL){ /* name does not matter */
break;
}
/* now check whether the names match: */
len = usbGetStringAscii(handle, dev->descriptor.iManufacturer,
0x0409, string, sizeof(string));
if(len < 0){
errorCode = USB_ERROR_IO;
avrdude_message(MSG_INFO, "Warning: cannot query manufacturer for device: %s\n",
usb_strerror());
}else{
errorCode = USB_ERROR_NOTFOUND;
/* avrdude_message(MSG_INFO, "seen device from vendor ->%s<-\n", string); */
if(strcmp(string, vendorName) == 0){
len = usbGetStringAscii(handle, dev->descriptor.iProduct,
0x0409, string, sizeof(string));
if(len < 0){
errorCode = USB_ERROR_IO;
avrdude_message(MSG_INFO, "Warning: cannot query product for device: %s\n",
usb_strerror());
}else{
errorCode = USB_ERROR_NOTFOUND;
/* avrdude_message(MSG_INFO, "seen product ->%s<-\n", string); */
if(strcmp(string, productName) == 0)
break;
}
}
}
usb_close(handle);
handle = NULL;
}
}
if(handle)
break;
}
if(handle != NULL){
int rval, retries = 3;
if(usb_set_configuration(handle, 1)){
avrdude_message(MSG_INFO, "Warning: could not set configuration: %s\n",
usb_strerror());
}
/* now try to claim the interface and detach the kernel HID driver on
* linux and other operating systems which support the call.
*/
while((rval = usb_claim_interface(handle, 0)) != 0 && retries-- > 0){
#ifdef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
if(usb_detach_kernel_driver_np(handle, 0) < 0){
avrdude_message(MSG_INFO, "Warning: could not detach kernel HID driver: %s\n",
usb_strerror());
}
#endif
}
if(rval != 0)
avrdude_message(MSG_INFO, "Warning: could not claim interface\n");
/* Continue anyway, even if we could not claim the interface. Control transfers
* should still work.
*/
errorCode = 0;
fdp->pfd = (void *)handle;
usesReportIDs = doReportIDs;
}
return errorCode;
}
/* ------------------------------------------------------------------------- */
static void usbCloseDevice(union filedescriptor *fdp)
{
usb_close((usb_dev_handle *)fdp->pfd);
}
/* ------------------------------------------------------------------------- */
static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len)
{
int bytesSent;
if(!usesReportIDs){
buffer++; /* skip dummy report ID */
len--;
}
bytesSent = usb_control_msg((usb_dev_handle *)fdp->pfd, USB_TYPE_CLASS |
USB_RECIP_INTERFACE | USB_ENDPOINT_OUT, USBRQ_HID_SET_REPORT,
reportType << 8 | buffer[0], 0, buffer, len, 5000);
if(bytesSent != len){
if(bytesSent < 0)
avrdude_message(MSG_INFO, "Error sending message: %s\n", usb_strerror());
return USB_ERROR_IO;
}
return 0;
}
/* ------------------------------------------------------------------------- */
static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber,
char *buffer, int *len)
{
int bytesReceived, maxLen = *len;
if(!usesReportIDs){
buffer++; /* make room for dummy report ID */
maxLen--;
}
bytesReceived = usb_control_msg((usb_dev_handle *)fdp->pfd, USB_TYPE_CLASS |
USB_RECIP_INTERFACE | USB_ENDPOINT_IN, USBRQ_HID_GET_REPORT,
reportType << 8 | reportNumber, 0, buffer, maxLen, 5000);
if(bytesReceived < 0){
avrdude_message(MSG_INFO, "Error sending message: %s\n", usb_strerror());
return USB_ERROR_IO;
}
*len = bytesReceived;
if(!usesReportIDs){
buffer[-1] = reportNumber; /* add dummy report ID */
len++;
}
return 0;
}
#endif /* WIN32NATIVE */
/* ------------------------------------------------------------------------ */
@@ -555,4 +658,4 @@ struct serial_device avrdoper_serdev =
.flags = SERDEV_FL_NONE,
};
#endif /* defined(HAVE_LIBHIDAPI) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) */
#endif /* defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID)) */

View File

@@ -25,7 +25,6 @@
#if !defined(WIN32NATIVE)
#include "ac_cfg.h"
#include <ctype.h>
#include <stdio.h>
@@ -37,6 +36,10 @@
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#ifdef __linux__
#include <linux/serial.h>
#endif
#include <fcntl.h>
#include <termios.h>
@@ -52,8 +55,13 @@ struct baud_mapping {
speed_t speed;
};
/* There are a lot more baud rates we could handle, but what's the point? */
static struct termios original_termios;
static int saved_original_termios;
#if !defined __linux__
/* For linux this mapping is no longer needed.
* (OSX and *BSD do not need this mapping either because for them,
* Bxxx is the same as xxx.) */
static struct baud_mapping baud_lookup_table [] = {
{ 1200, B1200 },
{ 2400, B2400 },
@@ -73,8 +81,6 @@ 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)
{
@@ -95,12 +101,19 @@ static speed_t serial_baud_lookup(long baud)
return baud;
}
#endif
static int ser_setspeed(union filedescriptor *fd, long baud)
{
int rc;
struct termios termios;
#if defined __linux__
/* for linux no conversion is needed*/
speed_t speed = baud;
#else
/* converting the baud rate to the bit set needed by posix way*/
speed_t speed = serial_baud_lookup (baud);
#endif
if (!isatty(fd->ifd))
return -ENOTTY;
@@ -128,16 +141,79 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
termios.c_cflag = (CS8 | CREAD | CLOCAL);
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 0;
#ifdef __linux__
/* Support for custom baud rate for linux is implemented by setting
* a dummy baud rate of 38400 and manupulating the custom divider of
* the serial interface*/
struct serial_struct ss;
int ioret = ioctl(fd->ifd, TIOCGSERIAL, &ss);
if (ioret < 0){
avrdude_message(MSG_INFO,
"%s: Cannot get serial port settings. ioctl returned %d\n",
progname, ioret);
return -errno;
}
ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
ss.custom_divisor = (ss.baud_base + (speed / 2)) / speed;
unsigned int closestSpeed = ss.baud_base / ss.custom_divisor;
cfsetospeed(&termios, speed);
cfsetispeed(&termios, speed);
if (closestSpeed < speed * 98 / 100 || closestSpeed > speed * 102 / 100) {
avrdude_message(MSG_INFO,
"%s: Cannot set serial port speed to %d. Closest possible is %d\n",
progname, speed, closestSpeed);
return -errno;
}
ioret= ioctl(fd->ifd, TIOCSSERIAL, &ss);
if (ioret < 0){
avrdude_message(MSG_INFO,
"%s: Cannot set serial port speed to %d. ioctl returned %d\n",
progname, speed, ioret);
return -errno;
}
if (cfsetispeed(&termios, B38400) < 0){
avrdude_message(MSG_INFO,
"%s: cfsetispeed: failed to set dummy baud\n",
progname);
return -errno;
}
if (cfsetospeed(&termios, B38400) < 0){
avrdude_message(MSG_INFO,
"%s: cfsetospeed: failed to set dummy baud\n",
progname);
return -errno;
}
#else /* !linux */
if (cfsetospeed(&termios, speed) < 0){
avrdude_message(MSG_INFO,
"%s: cfsetospeed: failed to set speed: %d\n",
progname, speed);
return -errno;
}
if (cfsetispeed(&termios, speed) < 0){
avrdude_message(MSG_INFO,
"%s: cfsetispeed: failed to set speed: %d\n",
progname, speed);
return -errno;
}
#endif /* linux */
rc = tcsetattr(fd->ifd, TCSANOW, &termios);
if (rc < 0) {
avrdude_message(MSG_INFO, "%s: ser_setspeed(): tcsetattr() failed\n",
progname);
return -errno;
}
#ifdef __linux__
/* a bit more linux specific stuff to set custom baud rates*/
if (ioctl(fd->ifd, TIOCGSERIAL, &ss) < 0){
avrdude_message(MSG_INFO, "%s: ioctl: failed to get port settins\n", progname);
return -errno;
}
ss.flags &= ~ASYNC_SPD_MASK;
if (ioctl(fd->ifd, TIOCSSERIAL, &ss) < 0){
avrdude_message(MSG_INFO, "%s: ioctl: failed to set port settins\n", progname);
return -errno;
}
#endif
/*
* Everything is now set up for a local line without modem control
@@ -159,35 +235,23 @@ static int ser_setspeed(union filedescriptor *fd, long baud)
static int
net_open(const char *port, union filedescriptor *fdp)
{
#ifdef HAVE_GETADDRINFO
char *hp, *hstr, *pstr;
int s, fd, ret = -1;
struct addrinfo hints;
struct addrinfo *result, *rp;
char *hstr, *pstr, *end;
unsigned int pnum;
int fd;
struct sockaddr_in sockaddr;
struct hostent *hp;
if ((hstr = hp = strdup(port)) == NULL) {
if ((hstr = strdup(port)) == NULL) {
avrdude_message(MSG_INFO, "%s: net_open(): Out of memory!\n",
progname);
return -1;
}
/*
* As numeric IPv6 addresses use colons as separators, we need to
* look for the last colon here, which separates the port number or
* service name from the host or IP address.
*/
if (((pstr = strrchr(hstr, ':')) == NULL) || (pstr == hstr)) {
if (((pstr = strchr(hstr, ':')) == NULL) || (pstr == hstr)) {
avrdude_message(MSG_INFO, "%s: net_open(): Mangled host:port string \"%s\"\n",
progname, hstr);
goto error;
}
/*
* Remove brackets from the host part, if present.
*/
if (*hstr == '[' && *(pstr-1) == ']') {
hstr++;
*(pstr-1) = '\0';
free(hstr);
return -1;
}
/*
@@ -195,49 +259,43 @@ net_open(const char *port, union filedescriptor *fdp)
*/
*pstr++ = '\0';
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
s = getaddrinfo(hstr, pstr, &hints, &result);
pnum = strtoul(pstr, &end, 10);
if (s != 0) {
avrdude_message(MSG_INFO,
"%s: net_open(): Cannot resolve "
"host=\"%s\", port=\"%s\": %s\n",
progname, hstr, pstr, gai_strerror(s));
goto error;
if ((*pstr == '\0') || (*end != '\0') || (pnum == 0) || (pnum > 65535)) {
avrdude_message(MSG_INFO, "%s: net_open(): Bad port number \"%s\"\n",
progname, pstr);
free(hstr);
return -1;
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (fd == -1) {
/* This one failed, loop over */
continue;
}
if (connect(fd, rp->ai_addr, rp->ai_addrlen) != -1) {
/* Success, we are connected */
break;
}
close(fd);
if ((hp = gethostbyname(hstr)) == NULL) {
avrdude_message(MSG_INFO, "%s: net_open(): unknown host \"%s\"\n",
progname, hstr);
free(hstr);
return -1;
}
if (rp == NULL) {
avrdude_message(MSG_INFO, "%s: net_open(): Cannot connect: %s\n",
free(hstr);
if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n",
progname, strerror(errno));
return -1;
}
else {
fdp->ifd = fd;
ret = 0;
}
freeaddrinfo(result);
error:
free(hp);
return ret;
#else
avrdude_message(MSG_INFO,
"%s: Networking is not supported on your platform.\n"
"If you need it, please open a bug report.\n", progname);
return -1;
#endif /* HAVE_GETADDRINFO */
memset(&sockaddr, 0, sizeof(struct sockaddr_in));
sockaddr.sin_family = AF_INET;
sockaddr.sin_port = htons(pnum);
memcpy(&(sockaddr.sin_addr.s_addr), hp->h_addr, sizeof(struct in_addr));
if (connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))) {
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n",
progname, strerror(errno));
return -1;
}
fdp->ifd = fd;
return 0;
}

View File

@@ -628,95 +628,9 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
return 0;
}
#ifdef HAVE_LIBWS2_32
static int net_drain(union filedescriptor *fd, int display)
{
LPVOID lpMsgBuf;
struct timeval timeout;
fd_set rfds;
int nfds;
unsigned char buf;
int rc;
if (fd->ifd < 0) {
avrdude_message(MSG_INFO, "%s: ser_drain(): connection not open\n", progname);
exit(1);
}
if (display) {
avrdude_message(MSG_INFO, "drain>");
}
timeout.tv_sec = 0;
timeout.tv_usec = 250000;
while (1) {
FD_ZERO(&rfds);
FD_SET(fd->ifd, &rfds);
reselect:
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
if (nfds == 0) {
if (display) {
avrdude_message(MSG_INFO, "<drain\n");
}
break;
}
else if (nfds == -1) {
if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS) {
avrdude_message(MSG_NOTICE, "%s: ser_drain(): programmer is not responding, reselecting\n", progname);
goto reselect;
} else {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
avrdude_message(MSG_INFO, "%s: ser_drain(): select(): %s\n", progname, (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
exit(1);
}
}
rc = recv(fd->ifd, &buf, 1, 0);
if (rc < 0) {
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, (char *)lpMsgBuf);
LocalFree(lpMsgBuf);
exit(1);
}
if (display) {
avrdude_message(MSG_INFO, "%02x ", buf);
}
}
return 0;
}
#endif
static int ser_drain(union filedescriptor *fd, int display)
{
#ifdef HAVE_LIBWS2_32
if (serial_over_ethernet) {
return net_drain(fd, display);
}
#endif
// int rc;
unsigned char buf[10];
BOOL readres;

View File

@@ -1,7 +1,7 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bsdhome.com>
* Copyright (C) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.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

View File

@@ -1,7 +1,7 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2000, 2001, 2002, 2003 Brian S. Dean <bsd@bsdhome.com>
* Copyright (C) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.org>
* Copyright (C) 2006 Joerg Wunsch <j@uriah.heep.sax.de>
*
* This program is free software; you can redistribute it and/or modify

View File

@@ -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) 2005 Juliane Holzt <avrdude@juliane.holzt.de>
* Copyright (C) 2005 Michael Holzt <kju-avr@fqdn.org>
* Copyright (C) 2005, 2006 Joerg Wunsch <j@uriah.heep.sax.de>
*
* This program is free software; you can redistribute it and/or modify

View File

@@ -1118,7 +1118,7 @@ static int stk500_getparm(PROGRAMMER * pgm, unsigned parm, unsigned * value)
else if (buf[0] != Resp_STK_OK) {
avrdude_message(MSG_INFO, "\n%s: stk500_getparm(): (a) protocol error, "
"expect=0x%02x, resp=0x%02x\n",
progname, Resp_STK_OK, buf[0]);
progname, Resp_STK_INSYNC, buf[0]);
return -3;
}

View File

@@ -78,9 +78,17 @@
// Retry count
#define RETRIES 5
#define DEBUG(...) avrdude_message(MSG_TRACE2, __VA_ARGS__)
#if 0
#define DEBUG(...) avrdude_message(MSG_INFO, __VA_ARGS__)
#else
#define DEBUG(...)
#endif
#define DEBUGRECV(...) avrdude_message(MSG_TRACE2, __VA_ARGS__)
#if 0
#define DEBUGRECV(...) avrdude_message(MSG_INFO, __VA_ARGS__)
#else
#define DEBUGRECV(...)
#endif
enum hvmode
{
@@ -348,9 +356,6 @@ static void stk500v2_jtagmkII_teardown(PROGRAMMER * pgm)
{
void *mycookie;
free(PDATA(pgm)->flash_pagecache);
free(PDATA(pgm)->eeprom_pagecache);
mycookie = pgm->cookie;
pgm->cookie = PDATA(pgm)->chained_pdata;
jtagmkII_teardown(pgm);
@@ -573,7 +578,6 @@ static int stk500v2_jtagmkII_recv(PROGRAMMER * pgm, unsigned char *msg,
return -1;
}
memcpy(msg, jtagmsg + 1, rv - 1);
free(jtagmsg);
return rv;
}
@@ -1290,14 +1294,14 @@ static int stk500v2_initialize(PROGRAMMER * pgm, AVRPART * p)
for (ln = lfirst(p->mem); ln; ln = lnext(ln)) {
m = ldata(ln);
if (strcmp(m->desc, "flash") == 0) {
if (m->page_size > 1) {
if (m->page_size > 0) {
if (m->page_size > 256)
PDATA(pgm)->flash_pagesize = 256;
else
PDATA(pgm)->flash_pagesize = m->page_size;
}
} else if (strcmp(m->desc, "eeprom") == 0) {
if (m->page_size > 1)
if (m->page_size > 0)
PDATA(pgm)->eeprom_pagesize = m->page_size;
}
}
@@ -1389,14 +1393,14 @@ static int stk500v2_jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
for (ln = lfirst(p->mem); ln; ln = lnext(ln)) {
m = ldata(ln);
if (strcmp(m->desc, "flash") == 0) {
if (m->page_size > 1) {
if (m->page_size > 0) {
if (m->page_size > 256)
PDATA(pgm)->flash_pagesize = 256;
else
PDATA(pgm)->flash_pagesize = m->page_size;
}
} else if (strcmp(m->desc, "eeprom") == 0) {
if (m->page_size > 1)
if (m->page_size > 0)
PDATA(pgm)->eeprom_pagesize = m->page_size;
}
}
@@ -1460,14 +1464,14 @@ static int stk500hv_initialize(PROGRAMMER * pgm, AVRPART * p, enum hvmode mode)
for (ln = lfirst(p->mem); ln; ln = lnext(ln)) {
m = ldata(ln);
if (strcmp(m->desc, "flash") == 0) {
if (m->page_size > 1) {
if (m->page_size > 0) {
if (m->page_size > 256)
PDATA(pgm)->flash_pagesize = 256;
else
PDATA(pgm)->flash_pagesize = m->page_size;
}
} else if (strcmp(m->desc, "eeprom") == 0) {
if (m->page_size > 1)
if (m->page_size > 0)
PDATA(pgm)->eeprom_pagesize = m->page_size;
}
}
@@ -1613,11 +1617,11 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port)
PDATA(pgm)->pgmtype = PGMTYPE_UNKNOWN;
if(strcasecmp(port, "avrdoper") == 0){
#if defined(HAVE_LIBHIDAPI) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID))
#if defined(HAVE_LIBUSB) || (defined(WIN32NATIVE) && defined(HAVE_LIBHID))
serdev = &avrdoper_serdev;
PDATA(pgm)->pgmtype = PGMTYPE_STK500;
#else
avrdude_message(MSG_INFO, "avrdoper requires avrdude with hid support.\n");
avrdude_message(MSG_INFO, "avrdude was compiled without usb support.\n");
return -1;
#endif
}
@@ -2172,9 +2176,6 @@ static int stk500isp_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
paddr = addr & ~(pagesize - 1);
paddr_ptr = &PDATA(pgm)->flash_pageaddr;
cache_ptr = PDATA(pgm)->flash_pagecache;
if ((mem->mode & 1) == 0)
/* old, unpaged device, really write single bytes */
pagesize = 1;
} else {
pagesize = mem->page_size;
if (pagesize == 0)
@@ -2823,17 +2824,11 @@ static int stk500v2_set_sck_period_mk2(PROGRAMMER * pgm, double v)
{
int i;
for (i = 0; i < sizeof(avrispmkIIfreqs) / sizeof(avrispmkIIfreqs[0]); i++) {
for (i = 0; i < sizeof(avrispmkIIfreqs); i++) {
if (1 / avrispmkIIfreqs[i] >= v)
break;
}
if (i >= sizeof(avrispmkIIfreqs) / sizeof(avrispmkIIfreqs[0])) {
avrdude_message(MSG_INFO, "%s: stk500v2_set_sck_period_mk2(): "
"invalid SCK period: %g\n", progname, v);
return -1;
}
avrdude_message(MSG_NOTICE2, "Using p = %.2f us for SCK (param = %d)\n",
1000000 / avrispmkIIfreqs[i], i);
@@ -3158,9 +3153,8 @@ static const char *stk600_get_cardname(const struct carddata *table,
static void stk500v2_display(PROGRAMMER * pgm, const char * p)
{
unsigned char maj = 0, min = 0, hdw = 0, topcard = 0,
maj_s1 = 0, min_s1 = 0, maj_s2 = 0, min_s2 = 0;
unsigned int rev = 0;
unsigned char maj, min, hdw, topcard, maj_s1, min_s1, maj_s2, min_s2;
unsigned int rev;
const char *topcard_name, *pgmname;
switch (PDATA(pgm)->pgmtype) {
@@ -3731,7 +3725,7 @@ static int stk600_xprog_program_enable(PROGRAMMER * pgm, AVRPART * p)
return -1;
}
if ((mem = avr_locate_mem(p, "eeprom")) != NULL) {
if (mem->page_size <= 1) {
if (mem->page_size == 0) {
avrdude_message(MSG_INFO, "%s: stk600_xprog_program_enable(): no EEPROM page_size parameter for PDI device\n",
progname);
return -1;
@@ -3938,8 +3932,7 @@ static int stk600_xprog_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
b[1] = XPRG_MEM_TYPE_FUSE;
} else if (strncmp(mem->desc, "lock", strlen("lock")) == 0) {
b[1] = XPRG_MEM_TYPE_LOCKBITS;
} else if (strcmp(mem->desc, "calibration") == 0 ||
strcmp(mem->desc, "prodsig") == 0) {
} else if (strcmp(mem->desc, "calibration") == 0) {
b[1] = XPRG_MEM_TYPE_FACTORY_CALIBRATION;
} else if (strcmp(mem->desc, "usersig") == 0) {
b[1] = XPRG_MEM_TYPE_USERSIG;
@@ -4013,8 +4006,7 @@ static int stk600_xprog_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
memtype = XPRG_MEM_TYPE_FUSE;
} else if (strncmp(mem->desc, "lock", strlen("lock")) == 0) {
memtype = XPRG_MEM_TYPE_LOCKBITS;
} else if (strcmp(mem->desc, "calibration") == 0 ||
strcmp(mem->desc, "prodsig") == 0) {
} else if (strcmp(mem->desc, "calibration") == 0) {
memtype = XPRG_MEM_TYPE_FACTORY_CALIBRATION;
} else if (strcmp(mem->desc, "usersig") == 0) {
memtype = XPRG_MEM_TYPE_USERSIG;

13
term.c
View File

@@ -342,7 +342,7 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
if (argc < 4) {
avrdude_message(MSG_INFO, "Usage: write <memtype> <addr> <byte1> "
"<byte2> ... <byteN>\n");
"<byte2> ... byteN>\n");
return -1;
}
@@ -624,7 +624,7 @@ static int cmd_fosc(PROGRAMMER * pgm, struct avrpart * p,
return -2;
}
if ((rc = pgm->set_fosc(pgm, v)) != 0) {
avrdude_message(MSG_INFO, "%s (fosc): failed to set oscillator frequency (rc = %d)\n",
avrdude_message(MSG_INFO, "%s (fosc): failed to set oscillator_frequency (rc = %d)\n",
progname, rc);
return -3;
}
@@ -780,12 +780,11 @@ static int cmd_verbose(PROGRAMMER * pgm, struct avrpart * p,
static int tokenize(char * s, char *** argv)
{
int i, n, l, k, nargs, offset;
int i, n, l, nargs, offset;
int len, slen;
char * buf;
int bufsize;
char ** bufv;
char * bufp;
char * q, * r;
char * nbuf;
char ** av;
@@ -822,15 +821,9 @@ static int tokenize(char * s, char *** argv)
/* realloc space for another 20 args */
bufsize += 20;
nargs += 20;
bufp = buf;
buf = realloc(buf, bufsize);
bufv = realloc(bufv, nargs*sizeof(char *));
nbuf = &buf[l];
/* correct bufv pointers */
k = buf - bufp;
for (i=0; i<n; i++) {
bufv[i] = bufv[i] + k;
}
for (i=n; i<nargs; i++)
bufv[i] = NULL;
}

View File

@@ -1,229 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:f="http://functions"
exclude-result-prefixes="xs f"
version="2.0">
<!--
avrdude - A Downloader/Uploader for AVR device programmers
Copyright (C) 2018 Morten Engelhardt Olsen <meolsen@atmel.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/>.
-->
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:variable name="architecture"
select="/avr-tools-device-file/devices/device/@architecture"/>
<xsl:choose>
<xsl:when test="$architecture = 'AVR8X'">
<xsl:call-template name="create-avr8x-config"/>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">No support for architecture '<xsl:value-of select="$architecture"/>'</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="create-avr8x-config">
<xsl:variable name="device-name"
select="/avr-tools-device-file/devices/device/@name"/>
<xsl:variable name="device-id">
<xsl:call-template name="get-device-id">
<xsl:with-param name="device-name" select="$device-name"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="parent-name">
<xsl:call-template name="get-parent-name">
<xsl:with-param name="device-name" select="$device-name"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="device-signature">
<xsl:call-template name="get-device-signature">
<xsl:with-param name="device-name" select="$device-name"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="write-conf-header">
<xsl:with-param name="device-name" select="$device-name"/>
</xsl:call-template>
<xsl:text>part parent "</xsl:text><xsl:value-of select="normalize-space($parent-name)"/><xsl:text>";&#xa;</xsl:text>
<xsl:text> id = "</xsl:text><xsl:value-of select="normalize-space($device-id)"/><xsl:text>";&#xa;</xsl:text>
<xsl:text> desc = "</xsl:text><xsl:value-of select="normalize-space($device-name)"/><xsl:text>";&#xa;</xsl:text>
<xsl:text> signature = </xsl:text><xsl:value-of select="normalize-space($device-signature)"/><xsl:text>;&#xa;</xsl:text>
<xsl:call-template name="write-memories">
<xsl:with-param name="device-name" select="$device-name"/>
</xsl:call-template>
<xsl:text>;&#xa;</xsl:text>
</xsl:template>
<xsl:template name="write-memories">
<xsl:param name="device-name"/>
<xsl:call-template name="write-memory">
<xsl:with-param name="memory-name" select="'PROGMEM'"/>
</xsl:call-template>
<xsl:call-template name="write-memory">
<xsl:with-param name="memory-name" select="'EEPROM'"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="write-memory">
<xsl:param name="memory-name"/>
<xsl:variable name="memory-segment" select="//memory-segment[@name = $memory-name]"/>
<xsl:choose>
<xsl:when test="not($memory-segment)">
<xsl:message terminate="yes">No memory-segment named '<xsl:value-of select="$memory-name"/>'</xsl:message>
</xsl:when>
<xsl:when test="count($memory-segment) > 1">
<xsl:message terminate="yes">More than one memory-segments named '<xsl:value-of select="$memory-name"/>'</xsl:message>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="write-memory-segment">
<xsl:with-param name="memory-segment" select="$memory-segment"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="write-memory-segment">
<xsl:param name="memory-segment"/>
<xsl:variable name="size">
<xsl:value-of select="concat('0x', f:decimalToHex(f:hexToDec($memory-segment/@size)))"/>
</xsl:variable>
<xsl:variable name="offset">
<xsl:choose>
<xsl:when test="$memory-segment/@type = 'flash' and $memory-segment/ancestor::device/@architecture = 'AVR8X'">
<xsl:variable name="progmem-base"
select="f:hexToDec($memory-segment/ancestor::device/property-groups/property-group[@name = 'UPDI_INTERFACE']/property[@name = 'PROGMEM_OFFSET']/@value)"/>
<xsl:value-of select="concat('0x', f:decimalToHex(f:hexToDec($memory-segment/@start) + $progmem-base))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat('0x', f:decimalToHex(f:hexToDec($memory-segment/@start)))"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:text>&#xa;</xsl:text>
<xsl:text> memory "</xsl:text><xsl:value-of select="$memory-segment/@type"/><xsl:text>"&#xa;</xsl:text>
<xsl:text> size = </xsl:text><xsl:value-of select="$size"/><xsl:text>;&#xa;</xsl:text>
<xsl:text> offset = </xsl:text><xsl:value-of select="$offset"/><xsl:text>;&#xa;</xsl:text>
<xsl:text> page_size = </xsl:text><xsl:value-of select="$memory-segment/@pagesize"/><xsl:text>;&#xa;</xsl:text>
<xsl:text> readsize = 0x100;&#xa;</xsl:text>
<xsl:text> ;&#xa;</xsl:text>
</xsl:template>
<xsl:template name="write-conf-header">
<xsl:param name="device-name"/>
<xsl:text>#------------------------------------------------------------&#xa;</xsl:text>
<xsl:text># </xsl:text><xsl:value-of select="$device-name"/><xsl:text>&#xa;</xsl:text>
<xsl:text>#------------------------------------------------------------&#xa;</xsl:text>
<xsl:text>&#xa;</xsl:text>
</xsl:template>
<xsl:template name="get-device-id">
<xsl:param name="device-name"/>
<xsl:choose>
<xsl:when test="contains($device-name, 'ATtiny')">
<xsl:value-of select="replace($device-name, 'ATtiny', 't')"/>
</xsl:when>
<xsl:when test="contains($device-name, 'ATmega')">
<xsl:value-of select="replace($device-name, 'ATmega', 'm')"/>
</xsl:when>
<xsl:when test="starts-with($device-name, 'AVR')">
<xsl:value-of select="lower-case($device-name)"/>
</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">Unable to deduce device id from '<xsl:value-of select="$device-name"/>'</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="get-parent-name">
<xsl:param name="device-name"/>
<xsl:choose>
<xsl:when test="contains($device-name, 'ATtiny')">.avr8x_tiny</xsl:when>
<xsl:when test="contains($device-name, 'ATmega')">.avr8x_mega</xsl:when>
<xsl:when test="matches($device-name, '^AVR[0-9]{1,3}D')">.avrdx</xsl:when>
<xsl:when test="matches($device-name, '^AVR[0-9]{1,3}E')">.avrex</xsl:when>
<xsl:otherwise>
<xsl:message terminate="yes">Unable to deduce parent name from '<xsl:value-of select="$device-name"/>'</xsl:message>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="get-device-signature">
<xsl:param name="device-name"/>
<xsl:variable name="signatures"
select="/avr-tools-device-file/devices/device/property-groups/property-group[@name = 'SIGNATURES']"/>
<xsl:for-each select="$signatures/property[contains(@name, 'SIGNATURE')]">
<xsl:value-of select="@value"/><xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
<!-- Helper functions (from https://stackoverflow.com/questions/22905134/convert-a-hexadecimal-number-to-an-integer-in-xslt) -->
<xsl:function name="f:hexToDec">
<xsl:param name="hex"/>
<xsl:variable name="dec"
select="string-length(substring-before('0123456789ABCDEF', substring($hex,1,1)))"/>
<xsl:choose>
<xsl:when test="matches($hex, '([0-9]*|[A-F]*)')">
<xsl:value-of
select="if ($hex = '') then 0
else $dec * f:power(16, string-length($hex) - 1) + f:hexToDec(substring($hex,2))"/>
</xsl:when>
<xsl:otherwise>
<xsl:message>Provided value is not hexadecimal...</xsl:message>
<xsl:value-of select="$hex"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
<xsl:function name="f:power">
<xsl:param name="base"/>
<xsl:param name="exp"/>
<xsl:sequence
select="if ($exp lt 0) then f:power(1.0 div $base, -$exp)
else if ($exp eq 0)
then 1e0
else $base * f:power($base, $exp - 1)"
/>
</xsl:function>
<xsl:function name="f:decimalToHex">
<xsl:param name="dec"/>
<xsl:if test="$dec > 0">
<xsl:value-of
select="f:decimalToHex(floor($dec div 16)),substring('0123456789ABCDEF', (($dec mod 16) + 1), 1)"
separator=""
/>
</xsl:if>
</xsl:function>
</xsl:stylesheet>

View File

@@ -40,8 +40,8 @@ mkdir -p ${BUILDDIR} || { echo "Cannot create build dir $BUILDDIR"; exit 1; }
cd ${BUILDDIR} || { echo "Cannot chdir to $BUILDDIR"; exit 1; }
LDFLAGS="-L${MINGW32_PREFIX}/lib -L${LIBUSB_PREFIX}/lib/gcc -L/tmp/libftdi1-1.3git_devkit_mingw32_13Dec2015/lib"
CPPFLAGS="-I${MINGW32_PREFIX}/include -I${LIBUSB_PREFIX}/include -I/tmp/libftdi1-1.3git_devkit_mingw32_13Dec2015/include"
LDFLAGS="-L${MINGW32_PREFIX}/lib -L${LIBUSB_PREFIX}/lib/gcc"
CPPFLAGS="-I${MINGW32_PREFIX}/include -I${LIBUSB_PREFIX}/include"
env \
CC="${CC}" \
@@ -51,4 +51,4 @@ env \
--host=$(../../config.guess) \
--target=${tgt}
${MAKE:-make} all
make all

View File

@@ -113,9 +113,7 @@ UPDATE * parse_op(char * s)
cp = p;
p = strrchr(cp, ':');
if (p == NULL) {
// missing format, default to "AUTO" for write and verify,
// and to binary for read operations:
upd->format = upd->op == DEVICE_READ? FMT_RBIN: FMT_AUTO;
upd->format = FMT_AUTO;
fnlen = strlen(cp);
upd->filename = (char *)malloc(fnlen + 1);
} else {
@@ -230,12 +228,6 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
/*
* read out the specified device memory and write it to a file
*/
if (upd->format == FMT_IMM) {
avrdude_message(MSG_INFO,
"%s: Invalid file format 'immediate' for output\n",
progname, upd->filename);
return -1;
}
if (quell_progress < 2) {
avrdude_message(MSG_INFO, "%s: reading %s memory:\n",
progname, mem->desc);
@@ -354,7 +346,6 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n",
progname, mem->desc, rc);
pgm->err_led(pgm, ON);
avr_free_part(v);
return -1;
}
report_progress (1,1,NULL);
@@ -369,7 +360,6 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
avrdude_message(MSG_INFO, "%s: verification error; content mismatch\n",
progname);
pgm->err_led(pgm, ON);
avr_free_part(v);
return -1;
}
@@ -379,7 +369,6 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
}
pgm->vfy_led(pgm, OFF);
avr_free_part(v);
}
else {
avrdude_message(MSG_INFO, "%s: invalid update operation (%d) requested\n",

View File

@@ -1,357 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2016 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
* 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/>.
*/
/* $Id$ */
/*
* USB interface via libhidapi for avrdude.
*/
#include "ac_cfg.h"
#if defined(HAVE_LIBHIDAPI)
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/time.h>
#include <wchar.h>
#include <hidapi/hidapi.h>
#include "avrdude.h"
#include "libavrdude.h"
#include "usbdevs.h"
#if defined(WIN32NATIVE)
/* someone has defined "interface" to "struct" in Cygwin */
# undef interface
#endif
/*
* The "baud" parameter is meaningless for USB devices, so we reuse it
* to pass the desired USB device ID.
*/
static int usbhid_open(char * port, union pinfo pinfo, union filedescriptor *fd)
{
hid_device *dev;
char *serno, *cp2;
size_t x;
unsigned char usbbuf[USBDEV_MAX_XFER_3 + 1];
if (fd->usb.max_xfer == 0)
fd->usb.max_xfer = USBDEV_MAX_XFER_3;
/*
* The syntax for usb devices is defined as:
*
* -P usb[:serialnumber]
*
* See if we've got a serial number passed here. The serial number
* might contain colons which we remove below, and we compare it
* right-to-left, so only the least significant nibbles need to be
* specified.
*/
if ((serno = strchr(port, ':')) != NULL)
{
/* first, drop all colons there if any */
cp2 = ++serno;
while ((cp2 = strchr(cp2, ':')) != NULL)
{
x = strlen(cp2) - 1;
memmove(cp2, cp2 + 1, x);
cp2[x] = '\0';
}
if (strlen(serno) > 12)
{
avrdude_message(MSG_INFO, "%s: usbhid_open(): invalid serial number \"%s\"\n",
progname, serno);
return -1;
}
wchar_t wserno[15];
mbstowcs(wserno, serno, 15);
size_t serlen = strlen(serno);
/*
* Now, try finding all devices matching VID:PID, and compare
* their serial numbers against the requested one.
*/
struct hid_device_info *list, *walk;
list = hid_enumerate(pinfo.usbinfo.vid, pinfo.usbinfo.pid);
if (list == NULL)
return -1;
walk = list;
while (walk)
{
avrdude_message(MSG_NOTICE, "%s: usbhid_open(): Found %ls, serno: %ls\n",
progname, walk->product_string, walk->serial_number);
size_t slen = wcslen(walk->serial_number);
if (slen >= serlen &&
wcscmp(walk->serial_number + slen - serlen, wserno) == 0)
{
/* found matching serial number */
break;
}
avrdude_message(MSG_DEBUG, "%s: usbhid_open(): serial number doesn't match\n",
progname);
walk = walk->next;
}
if (walk == NULL)
{
avrdude_message(MSG_INFO, "%s: usbhid_open(): No matching device found\n",
progname);
hid_free_enumeration(list);
return -1;
}
avrdude_message(MSG_DEBUG, "%s: usbhid_open(): Opening path %s\n",
progname, walk->path);
dev = hid_open_path(walk->path);
hid_free_enumeration(list);
if (dev == NULL)
{
avrdude_message(MSG_INFO,
"%s: usbhid_open(): Found device, but hid_open_path() failed\n",
progname);
return -1;
}
}
else
{
/*
* No serial number requested, pass straight to hid_open()
*/
dev = hid_open(pinfo.usbinfo.vid, pinfo.usbinfo.pid, NULL);
if (dev == NULL)
{
avrdude_message(MSG_INFO, "%s: usbhid_open(): No device found\n",
progname);
return -1;
}
}
fd->usb.handle = dev;
/*
* Try finding out the endpoint size. Alas, libhidapi doesn't
* provide us with an API function for that, nor for the report
* descriptor (which also contains that information).
*
* Since the Atmel tools a very picky to only respond to incoming
* packets that have full size, we need to know whether our device
* handles 512-byte data (JTAGICE3 in CMSIS-DAP mode, or AtmelICE,
* both on USB 2.0 connections), or 64-byte data only (both these on
* USB 1.1 connections, or mEDBG devices).
*
* In order to find out, we send a CMSIS-DAP DAP_Info command
* (0x00), with an ID of 0xFF (get maximum packet size). In theory,
* this gets us the desired information, but this suffers from a
* chicken-and-egg problem: the request must be sent with a
* full-sized packet lest the ICE won't answer. Thus, we send a
* 64-byte packet first, and if we don't get a timely reply,
* complete that request by sending another 448 bytes, and hope it
* will eventually reply.
*
* Note that libhidapi always requires a report ID as the first
* byte. If the target doesn't use report IDs (Atmel targets
* don't), this first byte must be 0x00. However, the length must
* be incremented by one, as the report ID will be omitted by the
* hidapi library.
*/
if (pinfo.usbinfo.vid == USB_VENDOR_ATMEL)
{
avrdude_message(MSG_DEBUG, "%s: usbhid_open(): Probing for max. packet size\n",
progname);
memset(usbbuf, 0, sizeof usbbuf);
usbbuf[0] = 0; /* no HID reports used */
usbbuf[1] = 0; /* DAP_Info */
usbbuf[2] = 0xFF; /* get max. packet size */
hid_write(dev, usbbuf, 65);
fd->usb.max_xfer = 64; /* first guess */
memset(usbbuf, 0, sizeof usbbuf);
int res = hid_read_timeout(dev, usbbuf, 10 /* bytes */, 50 /* milliseconds */);
if (res == 0) {
/* no timely response, assume 512 byte size */
hid_write(dev, usbbuf, (512 - 64) + 1);
fd->usb.max_xfer = 512;
res = hid_read_timeout(dev, usbbuf, 10, 50);
}
if (res <= 0) {
avrdude_message(MSG_INFO, "%s: usbhid_open(): No response from device\n",
progname);
hid_close(dev);
return -1;
}
if (usbbuf[0] != 0 || usbbuf[1] != 2) {
avrdude_message(MSG_INFO,
"%s: usbhid_open(): Unexpected reply to DAP_Info: 0x%02x 0x%02x\n",
progname, usbbuf[0], usbbuf[1]);
} else {
fd->usb.max_xfer = usbbuf[2] + (usbbuf[3] << 8);
avrdude_message(MSG_DEBUG,
"%s: usbhid_open(): Setting max_xfer from DAP_Info response to %d\n",
progname, fd->usb.max_xfer);
}
}
if (fd->usb.max_xfer > USBDEV_MAX_XFER_3) {
avrdude_message(MSG_INFO,
"%s: usbhid_open(): Unexpected max size %d, reducing to %d\n",
progname, fd->usb.max_xfer, USBDEV_MAX_XFER_3);
fd->usb.max_xfer = USBDEV_MAX_XFER_3;
}
return 0;
}
static void usbhid_close(union filedescriptor *fd)
{
hid_device *udev = (hid_device *)fd->usb.handle;
if (udev == NULL)
return;
hid_close(udev);
}
static int usbhid_send(union filedescriptor *fd, const unsigned char *bp, size_t mlen)
{
hid_device *udev = (hid_device *)fd->usb.handle;
int rv;
int i = mlen;
const unsigned char * p = bp;
unsigned char usbbuf[USBDEV_MAX_XFER_3 + 1];
int tx_size;
if (udev == NULL)
return -1;
tx_size = (mlen < USBDEV_MAX_XFER_3)? mlen: USBDEV_MAX_XFER_3;
usbbuf[0] = 0; /* no report ID used */
memcpy(usbbuf + 1, bp, tx_size);
rv = hid_write(udev, usbbuf, tx_size + 1);
if (rv < 0) {
avrdude_message(MSG_INFO, "%s: Failed to write %d bytes to USB\n",
progname, tx_size);
return -1;
}
if (rv != tx_size + 1)
avrdude_message(MSG_INFO, "%s: Short write to USB: %d bytes out of %d written\n",
progname, rv, tx_size + 1);
if (verbose > 4)
{
avrdude_message(MSG_TRACE2, "%s: Sent: ", progname);
while (i) {
unsigned char c = *p;
if (isprint(c)) {
avrdude_message(MSG_TRACE2, "%c ", c);
}
else {
avrdude_message(MSG_TRACE2, ". ");
}
avrdude_message(MSG_TRACE2, "[%02x] ", c);
p++;
i--;
}
avrdude_message(MSG_TRACE2, "\n");
}
return 0;
}
static int usbhid_recv(union filedescriptor *fd, unsigned char *buf, size_t nbytes)
{
hid_device *udev = (hid_device *)fd->usb.handle;
int i, rv;
unsigned char * p = buf;
if (udev == NULL)
return -1;
rv = i = hid_read_timeout(udev, buf, nbytes, 300);
if (i != nbytes)
avrdude_message(MSG_INFO,
"%s: Short read, read only %d out of %u bytes\n",
progname, i, nbytes);
if (verbose > 4)
{
avrdude_message(MSG_TRACE2, "%s: Recv: ", progname);
while (i) {
unsigned char c = *p;
if (isprint(c)) {
avrdude_message(MSG_TRACE2, "%c ", c);
}
else {
avrdude_message(MSG_TRACE2, ". ");
}
avrdude_message(MSG_TRACE2, "[%02x] ", c);
p++;
i--;
}
avrdude_message(MSG_TRACE2, "\n");
}
return rv;
}
static int usbhid_drain(union filedescriptor *fd, int display)
{
/*
* There is not much point in trying to flush any data
* on an USB endpoint, as the endpoint is supposed to
* start afresh after being configured from the host.
*
* As trying to flush the data here caused strange effects
* in some situations (see
* https://savannah.nongnu.org/bugs/index.php?43268 )
* better avoid it.
*/
return 0;
}
/*
* Device descriptor.
*/
struct serial_device usbhid_serdev =
{
.open = usbhid_open,
.close = usbhid_close,
.send = usbhid_send,
.recv = usbhid_recv,
.drain = usbhid_drain,
.flags = SERDEV_FL_NONE,
};
#endif /* HAVE_LIBHIDAPI */

View File

@@ -166,13 +166,6 @@ static int usbdev_open(char * port, union pinfo pinfo, union filedescriptor *fd)
fd->usb.eep = 0;
}
if(strstr(product, "mEDBG") != NULL)
{
/* The AVR Xplained Mini uses different endpoints. */
fd->usb.rep = 0x81;
fd->usb.wep = 0x02;
}
avrdude_message(MSG_NOTICE, "%s: usbdev_open(): Found %s, serno: %s\n",
progname, product, string);
if (serno != NULL)
@@ -360,7 +353,7 @@ static int usbdev_send(union filedescriptor *fd, const unsigned char *bp, size_t
}
bp += tx_size;
mlen -= tx_size;
} while (mlen > 0);
} while (tx_size == fd->usb.max_xfer);
if (verbose > 3)
{

107
usbasp.c
View File

@@ -120,8 +120,6 @@ struct pdata
int sckfreq_hz;
unsigned int capabilities;
int use_tpi;
int section_e;
int sck_3mhz;
};
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
@@ -133,7 +131,6 @@ struct pdata
// interface - management
static void usbasp_setup(PROGRAMMER * pgm);
static void usbasp_teardown(PROGRAMMER * pgm);
static int usbasp_parseextparms(PROGRAMMER * pgm, LISTID extparms);
// internal functions
static int usbasp_transmit(PROGRAMMER * pgm, unsigned char receive,
unsigned char functionid, const unsigned char *send,
@@ -195,31 +192,6 @@ static void usbasp_teardown(PROGRAMMER * pgm)
free(pgm->cookie);
}
static int usbasp_parseextparms(PROGRAMMER * pgm, LISTID extparms)
{
LNODEID ln;
const char *extended_param;
int rv = 0;
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
extended_param = ldata(ln);
if (strncmp(extended_param, "section_config", strlen("section_config")) == 0) {
avrdude_message(MSG_NOTICE2, "%s: usbasp_parseextparms(): set section_e to 1 (config section)\n",
progname);
PDATA(pgm)->section_e = 1;
continue;
}
avrdude_message(MSG_INFO, "%s: usbasp_parseextparms(): invalid extended parameter '%s'\n",
progname, extended_param);
rv = -1;
}
return rv;
}
/* Internal functions */
static const char *usbasp_get_funcname(unsigned char functionid)
@@ -598,9 +570,6 @@ static int usbasp_initialize(PROGRAMMER * pgm, AVRPART * p)
pdata->capabilities = 0;
pdata->use_tpi = ((pdata->capabilities & USBASP_CAP_TPI) != 0 && (p->flags & AVRPART_HAS_TPI) != 0) ? 1 : 0;
// query support for 3 MHz SCK in UsbAsp-flash firmware
// https://github.com/nofeletru/UsbAsp-flash
pdata->sck_3mhz = ((pdata->capabilities & USBASP_CAP_3MHZ) != 0) ? 1 :0;
if(pdata->use_tpi)
{
@@ -666,7 +635,7 @@ static int usbasp_spi_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
if (verbose == 3)
putc('\n', stderr);
avrdude_message(MSG_INFO, "%s: error: wrong response size\n",
avrdude_message(MSG_INFO, "%s: error: wrong responds size\n",
progname);
return -1;
}
@@ -867,7 +836,6 @@ static int usbasp_spi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
/* The list of SCK frequencies in Hz supported by USBasp */
static struct sckoptions_t usbaspSCKoptions[] = {
{ USBASP_ISP_SCK_3000, 3000000 },
{ USBASP_ISP_SCK_1500, 1500000 },
{ USBASP_ISP_SCK_750, 750000 },
{ USBASP_ISP_SCK_375, 375000 },
@@ -913,23 +881,14 @@ static int usbasp_spi_set_sck_period(PROGRAMMER *pgm, double sckperiod)
avrdude_message(MSG_NOTICE2, "%s: try to set SCK period to %g s (= %i Hz)\n", progname, sckperiod, sckfreq);
/* Check if programmer is capable of 3 MHz SCK, if not then ommit 3 MHz setting */
int i;
if (PDATA(pgm)->sck_3mhz) {
avrdude_message(MSG_NOTICE2, "%s: connected USBasp is capable of 3 MHz SCK\n",progname);
i = 0;
} else {
avrdude_message(MSG_NOTICE2, "%s: connected USBasp is not cabable of 3 MHz SCK\n",progname);
i = 1;
}
if (sckfreq >= usbaspSCKoptions[i].frequency) {
clockoption = usbaspSCKoptions[i].id;
usefreq = usbaspSCKoptions[i].frequency;
if (sckfreq >= usbaspSCKoptions[0].frequency) {
clockoption = usbaspSCKoptions[0].id;
usefreq = usbaspSCKoptions[0].frequency;
} else {
/* find clock option next to given clock */
for (; i < sizeof(usbaspSCKoptions) / sizeof(usbaspSCKoptions[0]); i++) {
int i;
for (i = 0; i < sizeof(usbaspSCKoptions) / sizeof(usbaspSCKoptions[0]); i++) {
if (sckfreq >= usbaspSCKoptions[i].frequency - 1) { /* subtract 1 to compensate round errors */
clockoption = usbaspSCKoptions[i].id;
usefreq = usbaspSCKoptions[i].frequency;
@@ -977,7 +936,7 @@ static int usbasp_tpi_recv_byte(PROGRAMMER * pgm)
if(usbasp_transmit(pgm, 1, USBASP_FUNC_TPI_RAWREAD, temp, temp, sizeof(temp)) != 1)
{
avrdude_message(MSG_INFO, "%s: error: wrong response size\n", progname);
avrdude_message(MSG_INFO, "%s: error: wrong responds size\n", progname);
return -1;
}
@@ -1056,40 +1015,21 @@ static int usbasp_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p)
static int usbasp_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
{
int pr_0;
int pr_1;
int nvm_cmd;
avrdude_message(MSG_DEBUG, "%s: usbasp_tpi_chip_erase()\n", progname);
switch (PDATA(pgm)->section_e) {
/* Config bits section erase */
case 1:
pr_0 = 0x41;
pr_1 = 0x3F;
nvm_cmd = NVMCMD_SECTION_ERASE;
avrdude_message(MSG_DEBUG, "%s: usbasp_tpi_chip_erase() - section erase\n", progname);
break;
/* Chip erase (flash only) */
default:
pr_0 = 0x01;
pr_1 = 0x40;
nvm_cmd = NVMCMD_CHIP_ERASE;
avrdude_message(MSG_DEBUG, "%s: usbasp_tpi_chip_erase() - chip erase\n", progname);
break;
}
/* Set PR */
/* Set PR to flash */
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(0));
usbasp_tpi_send_byte(pgm, pr_0);
usbasp_tpi_send_byte(pgm, 0x01);
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(1));
usbasp_tpi_send_byte(pgm, pr_1);
/* select what been erase */
usbasp_tpi_send_byte(pgm, 0x40);
/* select ERASE */
usbasp_tpi_send_byte(pgm, TPI_OP_SOUT(NVMCMD));
usbasp_tpi_send_byte(pgm, nvm_cmd);
usbasp_tpi_send_byte(pgm, NVMCMD_CHIP_ERASE);
/* dummy write */
usbasp_tpi_send_byte(pgm, TPI_OP_SST_INC);
usbasp_tpi_send_byte(pgm, 0x00);
usbasp_tpi_nvm_waitbusy(pgm);
usleep(p->chip_erase_delay);
pgm->initialize(pgm, p);
@@ -1156,24 +1096,6 @@ static int usbasp_tpi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
pr = addr + m->offset;
writed = 0;
/* must erase fuse first */
if(strcmp(m->desc, "fuse") == 0)
{
/* Set PR */
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(0));
usbasp_tpi_send_byte(pgm, (pr & 0xFF) | 1 );
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(1));
usbasp_tpi_send_byte(pgm, (pr >> 8) );
/* select SECTION_ERASE */
usbasp_tpi_send_byte(pgm, TPI_OP_SOUT(NVMCMD));
usbasp_tpi_send_byte(pgm, NVMCMD_SECTION_ERASE);
/* dummy write */
usbasp_tpi_send_byte(pgm, TPI_OP_SST_INC);
usbasp_tpi_send_byte(pgm, 0x00);
usbasp_tpi_nvm_waitbusy(pgm);
}
/* Set PR to flash */
usbasp_tpi_send_byte(pgm, TPI_OP_SSTPR(0));
usbasp_tpi_send_byte(pgm, (pr & 0xFF) | 1 );
@@ -1272,7 +1194,6 @@ void usbasp_initpgm(PROGRAMMER * pgm)
pgm->setup = usbasp_setup;
pgm->teardown = usbasp_teardown;
pgm->set_sck_period = usbasp_spi_set_sck_period;
pgm->parseextparams = usbasp_parseextparms;
}

View File

@@ -42,7 +42,6 @@
/* USBASP capabilities */
#define USBASP_CAP_TPI 0x01
#define USBASP_CAP_3MHZ (1 << 24) // 3 MHz SCK in UsbAsp-flash firmware
/* Block mode flags */
#define USBASP_BLOCKFLAG_FIRST 1
@@ -66,7 +65,6 @@
#define USBASP_ISP_SCK_375 10 /* 375 kHz */
#define USBASP_ISP_SCK_750 11 /* 750 kHz */
#define USBASP_ISP_SCK_1500 12 /* 1.5 MHz */
#define USBASP_ISP_SCK_3000 13 /* 3 MHz only UsbAsp-flash firmware*/
/* TPI instructions */
#define TPI_OP_SLD 0x20

View File

@@ -69,14 +69,7 @@
#define USBDEV_BULK_EP_WRITE_3 0x01
#define USBDEV_BULK_EP_READ_3 0x82
#define USBDEV_EVT_EP_READ_3 0x83
/*
* The mk3 tools (type jtagice3) have a maxPayloadSize of 912. When
* accessing paged memory the access should be limited to pageSize.
* When accessing memory without pageSize the payload should be
* limited to 256.
*/
#define USBDEV_MAX_XFER_3 912
#define USBDEV_MAX_XFER_3_UNPAGED 256
#define USBDEV_MAX_XFER_3 512
/*
* When operating on the JTAGICE3, usbdev_recv_frame() returns an

217
usbtiny.c
View File

@@ -47,19 +47,6 @@
# error "libusb needs either <usb.h> or <lusb0_usb.h>"
#endif
#include "tpi.h"
#define TPIPCR_GT_0b 0x07
#define TPI_STOP_BITS 0x03
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
# define LITTLE_TO_BIG_16(x) (htons(x))
#else
// WIN32
# define LITTLE_TO_BIG_16(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0x00FF))
#endif
#ifndef HAVE_UINT_T
typedef unsigned int uint_t;
#endif
@@ -186,109 +173,6 @@ static int usb_out (PROGRAMMER * pgm,
return nbytes;
}
/* Reverse the bits in a byte. Needed since TPI uses little-endian
bit order (LSB first) whereas SPI uses big-endian (MSB first).*/
static unsigned char reverse(unsigned char b) {
return
( (b & 0x01) << 7)
| ((b & 0x02) << 5)
| ((b & 0x04) << 3)
| ((b & 0x08) << 1)
| ((b & 0x10) >> 1)
| ((b & 0x20) >> 3)
| ((b & 0x40) >> 5)
| ((b & 0x80) >> 7);
}
/* Calculate even parity. */
static unsigned char tpi_parity(unsigned char b)
{
unsigned char parity = 0;
int i;
for (i = 0; i < 8; ++i) {
if (b & 1)
parity ^= 1;
b >>= 1;
}
return parity;
}
/* Encode 1 start bit (0), 8 data bits, 1 parity, 2 stop bits (1)
inside 16 bits. The data is padded to 16 bits by 4 leading 1s
(which will be ignored since they're not start bits). This layout
enables a write to be followed by a read. */
static unsigned short tpi_frame(unsigned char b) {
return LITTLE_TO_BIG_16(0xf000 |
(reverse(b) << 3) |
tpi_parity(b) << 2 |
TPI_STOP_BITS);
}
/* Transmit a single byte encapsulated in a 32-bit transfer. Unused
bits are padded with 1s. */
static int usbtiny_tpi_tx(PROGRAMMER *pgm, unsigned char b0)
{
unsigned char res[4];
if (usb_in(pgm, USBTINY_SPI, tpi_frame(b0), 0xffff,
res, sizeof(res), 8 * sizeof(res) * PDATA(pgm)->sck_period) < 0)
return -1;
if (verbose > 1)
fprintf(stderr, "CMD_TPI_TX: [0x%02x]\n", b0);
return 1;
}
/* Transmit a two bytes encapsulated in a 32-bit transfer. Unused
bits are padded with 1s. */
static int usbtiny_tpi_txtx(PROGRAMMER *pgm,
unsigned char b0, unsigned char b1)
{
unsigned char res[4];
if (usb_in(pgm, USBTINY_SPI, tpi_frame(b0), tpi_frame(b1),
res, sizeof(res), 8 * sizeof(res) * PDATA(pgm)->sck_period) < 0)
return -1;
if (verbose > 1)
fprintf(stderr, "CMD_TPI_TX_TX: [0x%02x 0x%02x]\n", b0, b1);
return 1;
}
/* Transmit a byte then receive a byte, all encapsulated in a 32-bit
transfer. Unused bits are padded with 1s. This code assumes that
the start bit of the byte being received arrives within at most 2
TPICLKs. We ensure this by calling avr_tpi_program_enable() with
delay==TPIPCR_GT_0b. */
static int usbtiny_tpi_txrx(PROGRAMMER *pgm, unsigned char b0)
{
unsigned char res[4], r;
short w;
if (usb_in(pgm, USBTINY_SPI, tpi_frame(b0), 0xffff,
res, sizeof(res), 8 * sizeof(res) * PDATA(pgm)->sck_period) < 0)
return -1;
w = (res[2] << 8) | res[3];
/* Look for start bit (there shoule be no more than two 1 bits): */
while (w < 0)
w <<= 1;
/* Now that we found the start bit, the top 9 bits contain the start
bit and the 8 data bits, but the latter in reverse order. */
r = reverse(w >> 7);
if (tpi_parity(r) != ((w >> 6) & 1)) {
fprintf(stderr, "%s: parity bit is wrong\n", __func__);
return -1;
}
if (((w >> 4) & 0x3) != TPI_STOP_BITS) {
fprintf(stderr, "%s: stop bits not received correctly\n", __func__);
return -1;
}
if (verbose > 1)
fprintf(stderr, "CMD_TPI_TX_RX: [0x%02x -> 0x%02x]\n", b0, r);
return r;
}
// Sometimes we just need to know the SPI command for the part to perform
// a function. Here we wrap this request for an operation so that we
// can just specify the part and operation and it'll do the right stuff
@@ -450,7 +334,6 @@ static int usbtiny_set_sck_period (PROGRAMMER *pgm, double v)
static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p )
{
unsigned char res[4]; // store the response from usbtinyisp
int tries;
// Check for bit-clock and tell the usbtiny to adjust itself
if (pgm->bitclock > 0.0) {
@@ -470,40 +353,8 @@ static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p )
// Let the device wake up.
usleep(50000);
if (p->flags & AVRPART_HAS_TPI) {
/* Since there is a single TPIDATA line, MOSI and MISO must be
linked together through a 1kOhm resistor. Verify that
everything we send on MOSI gets mirrored back on MISO. */
if (verbose >= 2)
fprintf(stderr, "doing MOSI-MISO link check\n");
memset(res, 0xaa, sizeof(res));
if (usb_in(pgm, USBTINY_SPI, LITTLE_TO_BIG_16(0x1234), LITTLE_TO_BIG_16(0x5678),
res, 4, 32 * PDATA(pgm)->sck_period) < 0) {
fprintf(stderr, "usb_in() failed\n");
return -1;
}
if (res[0] != 0x12 || res[1] != 0x34 || res[2] != 0x56 || res[3] != 0x78) {
fprintf(stderr,
"MOSI->MISO check failed (got 0x%02x 0x%02x 0x%02x 0x%02x)\n"
"\tPlease verify that MISO is connected directly to TPIDATA and\n"
"\tMOSI is connected to TPIDATA through a 1kOhm resistor.\n",
res[0], res[1], res[2], res[3]);
return -1;
}
/* keep TPIDATA high for >= 16 clock cycles: */
if (usb_in(pgm, USBTINY_SPI, 0xffff, 0xffff, res, 4,
32 * PDATA(pgm)->sck_period) < 0)
{
fprintf(stderr, "Unable to switch chip into TPI mode\n");
return -1;
}
}
for (tries = 0; tries < 4; ++tries) {
if (pgm->program_enable(pgm, p) >= 0)
break;
// Attempt to use the underlying avrdude methods to connect (MEME: is this kosher?)
if (! usbtiny_avr_op(pgm, p, AVR_OP_PGM_ENABLE, res)) {
// no response, RESET and try again
if (usb_control(pgm, USBTINY_POWERUP,
PDATA(pgm)->sck_period, RESET_HIGH) < 0 ||
@@ -511,9 +362,11 @@ static int usbtiny_initialize (PROGRAMMER *pgm, AVRPART *p )
PDATA(pgm)->sck_period, RESET_LOW) < 0)
return -1;
usleep(50000);
if ( ! usbtiny_avr_op( pgm, p, AVR_OP_PGM_ENABLE, res)) {
// give up
return -1;
}
}
if (tries >= 4)
return -1;
return 0;
}
@@ -550,50 +403,11 @@ static int usbtiny_cmd(PROGRAMMER * pgm, const unsigned char *cmd, unsigned char
res[2] == cmd[1]); // AVR's do a delayed-echo thing
}
int usbtiny_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd,
int cmd_len, unsigned char *res, int res_len)
{
unsigned char b0, b1;
int tx, rx, r;
/* Transmits command two bytes at the time until we're down to 0 or
1 command byte. Then we're either done or we transmit the final
byte optionally followed by reading 1 byte. With the current TPI
protocol, we never receive more than one byte. */
for (tx = rx = 0; tx < cmd_len; ) {
b0 = cmd[tx++];
if (tx < cmd_len) {
b1 = cmd[tx++];
if (usbtiny_tpi_txtx(pgm, b0, b1) < 0)
return -1;
} else {
if (res_len > 0) {
if ((r = usbtiny_tpi_txrx(pgm, b0)) < 0)
return -1;
res[rx++] = r;
} else {
if (usbtiny_tpi_tx(pgm, b0) < 0)
return -1;
}
}
}
if (rx < res_len) {
fprintf(stderr, "%s: unexpected cmd_len=%d/res_len=%d\n",
__func__, cmd_len, res_len);
return -1;
}
return 0;
}
/* Send the chip-erase command */
static int usbtiny_chip_erase(PROGRAMMER * pgm, AVRPART * p)
{
unsigned char res[4];
if (p->flags & AVRPART_HAS_TPI)
return avr_tpi_chip_erase(pgm, p);
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
avrdude_message(MSG_INFO, "Chip erase instruction not defined for part \"%s\"\n",
p->desc);
@@ -641,9 +455,6 @@ static int usbtiny_paged_load (PROGRAMMER * pgm, AVRPART * p, AVRMEM* m,
for (; addr < maxaddr; addr += chunk) {
chunk = PDATA(pgm)->chunk_size; // start with the maximum chunk size possible
if (addr + chunk > maxaddr) {
chunk = maxaddr - addr;
}
// Send the chunk of data to the USBtiny with the function we want
// to perform
@@ -699,9 +510,6 @@ static int usbtiny_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
for (; addr < maxaddr; addr += chunk) {
// start with the max chunk size
chunk = PDATA(pgm)->chunk_size;
if (addr + chunk > maxaddr) {
chunk = maxaddr - addr;
}
// we can only write a page at a time anyways
if (m->paged && chunk > page_size)
@@ -730,16 +538,6 @@ static int usbtiny_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
return n_bytes;
}
static int usbtiny_program_enable(PROGRAMMER *pgm, AVRPART *p)
{
unsigned char buf[4];
if (p->flags & AVRPART_HAS_TPI)
return avr_tpi_program_enable(pgm, p, TPIPCR_GT_0b);
else
return usbtiny_avr_op(pgm, p, AVR_OP_PGM_ENABLE, buf);
}
void usbtiny_initpgm ( PROGRAMMER* pgm )
{
strcpy(pgm->type, "USBtiny");
@@ -748,10 +546,9 @@ void usbtiny_initpgm ( PROGRAMMER* pgm )
pgm->initialize = usbtiny_initialize;
pgm->enable = usbtiny_enable;
pgm->disable = usbtiny_disable;
pgm->program_enable = usbtiny_program_enable;
pgm->program_enable = NULL;
pgm->chip_erase = usbtiny_chip_erase;
pgm->cmd = usbtiny_cmd;
pgm->cmd_tpi = usbtiny_cmd_tpi;
pgm->open = usbtiny_open;
pgm->close = usbtiny_close;
pgm->read_byte = avr_read_byte_default;

View File

@@ -45,7 +45,7 @@
// The SCK speed can be set by avrdude, to allow programming of slow-clocked parts
#define SCK_MIN 1 // usec delay (target clock >= 4 MHz)
#define SCK_MAX 250 // usec (target clock >= 16 kHz)
#define SCK_MAX 250 // usec (target clock >= 16 KHz)
#define SCK_DEFAULT 10 // usec (target clock >= 0.4 MHz)
// How much data, max, do we want to send in one USB packet?

View File

@@ -45,7 +45,6 @@ void DisplayErrorText(DWORD dwLastError) {
int exists(char *filename) {
FILE * pFile;
pFile = fopen(filename, "r");
if (pFile) fclose(pFile);
return pFile != NULL;
}

1783
xbee.c

File diff suppressed because it is too large Load Diff

27
xbee.h
View File

@@ -1,27 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2015-2020 David Sainty
*
* 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/>.
*/
/* $Id$ */
#ifndef xbee_h__
#define xbee_h__
extern const char xbee_desc[];
void xbee_initpgm (PROGRAMMER * pgm);
#endif