Merge branch 'avrdudes:main' into hv-updi

This commit is contained in:
Hans 2022-06-25 22:47:27 +02:00 committed by GitHub
commit 8159c46013
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 1567 additions and 1288 deletions

View File

@ -20,7 +20,11 @@ name: Build
on: on:
push: push:
branches-ignore:
- 'onlinedocs'
pull_request: pull_request:
branches-ignore:
- 'onlinedocs'
workflow_call: workflow_call:
env: env:

View File

@ -21,7 +21,7 @@
# cmake --build build # cmake --build build
cmake_minimum_required(VERSION 3.12) cmake_minimum_required(VERSION 3.12)
project(avrdude VERSION 6.99) project(avrdude VERSION 7.0)
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True) set(CMAKE_C_STANDARD_REQUIRED True)
@ -35,6 +35,13 @@ option(USE_LIBUSBWIN32 "Prefer libusb-win32 over libusb" OFF)
option(DEBUG_CMAKE "Enable debugging output for this CMake project" OFF) option(DEBUG_CMAKE "Enable debugging output for this CMake project" OFF)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF) option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
if(WIN32)
# Prefer static libraries over DLLs on Windows
option(USE_STATIC_LIBS "Use static libraries" ON)
else()
option(USE_STATIC_LIBS "Use static libraries" OFF)
endif()
include(CheckIncludeFile) include(CheckIncludeFile)
include(CheckSymbolExists) include(CheckSymbolExists)
include(FetchContent) include(FetchContent)
@ -110,14 +117,14 @@ endif()
# Detect installed libraries # Detect installed libraries
# ===================================== # =====================================
# Prefer static libraries over DLLs on Windows if(USE_STATIC_LIBS)
if(WIN32)
set(PREFERRED_LIBELF libelf.a elf) set(PREFERRED_LIBELF libelf.a elf)
set(PREFERRED_LIBUSB libusb.a usb) set(PREFERRED_LIBUSB libusb.a usb)
set(PREFERRED_LIBUSB_1_0 libusb-1.0.a usb-1.0) set(PREFERRED_LIBUSB_1_0 libusb-1.0.a usb-1.0)
set(PREFERRED_LIBHIDAPI libhidapi.a libhidapi-libusb.a libhidapi-hidraw.a hidapi hidapi-libusb hidapi-hidraw) set(PREFERRED_LIBHIDAPI libhidapi.a libhidapi-libusb.a libhidapi-hidraw.a hidapi hidapi-libusb hidapi-hidraw)
set(PREFERRED_LIBFTDI libftdi.a ftdi) set(PREFERRED_LIBFTDI libftdi.a ftdi)
set(PREFERRED_LIBFTDI1 libftdi1.a ftdi1) set(PREFERRED_LIBFTDI1 libftdi1.a ftdi1)
set(PREFERRED_LIBREADLINE libreadline.a)
else() else()
set(PREFERRED_LIBELF elf) set(PREFERRED_LIBELF elf)
set(PREFERRED_LIBUSB usb) set(PREFERRED_LIBUSB usb)
@ -125,6 +132,7 @@ else()
set(PREFERRED_LIBHIDAPI hidapi hidapi-libusb hidapi-hidraw) set(PREFERRED_LIBHIDAPI hidapi hidapi-libusb hidapi-hidraw)
set(PREFERRED_LIBFTDI ftdi) set(PREFERRED_LIBFTDI ftdi)
set(PREFERRED_LIBFTDI1 ftdi1) set(PREFERRED_LIBFTDI1 ftdi1)
set(PREFERRED_LIBREADLINE readline)
endif() endif()
# ------------------------------------- # -------------------------------------
@ -182,6 +190,9 @@ endif()
# Find libhidapi # Find libhidapi
find_library(HAVE_LIBHID NAMES hid) find_library(HAVE_LIBHID NAMES hid)
if(HAVE_LIBHID)
set(LIB_LIBHID ${HAVE_LIBHID})
endif()
find_library(HAVE_LIBHIDAPI NAMES ${PREFERRED_LIBHIDAPI}) find_library(HAVE_LIBHIDAPI NAMES ${PREFERRED_LIBHIDAPI})
if(HAVE_LIBHIDAPI) if(HAVE_LIBHIDAPI)
@ -209,7 +220,7 @@ endif()
# ------------------------------------- # -------------------------------------
# Find libreadline # Find libreadline
find_library(HAVE_LIBREADLINE NAMES readline) find_library(HAVE_LIBREADLINE NAMES ${PREFERRED_LIBREADLINE})
if(HAVE_LIBREADLINE) if(HAVE_LIBREADLINE)
set(LIB_LIBREADLINE ${HAVE_LIBREADLINE}) set(LIB_LIBREADLINE ${HAVE_LIBREADLINE})
endif() endif()

91
NEWS
View File

@ -5,7 +5,31 @@ Approximate change log for AVRDUDE by version.
(For detailed changes, see the version control system logs.) (For detailed changes, see the version control system logs.)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Changes since version 6.4: Changes since version 7.0:
* Major changes compared to the previous version:
* New devices supported:
* New programmers supported:
* Issues fixed:
- Fix micronucleus bootloader to check for unresponsive USB
devices #945
- Fix src/CMakeLists.txt to honor CMAKE_INSTALL_LIBDIR #972
* Pull requests:
- Fix .Dd macro in manpage #949
- fix M1 homebrew path #950
- CMake Enhancements #962
- Reduce programmer desc string length in avrdude.conf
to < 80 characters #1000
* Internals:
Changes in version 7.0:
* Major changes compared to the previous version: * Major changes compared to the previous version:
@ -13,6 +37,17 @@ Changes since version 6.4:
- Started to add CMake (by now, parallel with autoconf/automake) - Started to add CMake (by now, parallel with autoconf/automake)
- New-architecture devices (AVR8X mega and tiny) can access all - New-architecture devices (AVR8X mega and tiny) can access all
fuses, and memory display shows meaningful alias names fuses, and memory display shows meaningful alias names
- The "safemode" feature has been removed. The major class of
programmers it has been designed for (lowlevel bitbang
programmers on parallel or serial ports) virtually doesn't exist
anymore, and the fuse combination that was covered by it do not
match the fuses of modern AVR devices anyway.
- avrdude.conf is now being looked up in the location of the
executable file first, before considering the configured default
location; this eases a "portable use" where the entire suite is
not installed into its configured default location. (Basically
only relevant for unixoid systems; on Windows, this search order
has been used for many years already.)
* New devices supported: * New devices supported:
@ -30,6 +65,7 @@ Changes since version 6.4:
- ATtiny3224, ATtiny3226 and ATtiny3227 - ATtiny3224, ATtiny3226 and ATtiny3227
- AVR16DD14/20/28/32, AVR32DD14/20/28/32 and AVR64DD14/20/28/32 - AVR16DD14/20/28/32, AVR32DD14/20/28/32 and AVR64DD14/20/28/32
- AVR8EA28/32, AVR16EA28/32/48, AVR32EA28/32/48 and AVR64EA28/32/64 - AVR8EA28/32, AVR16EA28/32/48, AVR32EA28/32/48 and AVR64EA28/32/64
- ATmega16U4
* New programmers supported: * New programmers supported:
@ -40,6 +76,8 @@ Changes since version 6.4:
- Teensy bootloader (PR #802) - Teensy bootloader (PR #802)
- Micronucleus bootloader (PR #786) - Micronucleus bootloader (PR #786)
- ft232h (generic variant, PR #842) - ft232h (generic variant, PR #842)
- Kristech KT-LINK FT2232H interface with IO switching and voltage
buffers (PR #930)
* Issues fixed: * Issues fixed:
@ -63,6 +101,22 @@ Changes since version 6.4:
- Segmentation fault when writing ATtiny104 fuse #823 - Segmentation fault when writing ATtiny104 fuse #823
- USBasp returns ERANGE for unknown error #848 - USBasp returns ERANGE for unknown error #848
- Compiler warnings #856 - Compiler warnings #856
- Can't get serialupdi to work #874
- Rework HID support for Windows #881
- List of signing keys? #884
- Pickit4 UPDI is writing at offset 0x4000 into flash instead of 0x0000. #892
- SerialUPDI programmer can't write to usersig/userrow in terminal mode #889
- Signature read command for ATmega165* was wrong (no-id)
- Cannot use non-standard baud rates for uploading on MacOS #771
- Wrong values in avrdude.conf #897
- AVR-Eclipse plugin broken by missing -u commandline option #890
- Timeout passed to hid_read_timeout() is too short for instances
where the EDBG AVRISP 'Enter Programming Mode' command fails #900
- Terminal write mode doesn't support string input (yet) #913
- Terminal mode: memory fill with strings may cause Avrdude to crash. #922
- Some parts have wrong or missing ISP commands #915
- Incorrect -b conversion for linuxspi programmer #927
- ATtiny43U calibration memory size #921
* Pull requests: * Pull requests:
@ -119,10 +173,45 @@ Changes since version 6.4:
- Fix libusb-1.0 error strings #850 - Fix libusb-1.0 error strings #850
- Assign proper type to msg[] in errstr() #857 - Assign proper type to msg[] in errstr() #857
- Fix Arduino retry attempts #855 - Fix Arduino retry attempts #855
- CMake: use CMAKE_CURRENT_BINARY_DIR to locate avrdude.conf #858
- Remove the "safemode" feature. #859
- Add support for reading from more memory sections #863
- Alias keyword #868
- Add fuse name aliases to avrdude.conf + tweak update.c #869
- Print JTAG3 clocks after configuration + string formatting #853
- Tweak programmer info formatting strings #872
- Remove libhid support in ser_avrdoper.c in favor of libhidapi #882
- Reduce jtag3 output verbosity #877
- Fix Curiosity Nano target voltage #878
- Smallest possible fix for PL2303HX #885
- Add missing USBtiny derived programmers #873
- Cleanup of POSIX serial init code #886
- Avrdude terminal write improvements #880
- Add userrow and usersig aliases #888
- For UPDI devices do not add offset when accessing flash. #895
- Support both userrow and usersig names #893
- Fix ugly terminal write bug #896
- Improve terminal read functionality #894
- Macos nonstandard baudrates #898
- Fix errors in Avrdude.conf #899
- Minor terminal write improvements #902
- Term docs #903
- Add progressbar for read and write command #912
- Add MacOS serial/parallel port note #908
- Add ATmega16U4 to avrdude.conf #910
- Mask out unused ATmega32U4 efuse bits #909
- Increased timeout passed to hid_read_timeout() #901
- Add terminal write string functionality #914
- Update documentation link to new URL #929
- Fix terminal write buffer overflow issue #924
- Fix linuxspi baud to clock period calculation #931
- Added KT-LINK FT2232H interface with IO switching and voltage buffers. #930
* Internals: * Internals:
- Development moved to Github - Development moved to Github
- Addition of "alias" keyword to avrdude.conf.in syntax; used
for fuse name aliases right now
Version 6.4: Version 6.4:

View File

@ -16,6 +16,10 @@ with the help of [various contributors](./AUTHORS).
The latest version of AVRDUDE is always available here:\ The latest version of AVRDUDE is always available here:\
<https://github.com/avrdudes/avrdude> <https://github.com/avrdudes/avrdude>
## Documentation
Documentation for current and previous releases is [on Github Pages](https://avrdudes.github.io/avrdude/).
## Getting AVRDUDE for Windows ## Getting AVRDUDE for Windows
To get AVRDUDE for Windows, install the latest version from the [Releases](http://download.savannah.gnu.org/releases/avrdude/) page. To get AVRDUDE for Windows, install the latest version from the [Releases](http://download.savannah.gnu.org/releases/avrdude/) page.
@ -57,4 +61,4 @@ avrdude -c arduino -P COM1 -b 115200 -p atmega328p -D -U flash:w:objs/blink.hex:
There are many different programmers and options that may be required for the programming to succeed. There are many different programmers and options that may be required for the programming to succeed.
For more information, refer to the [AVRDUDE documentation](http://download.savannah.gnu.org/releases/avrdude/avrdude-doc-6.4.pdf). For more information, refer to the [AVRDUDE documentation](https://avrdudes.github.io/avrdude/).

View File

@ -49,9 +49,15 @@ case "${ostype}" in
if [ -f /opt/local/bin/port ] if [ -f /opt/local/bin/port ]
then then
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/local/lib" build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/local/lib"
else
# Apple M1 (may be new version of homebrew also)
if [ -d /opt/homebrew ]
then
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/homebrew/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/homebrew/Cellar"
else else
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar" build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar"
fi fi
fi
;; ;;
freebsd) freebsd)

View File

@ -51,15 +51,10 @@ include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
add_compile_definitions(CONFIG_DIR=\"${CONFIG_DIR}\") add_compile_definitions(CONFIG_DIR=\"${CONFIG_DIR}\")
if(WIN32) if(WIN32)
set(EXTRA_WINDOWS_SOURCES "${PROJECT_BINARY_DIR}/src/windows.rc") set(EXTRA_WINDOWS_RESOURCES "${PROJECT_BINARY_DIR}/src/windows.rc")
set(EXTRA_WINDOWS_LIBRARIES setupapi ws2_32) set(EXTRA_WINDOWS_LIBRARIES setupapi ws2_32)
endif() endif()
if(NOT WIN32)
set(LIB_MATH m)
add_compile_options(-Wall) # -Wextra
endif()
if(MSVC) if(MSVC)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS=1) add_compile_definitions(_CRT_SECURE_NO_WARNINGS=1)
add_compile_definitions(_CRT_NONSTDC_NO_WARNINGS=1) add_compile_definitions(_CRT_NONSTDC_NO_WARNINGS=1)
@ -79,6 +74,9 @@ if(MSVC)
set(EXTRA_WINDOWS_INCLUDES ${EXTRA_WINDOWS_INCLUDES} set(EXTRA_WINDOWS_INCLUDES ${EXTRA_WINDOWS_INCLUDES}
"msvc" "msvc"
) )
else()
set(LIB_MATH m)
add_compile_options(-Wall) # -Wextra
endif() endif()
# ===================================== # =====================================
@ -173,7 +171,6 @@ add_library(libavrdude
ppi.c ppi.c
ppi.h ppi.h
ppiwin.c ppiwin.c
safemode.c
serbb.h serbb.h
serbb_posix.c serbb_posix.c
serbb_win32.c serbb_win32.c
@ -217,6 +214,7 @@ add_library(libavrdude
xbee.c xbee.c
${FLEX_Parser_OUTPUTS} ${FLEX_Parser_OUTPUTS}
${BISON_Parser_OUTPUTS} ${BISON_Parser_OUTPUTS}
"${EXTRA_WINDOWS_SOURCES}"
) )
set_target_properties(libavrdude PROPERTIES set_target_properties(libavrdude PROPERTIES
@ -240,6 +238,7 @@ target_link_libraries(libavrdude
${LIB_LIBELF} ${LIB_LIBELF}
${LIB_LIBUSB} ${LIB_LIBUSB}
${LIB_LIBUSB_1_0} ${LIB_LIBUSB_1_0}
${LIB_LIBHID}
${LIB_LIBHIDAPI} ${LIB_LIBHIDAPI}
${LIB_LIBFTDI} ${LIB_LIBFTDI}
${LIB_LIBFTDI1} ${LIB_LIBFTDI1}
@ -253,7 +252,7 @@ add_executable(avrdude
term.h term.h
whereami.c whereami.c
whereami.h whereami.h
"${EXTRA_WINDOWS_SOURCES}" "${EXTRA_WINDOWS_RESOURCES}"
) )
target_link_libraries(avrdude PUBLIC libavrdude) target_link_libraries(avrdude PUBLIC libavrdude)
@ -264,9 +263,9 @@ target_link_libraries(avrdude PUBLIC libavrdude)
install(TARGETS avrdude DESTINATION bin) install(TARGETS avrdude DESTINATION bin)
install(TARGETS libavrdude install(TARGETS libavrdude
LIBRARY DESTINATION lib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION lib ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION include COMPONENT dev PUBLIC_HEADER DESTINATION include COMPONENT dev
) )
install(FILES "${PROJECT_BINARY_DIR}/avrdude.conf" TYPE SYSCONF) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/avrdude.conf" TYPE SYSCONF)
install(FILES avrdude.1 TYPE MAN) install(FILES avrdude.1 TYPE MAN)

View File

@ -148,7 +148,6 @@ libavrdude_a_SOURCES = \
ppi.c \ ppi.c \
ppi.h \ ppi.h \
ppiwin.c \ ppiwin.c \
safemode.c \
serbb.h \ serbb.h \
serbb_posix.c \ serbb_posix.c \
serbb_win32.c \ serbb_win32.c \

View File

@ -791,30 +791,6 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char data) unsigned long addr, unsigned char data)
{ {
unsigned char safemode_lfuse;
unsigned char safemode_hfuse;
unsigned char safemode_efuse;
unsigned char safemode_fuse;
/* If we write the fuses, then we need to tell safemode that they *should* change */
safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
if (strcmp(mem->desc, "fuse")==0) {
safemode_fuse = data;
}
if (strcmp(mem->desc, "lfuse")==0) {
safemode_lfuse = data;
}
if (strcmp(mem->desc, "hfuse")==0) {
safemode_hfuse = data;
}
if (strcmp(mem->desc, "efuse")==0) {
safemode_efuse = data;
}
safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
return pgm->write_byte(pgm, p, mem, addr, data); return pgm->write_byte(pgm, p, mem, addr, data);
} }

View File

@ -18,7 +18,7 @@
.\" .\"
.\" $Id$ .\" $Id$
.\" .\"
.Dd DATE November 22, 2021 .Dd November 22, 2021
.Os .Os
.Dt AVRDUDE 1 .Dt AVRDUDE 1
.Sh NAME .Sh NAME
@ -607,40 +607,11 @@ Posix systems (by now).
.It Fl q .It Fl q
Disable (or quell) output of the progress bar while reading or writing Disable (or quell) output of the progress bar while reading or writing
to the device. Specify it a second time for even quieter operation. to the device. Specify it a second time for even quieter operation.
.It Fl s
Disable safemode prompting. When safemode discovers that one or more
fuse bits have unintentionally changed, it will prompt for
confirmation regarding whether or not it should attempt to recover the
fuse bit(s). Specifying this flag disables the prompt and assumes
that the fuse bit(s) should be recovered without asking for
confirmation first.
.It Fl t .It Fl t
Tells Tells
.Nm .Nm
to enter the interactive ``terminal'' mode instead of up- or downloading to enter the interactive ``terminal'' mode instead of up- or downloading
files. See below for a detailed description of the terminal mode. files. See below for a detailed description of the terminal mode.
.It Fl u
Disable the safemode fuse bit checks. Safemode is enabled by default
and is intended to prevent unintentional fuse bit changes. When
enabled, safemode will issue a warning if the any fuse bits are found
to be different at program exit than they were when
.Nm
was invoked. Safemode won't alter fuse bits itself, but rather will
prompt for instructions, unless the terminal is non-interactive, in
which case safemode is disabled. See the
.Fl s
option to disable safemode prompting.
.Pp
If one of the configuration files has a line
.Dl "default_safemode = no;"
safemode is disabled by default.
The
.Fl u
option's effect is negated in that case, i. e. it
.Em enables
safemode.
.Pp
Safemode is always disabled for AVR32, Xmega and TPI devices.
.It Xo Fl U Ar memtype Ns .It Xo Fl U Ar memtype Ns
.Ar \&: Ns Ar op Ns .Ar \&: Ns Ar op Ns
.Ar \&: Ns Ar filename Ns .Ar \&: Ns Ar filename Ns

View File

@ -339,10 +339,6 @@ default_parallel = "@DEFAULT_PAR_PORT@";
default_serial = "@DEFAULT_SER_PORT@"; default_serial = "@DEFAULT_SER_PORT@";
# default_bitclock = 2.5; # default_bitclock = 2.5;
# Turn off safemode by default
#default_safemode = no;
# #
# PROGRAMMER DEFINITIONS # PROGRAMMER DEFINITIONS
# #
@ -597,6 +593,38 @@ programmer
reset = 3; # TMS 7 reset = 3; # TMS 7
; ;
# Kristech KT-LINK FT2232H interface with IO switching and voltage buffers.
# Created on 20220410 by CeDeROM Tomasz CEDRO (www.cederom.io).
# Interface DataSheet: https://kristech.pl/files/KT-LINK-UM-ENG.pdf
# AVRDUDE FT2232H PIN NUMBER DECODE:
# | 0 | 1 | .. | 7 | 8 | 9 | .. | 15 |
# | ADBUS0 | ADBUS1 | .. | ADBUS7 | ACBUS0 | ACBUS1 | .. | ACBUS7 |
# KT-LINK JTAG CONN:
# 1=Vsense(->EXT13), 19=5V(EXT1->EXT3), 20=GND, 3=TPIRST, 9=TPICLK, 7=TPIDATA.
# INTERNALS CONFIGURATION ("~" MEANS ACTIVE LOW):
# ~TRST_EN=10(ACBUS2), ~CLK_EN=14(ACBUS6), ~MOSI_EN=13(ACBUS5),
# TMS_SEL=5(ADBUS5), ~TMS_EN=12(ACBUS4), LED=~15(ACBUS7).
# CONNECTION NOTES:
# * Connect EXT connector pin 1 with 3 to get 5V on JTAG connector pin 19.
# * Connect JTAG connector pin 1 to 5V (i.e. EXT pin 13 or JTAG pin 19).
# * For TPI connection use resistors: TDO --[470R]-- TPIDATA --[470R]-- TDI.
# * Powering target from JTAG pin 19 allows KT-LINK current measurement.
programmer
id = "ktlink";
desc = "KT-LINK FT2232H interface with IO switching and voltage buffers.";
type = "avrftdi";
connection_type = usb;
usbvid= 0x0403;
usbpid= 0xBBE2;
usbdev= "A";
reset = 8;
sck = 0;
mosi = 1;
miso = 2;
buff = ~10,~14,~13,5;
rdyled = ~15;
;
programmer programmer
id = "serialupdi"; id = "serialupdi";
desc = "SerialUPDI"; desc = "SerialUPDI";
@ -890,6 +918,24 @@ programmer
usbpid = 0x0c9f; usbpid = 0x0c9f;
; ;
programmer
id = "arduinoisp";
desc = "Arduino ISP Programmer";
type = "usbtiny";
connection_type = usb;
usbvid = 0x2341;
usbpid = 0x0049;
;
programmer
id = "arduinoisporg";
desc = "Arduino ISP Programmer";
type = "usbtiny";
connection_type = usb;
usbvid = 0x2A03;
usbpid = 0x0049;
;
# commercial version of USBtiny, using a separate VID/PID # commercial version of USBtiny, using a separate VID/PID
programmer programmer
id = "ehajo-isp"; id = "ehajo-isp";
@ -900,6 +946,17 @@ programmer
usbpid = 0x0BA5; usbpid = 0x0BA5;
; ;
# commercial version of USBtiny, using a separate VID/PID
# https://github.com/IowaScaledEngineering/ckt-avrprogrammer
programmer
id = "iseavrprog";
desc = "USBtiny-based programmer, https://iascaled.com";
type = "usbtiny";
connection_type = usb;
usbvid = 0x1209;
usbpid = 0x6570;
;
programmer programmer
id = "micronucleus"; id = "micronucleus";
desc = "Micronucleus Bootloader"; desc = "Micronucleus Bootloader";
@ -918,16 +975,6 @@ programmer
usbpid = 0x0478; usbpid = 0x0478;
; ;
# commercial version of USBtiny, using a separate VID/PID
programmer
id = "iseavrprog";
desc = "USBtiny-based USB programmer, https://github.com/IowaScaledEngineering/ckt-avrprogrammer";
type = "usbtiny";
connection_type = usb;
usbvid = 0x1209;
usbpid = 0x6570;
;
programmer programmer
id = "butterfly"; id = "butterfly";
desc = "Atmel Butterfly Development Board"; desc = "Atmel Butterfly Development Board";
@ -4727,8 +4774,37 @@ part parent "m324p"
signature = 0x1e 0x94 0x0a; signature = 0x1e 0x94 0x0a;
memory "eeprom" memory "eeprom"
paged = no; /* leave this "no" */
size = 512; size = 512;
page_size = 4; page_size = 4;
min_write_delay = 9000;
max_write_delay = 9000;
readback_p1 = 0xff;
readback_p2 = 0xff;
read = " 1 0 1 0 0 0 0 0",
" 0 0 x x x a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
write = " 1 1 0 0 0 0 0 0",
" 0 0 x x x a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_lo = " 1 1 0 0 0 0 0 1",
" 0 0 0 0 0 0 0 0",
" 0 0 0 0 0 0 a1 a0",
" i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x a10 a9 a8",
" a7 a6 a5 a4 a3 a2 0 0",
" x x x x x x x x";
mode = 0x41;
delay = 10;
blocksize = 128;
readsize = 256;
; ;
memory "flash" memory "flash"
@ -4736,7 +4812,41 @@ part parent "m324p"
size = 16384; size = 16384;
page_size = 128; page_size = 128;
num_pages = 128; num_pages = 128;
min_write_delay = 4500;
max_write_delay = 4500;
readback_p1 = 0xff;
readback_p2 = 0xff;
read_lo = " 0 0 1 0 0 0 0 0",
" 0 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
read_hi = " 0 0 1 0 1 0 0 0",
" 0 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
loadpage_lo = " 0 1 0 0 0 0 0 0",
" 0 0 x x x x x x",
" x x a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_hi = " 0 1 0 0 1 0 0 0",
" 0 0 x x x x x x",
" x x a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
writepage = " 0 1 0 0 1 1 0 0",
" 0 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 x x x x x x",
" x x x x x x x x";
mode = 0x21;
delay = 6;
blocksize = 256;
readsize = 256;
; ;
; ;
#------------------------------------------------------------ #------------------------------------------------------------
@ -5893,7 +6003,7 @@ part
" i i i i i i i i"; " i i i i i i i i";
writepage = " 0 1 0 0 1 1 0 0", writepage = " 0 1 0 0 1 1 0 0",
" x x x a12 a11 a10 a9 a8", " x a14 a13 a12 a11 a10 a9 a8",
" a7 a6 x x x x x x", " a7 a6 x x x x x x",
" x x x x x x x x"; " x x x x x x x x";
@ -5966,7 +6076,7 @@ part
part parent "m329" part parent "m329"
id = "m329a"; id = "m329a";
desc = "ATmega329a"; desc = "ATmega329A";
; ;
#------------------------------------------------------------ #------------------------------------------------------------
@ -6147,7 +6257,7 @@ part
" i i i i i i i i"; " i i i i i i i i";
writepage = " 0 1 0 0 1 1 0 0", writepage = " 0 1 0 0 1 1 0 0",
" x x x a12 a11 a10 a9 a8", "a15 a14 a13 a12 a11 a10 a9 a8",
" a7 x x x x x x x", " a7 x x x x x x x",
" x x x x x x x x"; " x x x x x x x x";
@ -8832,7 +8942,7 @@ part
"a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
write = "1 1 0 0 0 0 0 0 0 0 x x x x x a8", write = "1 1 0 0 0 0 0 0 0 0 x x x x x a8",
"a8 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
loadpage_lo = " 1 1 0 0 0 0 0 1", loadpage_lo = " 1 1 0 0 0 0 0 1",
" 0 0 0 0 0 0 0 0", " 0 0 0 0 0 0 0 0",
@ -8840,8 +8950,8 @@ part
" i i i i i i i i"; " i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0", writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x x x x", " 0 0 x x x x x a8",
" 0 0 a5 a4 a3 a2 0 0", " a7 a6 a5 a4 a3 a2 0 0",
" x x x x x x x x"; " x x x x x x x x";
mode = 0x41; mode = 0x41;
@ -9019,7 +9129,7 @@ part
"a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o"; "a7 a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
write = "1 1 0 0 0 0 0 0 0 0 x x x x x a8", write = "1 1 0 0 0 0 0 0 0 0 x x x x x a8",
"a8 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i"; "a7 a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
loadpage_lo = " 1 1 0 0 0 0 0 1", loadpage_lo = " 1 1 0 0 0 0 0 1",
" 0 0 0 0 0 0 0 0", " 0 0 0 0 0 0 0 0",
@ -9027,8 +9137,8 @@ part
" i i i i i i i i"; " i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0", writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x x x x", " 0 0 x x x x x a8",
" 0 0 a5 a4 a3 a2 0 0", " a7 a6 a5 a4 a3 a2 0 0",
" x x x x x x x x"; " x x x x x x x x";
mode = 0x41; mode = 0x41;
@ -9762,6 +9872,81 @@ part parent "m328"
signature = 0x1e 0x96 0x84; signature = 0x1e 0x96 0x84;
bs2 = 0xe2; bs2 = 0xe2;
memory "eeprom"
paged = no;
size = 2048;
page_size = 8;
min_write_delay = 3600;
max_write_delay = 3600;
readback_p1 = 0xff;
readback_p2 = 0xff;
read = " 1 0 1 0 0 0 0 0",
" 0 0 0 x x a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
write = " 1 1 0 0 0 0 0 0",
" 0 0 0 x x a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_lo = " 1 1 0 0 0 0 0 1",
" 0 0 0 0 0 0 0 0",
" 0 0 0 0 0 a2 a1 a0",
" i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x a10 a9 a8",
" a7 a6 a5 a4 a3 0 0 0",
" x x x x x x x x";
mode = 0x41;
delay = 20;
blocksize = 4;
readsize = 256;
;
memory "flash"
paged = yes;
size = 65536;
page_size = 256;
num_pages = 256;
min_write_delay = 4500;
max_write_delay = 4500;
readback_p1 = 0xff;
readback_p2 = 0xff;
read_lo = " 0 0 1 0 0 0 0 0",
" a15 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
read_hi = " 0 0 1 0 1 0 0 0",
" a15 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
loadpage_lo = " 0 1 0 0 0 0 0 0",
" 0 0 0 x x x x x",
" x a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_hi = " 0 1 0 0 1 0 0 0",
" 0 0 0 x x x x x",
" x a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
writepage = " 0 1 0 0 1 1 0 0",
" a15 a14 a13 a12 a11 a10 a9 a8",
" a7 x x x x x x x",
" x x x x x x x x";
mode = 0x41;
delay = 6;
blocksize = 128;
readsize = 256;
;
memory "efuse" memory "efuse"
size = 1; size = 1;
min_write_delay = 4500; min_write_delay = 4500;
@ -10233,7 +10418,7 @@ part
" i i i i i i i i"; " i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0", writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x x x x", " 0 0 x x x x x a8",
" a7 a6 a5 a4 a3 a2 0 0", " a7 a6 a5 a4 a3 a2 0 0",
" x x x x x x x x"; " x x x x x x x x";
@ -12101,7 +12286,7 @@ part
writepage = " 1 1 0 0 0 0 1 0", writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x x x x", " 0 0 x x x x x x",
" x a6 a5 a4 a3 a2 0 0", " a7 a6 a5 a4 a3 a2 0 0",
" x x x x x x x x"; " x x x x x x x x";
mode = 0x41; mode = 0x41;
@ -12293,8 +12478,8 @@ part
" i i i i i i i i"; " i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0", writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x x x x", " 0 0 x x x x x a8",
" x a6 a5 a4 a3 a2 0 0", " a7 a6 a5 a4 a3 a2 0 0",
" x x x x x x x x"; " x x x x x x x x";
mode = 0x41; mode = 0x41;
@ -12535,7 +12720,7 @@ part parent "t84"
part part
id = "t43u"; id = "t43u";
desc = "ATtiny43u"; desc = "ATtiny43U";
has_debugwire = yes; has_debugwire = yes;
flash_instr = 0xB4, 0x07, 0x17; flash_instr = 0xB4, 0x07, 0x17;
eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D,
@ -12595,7 +12780,7 @@ part
readback_p1 = 0xff; readback_p1 = 0xff;
readback_p2 = 0xff; readback_p2 = 0xff;
read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x", read = "1 0 1 0 0 0 0 0 0 0 0 x x x x x",
"0 0 a4 a3 a2 a1 a0 o o o o o o o o"; "0 0 a5 a4 a3 a2 a1 a0 o o o o o o o o";
write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x", write = "1 1 0 0 0 0 0 0 0 0 0 x x x x x",
"0 0 a5 a4 a3 a2 a1 a0 i i i i i i i i"; "0 0 a5 a4 a3 a2 a1 a0 i i i i i i i i";
@ -12664,6 +12849,8 @@ part
size = 1; size = 1;
write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x", write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
"x x x x x x x x 1 1 i i i i i i"; "x x x x x x x x 1 1 i i i i i i";
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 4500; min_write_delay = 4500;
max_write_delay = 4500; max_write_delay = 4500;
; ;
@ -12702,12 +12889,203 @@ part
; ;
memory "calibration" memory "calibration"
size = 2; size = 1;
read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x", read = "0 0 1 1 1 0 0 0 0 0 0 x x x x x",
"0 0 0 0 0 0 0 a0 o o o o o o o o"; "0 0 0 0 0 0 0 a0 o o o o o o o o";
; ;
; ;
#------------------------------------------------------------
# ATmega16u4
#------------------------------------------------------------
part
id = "m16u4";
desc = "ATmega16U4";
signature = 0x1e 0x94 0x88;
usbpid = 0x2ff4;
has_jtag = yes;
# stk500_devcode = 0xB2;
# avr910_devcode = 0x43;
chip_erase_delay = 9000;
pagel = 0xD7;
bs2 = 0xA0;
reset = dedicated;
pgm_enable = "1 0 1 0 1 1 0 0 0 1 0 1 0 0 1 1",
"x x x x x x x x x x x x x x x x";
chip_erase = "1 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0",
"x x x x x x x x x x x x x x x x";
timeout = 200;
stabdelay = 100;
cmdexedelay = 25;
synchloops = 32;
bytedelay = 0;
pollindex = 3;
pollvalue = 0x53;
predelay = 1;
postdelay = 1;
pollmethod = 1;
pp_controlstack =
0x0E, 0x1E, 0x0F, 0x1F, 0x2E, 0x3E, 0x2F, 0x3F,
0x4E, 0x5E, 0x4F, 0x5F, 0x6E, 0x7E, 0x6F, 0x7F,
0x66, 0x76, 0x67, 0x77, 0x6A, 0x7A, 0x6B, 0x7B,
0xBE, 0xFD, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00;
hventerstabdelay = 100;
progmodedelay = 0;
latchcycles = 5;
togglevtg = 1;
poweroffdelay = 15;
resetdelayms = 1;
resetdelayus = 0;
hvleavestabdelay = 15;
chiperasepulsewidth = 0;
chiperasepolltimeout = 10;
programfusepulsewidth = 0;
programfusepolltimeout = 5;
programlockpulsewidth = 0;
programlockpolltimeout = 5;
idr = 0x31;
spmcr = 0x57;
rampz = 0x3b;
allowfullpagebitstream = no;
ocdrev = 3;
memory "eeprom"
paged = no; /* leave this "no" */
page_size = 4; /* for parallel programming */
size = 512;
min_write_delay = 9000;
max_write_delay = 9000;
readback_p1 = 0x00;
readback_p2 = 0x00;
read = " 1 0 1 0 0 0 0 0",
" x x x x x x x a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
write = " 1 1 0 0 0 0 0 0",
" x x x x x x x a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_lo = " 1 1 0 0 0 0 0 1",
" 0 0 0 0 0 0 0 0",
" 0 0 0 0 0 0 a1 a0",
" i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x x x a8",
" a7 a6 a5 a4 a3 a2 0 0",
" x x x x x x x x";
mode = 0x41;
delay = 20;
blocksize = 4;
readsize = 256;
;
memory "flash"
paged = yes;
size = 16384;
page_size = 128;
num_pages = 128;
min_write_delay = 4500;
max_write_delay = 4500;
readback_p1 = 0x00;
readback_p2 = 0x00;
read_lo = " 0 0 1 0 0 0 0 0",
" 0 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
read_hi = " 0 0 1 0 1 0 0 0",
" 0 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o";
loadpage_lo = " 0 1 0 0 0 0 0 0",
" x x x x x x x x",
" x x a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
loadpage_hi = " 0 1 0 0 1 0 0 0",
" x x x x x x x x",
" x x a5 a4 a3 a2 a1 a0",
" i i i i i i i i";
writepage = " 0 1 0 0 1 1 0 0",
" a15 a14 a13 a12 a11 a10 a9 a8",
" a7 a6 x x x x x x",
" x x x x x x x x";
mode = 0x41;
delay = 6;
blocksize = 128;
readsize = 256;
;
memory "lfuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 0 0 0",
"x x x x x x x x i i i i i i i i";
read = "0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "hfuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 1 0 0 0",
"x x x x x x x x i i i i i i i i";
read = "0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "efuse"
size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
"x x x x x x x x 1 1 1 1 i i i i";
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "lock"
size = 1;
read = "0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x x x 0 0 o o o o o o";
write = "1 0 1 0 1 1 0 0 1 1 1 x x x x x",
"x x x x x x x x 1 1 i i i i i i";
min_write_delay = 9000;
max_write_delay = 9000;
;
memory "calibration"
size = 1;
read = "0 0 1 1 1 0 0 0 x x x x x x x x",
"0 0 0 0 0 0 0 0 o o o o o o o o";
;
memory "signature"
size = 3;
read = "0 0 1 1 0 0 0 0 x x x x x x x x",
"x x x x x x a1 a0 o o o o o o o o";
;
;
#------------------------------------------------------------ #------------------------------------------------------------
# ATmega32u4 # ATmega32u4
#------------------------------------------------------------ #------------------------------------------------------------
@ -12788,12 +13166,12 @@ part
loadpage_lo = " 1 1 0 0 0 0 0 1", loadpage_lo = " 1 1 0 0 0 0 0 1",
" 0 0 0 0 0 0 0 0", " 0 0 0 0 0 0 0 0",
" 0 0 0 0 0 a2 a1 a0", " 0 0 0 0 0 0 a1 a0",
" i i i i i i i i"; " i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0", writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x a10 a9 a8", " 0 0 x x x a10 a9 a8",
" a7 a6 a5 a4 a3 0 0 0", " a7 a6 a5 a4 a3 a2 0 0",
" x x x x x x x x"; " x x x x x x x x";
mode = 0x41; mode = 0x41;
@ -12867,7 +13245,7 @@ part
memory "efuse" memory "efuse"
size = 1; size = 1;
write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0",
"x x x x x x x x x x x x i i i i"; "x x x x x x x x 1 1 1 1 i i i i";
read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0", read = "0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0",
"x x x x x x x x o o o o o o o o"; "x x x x x x x x o o o o o o o o";
@ -13187,7 +13565,7 @@ part
" i i i i i i i i"; " i i i i i i i i";
writepage = " 1 1 0 0 0 0 1 0", writepage = " 1 1 0 0 0 0 1 0",
" 0 0 x x x a10 a9 a8", " 0 0 x x a11 a10 a9 a8",
" a7 a6 a5 a4 a3 0 0 0", " a7 a6 a5 a4 a3 0 0 0",
" x x x x x x x x"; " x x x x x x x x";
@ -14249,7 +14627,7 @@ part
part part
id = "m165"; id = "m165";
desc = "ATmega165"; desc = "ATmega165";
signature = 0x1e 0x94 0x07; signature = 0x1e 0x94 0x10;
has_jtag = yes; has_jtag = yes;
# stk500_devcode = 0x??; # stk500_devcode = 0x??;
# avr910_devcode = 0x??; # avr910_devcode = 0x??;
@ -14423,7 +14801,7 @@ part
memory "signature" memory "signature"
size = 3; size = 3;
read = "0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0", read = "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0",
"x x x x x x a1 a0 o o o o o o o o"; "x x x x x x a1 a0 o o o o o o o o";
; ;
@ -15431,6 +15809,13 @@ part parent "x128c3"
id = "x128d4"; id = "x128d4";
desc = "ATxmega128D4"; desc = "ATxmega128D4";
signature = 0x1e 0x97 0x47; signature = 0x1e 0x97 0x47;
memory "flash"
size = 0x22000;
offset = 0x800000;
page_size = 0x100;
readsize = 0x100;
;
; ;
#------------------------------------------------------------ #------------------------------------------------------------
@ -16239,28 +16624,28 @@ part
readback_p1 = 0xff; readback_p1 = 0xff;
readback_p2 = 0xff; readback_p2 = 0xff;
read_lo = " 0 0 1 0 0 0 0 0", read_lo = " 0 0 1 0 0 0 0 0",
" 0 0 0 a12 a11 a10 a9 a8", " 0 0 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0", " a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o"; " o o o o o o o o";
read_hi = " 0 0 1 0 1 0 0 0", read_hi = " 0 0 1 0 1 0 0 0",
" 0 0 0 a12 a11 a10 a9 a8", " 0 0 a13 a12 a11 a10 a9 a8",
" a7 a6 a5 a4 a3 a2 a1 a0", " a7 a6 a5 a4 a3 a2 a1 a0",
" o o o o o o o o"; " o o o o o o o o";
loadpage_lo = " 0 1 0 0 0 0 0 0", loadpage_lo = " 0 1 0 0 0 0 0 0",
" 0 0 0 x x x x x", " 0 0 0 x x x x x",
" x x a5 a4 a3 a2 a1 a0", " x x x x a3 a2 a1 a0",
" i i i i i i i i"; " i i i i i i i i";
loadpage_hi = " 0 1 0 0 1 0 0 0", loadpage_hi = " 0 1 0 0 1 0 0 0",
" 0 0 0 x x x x x", " 0 0 0 x x x x x",
" x x a5 a4 a3 a2 a1 a0", " x x x x a3 a2 a1 a0",
" i i i i i i i i"; " i i i i i i i i";
writepage = " 0 1 0 0 1 1 0 0", writepage = " 0 1 0 0 1 1 0 0",
" 0 0 0 a12 a11 a10 a9 a8", " 0 0 a13 a12 a11 a10 a9 a8",
" a7 a6 x x x x x x", " a7 a6 a5 a4 x x x x",
" x x x x x x x x"; " x x x x x x x x";
mode = 0x41; mode = 0x41;
@ -16499,7 +16884,7 @@ part parent ".reduced_core_tiny"
part part
id = "m406"; id = "m406";
desc = "ATMEGA406"; desc = "ATmega406";
has_jtag = yes; has_jtag = yes;
signature = 0x1e 0x95 0x07; signature = 0x1e 0x95 0x07;
@ -16632,9 +17017,7 @@ part
; ;
memory "wdtcfg" memory "wdtcfg"
size = 1; alias "fuse0";
offset = 0x1280;
readsize = 1;
; ;
memory "fuse1" memory "fuse1"
@ -16644,9 +17027,7 @@ part
; ;
memory "bodcfg" memory "bodcfg"
size = 1; alias "fuse1";
offset = 0x1281;
readsize = 1;
; ;
memory "fuse2" memory "fuse2"
@ -16656,9 +17037,7 @@ part
; ;
memory "osccfg" memory "osccfg"
size = 1; alias "fuse2";
offset = 0x1282;
readsize = 1;
; ;
memory "fuse4" memory "fuse4"
@ -16668,9 +17047,7 @@ part
; ;
memory "tcd0cfg" memory "tcd0cfg"
size = 1; alias "fuse4";
offset = 0x1284;
readsize = 1;
; ;
memory "fuse5" memory "fuse5"
@ -16680,9 +17057,7 @@ part
; ;
memory "syscfg0" memory "syscfg0"
size = 1; alias "fuse5";
offset = 0x1285;
readsize = 1;
; ;
memory "fuse6" memory "fuse6"
@ -16692,9 +17067,7 @@ part
; ;
memory "syscfg1" memory "syscfg1"
size = 1; alias "fuse6";
offset = 0x1286;
readsize = 1;
; ;
memory "fuse7" memory "fuse7"
@ -16704,9 +17077,11 @@ part
; ;
memory "append" memory "append"
size = 1; alias "fuse7";
offset = 0x1287; ;
readsize = 1;
memory "codesize"
alias "fuse7";
; ;
memory "fuse8" memory "fuse8"
@ -16716,9 +17091,11 @@ part
; ;
memory "bootend" memory "bootend"
size = 1; alias "fuse8";
offset = 0x1288; ;
readsize = 1;
memory "bootsize"
alias "fuse8";
; ;
memory "lock" memory "lock"
@ -16742,12 +17119,16 @@ part parent ".avr8x"
desc = "AVR8X tiny family common values"; desc = "AVR8X tiny family common values";
family_id = "tinyAVR"; family_id = "tinyAVR";
memory "usersig" memory "userrow"
size = 0x20; size = 0x20;
offset = 0x1300; offset = 0x1300;
page_size = 0x20; page_size = 0x20;
readsize = 0x100; readsize = 0x100;
; ;
memory "usersig"
alias "userrow";
;
; ;
#------------------------------------------------------------ #------------------------------------------------------------
@ -16759,12 +17140,16 @@ part parent ".avr8x"
desc = "AVR8X mega family common values"; desc = "AVR8X mega family common values";
family_id = "megaAVR"; family_id = "megaAVR";
memory "usersig" memory "userrow"
size = 0x40; size = 0x40;
offset = 0x1300; offset = 0x1300;
page_size = 0x40; page_size = 0x40;
readsize = 0x100; readsize = 0x100;
; ;
memory "usersig"
alias "userrow";
;
; ;
#------------------------------------------------------------ #------------------------------------------------------------
@ -17900,9 +18285,7 @@ part
; ;
memory "wdtcfg" memory "wdtcfg"
size = 1; alias "fuse0";
offset = 0x1050;
readsize = 1;
; ;
memory "fuse1" memory "fuse1"
@ -17912,9 +18295,7 @@ part
; ;
memory "bodcfg" memory "bodcfg"
size = 1; alias "fuse1";
offset = 0x1051;
readsize = 1;
; ;
memory "fuse2" memory "fuse2"
@ -17924,9 +18305,7 @@ part
; ;
memory "osccfg" memory "osccfg"
size = 1; alias "fuse2";
offset = 0x1052;
readsize = 1;
; ;
memory "fuse4" memory "fuse4"
@ -17936,9 +18315,7 @@ part
; ;
memory "tcd0cfg" memory "tcd0cfg"
size = 1; alias "fuse4";
offset = 0x1054;
readsize = 1;
; ;
memory "fuse5" memory "fuse5"
@ -17948,9 +18325,7 @@ part
; ;
memory "syscfg0" memory "syscfg0"
size = 1; alias "fuse5";
offset = 0x1055;
readsize = 1;
; ;
memory "fuse6" memory "fuse6"
@ -17960,9 +18335,7 @@ part
; ;
memory "syscfg1" memory "syscfg1"
size = 1; alias "fuse6";
offset = 0x1056;
readsize = 1;
; ;
memory "fuse7" memory "fuse7"
@ -17972,15 +18345,11 @@ part
; ;
memory "codesize" memory "codesize"
size = 1; alias "fuse7";
offset = 0x1057;
readsize = 1;
; ;
memory "append" memory "append"
size = 1; alias "fuse7";
offset = 0x1057;
readsize = 1;
; ;
memory "fuse8" memory "fuse8"
@ -17990,15 +18359,11 @@ part
; ;
memory "bootsize" memory "bootsize"
size = 1; alias "fuse8";
offset = 0x1058;
readsize = 1;
; ;
memory "bootend" memory "bootend"
size = 1; alias "fuse8";
offset = 0x1058;
readsize = 1;
; ;
memory "lock" memory "lock"
@ -18015,6 +18380,10 @@ part
readsize = 0x20; readsize = 0x20;
; ;
memory "usersig"
alias "userrow";
;
memory "data" memory "data"
# SRAM, only used to supply the offset # SRAM, only used to supply the offset
offset = 0x1000000; offset = 0x1000000;
@ -18851,6 +19220,10 @@ part parent ".avrdx"
page_size = 0x40; page_size = 0x40;
readsize = 0x40; readsize = 0x40;
; ;
memory "usersig"
alias "userrow";
;
; ;
#------------------------------------------------------------ #------------------------------------------------------------

View File

@ -260,6 +260,21 @@ AVRMEM * avr_new_memtype(void)
return m; return m;
} }
AVRMEM_ALIAS * avr_new_memalias(void)
{
AVRMEM_ALIAS * m;
m = (AVRMEM_ALIAS *)malloc(sizeof(*m));
if (m == NULL) {
avrdude_message(MSG_INFO, "avr_new_memalias(): out of memory\n");
exit(1);
}
memset(m, 0, sizeof(*m));
return m;
}
/* /*
* Allocate and initialize memory buffers for each of the device's * Allocate and initialize memory buffers for each of the device's
@ -326,6 +341,17 @@ AVRMEM * avr_dup_mem(AVRMEM * m)
return n; return n;
} }
AVRMEM_ALIAS * avr_dup_memalias(AVRMEM_ALIAS * m)
{
AVRMEM_ALIAS * n;
n = avr_new_memalias();
*n = *m;
return n;
}
void avr_free_mem(AVRMEM * m) void avr_free_mem(AVRMEM * m)
{ {
int i; int i;
@ -348,7 +374,36 @@ void avr_free_mem(AVRMEM * m)
free(m); free(m);
} }
AVRMEM * avr_locate_mem(AVRPART * p, char * desc) void avr_free_memalias(AVRMEM_ALIAS * m)
{
free(m);
}
AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, char * desc)
{
AVRMEM_ALIAS * m, * match;
LNODEID ln;
int matches;
int l;
l = strlen(desc);
matches = 0;
match = NULL;
for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) {
m = ldata(ln);
if (strncmp(desc, m->desc, l) == 0) {
match = m;
matches++;
}
}
if (matches == 1)
return match;
return NULL;
}
AVRMEM * avr_locate_mem_noalias(AVRPART * p, char * desc)
{ {
AVRMEM * m, * match; AVRMEM * m, * match;
LNODEID ln; LNODEID ln;
@ -373,11 +428,54 @@ AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
} }
AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
{
AVRMEM * m, * match;
AVRMEM_ALIAS * alias;
LNODEID ln;
int matches;
int l;
l = strlen(desc);
matches = 0;
match = NULL;
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
m = ldata(ln);
if (strncmp(desc, m->desc, l) == 0) {
match = m;
matches++;
}
}
if (matches == 1)
return match;
/* not yet found: look for matching alias name */
alias = avr_locate_memalias(p, desc);
if (alias != NULL)
return alias->aliased_mem;
return NULL;
}
AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig)
{
AVRMEM_ALIAS * m;
LNODEID ln;
for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) {
m = ldata(ln);
if (m->aliased_mem == m_orig)
return m;
}
return NULL;
}
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
int type, int verbose) int type, int verbose)
{ {
static LNODEID ln;
static AVRMEM * n;
static unsigned int prev_mem_offset, prev_mem_size; static unsigned int prev_mem_offset, prev_mem_size;
int i, j; int i, j;
char * optr; char * optr;
@ -398,25 +496,14 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
prefix, prefix, prefix); prefix, prefix, prefix);
} }
// Get the next memory section, and stop before going out of band
if (ln == NULL)
ln = lnext(lfirst(p->mem));
else
ln = lnext(ln);
if (ln != NULL)
n = ldata(ln);
// Only print memory section if the previous section printed isn't identical // Only print memory section if the previous section printed isn't identical
if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) { if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) {
prev_mem_offset = m->offset; prev_mem_offset = m->offset;
prev_mem_size = m->size; prev_mem_size = m->size;
AVRMEM_ALIAS *ap = avr_find_memalias(p, m);
/* Show alias if the current and the next memory section has the same offset /* Show alias if the current and the next memory section has the same offset
and size, we're not out of band and a family_id is present */ and size, we're not out of band and a family_id is present */
char * mem_desc_alias = m->offset == n->offset && \ char * mem_desc_alias = ap? ap->desc: "";
m->size == n->size && \
ln != NULL && \
strcmp(p->family_id, "") != 0 ?
n->desc : "";
fprintf(f, fprintf(f,
"%s%-11s %-8s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n", "%s%-11s %-8s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
prefix, prefix,
@ -488,6 +575,7 @@ AVRPART * avr_new_part(void)
p->ocdrev = -1; p->ocdrev = -1;
p->mem = lcreat(NULL, 0); p->mem = lcreat(NULL, 0);
p->mem_alias = lcreat(NULL, 0);
return p; return p;
} }
@ -496,19 +584,35 @@ AVRPART * avr_new_part(void)
AVRPART * avr_dup_part(AVRPART * d) AVRPART * avr_dup_part(AVRPART * d)
{ {
AVRPART * p; AVRPART * p;
LISTID save; LISTID save, save2;
LNODEID ln; LNODEID ln, ln2;
int i; int i;
p = avr_new_part(); p = avr_new_part();
save = p->mem; save = p->mem;
save2 = p->mem_alias;
*p = *d; *p = *d;
p->mem = save; p->mem = save;
p->mem_alias = save2;
for (ln=lfirst(d->mem); ln; ln=lnext(ln)) { for (ln=lfirst(d->mem); ln; ln=lnext(ln)) {
ladd(p->mem, avr_dup_mem(ldata(ln))); AVRMEM *m = ldata(ln);
AVRMEM *m2 = avr_dup_mem(m);
ladd(p->mem, m2);
// see if there is any alias for it
for (ln2=lfirst(d->mem_alias); ln2; ln2=lnext(ln2)) {
AVRMEM_ALIAS *a = ldata(ln2);
if (a->aliased_mem == m) {
// yes, duplicate it
AVRMEM_ALIAS *a2 = avr_dup_memalias(a);
// ... adjust the pointer ...
a2->aliased_mem = m2;
// ... and add to new list
ladd(p->mem_alias, a2);
}
}
} }
for (i = 0; i < AVR_OP_MAX; i++) { for (i = 0; i < AVR_OP_MAX; i++) {
@ -523,6 +627,8 @@ void avr_free_part(AVRPART * d)
int i; int i;
ldestroy_cb(d->mem, (void(*)(void *))avr_free_mem); ldestroy_cb(d->mem, (void(*)(void *))avr_free_mem);
d->mem = NULL; d->mem = NULL;
ldestroy_cb(d->mem_alias, (void(*)(void *))avr_free_memalias);
d->mem_alias = NULL;
for(i=0;i<sizeof(d->op)/sizeof(d->op[0]);i++) for(i=0;i<sizeof(d->op)/sizeof(d->op[0]);i++)
{ {
if (d->op[i] != NULL) if (d->op[i] != NULL)

View File

@ -36,7 +36,6 @@ char default_programmer[MAX_STR_CONST];
char default_parallel[PATH_MAX]; char default_parallel[PATH_MAX];
char default_serial[PATH_MAX]; char default_serial[PATH_MAX];
double default_bitclock; double default_bitclock;
int default_safemode;
char string_buf[MAX_STR_CONST]; char string_buf[MAX_STR_CONST];
char *string_buf_ptr; char *string_buf_ptr;
@ -48,6 +47,7 @@ AVRPART * current_part;
AVRMEM * current_mem; AVRMEM * current_mem;
LISTID part_list; LISTID part_list;
LISTID programmers; LISTID programmers;
bool is_alias;
int lineno; int lineno;
const char * infile; const char * infile;
@ -73,6 +73,7 @@ int init_config(void)
current_mem = NULL; current_mem = NULL;
part_list = lcreat(NULL, 0); part_list = lcreat(NULL, 0);
programmers = lcreat(NULL, 0); programmers = lcreat(NULL, 0);
is_alias = false;
lineno = 1; lineno = 1;
infile = NULL; infile = NULL;

View File

@ -54,6 +54,7 @@ extern int lineno;
extern const char * infile; extern const char * infile;
extern LISTID string_list; extern LISTID string_list;
extern LISTID number_list; extern LISTID number_list;
extern bool is_alias; // current entry is alias
#if !defined(HAS_YYSTYPE) #if !defined(HAS_YYSTYPE)

View File

@ -68,6 +68,7 @@ static int pin_name;
%token K_PAGE_SIZE %token K_PAGE_SIZE
%token K_PAGED %token K_PAGED
%token K_ALIAS
%token K_BAUDRATE %token K_BAUDRATE
%token K_BS2 %token K_BS2
%token K_BUFF %token K_BUFF
@ -77,7 +78,6 @@ static int pin_name;
%token K_DEFAULT_BITCLOCK %token K_DEFAULT_BITCLOCK
%token K_DEFAULT_PARALLEL %token K_DEFAULT_PARALLEL
%token K_DEFAULT_PROGRAMMER %token K_DEFAULT_PROGRAMMER
%token K_DEFAULT_SAFEMODE
%token K_DEFAULT_SERIAL %token K_DEFAULT_SERIAL
%token K_DESC %token K_DESC
%token K_FAMILY_ID %token K_FAMILY_ID
@ -257,14 +257,6 @@ def :
K_DEFAULT_BITCLOCK TKN_EQUAL number_real TKN_SEMI { K_DEFAULT_BITCLOCK TKN_EQUAL number_real TKN_SEMI {
default_bitclock = $3->value.number_real; default_bitclock = $3->value.number_real;
free_token($3); free_token($3);
} |
K_DEFAULT_SAFEMODE TKN_EQUAL yesno TKN_SEMI {
if ($3->primary == K_YES)
default_safemode = 1;
else if ($3->primary == K_NO)
default_safemode = 0;
free_token($3);
} }
; ;
@ -1248,12 +1240,17 @@ part_parm :
{ {
AVRMEM * existing_mem; AVRMEM * existing_mem;
existing_mem = avr_locate_mem(current_part, current_mem->desc); existing_mem = avr_locate_mem_noalias(current_part, current_mem->desc);
if (existing_mem != NULL) { if (existing_mem != NULL) {
lrmv_d(current_part->mem, existing_mem); lrmv_d(current_part->mem, existing_mem);
avr_free_mem(existing_mem); avr_free_mem(existing_mem);
} }
if (is_alias) {
avr_free_mem(current_mem); // alias mem has been already entered below
is_alias = false;
} else {
ladd(current_part->mem, current_mem); ladd(current_part->mem, current_mem);
}
current_mem = NULL; current_mem = NULL;
} | } |
@ -1290,6 +1287,7 @@ yesno :
mem_specs : mem_specs :
mem_spec TKN_SEMI | mem_spec TKN_SEMI |
mem_alias TKN_SEMI |
mem_specs mem_spec TKN_SEMI mem_specs mem_spec TKN_SEMI
; ;
@ -1419,6 +1417,38 @@ mem_spec :
} }
; ;
mem_alias :
K_ALIAS TKN_STRING
{
AVRMEM * existing_mem;
existing_mem = avr_locate_mem(current_part, $2->value.string);
if (existing_mem == NULL) {
yyerror("%s alias to non-existent memory %s",
current_mem->desc, $2->value.string);
free_token($2);
YYABORT;
}
// if this alias does already exist, drop the old one
AVRMEM_ALIAS * alias = avr_locate_memalias(current_part, current_mem->desc);
if (alias) {
lrmv_d(current_part->mem_alias, alias);
avr_free_memalias(alias);
}
is_alias = true;
alias = avr_new_memalias();
// alias->desc and current_mem->desc have the same length
// definition, thus no need to check for length here
strcpy(alias->desc, current_mem->desc);
alias->aliased_mem = existing_mem;
ladd(current_part->mem_alias, alias);
free_token($2);
}
;
%% %%

View File

@ -23,7 +23,7 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_PREREQ(2.60) AC_PREREQ(2.60)
AC_INIT(avrdude, 6.99-20211218, avrdude-dev@nongnu.org) AC_INIT(avrdude, 7.0-20220508, avrdude-dev@nongnu.org)
AC_CANONICAL_BUILD AC_CANONICAL_BUILD
AC_CANONICAL_HOST AC_CANONICAL_HOST

View File

@ -40,7 +40,7 @@ all-local: info html ps pdf
html: avrdude-html/avrdude.html html: avrdude-html/avrdude.html
avrdude-html/avrdude.html: $(srcdir)/$(info_TEXINFOS) $(GENERATED_TEXINFOS) avrdude-html/avrdude.html: $(srcdir)/$(info_TEXINFOS) $(GENERATED_TEXINFOS)
texi2html -split_node $(srcdir)/$(info_TEXINFOS) texi2html --split=node --css-include=$(srcdir)/avrdude.css $(srcdir)/$(info_TEXINFOS)
if [ -e ./avrdude.html -o -e ./avrdude_1.html ]; then \ if [ -e ./avrdude.html -o -e ./avrdude_1.html ]; then \
mkdir -p avrdude-html ; \ mkdir -p avrdude-html ; \
mv -f *.html avrdude-html ; \ mv -f *.html avrdude-html ; \

20
src/doc/avrdude.css Normal file
View File

@ -0,0 +1,20 @@
body { background-color: #ffd; }
h1 { text-shadow: .05em .05em #ccc; }
table {
border: 3px solid #ccf;
background-color: white;
}
div.smallexample {
background-color: #dfd;
border: 3px solid #cfc;
}
div.example {
background-color: #dfd;
border: 3px solid #cfc;
}
samp {
color: blue;
}
code {
color: green;
}

View File

@ -28,9 +28,7 @@ This file documents the avrdude program.
For avrdude version @value{VERSION}, @value{UPDATED}. For avrdude version @value{VERSION}, @value{UPDATED}.
Copyright @copyright{} 2003, 2005 Brian Dean Copyright @copyright{} Brian Dean, J@"org Wunsch
Copyright @copyright{} 2006 - 2021 J@"org Wunsch
Permission is granted to make and distribute verbatim copies of Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice this manual provided the copyright notice and this permission notice
@ -64,13 +62,10 @@ the terms of the GNU Free Documentation License (FDL), version 1.3.
@author by Brian S. Dean @author by Brian S. Dean
@page @page
Send comments on AVRDUDE to @w{@email{avrdude-dev@@nongnu.org}}.
Use @uref{http://savannah.nongnu.org/bugs/?group=avrdude} to report bugs. Use @uref{https://github.com/avrdudes/avrdude/issues} to report bugs and ask questions.
Copyright @copyright{} 2003,2005 Brian S. Dean Copyright @copyright{} Brian S. Dean, J@"org Wunsch
Copyright @copyright{} 2006 - 2013 J@"org Wunsch
@sp 2 @sp 2
Permission is granted to make and distribute verbatim copies of Permission is granted to make and distribute verbatim copies of
@ -102,13 +97,9 @@ programs to Atmel AVR microcontrollers.
For avrdude version @value{VERSION}, @value{UPDATED}. For avrdude version @value{VERSION}, @value{UPDATED}.
Send comments on AVRDUDE to @w{@email{avrdude-dev@@nongnu.org}}. Use @uref{https://github.com/avrdudes/avrdude/issues} to report bugs and ask questions.
Use @uref{http://savannah.nongnu.org/bugs/?group=avrdude} to report bugs. Copyright @copyright{} Brian S. Dean, J@"org Wunsch
Copyright @copyright{} 2003,2005 Brian S. Dean
Copyright @copyright{} 2006 J@"org Wunsch
@end ifinfo @end ifinfo
@menu @menu
@ -119,6 +110,7 @@ Copyright @copyright{} 2006 J@"org Wunsch
* Programmer Specific Information:: * Programmer Specific Information::
* Platform Dependent Information:: * Platform Dependent Information::
* Troubleshooting:: * Troubleshooting::
* Index::
@end menu @end menu
@c @c
@ -127,7 +119,7 @@ Copyright @copyright{} 2006 J@"org Wunsch
@node Introduction, Command Line Options, Top, Top @node Introduction, Command Line Options, Top, Top
@comment node-name, next, previous, up @comment node-name, next, previous, up
@chapter Introduction @chapter Introduction
@cindex introduction @cindex Introduction
AVRDUDE - AVR Downloader Uploader - is a program for downloading and AVRDUDE - AVR Downloader Uploader - is a program for downloading and
uploading the on-chip memories of Atmel's AVR microcontrollers. It can uploading the on-chip memories of Atmel's AVR microcontrollers. It can
@ -145,6 +137,8 @@ from the contents of a file, while interactive mode is useful for
exploring memory contents, modifying individual bytes of eeprom, exploring memory contents, modifying individual bytes of eeprom,
programming fuse/lock bits, etc. programming fuse/lock bits, etc.
@cindex Programmers supported
AVRDUDE supports the following basic programmer types: Atmel's STK500, AVRDUDE supports the following basic programmer types: Atmel's STK500,
Atmel's AVRISP and AVRISP mkII devices, Atmel's AVRISP and AVRISP mkII devices,
Atmel's STK600, Atmel's STK600,
@ -345,6 +339,7 @@ below for Teensy specific options.
@c Node @c Node
@c @c
@node History, , Introduction, Introduction @node History, , Introduction, Introduction
@cindex History
@section History and Credits @section History and Credits
AVRDUDE was written by Brian S. Dean under the name of AVRPROG to run on AVRDUDE was written by Brian S. Dean under the name of AVRPROG to run on
@ -353,13 +348,15 @@ AVRDUDE when interest grew in a Windows port of the software so that the
name did not conflict with AVRPROG.EXE which is the name of Atmel's name did not conflict with AVRPROG.EXE which is the name of Atmel's
Windows programming software. Windows programming software.
The AVRDUDE source now resides in the public CVS repository on For many years, the AVRDUDE source resided in public repositories on
savannah.gnu.org (@url{http://savannah.gnu.org/projects/avrdude/}), savannah.nongnu.org,
where it continues to be enhanced and ported to other systems. In where it continued to be enhanced and ported to other systems. In
addition to FreeBSD, AVRDUDE now runs on Linux and Windows. The addition to FreeBSD, AVRDUDE now runs on Linux and Windows. The
developers behind the porting effort primarily were Ted Roth, Eric developers behind the porting effort primarily were Ted Roth, Eric
Weddington, and Joerg Wunsch. Weddington, and Joerg Wunsch.
In 2022, the project moved to Github (@url{https://github.com/avrdudes/avrdude/}).
And in the spirit of many open source projects, this manual also draws And in the spirit of many open source projects, this manual also draws
on the work of others. The initial revision was composed of parts of on the work of others. The initial revision was composed of parts of
the original Unix manual page written by Joerg Wunsch, the original web the original Unix manual page written by Joerg Wunsch, the original web
@ -374,7 +371,6 @@ Roth.
@c @c
@node Command Line Options, Terminal Mode Operation, Introduction, Top @node Command Line Options, Terminal Mode Operation, Introduction, Top
@chapter Command Line Options @chapter Command Line Options
@cindex options
@menu @menu
* Option Descriptions:: * Option Descriptions::
@ -386,6 +382,7 @@ Roth.
@c Node @c Node
@c @c
@node Option Descriptions, Programmers accepting extended parameters, Command Line Options, Command Line Options @node Option Descriptions, Programmers accepting extended parameters, Command Line Options, Command Line Options
@cindex Options (command-line)
@section Option Descriptions @section Option Descriptions
@noindent @noindent
@ -410,6 +407,8 @@ but it can be added to the configuration file if you have the Atmel
datasheet so that you can enter the programming specifications. datasheet so that you can enter the programming specifications.
Currently, the following MCU types are understood: Currently, the following MCU types are understood:
@cindex Device support
@multitable @columnfractions .15 .3 @multitable @columnfractions .15 .3
@include parts.texi @include parts.texi
@end multitable @end multitable
@ -461,6 +460,8 @@ file without any code changes to AVRDUDE. Simply copy an existing entry
and change the pin definitions to match that of the unknown programmer. and change the pin definitions to match that of the unknown programmer.
Currently, the following programmer ids are understood and supported: Currently, the following programmer ids are understood and supported:
@cindex Programmer support
@multitable @columnfractions .2 .6 @multitable @columnfractions .2 .6
@include programmers.texi @include programmers.texi
@end multitable @end multitable
@ -681,32 +682,6 @@ Posix systems (by now).
Disable (or quell) output of the progress bar while reading or writing Disable (or quell) output of the progress bar while reading or writing
to the device. Specify it a second time for even quieter operation. to the device. Specify it a second time for even quieter operation.
@item -u
Disables the default behaviour of reading out the fuses three times before
programming, then verifying at the end of programming that the fuses have not
changed. If you want to change fuses you will need to specify this option,
as avrdude will see the fuses have changed (even though you wanted to) and
will change them back for your "safety". This option was designed to
prevent cases of fuse bits magically changing (usually called @emph{safemode}).
If one of the configuration files contains a line
@code{default_safemode = no;}
safemode is disabled by default.
The @option{-u} option's effect is negated in that case, i. e. it
@emph{enables} safemode.
Safemode is always disabled for AVR32, Xmega and TPI devices.
@item -s
Disable safemode prompting. When safemode discovers that one or more
fuse bits have unintentionally changed, it will prompt for
confirmation regarding whether or not it should attempt to recover the
fuse bit(s). Specifying this flag disables the prompt and assumes
that the fuse bit(s) should be recovered without asking for
confirmation first.
@item -t @item -t
Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up- Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up-
or downloading files. See below for a detailed description of the or downloading files. See below for a detailed description of the
@ -864,7 +839,7 @@ accepting extended parameters.
@c @c
@node Programmers accepting extended parameters, Example Command Line Invocations, Option Descriptions, Command Line Options @node Programmers accepting extended parameters, Example Command Line Invocations, Option Descriptions, Command Line Options
@section Programmers accepting extended parameters @section Programmers accepting extended parameters
@cindex @code{-x} AVR Dragon
@table @code @table @code
@item JTAG ICE mkII/3 @item JTAG ICE mkII/3
@ -881,6 +856,7 @@ Each AVR unit within the chain shifts by 4 bits.
Other JTAG units might require a different bit shift count. Other JTAG units might require a different bit shift count.
@end table @end table
@cindex @code{-x} AVR910
@item AVR910 @item AVR910
The AVR910 programmer type accepts the following extended parameter: The AVR910 programmer type accepts the following extended parameter:
@ -901,13 +877,16 @@ Use
programmer creates errors during initial sequence. programmer creates errors during initial sequence.
@end table @end table
@cindex @code{-x} Arduino
@item Arduino @item Arduino
The Arduino programmer type accepts the following extended parameter: The Arduino programmer type accepts the following extended parameter:
@table @code @table @code
@item @samp{attemps=VALUE} @item @samp{attemps=VALUE}
Overide the default number of connection retry attempt by using @var{VALUE}. Overide the default number of connection retry attempt by using @var{VALUE}.
@end table
@cindex @code{-x} Buspirate
@item BusPirate @item BusPirate
The BusPirate programmer type accepts the following extended parameters: The BusPirate programmer type accepts the following extended parameters:
@ -997,6 +976,7 @@ The default value is 100ms. Using 10ms might work in most cases.
@end table @end table
@cindex @code{-x} Micronucleus bootloader
@item Micronucleus bootloader @item Micronucleus bootloader
When using the Micronucleus programmer type, the When using the Micronucleus programmer type, the
@ -1009,6 +989,7 @@ If no time-out is specified, AVRDUDE will wait indefinitely until the
device is plugged in. device is plugged in.
@end table @end table
@cindex @code{-x} Teensy bootloader
@item Teensy bootloader @item Teensy bootloader
When using the Teensy programmer type, the When using the Teensy programmer type, the
@ -1021,6 +1002,7 @@ If no time-out is specified, AVRDUDE will wait indefinitely until the
device is plugged in. device is plugged in.
@end table @end table
@cindex @code{-x} Wiring
@item Wiring @item Wiring
When using the Wiring programmer type, the When using the Wiring programmer type, the
@ -1032,6 +1014,7 @@ After performing the port open phase, AVRDUDE will wait/snooze for
No toggling of DTR/RTS is performed if @var{snooze} > 0. No toggling of DTR/RTS is performed if @var{snooze} > 0.
@end table @end table
@cindex @code{-x} PICkit2
@item PICkit2 @item PICkit2
Connection to the PICkit2 programmer: Connection to the PICkit2 programmer:
@multitable @columnfractions .05 .3 @multitable @columnfractions .05 .3
@ -1052,6 +1035,7 @@ 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). Sets the timeout for USB reads and writes in milliseconds (default is 1500 ms).
@end table @end table
@cindex @code{-x} USBasp
@item USBasp @item USBasp
Extended parameters: Extended parameters:
@table @code @table @code
@ -1062,6 +1046,7 @@ rather than entire chip.
Only applicable to TPI devices (ATtiny 4/5/9/10/20/40). Only applicable to TPI devices (ATtiny 4/5/9/10/20/40).
@end table @end table
@cindex @code{-x} xbee
@item xbee @item xbee
Extended parameters: Extended parameters:
@table @code @table @code
@ -1078,6 +1063,7 @@ The remaining two necessary XBee-to-MCU connections are not selectable
the MCU's TXD line. the MCU's TXD line.
@end table @end table
@cindex @code{-x} serialupdi
@item serialupdi @item serialupdi
Extended parameters: Extended parameters:
@table @code @table @code
@ -1133,8 +1119,6 @@ Reading | ################################################## | 100% 6.83s
avrdude: verifying ... avrdude: verifying ...
avrdude: 19278 bytes of flash verified avrdude: 19278 bytes of flash verified
avrdude: safemode: Fuses OK
avrdude done. Thank you. avrdude done. Thank you.
% %
@ -1162,8 +1146,6 @@ Reading | ################################################## | 100% 46.10s
avrdude: writing output file "c:/diag flash.bin" avrdude: writing output file "c:/diag flash.bin"
avrdude: safemode: Fuses OK
avrdude done. Thank you. avrdude done. Thank you.
% %
@ -1284,6 +1266,7 @@ commands can be recalled and edited.
@end menu @end menu
@node Terminal Mode Commands, Terminal Mode Examples, Terminal Mode Operation, Terminal Mode Operation @node Terminal Mode Commands, Terminal Mode Examples, Terminal Mode Operation, Terminal Mode Operation
@cindex Terminal Mode
@section Terminal Mode Commands @section Terminal Mode Commands
@noindent @noindent
@ -1291,20 +1274,83 @@ The following commands are implemented:
@table @code @table @code
@item dump @var{memtype} @var{addr} @var{nbytes} @item dump @var{memtype} [@var{start_addr} [@var{nbytes}]]
Read @var{nbytes} from the specified memory area, and display them in Read @var{nbytes} from the specified memory area, and display them in
the usual hexadecimal and ASCII form. the usual hexadecimal and ASCII form.
@item dump @item dump @var{memtype} [@var{start_addr}] @dots{}
Start reading from @var{start_addr}, all the way to the last memory address.
@item dump @var{memtype}
Continue dumping the memory contents for another @var{nbytes} where the Continue dumping the memory contents for another @var{nbytes} where the
previous dump command left off. previous dump command left off.
@item write @var{memtype} @var{addr} @var{byte1} @dots{} @var{byteN} @item write @var{memtype} @var{start_addr} @var{data1} @var{data2} @dots{} @var{dataN}
Manually program the respective memory cells, starting at address addr, Manually program the respective memory cells, starting at address @var{start_addr},
using the values @var{byte1} through @var{byteN}. This feature is not using the values @var{data1} through @var{dataN}. This feature is not
implemented for bank-addressed memories such as the flash memory of implemented for bank-addressed memories such as the flash memory of
ATMega devices. ATMega devices.
Items @var{dataN} can have the following formats:
@multitable @columnfractions .3 .4 .3
@item @strong{Type}
@tab @strong{Example}
@tab @strong{Size (bytes)}
@item Character
@tab @code{'A'}
@tab 1
@item Decimal integer
@tab 12345
@tab 1, 2, 4, or 8 (see below)
@item Octal integer
@tab 012345
@tab 1, 2, 4, or 8 (see below)
@item Hexadecimal integer
@tab 0x12345
@tab 1, 2, 4, or 8 (see below)
@item Float
@tab 3.1415926
@tab 4
@end multitable
Integer constants can be 1, 2, 4, or 8 bytes long.
By default, the smallest possible size will be used where
the specified number just fits into.
A specific size can be denoted by appending one of these suffixes:
@table @code
@item LL
@itemx ll
8 bytes / 64 bits
@item L
@itemx l
4 bytes / 32 bits
@item H
@itemx h
@itemx S
@itemx s
2 bytes / 16 bits
@item HH
@itemx hh
1 byte / 8 bits
@end table
Similarly, floating-point constants can have an @code{F} or @code{f}
appended, but only 32-bit floating-point values are supported.
@item write @var{memtype} @var{start_addr} @var{length} @var{data1} @var{data2} @var{dataN} @dots{}
Similar to the above, but @var{length} byte of the memory are written.
For that purpose, after writing the initial items, @var{dataN} is
replicated as many times as needed.
@item erase @item erase
Perform a chip erase. Perform a chip erase.
@ -1397,6 +1443,7 @@ Display the current target supply voltage and JTAG bit clock rate/period.
@c Node @c Node
@c @c
@node Terminal Mode Examples, , Terminal Mode Commands, Terminal Mode Operation @node Terminal Mode Examples, , Terminal Mode Commands, Terminal Mode Operation
@cindex Terminal Mode
@section Terminal Mode Examples @section Terminal Mode Examples
@noindent @noindent
@ -1408,7 +1455,6 @@ Display part parameters, modify eeprom cells, perform a chip erase:
avrdude: AVR device initialized and ready to accept instructions avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e9702 avrdude: Device signature = 0x1e9702
avrdude: current erase-rewrite cycle count is 52 (if being tracked)
avrdude> part avrdude> part
>>> part >>> part
@ -1470,7 +1516,6 @@ display the factory defaults, then reprogram:
avrdude: AVR device initialized and ready to accept instructions avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e9702 avrdude: Device signature = 0x1e9702
avrdude: current erase-rewrite cycle count is 52 (if being tracked)
avrdude> d efuse avrdude> d efuse
>>> d efuse >>> d efuse
0000 fd |. | 0000 fd |. |
@ -1496,11 +1541,56 @@ avrdude>
@end cartouche @end cartouche
@end smallexample @end smallexample
@smallexample
@cartouche
% avrdude -c pkobn_updi -p avr128db48 -t
Vtarget : 4.71 V
PDI/UPDI clock Xmega/megaAVR : 100 kHz
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.01s
avrdude: Device signature = 0x1e970c (probably avr128db48)
avrdude> write eeprom 0 1234567890 'A' 'V' 'R' 2.718282 "Hello World!"
>>> write eeprom 0 1234567890 'A' 'V' 'R' 2.718282 "Hello World!"
Warning: no size suffix specified for "1234567890". Writing 4 byte(s)
Info: Writing 24 bytes starting from address 0x00
avrdude> dump eeprom 0 32
>>> dump eeprom 0 32
0000 d2 02 96 49 41 56 52 55 f8 2d 40 48 65 6c 6c 6f |...IAVRU.-@@Hello|
0010 20 57 6f 72 6c 64 21 00 ff ff ff ff ff ff ff ff | World!.........|
avrdude> q
@end cartouche
@end smallexample
The following example demonstrates the second form of the @code{write}
command where the last data value provided is used to fill up the
indicated memory range.
@smallexample
@cartouche
avrdude> write eeprom 0x00 0x20 'a' 'b' 'c' 0x11 0xcafe 0x55 ...
>>> write eeprom 0x00 0x20 'a' 'b' 'c' 0x11 0xcafe 0x55 ...
avrdude> dump eeprom 0 0x30
>>> dump eeprom 0 0x30
0000 61 62 63 11 fe ca 55 55 55 55 55 55 55 55 55 55 |abc...UUUUUUUUUU|
0010 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 |UUUUUUUUUUUUUUUU|
0020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
@end cartouche
@end smallexample
@c @c
@c Node @c Node
@c @c
@node Configuration File, Programmer Specific Information, Terminal Mode Operation, Top @node Configuration File, Programmer Specific Information, Terminal Mode Operation, Top
@cindex Configuration File
@cindex @code{avrdude.conf}
@chapter Configuration File @chapter Configuration File
@noindent @noindent
@ -1845,9 +1935,6 @@ flash pages of the application section.
Reading fuse and lock bits is fully supported. Reading fuse and lock bits is fully supported.
Note that due to the inability to write the fuse bits, the safemode
functionality does not make sense for these boot loaders.
@end itemize @end itemize
@c @c
@ -1866,6 +1953,7 @@ functionality does not make sense for these boot loaders.
@c Node @c Node
@c @c
@node Atmel STK600, Atmel DFU bootloader using FLIP version 1, Programmer Specific Information, Programmer Specific Information @node Atmel STK600, Atmel DFU bootloader using FLIP version 1, Programmer Specific Information, Programmer Specific Information
@cindex STK600
@section Atmel STK600 @section Atmel STK600
@c @c
@ -1962,6 +2050,7 @@ least 4.5 V in order to work. This can be done using
@c Node @c Node
@c @c
@node Atmel DFU bootloader using FLIP version 1, SerialUPDI programmer , Atmel STK600, Programmer Specific Information @node Atmel DFU bootloader using FLIP version 1, SerialUPDI programmer , Atmel STK600, Programmer Specific Information
@cindex DFU bootloader
@section Atmel DFU bootloader using FLIP version 1 @section Atmel DFU bootloader using FLIP version 1
Bootloaders using the FLIP protocol version 1 experience some very Bootloaders using the FLIP protocol version 1 experience some very
@ -1990,6 +2079,7 @@ versions of the bootloader.
@c Node @c Node
@c @c
@node SerialUPDI programmer, , Atmel DFU bootloader using FLIP version 1, Programmer Specific Information @node SerialUPDI programmer, , Atmel DFU bootloader using FLIP version 1, Programmer Specific Information
@cindex SerialUPDI
@section SerialUPDI programmer @section SerialUPDI programmer
SerialUPDI programmer can be used for programming UPDI-only devices SerialUPDI programmer can be used for programming UPDI-only devices
@ -2021,9 +2111,6 @@ fuse, extended fuse) have no meaning whatsoever, as they have been
simply replaced by array of fuses: fuse0..9. Therefore you can simply simply replaced by array of fuses: fuse0..9. Therefore you can simply
ignore this particular line of AVRDUDE output. ignore this particular line of AVRDUDE output.
In connection to the above, @emph{safemode} has no meaning in context
of UPDI devices and should be ignored.
Currently available devices support only UPDI NVM programming model 0 Currently available devices support only UPDI NVM programming model 0
and 2, but there is also experimental implementation of model 3 - not and 2, but there is also experimental implementation of model 3 - not
yet tested. yet tested.
@ -2243,6 +2330,8 @@ configuration file will be always be @code{/etc/avrdude.conf}.
@noindent @noindent
The parallel and serial port device file names are system specific. The parallel and serial port device file names are system specific.
MacOS has no default serial or parallel port names, but available
ports can be found under @code{/dev/cu.*}.
The following table lists the default names for a given system. The following table lists the default names for a given system.
@multitable @columnfractions .30 .30 .30 @multitable @columnfractions .30 .30 .30
@ -2475,13 +2564,13 @@ such as @option{--prefix} and @option{--datadir}.
@c @c
@c Node @c Node
@c @c
@node Troubleshooting, ,Platform Dependent Information ,Top @node Troubleshooting,Index ,Platform Dependent Information ,Top
@appendix Troubleshooting @appendix Troubleshooting
@noindent @noindent
In general, please report any bugs encountered via In general, please report any bugs encountered via
@* @*
@url{http://savannah.nongnu.org/bugs/?group=avrdude}. @url{https://github.com/avrdudes/avrdude/issues}.
@itemize @bullet @itemize @bullet
@ -2786,7 +2875,11 @@ erase cycle.
@end itemize @end itemize
@node Index, , Troubleshooting, Top
@unnumbered Concept Index
@printindex cp
@bye @bye

View File

@ -493,7 +493,7 @@ static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
} }
if (serial_send(&pgm->fd, buf, max_xfer) != 0) { 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", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_send(): failed to send command to serial port\n",
progname); progname);
return -1; return -1;
} }
@ -509,7 +509,7 @@ static int jtag3_edbg_send(PROGRAMMER * pgm, unsigned char * data, size_t len)
(frag == nfragments - 1 && status[1] != 0x01)) (frag == nfragments - 1 && status[1] != 0x01))
{ {
/* what to do in this case? */ /* what to do in this case? */
avrdude_message(MSG_INFO, "%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_send(): Unexpected response 0x%02x, 0x%02x\n",
progname, status[0], status[1]); progname, status[0], status[1]);
} }
data += this_len; data += this_len;
@ -596,36 +596,36 @@ static int jtag3_edbg_signoff(PROGRAMMER * pgm)
buf[1] = CMSISDAP_LED_CONNECT; buf[1] = CMSISDAP_LED_CONNECT;
buf[2] = 0; buf[2] = 0;
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) { if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
progname); progname);
return -1; return -1;
} }
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer); rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) { if (rv != pgm->fd.usb.max_xfer) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
progname, rv); progname, rv);
return -1; return -1;
} }
if (status[0] != CMSISDAP_CMD_LED || if (status[0] != CMSISDAP_CMD_LED ||
status[1] != 0) status[1] != 0)
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n",
progname, status[0], status[1]); progname, status[0], status[1]);
buf[0] = CMSISDAP_CMD_DISCONNECT; buf[0] = CMSISDAP_CMD_DISCONNECT;
if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) { if (serial_send(&pgm->fd, buf, pgm->fd.usb.max_xfer) != 0) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_signoff(): failed to send command to serial port\n",
progname); progname);
return -1; return -1;
} }
rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer); rv = serial_recv(&pgm->fd, status, pgm->fd.usb.max_xfer);
if (rv != pgm->fd.usb.max_xfer) { if (rv != pgm->fd.usb.max_xfer) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_signoff(): failed to read from serial port (%d)\n",
progname, rv); progname, rv);
return -1; return -1;
} }
if (status[0] != CMSISDAP_CMD_DISCONNECT || if (status[0] != CMSISDAP_CMD_DISCONNECT ||
status[1] != 0) status[1] != 0)
avrdude_message(MSG_INFO, "%s: jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_signoff(): unexpected response 0x%02x, 0x%02x\n",
progname, status[0], status[1]); progname, status[0], status[1]);
return 0; return 0;
@ -686,12 +686,12 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
avrdude_message(MSG_TRACE, "%s: jtag3_edbg_recv():\n", progname); avrdude_message(MSG_TRACE, "%s: jtag3_edbg_recv():\n", progname);
if ((buf = malloc(USBDEV_MAX_XFER_3)) == NULL) { if ((buf = malloc(USBDEV_MAX_XFER_3)) == NULL) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): out of memory\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): out of memory\n",
progname); progname);
return -1; return -1;
} }
if ((request = malloc(pgm->fd.usb.max_xfer)) == NULL) { if ((request = malloc(pgm->fd.usb.max_xfer)) == NULL) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): out of memory\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): out of memory\n",
progname); progname);
free(buf); free(buf);
return -1; return -1;
@ -706,7 +706,7 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
request[0] = EDBG_VENDOR_AVR_RSP; request[0] = EDBG_VENDOR_AVR_RSP;
if (serial_send(&pgm->fd, request, pgm->fd.usb.max_xfer) != 0) { 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", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n",
progname); progname);
free(request); free(request);
free(*msg); free(*msg);
@ -725,7 +725,7 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
} }
if (buf[0] != EDBG_VENDOR_AVR_RSP) { if (buf[0] != EDBG_VENDOR_AVR_RSP) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected response 0x%02x\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): Unexpected response 0x%02x\n",
progname, buf[0]); progname, buf[0]);
free(*msg); free(*msg);
free(request); free(request);
@ -736,7 +736,7 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
// Documentation says: // Documentation says:
// "FragmentInfo 0x00 indicates that no response data is // "FragmentInfo 0x00 indicates that no response data is
// available, and the rest of the packet is ignored." // available, and the rest of the packet is ignored."
avrdude_message(MSG_INFO, avrdude_message(MSG_NOTICE,
"%s: jtag3_edbg_recv(): " "%s: jtag3_edbg_recv(): "
"No response available\n", "No response available\n",
progname); progname);
@ -752,7 +752,7 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
thisfrag = 1; thisfrag = 1;
} else { } else {
if (nfrags != (buf[1] & 0x0F)) { if (nfrags != (buf[1] & 0x0F)) {
avrdude_message(MSG_INFO, avrdude_message(MSG_NOTICE,
"%s: jtag3_edbg_recv(): " "%s: jtag3_edbg_recv(): "
"Inconsistent # of fragments; had %d, now %d\n", "Inconsistent # of fragments; had %d, now %d\n",
progname, nfrags, (buf[1] & 0x0F)); progname, nfrags, (buf[1] & 0x0F));
@ -762,7 +762,7 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
} }
} }
if (thisfrag != ((buf[1] >> 4) & 0x0F)) { if (thisfrag != ((buf[1] >> 4) & 0x0F)) {
avrdude_message(MSG_INFO, avrdude_message(MSG_NOTICE,
"%s: jtag3_edbg_recv(): " "%s: jtag3_edbg_recv(): "
"Inconsistent fragment number; expect %d, got %d\n", "Inconsistent fragment number; expect %d, got %d\n",
progname, thisfrag, ((buf[1] >> 4) & 0x0F)); progname, thisfrag, ((buf[1] >> 4) & 0x0F));
@ -773,12 +773,12 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) {
int thislen = (buf[2] << 8) | buf[3]; int thislen = (buf[2] << 8) | buf[3];
if (thislen > rv + 4) { if (thislen > rv + 4) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Unexpected length value (%d > %d)\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): Unexpected length value (%d > %d)\n",
progname, thislen, rv + 4); progname, thislen, rv + 4);
thislen = rv + 4; thislen = rv + 4;
} }
if (len + thislen > USBDEV_MAX_XFER_3) { if (len + thislen > USBDEV_MAX_XFER_3) {
avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Length exceeds max size (%d > %d)\n", avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): Length exceeds max size (%d > %d)\n",
progname, len + thislen, USBDEV_MAX_XFER_3); progname, len + thislen, USBDEV_MAX_XFER_3);
thislen = USBDEV_MAX_XFER_3 - len; thislen = USBDEV_MAX_XFER_3 - len;
} }
@ -865,7 +865,7 @@ int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) {
"%s: Device is locked! Chip erase required to unlock.\n", "%s: Device is locked! Chip erase required to unlock.\n",
progname); progname);
} else { } else {
avrdude_message(MSG_INFO, "%s: bad response to %s command: 0x%02x\n", avrdude_message(MSG_NOTICE, "%s: bad response to %s command: 0x%02x\n",
progname, descr, c); progname, descr, c);
} }
status = (*resp)[3]; status = (*resp)[3];
@ -1129,7 +1129,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
if (PDATA(pgm)->set_sck(pgm, parm) < 0) if (PDATA(pgm)->set_sck(pgm, parm) < 0)
return -1; return -1;
} }
jtag3_print_parms1(pgm, progbuf);
if (conn == PARM3_CONN_JTAG) if (conn == PARM3_CONN_JTAG)
{ {
avrdude_message(MSG_NOTICE2, "%s: jtag3_initialize(): " avrdude_message(MSG_NOTICE2, "%s: jtag3_initialize(): "
@ -1174,7 +1174,8 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
u32_to_b4(xd.nvm_fuse_offset, m->offset & ~7); u32_to_b4(xd.nvm_fuse_offset, m->offset & ~7);
} else if (matches(m->desc, "lock")) { } else if (matches(m->desc, "lock")) {
u32_to_b4(xd.nvm_lock_offset, m->offset); u32_to_b4(xd.nvm_lock_offset, m->offset);
} else if (strcmp(m->desc, "usersig") == 0) { } else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
u32_to_b4(xd.nvm_user_sig_offset, m->offset); u32_to_b4(xd.nvm_user_sig_offset, m->offset);
} else if (strcmp(m->desc, "prodsig") == 0) { } else if (strcmp(m->desc, "prodsig") == 0) {
u32_to_b4(xd.nvm_prod_sig_offset, m->offset); u32_to_b4(xd.nvm_prod_sig_offset, m->offset);
@ -1225,7 +1226,8 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
u16_to_b2(xd.eeprom_bytes, m->size); u16_to_b2(xd.eeprom_bytes, m->size);
u16_to_b2(xd.eeprom_base, m->offset); u16_to_b2(xd.eeprom_base, m->offset);
} }
else if (strcmp(m->desc, "usersig") == 0) else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0)
{ {
u16_to_b2(xd.user_sig_bytes, m->size); u16_to_b2(xd.user_sig_bytes, m->size);
u16_to_b2(xd.user_sig_base, m->offset); u16_to_b2(xd.user_sig_base, m->offset);
@ -1269,7 +1271,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
"xd->flash_page_size=%x\n\t" "xd->flash_page_size=%x\n\t"
"xd->eeprom_page_size=%x\n\t" "xd->eeprom_page_size=%x\n\t"
"xd->nvmctrl=%x %x\n\t" "xd->nvmctrl=%x %x\n\t"
"xd->ocd=%x %x\n\t", "xd->ocd=%x %x\n\t"
"xd->address_mode=%x\n", "xd->address_mode=%x\n",
xd.prog_base_msb, xd.prog_base_msb,
xd.prog_base[0], xd.prog_base[1], xd.prog_base[0], xd.prog_base[1],
@ -1355,11 +1357,12 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
if ((status = jtag3_command(pgm, cmd, 4, &resp, "AVR sign-on")) >= 0) if ((status = jtag3_command(pgm, cmd, 4, &resp, "AVR sign-on")) >= 0)
break; break;
avrdude_message(MSG_INFO, "%s: retrying with external reset applied\n", avrdude_message(MSG_NOTICE, "%s: retrying with external reset applied\n",
progname); progname);
} }
if (use_ext_reset > 1) { if (use_ext_reset > 1) {
if(strcmp(pgm->type, "JTAGICE3") == 0 && p->flags & AVRPART_HAS_JTAG)
avrdude_message(MSG_INFO, "%s: JTAGEN fuse disabled?\n", progname); avrdude_message(MSG_INFO, "%s: JTAGEN fuse disabled?\n", progname);
return -1; return -1;
} }
@ -1689,9 +1692,10 @@ static int jtag3_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[3] = XMEGA_ERASE_BOOT_PAGE; cmd[3] = XMEGA_ERASE_BOOT_PAGE;
} else if (strcmp(m->desc, "eeprom") == 0) { } else if (strcmp(m->desc, "eeprom") == 0) {
cmd[3] = XMEGA_ERASE_EEPROM_PAGE; cmd[3] = XMEGA_ERASE_EEPROM_PAGE;
} else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { } else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
cmd[3] = XMEGA_ERASE_USERSIG; cmd[3] = XMEGA_ERASE_USERSIG;
} else if ( ( strcmp(m->desc, "boot") == 0 ) ) { } else if (strcmp(m->desc, "boot") == 0) {
cmd[3] = XMEGA_ERASE_BOOT_PAGE; cmd[3] = XMEGA_ERASE_BOOT_PAGE;
} else { } else {
cmd[3] = XMEGA_ERASE_APP_PAGE; cmd[3] = XMEGA_ERASE_APP_PAGE;
@ -1763,9 +1767,10 @@ static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
} }
cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM_XMEGA : MTYPE_EEPROM_PAGE; cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM_XMEGA : MTYPE_EEPROM_PAGE;
PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
} else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { } else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
cmd[3] = MTYPE_USERSIG; cmd[3] = MTYPE_USERSIG;
} else if ( ( strcmp(m->desc, "boot") == 0 ) ) { } else if (strcmp(m->desc, "boot") == 0) {
cmd[3] = MTYPE_BOOT_FLASH; cmd[3] = MTYPE_BOOT_FLASH;
} else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) { } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) {
cmd[3] = MTYPE_FLASH; cmd[3] = MTYPE_FLASH;
@ -1852,11 +1857,12 @@ static int jtag3_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE; cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
if (pgm->flag & PGM_FL_IS_DW) if (pgm->flag & PGM_FL_IS_DW)
return -1; return -1;
} else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) { } else if (strcmp(m->desc, "prodsig") == 0) {
cmd[3] = MTYPE_PRODSIG; cmd[3] = MTYPE_PRODSIG;
} else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { } else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
cmd[3] = MTYPE_USERSIG; cmd[3] = MTYPE_USERSIG;
} else if ( ( strcmp(m->desc, "boot") == 0 ) ) { } else if (strcmp(m->desc, "boot") == 0) {
cmd[3] = MTYPE_BOOT_FLASH; cmd[3] = MTYPE_BOOT_FLASH;
} else if ( p->flags & AVRPART_HAS_PDI ) { } else if ( p->flags & AVRPART_HAS_PDI ) {
cmd[3] = MTYPE_FLASH; cmd[3] = MTYPE_FLASH;
@ -1968,10 +1974,23 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
cmd[3] = MTYPE_FUSE_BITS; cmd[3] = MTYPE_FUSE_BITS;
if (!(p->flags & AVRPART_HAS_UPDI)) if (!(p->flags & AVRPART_HAS_UPDI))
addr = mem->offset & 7; addr = mem->offset & 7;
} else if (strcmp(mem->desc, "usersig") == 0) { } else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
cmd[3] = MTYPE_USERSIG; cmd[3] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) { } else if (strcmp(mem->desc, "prodsig") == 0) {
cmd[3] = MTYPE_PRODSIG; cmd[3] = MTYPE_PRODSIG;
} else if (strcmp(mem->desc, "sernum") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osccal16") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osccal20") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "tempsense") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osc16err") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "osc20err") == 0) {
cmd[3] = MTYPE_SIGN_JTAG;
} else if (strcmp(mem->desc, "calibration") == 0) { } else if (strcmp(mem->desc, "calibration") == 0) {
cmd[3] = MTYPE_OSCCAL_BYTE; cmd[3] = MTYPE_OSCCAL_BYTE;
if (pgm->flag & PGM_FL_IS_DW) if (pgm->flag & PGM_FL_IS_DW)
@ -2117,7 +2136,8 @@ static int jtag3_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
cmd[3] = MTYPE_FUSE_BITS; cmd[3] = MTYPE_FUSE_BITS;
if (!(p->flags & AVRPART_HAS_UPDI)) if (!(p->flags & AVRPART_HAS_UPDI))
addr = mem->offset & 7; addr = mem->offset & 7;
} else if (strcmp(mem->desc, "usersig") == 0) { } else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
cmd[3] = MTYPE_USERSIG; cmd[3] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) { } else if (strcmp(mem->desc, "prodsig") == 0) {
cmd[3] = MTYPE_PRODSIG; cmd[3] = MTYPE_PRODSIG;
@ -2232,7 +2252,7 @@ int jtag3_getparm(PROGRAMMER * pgm, unsigned char scope,
c = resp[1]; c = resp[1];
if (c != RSP3_DATA || status < 3) { if (c != RSP3_DATA || status < 3) {
avrdude_message(MSG_INFO, "%s: jtag3_getparm(): " avrdude_message(MSG_NOTICE, "%s: jtag3_getparm(): "
"bad response to %s\n", "bad response to %s\n",
progname, descr); progname, descr);
free(resp); free(resp);
@ -2317,9 +2337,8 @@ static int jtag3_set_vtarget(PROGRAMMER * pgm, double v)
utarg = (unsigned)(v * 1000); utarg = (unsigned)(v * 1000);
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) { if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) {
avrdude_message(MSG_INFO, "%s: jtag3_set_vtarget(): cannot obtain V[aref]\n", avrdude_message(MSG_INFO, "%s: jtag3_set_vtarget(): cannot obtain V[target]\n",
progname); progname);
return -1;
} }
uaref = b2_to_u16(buf); uaref = b2_to_u16(buf);
@ -2328,8 +2347,11 @@ static int jtag3_set_vtarget(PROGRAMMER * pgm, double v)
avrdude_message(MSG_INFO, "%s: jtag3_set_vtarget(): changing V[target] from %.1f to %.1f\n", avrdude_message(MSG_INFO, "%s: jtag3_set_vtarget(): changing V[target] from %.1f to %.1f\n",
progname, uaref / 1000.0, v); progname, uaref / 1000.0, v);
if (jtag3_setparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, sizeof(buf)) < 0) if (jtag3_setparm(pgm, SCOPE_GENERAL, 1, PARM3_VADJUST, buf, sizeof(buf)) < 0) {
avrdude_message(MSG_INFO, "%s: jtag3_set_vtarget(): cannot confirm new V[target] value\n",
progname);
return -1; return -1;
}
return 0; return 0;
} }
@ -2368,14 +2390,12 @@ static void jtag3_display(PROGRAMMER * pgm, const char * p)
memmove(resp, resp + 3, status - 3); memmove(resp, resp + 3, status - 3);
resp[status - 3] = 0; resp[status - 3] = 0;
avrdude_message(MSG_INFO, "%sICE hardware version: %d\n", p, parms[0]); avrdude_message(MSG_INFO, "%sICE HW version : %d\n", p, parms[0]);
avrdude_message(MSG_INFO, "%sICE firmware version: %d.%02d (rel. %d)\n", p, avrdude_message(MSG_INFO, "%sICE FW version : %d.%02d (rel. %d)\n", p,
parms[1], parms[2], parms[1], parms[2],
(parms[3] | (parms[4] << 8))); (parms[3] | (parms[4] << 8)));
avrdude_message(MSG_INFO, "%sSerial number : %s\n", p, resp); avrdude_message(MSG_INFO, "%sSerial number : %s", p, resp);
free(resp); free(resp);
jtag3_print_parms1(pgm, p);
} }
@ -2386,29 +2406,41 @@ static void jtag3_print_parms1(PROGRAMMER * pgm, const char * p)
if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0)
return; return;
avrdude_message(MSG_INFO, "%sVtarget : %.2f V\n", p, avrdude_message(MSG_INFO, "%sVtarget %s: %.2f V\n", p,
b2_to_u16(buf) / 1000.0); verbose ? "" : " ", b2_to_u16(buf) / 1000.0);
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0)
return; return;
if (b2_to_u16(buf) > 0) {
avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/program : %u kHz\n", p, avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/program : %u kHz\n", p,
b2_to_u16(buf)); b2_to_u16(buf));
}
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0)
return; return;
if (b2_to_u16(buf) > 0) {
avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/debug : %u kHz\n", p, avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/debug : %u kHz\n", p,
b2_to_u16(buf)); b2_to_u16(buf));
}
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
return; return;
if (b2_to_u16(buf) > 0) {
avrdude_message(MSG_INFO, "%sJTAG clock Xmega : %u kHz\n", p, avrdude_message(MSG_INFO, "%sJTAG clock Xmega : %u kHz\n", p,
b2_to_u16(buf)); b2_to_u16(buf));
}
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0) if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0)
return; return;
avrdude_message(MSG_INFO, "%sPDI clock Xmega : %u kHz\n", p,
if (b2_to_u16(buf) > 0) {
avrdude_message(MSG_INFO, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n\n", p,
b2_to_u16(buf)); b2_to_u16(buf));
} }
}
static void jtag3_print_parms(PROGRAMMER * pgm) static void jtag3_print_parms(PROGRAMMER * pgm)
{ {
@ -2444,13 +2476,13 @@ static unsigned int jtag3_memaddr(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, uns
* Non-Xmega device. * Non-Xmega device.
*/ */
if (p->flags & AVRPART_HAS_UPDI) { if (p->flags & AVRPART_HAS_UPDI) {
if (strcmp(m->desc, "fuses") == 0) { if (strcmp(m->desc, "flash") == 0) {
addr += m->offset; return addr;
} }
else if (matches(m->desc, "fuse")) { else if (m->size == 1) {
addr = m->offset; addr = m->offset;
} }
else if (strcmp(m->desc, "flash") != 0) { else if (m->size > 1) {
addr += m->offset; addr += m->offset;
} }
} }

View File

@ -1275,8 +1275,8 @@ static void jtagmkI_display(PROGRAMMER * pgm, const char * p)
jtagmkI_getparm(pgm, PARM_SW_VERSION, &fw) < 0) jtagmkI_getparm(pgm, PARM_SW_VERSION, &fw) < 0)
return; return;
avrdude_message(MSG_INFO, "%sICE hardware version: 0x%02x\n", p, hw); avrdude_message(MSG_INFO, "%sICE HW version: 0x%02x\n", p, hw);
avrdude_message(MSG_INFO, "%sICE firmware version: 0x%02x\n", p, fw); avrdude_message(MSG_INFO, "%sICE FW version: 0x%02x\n", p, fw);
jtagmkI_print_parms1(pgm, p); jtagmkI_print_parms1(pgm, p);

View File

@ -1056,7 +1056,8 @@ static void jtagmkII_set_xmega_params(PROGRAMMER * pgm, AVRPART * p)
u32_to_b4(sendbuf.dd.nvm_fuse_offset, m->offset & ~7); u32_to_b4(sendbuf.dd.nvm_fuse_offset, m->offset & ~7);
} else if (strncmp(m->desc, "lock", 4) == 0) { } else if (strncmp(m->desc, "lock", 4) == 0) {
u32_to_b4(sendbuf.dd.nvm_lock_offset, m->offset); u32_to_b4(sendbuf.dd.nvm_lock_offset, m->offset);
} else if (strcmp(m->desc, "usersig") == 0) { } else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
u32_to_b4(sendbuf.dd.nvm_user_sig_offset, m->offset); u32_to_b4(sendbuf.dd.nvm_user_sig_offset, m->offset);
} else if (strcmp(m->desc, "prodsig") == 0) { } else if (strcmp(m->desc, "prodsig") == 0) {
u32_to_b4(sendbuf.dd.nvm_prod_sig_offset, m->offset); u32_to_b4(sendbuf.dd.nvm_prod_sig_offset, m->offset);
@ -1933,9 +1934,10 @@ static int jtagmkII_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[1] = XMEGA_ERASE_BOOT_PAGE; cmd[1] = XMEGA_ERASE_BOOT_PAGE;
} else if (strcmp(m->desc, "eeprom") == 0) { } else if (strcmp(m->desc, "eeprom") == 0) {
cmd[1] = XMEGA_ERASE_EEPROM_PAGE; cmd[1] = XMEGA_ERASE_EEPROM_PAGE;
} else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { } else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
cmd[1] = XMEGA_ERASE_USERSIG; cmd[1] = XMEGA_ERASE_USERSIG;
} else if ( ( strcmp(m->desc, "boot") == 0 ) ) { } else if (strcmp(m->desc, "boot") == 0) {
cmd[1] = XMEGA_ERASE_BOOT_PAGE; cmd[1] = XMEGA_ERASE_BOOT_PAGE;
} else { } else {
cmd[1] = XMEGA_ERASE_APP_PAGE; cmd[1] = XMEGA_ERASE_APP_PAGE;
@ -2046,9 +2048,10 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
} }
cmd[1] = (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI)) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE; cmd[1] = (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI)) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L;
} else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { } else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
cmd[1] = MTYPE_USERSIG; cmd[1] = MTYPE_USERSIG;
} else if ( ( strcmp(m->desc, "boot") == 0 ) ) { } else if (strcmp(m->desc, "boot") == 0) {
cmd[1] = MTYPE_BOOT_FLASH; cmd[1] = MTYPE_BOOT_FLASH;
} else if (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI)) { } else if (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI)) {
cmd[1] = MTYPE_FLASH; cmd[1] = MTYPE_FLASH;
@ -2159,11 +2162,12 @@ static int jtagmkII_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
cmd[1] = (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI)) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE; cmd[1] = (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI)) ? MTYPE_EEPROM : MTYPE_EEPROM_PAGE;
if (pgm->flag & PGM_FL_IS_DW) if (pgm->flag & PGM_FL_IS_DW)
return -1; return -1;
} else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) { } else if (strcmp(m->desc, "prodsig") == 0) {
cmd[1] = MTYPE_PRODSIG; cmd[1] = MTYPE_PRODSIG;
} else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { } else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
cmd[1] = MTYPE_USERSIG; cmd[1] = MTYPE_USERSIG;
} else if ( ( strcmp(m->desc, "boot") == 0 ) ) { } else if (strcmp(m->desc, "boot") == 0) {
cmd[1] = MTYPE_BOOT_FLASH; cmd[1] = MTYPE_BOOT_FLASH;
} else if (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI)) { } else if (p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_UPDI)) {
cmd[1] = MTYPE_FLASH; cmd[1] = MTYPE_FLASH;
@ -2291,7 +2295,8 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsupp = 1; unsupp = 1;
} else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) {
cmd[1] = MTYPE_FUSE_BITS; cmd[1] = MTYPE_FUSE_BITS;
} else if (strcmp(mem->desc, "usersig") == 0) { } else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
cmd[1] = MTYPE_USERSIG; cmd[1] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) { } else if (strcmp(mem->desc, "prodsig") == 0) {
cmd[1] = MTYPE_PRODSIG; cmd[1] = MTYPE_PRODSIG;
@ -2460,7 +2465,8 @@ static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsupp = 1; unsupp = 1;
} else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) {
cmd[1] = MTYPE_FUSE_BITS; cmd[1] = MTYPE_FUSE_BITS;
} else if (strcmp(mem->desc, "usersig") == 0) { } else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
cmd[1] = MTYPE_USERSIG; cmd[1] = MTYPE_USERSIG;
} else if (strcmp(mem->desc, "prodsig") == 0) { } else if (strcmp(mem->desc, "prodsig") == 0) {
cmd[1] = MTYPE_PRODSIG; cmd[1] = MTYPE_PRODSIG;
@ -2688,10 +2694,10 @@ static void jtagmkII_display(PROGRAMMER * pgm, const char * p)
jtagmkII_getparm(pgm, PAR_FW_VERSION, fw) < 0) jtagmkII_getparm(pgm, PAR_FW_VERSION, fw) < 0)
return; return;
avrdude_message(MSG_INFO, "%sM_MCU hardware version: %d\n", p, hw[0]); avrdude_message(MSG_INFO, "%sM_MCU HW version: %d\n", p, hw[0]);
avrdude_message(MSG_INFO, "%sM_MCU firmware version: %d.%02d\n", p, fw[1], fw[0]); avrdude_message(MSG_INFO, "%sM_MCU FW version: %d.%02d\n", p, fw[1], fw[0]);
avrdude_message(MSG_INFO, "%sS_MCU hardware version: %d\n", p, hw[1]); avrdude_message(MSG_INFO, "%sS_MCU HW version: %d\n", p, hw[1]);
avrdude_message(MSG_INFO, "%sS_MCU firmware version: %d.%02d\n", p, fw[3], fw[2]); avrdude_message(MSG_INFO, "%sS_MCU FW version: %d.%02d\n", p, fw[3], fw[2]);
avrdude_message(MSG_INFO, "%sSerial number : %02x:%02x:%02x:%02x:%02x:%02x\n", avrdude_message(MSG_INFO, "%sSerial number : %02x:%02x:%02x:%02x:%02x:%02x\n",
p, PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2], PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]); p, PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2], PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]);

View File

@ -117,6 +117,7 @@ SIGN [+-]
<strng>\n { yyerror("unterminated character constant"); <strng>\n { yyerror("unterminated character constant");
return YYERRCODE; } return YYERRCODE; }
alias { yylval=NULL; return K_ALIAS; }
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; } allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; } avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
bank_size { yylval=NULL; return K_PAGE_SIZE; } bank_size { yylval=NULL; return K_PAGE_SIZE; }
@ -137,7 +138,6 @@ dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; } default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; }
default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; } default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; } default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
default_safemode { yylval=NULL; return K_DEFAULT_SAFEMODE; }
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; } default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
delay { yylval=NULL; return K_DELAY; } delay { yylval=NULL; return K_DELAY; }
desc { yylval=NULL; return K_DESC; } desc { yylval=NULL; return K_DESC; }

View File

@ -261,6 +261,7 @@ typedef struct avrpart {
OPCODE * op[AVR_OP_MAX]; /* opcodes */ OPCODE * op[AVR_OP_MAX]; /* opcodes */
LISTID mem; /* avr memory definitions */ LISTID mem; /* avr memory definitions */
LISTID mem_alias; /* memory alias definitions */
char config_file[PATH_MAX]; /* config file where defined */ char config_file[PATH_MAX]; /* config file where defined */
int lineno; /* config file line number */ int lineno; /* config file line number */
} AVRPART; } AVRPART;
@ -292,6 +293,11 @@ typedef struct avrmem {
OPCODE * op[AVR_OP_MAX]; /* opcodes */ OPCODE * op[AVR_OP_MAX]; /* opcodes */
} AVRMEM; } AVRMEM;
typedef struct avrmem_alias {
char desc[AVR_MEMDESCLEN]; /* alias name ("syscfg0" etc.) */
AVRMEM *aliased_mem;
} AVRMEM_ALIAS;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -307,10 +313,15 @@ int avr_get_output_index(OPCODE * op);
/* Functions for AVRMEM structures */ /* Functions for AVRMEM structures */
AVRMEM * avr_new_memtype(void); AVRMEM * avr_new_memtype(void);
AVRMEM_ALIAS * avr_new_memalias(void);
int avr_initmem(AVRPART * p); int avr_initmem(AVRPART * p);
AVRMEM * avr_dup_mem(AVRMEM * m); AVRMEM * avr_dup_mem(AVRMEM * m);
void avr_free_mem(AVRMEM * m); void avr_free_mem(AVRMEM * m);
void avr_free_memalias(AVRMEM_ALIAS * m);
AVRMEM * avr_locate_mem(AVRPART * p, char * desc); AVRMEM * avr_locate_mem(AVRPART * p, char * desc);
AVRMEM * avr_locate_mem_noalias(AVRPART * p, char * desc);
AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, char * desc);
AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig);
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
int type, int verbose); int type, int verbose);
@ -831,30 +842,6 @@ int fileio(int op, char * filename, FILEFMT format,
#endif #endif
/* formerly safemode.h */
#ifdef __cplusplus
extern "C" {
#endif
/* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or "efuse") and verifies it. Will try up to tries
amount of times before giving up */
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries);
/* Reads the fuses three times, checking that all readings are the same. This will ensure that the before values aren't in error! */
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse, PROGRAMMER * pgm, AVRPART * p);
/* This routine will store the current values pointed to by lfuse, hfuse, and efuse into an internal buffer in this routine
when save is set to 1. When save is 0 (or not 1 really) it will copy the values from the internal buffer into the locations
pointed to be lfuse, hfuse, and efuse. This allows you to change the fuse bits if needed from another routine (ie: have it so
if user requests fuse bits are changed, the requested value is now verified */
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse);
#ifdef __cplusplus
}
#endif
/* formerly update.h */ /* formerly update.h */
enum { enum {
@ -926,7 +913,6 @@ extern char default_programmer[];
extern char default_parallel[]; extern char default_parallel[];
extern char default_serial[]; extern char default_serial[];
extern double default_bitclock; extern double default_bitclock;
extern int default_safemode;
/* This name is fixed, it's only here for symmetry with /* This name is fixed, it's only here for symmetry with
* default_parallel and default_serial. */ * default_parallel and default_serial. */

View File

@ -223,7 +223,7 @@ static int linuxspi_open(PROGRAMMER *pgm, char *port)
avrdude_message(MSG_INFO, avrdude_message(MSG_INFO,
"%s: obsolete use of -b <clock> option for bit clock; use -B <clock>\n", "%s: obsolete use of -b <clock> option for bit clock; use -B <clock>\n",
progname); progname);
pgm->bitclock = 1E6 / pgm->baudrate; pgm->bitclock = 1.0 / pgm->baudrate;
} }
if (pgm->bitclock == 0) { if (pgm->bitclock == 0) {
avrdude_message(MSG_NOTICE, avrdude_message(MSG_NOTICE,

View File

@ -122,9 +122,6 @@ static void usage(void)
" is performed in the order specified.\n" " is performed in the order specified.\n"
" -n Do not write anything to the device.\n" " -n Do not write anything to the device.\n"
" -V Do not verify.\n" " -V Do not verify.\n"
" -u Disable safemode, default when running from a script.\n"
" -s Silent safemode operation, will not ask you if\n"
" fuses should be changed back.\n"
" -t Enter terminal mode.\n" " -t Enter terminal mode.\n"
" -E <exitspec>[,<exitspec>] List programmer exit specifications.\n" " -E <exitspec>[,<exitspec>] List programmer exit specifications.\n"
" -x <extended_param> Pass <extended_param> to programmer.\n" " -x <extended_param> Pass <extended_param> to programmer.\n"
@ -349,19 +346,11 @@ int main(int argc, char * argv [])
int baudrate; /* override default programmer baud rate */ int baudrate; /* override default programmer baud rate */
double bitclock; /* Specify programmer bit clock (JTAG ICE) */ double bitclock; /* Specify programmer bit clock (JTAG ICE) */
int ispdelay; /* Specify the delay for ISP clock */ int ispdelay; /* Specify the delay for ISP clock */
int safemode; /* Enable safemode, 1=safemode on, 0=normal */
int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */
int init_ok; /* Device initialization worked well */ int init_ok; /* Device initialization worked well */
int is_open; /* Device open succeeded */ int is_open; /* Device open succeeded */
char * logfile; /* Use logfile rather than stderr for diagnostics */ char * logfile; /* Use logfile rather than stderr for diagnostics */
enum updateflags uflags = UF_AUTO_ERASE; /* Flags for do_op() */ enum updateflags uflags = UF_AUTO_ERASE; /* Flags for do_op() */
unsigned char safemode_lfuse = 0xff;
unsigned char safemode_hfuse = 0xff;
unsigned char safemode_efuse = 0xff;
unsigned char safemode_fuse = 0xff;
char * safemode_response;
int fuses_updated = 0;
#if !defined(WIN32) #if !defined(WIN32)
char * homedir; char * homedir;
#endif #endif
@ -394,7 +383,6 @@ int main(int argc, char * argv [])
default_parallel[0] = 0; default_parallel[0] = 0;
default_serial[0] = 0; default_serial[0] = 0;
default_bitclock = 0.0; default_bitclock = 0.0;
default_safemode = -1;
init_config(); init_config();
@ -434,8 +422,6 @@ int main(int argc, char * argv [])
baudrate = 0; baudrate = 0;
bitclock = 0.0; bitclock = 0.0;
ispdelay = 0; ispdelay = 0;
safemode = 1; /* Safemode on by default */
silentsafe = 0; /* Ask by default */
is_open = 0; is_open = 0;
logfile = NULL; logfile = NULL;
@ -581,17 +567,13 @@ int main(int argc, char * argv [])
quell_progress++ ; quell_progress++ ;
break; break;
case 's' : /* Silent safemode */
silentsafe = 1;
safemode = 1;
break;
case 't': /* enter terminal mode */ case 't': /* enter terminal mode */
terminal = 1; terminal = 1;
break; break;
case 'u' : /* Disable safemode */ case 'u':
safemode = 0; avrdude_message(MSG_INFO, "%s: \"safemode\" feature no longer supported\n",
progname);
break; break;
case 'U': case 'U':
@ -975,29 +957,6 @@ int main(int argc, char * argv [])
} }
} }
if (default_safemode == 0) {
/* configuration disables safemode: revert meaning of -u */
if (safemode == 0)
/* -u was given: enable safemode */
safemode = 1;
else
/* -u not given: turn off */
safemode = 0;
}
if (isatty(STDIN_FILENO) == 0 && silentsafe == 0)
safemode = 0; /* Turn off safemode if this isn't a terminal */
if(p->flags & AVRPART_AVR32) {
safemode = 0;
}
if(p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_TPI)) {
safemode = 0;
}
if (avr_initmem(p) != 0) if (avr_initmem(p) != 0)
{ {
avrdude_message(MSG_INFO, "\n%s: failed to initialize memories\n", avrdude_message(MSG_INFO, "\n%s: failed to initialize memories\n",
@ -1281,36 +1240,6 @@ int main(int argc, char * argv [])
} }
} }
if (init_ok && safemode == 1) {
/* If safemode is enabled, go ahead and read the current low, high,
and extended fuse bytes as needed */
rc = safemode_readfuses(&safemode_lfuse, &safemode_hfuse,
&safemode_efuse, &safemode_fuse, pgm, p);
if (rc != 0) {
//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"
" Safemode disabled.\n", progname);
}
else
{
avrdude_message(MSG_INFO, "%s: safemode: To protect your AVR the programming "
"will be aborted\n",
progname);
exitrc = 1;
goto main_exit;
}
} else {
//Save the fuses as default
safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
}
}
if (uflags & UF_AUTO_ERASE) { if (uflags & UF_AUTO_ERASE) {
if ((p->flags & AVRPART_HAS_PDI) && pgm->page_erase != NULL && if ((p->flags & AVRPART_HAS_PDI) && pgm->page_erase != NULL &&
lsize(updates) > 0) { lsize(updates) > 0) {
@ -1386,169 +1315,6 @@ int main(int argc, char * argv [])
} }
} }
/* Right before we exit programming mode, which will make the fuse
bits active, check to make sure they are still correct */
if (safemode == 1) {
/* If safemode is enabled, go ahead and read the current low,
* high, and extended fuse bytes as needed */
unsigned char safemodeafter_lfuse = 0xff;
unsigned char safemodeafter_hfuse = 0xff;
unsigned char safemodeafter_efuse = 0xff;
unsigned char safemodeafter_fuse = 0xff;
unsigned char failures = 0;
char yes[1] = {'y'};
if (quell_progress < 2) {
avrdude_message(MSG_INFO, "\n");
}
//Restore the default fuse values
safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
/* Try reading back fuses, make sure they are reliable to read back */
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
&safemodeafter_efuse, &safemodeafter_fuse, pgm, p) != 0) {
/* Uh-oh.. try once more to read back fuses */
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
&safemodeafter_efuse, &safemodeafter_fuse, pgm, p) != 0) {
avrdude_message(MSG_INFO, "%s: safemode: Sorry, reading back fuses was unreliable. "
"I have given up and exited programming mode\n",
progname);
exitrc = 1;
goto main_exit;
}
}
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)) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: fuse changed! Was %x, and is now %x\n",
progname, safemode_fuse, safemodeafter_fuse);
/* Ask user - should we change them */
if (silentsafe == 0)
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
else
safemode_response = yes;
if (tolower((int)(safemode_response[0])) == 'y') {
/* Enough chit-chat, time to program some fuses and check them */
if (safemode_writefuse (safemode_fuse, "fuse", pgm, p,
10) == 0) {
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
}
else {
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
failures++;
}
}
}
/* 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)) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: lfuse changed! Was %x, and is now %x\n",
progname, safemode_lfuse, safemodeafter_lfuse);
/* Ask user - should we change them */
if (silentsafe == 0)
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
else
safemode_response = yes;
if (tolower((int)(safemode_response[0])) == 'y') {
/* Enough chit-chat, time to program some fuses and check them */
if (safemode_writefuse (safemode_lfuse, "lfuse", pgm, p,
10) == 0) {
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
}
else {
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
failures++;
}
}
}
/* 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)) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: hfuse changed! Was %x, and is now %x\n",
progname, safemode_hfuse, safemodeafter_hfuse);
/* Ask user - should we change them */
if (silentsafe == 0)
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
else
safemode_response = yes;
if (tolower((int)(safemode_response[0])) == 'y') {
/* Enough chit-chat, time to program some fuses and check them */
if (safemode_writefuse(safemode_hfuse, "hfuse", pgm, p,
10) == 0) {
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
}
else {
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
failures++;
}
}
}
/* 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)) {
fuses_updated = 1;
avrdude_message(MSG_INFO, "%s: safemode: efuse changed! Was %x, and is now %x\n",
progname, safemode_efuse, safemodeafter_efuse);
/* Ask user - should we change them */
if (silentsafe == 0)
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
else
safemode_response = yes;
if (tolower((int)(safemode_response[0])) == 'y') {
/* Enough chit-chat, time to program some fuses and check them */
if (safemode_writefuse (safemode_efuse, "efuse", pgm, p,
10) == 0) {
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
}
else {
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
failures++;
}
}
}
if (quell_progress < 2) {
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);
}
else {
avrdude_message(MSG_INFO, "Fuses not recovered, sorry\n");
}
}
if (fuses_updated) {
exitrc = 1;
}
}
main_exit: main_exit:
/* /*

View File

@ -139,6 +139,22 @@ static int micronucleus_check_connection(pdata_t* pdata)
} }
} }
static bool micronucleus_is_device_responsive(pdata_t* pdata, struct usb_device* device)
{
pdata->usb_handle = usb_open(device);
if (pdata->usb_handle == NULL)
{
return false;
}
int result = micronucleus_check_connection(pdata);
usb_close(pdata->usb_handle);
pdata->usb_handle = NULL;
return result >= 0;
}
static int micronucleus_reconnect(pdata_t* pdata) static int micronucleus_reconnect(pdata_t* pdata)
{ {
struct usb_device* device = usb_device(pdata->usb_handle); struct usb_device* device = usb_device(pdata->usb_handle);
@ -696,6 +712,7 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
usb_init(); usb_init();
bool show_retry_message = true; bool show_retry_message = true;
bool show_unresponsive_device_message = true;
time_t start_time = time(NULL); time_t start_time = time(NULL);
for (;;) for (;;)
@ -717,6 +734,19 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
pdata->major_version = (uint8_t)(device->descriptor.bcdDevice >> 8); pdata->major_version = (uint8_t)(device->descriptor.bcdDevice >> 8);
pdata->minor_version = (uint8_t)(device->descriptor.bcdDevice >> 0); pdata->minor_version = (uint8_t)(device->descriptor.bcdDevice >> 0);
if (!micronucleus_is_device_responsive(pdata, device))
{
if (show_unresponsive_device_message)
{
avrdude_message(MSG_INFO, "%s: WARNING: Unresponsive Micronucleus device detected, please reconnect...\n",
progname);
show_unresponsive_device_message = false;
}
continue;
}
avrdude_message(MSG_NOTICE, "%s: Found device with Micronucleus V%d.%d, bus:device: %s:%s\n", avrdude_message(MSG_NOTICE, "%s: Found device with Micronucleus V%d.%d, bus:device: %s:%s\n",
progname, progname,
pdata->major_version, pdata->minor_version, pdata->major_version, pdata->minor_version,

View File

@ -1,318 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* avrdude is Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
*
* This file: Copyright (C) 2005-2007 Colin O'Flynn <coflynn@newae.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include "ac_cfg.h"
#include "avrdude.h"
#include "libavrdude.h"
/* This value from ac_cfg.h */
/*
* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or
* "efuse") and verifies it. Will try up to tries amount of times
* before giving up
*/
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm,
AVRPART * p, int tries)
{
AVRMEM * m;
unsigned char fuseread;
int returnvalue = -1;
m = avr_locate_mem(p, fusename);
if (m == NULL) {
return -1;
}
/* Keep trying to write then read back the fuse values */
while (tries > 0) {
if (avr_write_byte(pgm, p, m, 0, fuse) != 0)
{
continue;
}
if (pgm->read_byte(pgm, p, m, 0, &fuseread) != 0)
{
continue;
}
/* Report information to user if needed */
avrdude_message(MSG_NOTICE, "%s: safemode: Wrote %s to %x, read as %x. %d attempts left\n",
progname, fusename, fuse, fuseread, tries-1);
/* If fuse wrote OK, no need to keep going */
if (fuse == fuseread) {
tries = 0;
returnvalue = 0;
}
tries--;
}
return returnvalue;
}
/*
* Reads the fuses three times, checking that all readings are the
* same. This will ensure that the before values aren't in error!
*/
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse,
unsigned char * efuse, unsigned char * fuse,
PROGRAMMER * pgm, AVRPART * p)
{
unsigned char value;
unsigned char fusegood = 0;
unsigned char allowfuseread = 1;
unsigned char safemode_lfuse;
unsigned char safemode_hfuse;
unsigned char safemode_efuse;
unsigned char safemode_fuse;
AVRMEM * m;
safemode_lfuse = *lfuse;
safemode_hfuse = *hfuse;
safemode_efuse = *efuse;
safemode_fuse = *fuse;
/* Read fuse three times */
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
to generate a verify error */
m = avr_locate_mem(p, "fuse");
if (m != NULL) {
fusegood = 0; /* By default fuse is a failure */
if(pgm->read_byte(pgm, p, m, 0, &safemode_fuse) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 1, fuse value: %x\n",progname, safemode_fuse);
if(pgm->read_byte(pgm, p, m, 0, &value) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 2, fuse value: %x\n",progname, value);
if (value == safemode_fuse) {
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 3, fuse value: %x\n",progname, value);
if (value == safemode_fuse)
{
fusegood = 1; /* Fuse read OK three times */
}
}
}
//Programmer does not allow fuse reading.... no point trying anymore
if (allowfuseread == 0)
{
return -5;
}
if (fusegood == 0) {
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read fuse properly. "
"Programmer may not be reliable.\n", progname);
return -1;
}
else if (fusegood == 1) {
avrdude_message(MSG_NOTICE, "%s: safemode: fuse reads as %X\n", progname, safemode_fuse);
}
/* Read lfuse three times */
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
to generate a verify error */
m = avr_locate_mem(p, "lfuse");
if (m != NULL) {
fusegood = 0; /* By default fuse is a failure */
if (pgm->read_byte(pgm, p, m, 0, &safemode_lfuse) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 1, lfuse value: %x\n",progname, safemode_lfuse);
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 2, lfuse value: %x\n",progname, value);
if (value == safemode_lfuse) {
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 3, lfuse value: %x\n",progname, value);
if (value == safemode_lfuse){
fusegood = 1; /* Fuse read OK three times */
}
}
}
//Programmer does not allow fuse reading.... no point trying anymore
if (allowfuseread == 0)
{
return -5;
}
if (fusegood == 0) {
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read lfuse properly. "
"Programmer may not be reliable.\n", progname);
return -1;
}
else if (fusegood == 1) {
avrdude_message(MSG_NOTICE, "%s: safemode: lfuse reads as %X\n", progname, safemode_lfuse);
}
/* Read hfuse three times */
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
to generate a verify error */
m = avr_locate_mem(p, "hfuse");
if (m != NULL) {
fusegood = 0; /* By default fuse is a failure */
if (pgm->read_byte(pgm, p, m, 0, &safemode_hfuse) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 1, hfuse value: %x\n",progname, safemode_hfuse);
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 2, hfuse value: %x\n",progname, value);
if (value == safemode_hfuse) {
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 3, hfuse value: %x\n",progname, value);
if (value == safemode_hfuse){
fusegood = 1; /* Fuse read OK three times */
}
}
}
//Programmer does not allow fuse reading.... no point trying anymore
if (allowfuseread == 0)
{
return -5;
}
if (fusegood == 0) {
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read hfuse properly. "
"Programmer may not be reliable.\n", progname);
return -2;
}
else if (fusegood == 1){
avrdude_message(MSG_NOTICE, "%s: safemode: hfuse reads as %X\n", progname, safemode_hfuse);
}
/* Read efuse three times */
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
to generate a verify error */
m = avr_locate_mem(p, "efuse");
if (m != NULL) {
fusegood = 0; /* By default fuse is a failure */
if (pgm->read_byte(pgm, p, m, 0, &safemode_efuse) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 1, efuse value: %x\n",progname, safemode_efuse);
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 2, efuse value: %x\n",progname, value);
if (value == safemode_efuse) {
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
{
allowfuseread = 0;
}
avrdude_message(MSG_DEBUG, "%s: safemode read 3, efuse value: %x\n",progname, value);
if (value == safemode_efuse){
fusegood = 1; /* Fuse read OK three times */
}
}
}
//Programmer does not allow fuse reading.... no point trying anymore
if (allowfuseread == 0)
{
return -5;
}
if (fusegood == 0) {
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read efuse properly. "
"Programmer may not be reliable.\n", progname);
return -3;
}
else if (fusegood == 1) {
avrdude_message(MSG_NOTICE, "%s: safemode: efuse reads as %X\n", progname, safemode_efuse);
}
*lfuse = safemode_lfuse;
*hfuse = safemode_hfuse;
*efuse = safemode_efuse;
*fuse = safemode_fuse;
return 0;
}
/*
* This routine will store the current values pointed to by lfuse,
* hfuse, and efuse into an internal buffer in this routine when save
* is set to 1. When save is 0 (or not 1 really) it will copy the
* values from the internal buffer into the locations pointed to be
* lfuse, hfuse, and efuse. This allows you to change the fuse bits if
* needed from another routine (ie: have it so if user requests fuse
* bits are changed, the requested value is now verified
*/
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse,
unsigned char * efuse, unsigned char * fuse)
{
static unsigned char safemode_lfuse = 0xff;
static unsigned char safemode_hfuse = 0xff;
static unsigned char safemode_efuse = 0xff;
static unsigned char safemode_fuse = 0xff;
switch (save) {
/* Save the fuses as safemode setting */
case 1:
safemode_lfuse = *lfuse;
safemode_hfuse = *hfuse;
safemode_efuse = *efuse;
safemode_fuse = *fuse;
break;
/* Read back the fuses */
default:
*lfuse = safemode_lfuse;
*hfuse = safemode_hfuse;
*efuse = safemode_efuse;
*fuse = safemode_fuse;
break;
}
return 0;
}

View File

@ -26,11 +26,12 @@
#include "ac_cfg.h" #include "ac_cfg.h"
#if defined(HAVE_LIBHIDAPI) || (defined(WIN32) && defined(HAVE_LIBHID)) #if defined(HAVE_LIBHIDAPI)
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <hidapi/hidapi.h>
#include "avrdude.h" #include "avrdude.h"
#include "libavrdude.h" #include "libavrdude.h"
@ -64,12 +65,6 @@ 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, static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName,
int product, char *productName, int doReportIDs) int product, char *productName, int doReportIDs)
{ {
@ -154,181 +149,6 @@ static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNum
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
#else /* !defined(HAVE_LIBHIDAPI) */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <setupapi.h>
#include <hidsdi.h>
#include <hidpi.h>
#ifdef USB_DEBUG
#define DEBUG_PRINT(arg) printf arg
#else
#define DEBUG_PRINT(arg)
#endif
/* ------------------------------------------------------------------------ */
static void convertUniToAscii(char *buffer)
{
unsigned short *uni = (void *)buffer;
char *ascii = buffer;
while(*uni != 0){
if(*uni >= 256){
*ascii++ = '?';
uni++;
}else{
*ascii++ = *uni++;
}
}
*ascii++ = 0;
}
static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName,
int product, char *productName, int usesReportIDs)
{
GUID hidGuid; /* GUID for HID driver */
HDEVINFO deviceInfoList;
SP_DEVICE_INTERFACE_DATA deviceInfo;
SP_DEVICE_INTERFACE_DETAIL_DATA *deviceDetails = NULL;
DWORD size;
int i, openFlag = 0; /* may be FILE_FLAG_OVERLAPPED */
int errorCode = USB_ERROR_NOTFOUND;
HANDLE handle = INVALID_HANDLE_VALUE;
HIDD_ATTRIBUTES deviceAttributes;
HidD_GetHidGuid(&hidGuid);
deviceInfoList = SetupDiGetClassDevs(&hidGuid, NULL, NULL,
DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
deviceInfo.cbSize = sizeof(deviceInfo);
for(i=0;;i++){
if(handle != INVALID_HANDLE_VALUE){
CloseHandle(handle);
handle = INVALID_HANDLE_VALUE;
}
if(!SetupDiEnumDeviceInterfaces(deviceInfoList, 0, &hidGuid, i, &deviceInfo))
break; /* no more entries */
/* first do a dummy call just to determine the actual size required */
SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, NULL, 0, &size, NULL);
if(deviceDetails != NULL)
free(deviceDetails);
deviceDetails = malloc(size);
deviceDetails->cbSize = sizeof(*deviceDetails);
/* this call is for real: */
SetupDiGetDeviceInterfaceDetail(deviceInfoList, &deviceInfo, deviceDetails,
size, &size, NULL);
DEBUG_PRINT(("checking HID path \"%s\"\n", deviceDetails->DevicePath));
/* attempt opening for R/W -- we don't care about devices which can't be accessed */
handle = CreateFile(deviceDetails->DevicePath, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
openFlag, NULL);
if(handle == INVALID_HANDLE_VALUE){
DEBUG_PRINT(("opening failed: %d\n", (int)GetLastError()));
/* errorCode = USB_ERROR_ACCESS; opening will always fail for mouse -- ignore */
continue;
}
deviceAttributes.Size = sizeof(deviceAttributes);
HidD_GetAttributes(handle, &deviceAttributes);
DEBUG_PRINT(("device attributes: vid=%d pid=%d\n",
deviceAttributes.VendorID, deviceAttributes.ProductID));
if(deviceAttributes.VendorID != vendor || deviceAttributes.ProductID != product)
continue; /* ignore this device */
errorCode = USB_ERROR_NOTFOUND;
if(vendorName != NULL && productName != NULL){
char buffer[512];
if(!HidD_GetManufacturerString(handle, buffer, sizeof(buffer))){
DEBUG_PRINT(("error obtaining vendor name\n"));
errorCode = USB_ERROR_IO;
continue;
}
convertUniToAscii(buffer);
DEBUG_PRINT(("vendorName = \"%s\"\n", buffer));
if(strcmp(vendorName, buffer) != 0)
continue;
if(!HidD_GetProductString(handle, buffer, sizeof(buffer))){
DEBUG_PRINT(("error obtaining product name\n"));
errorCode = USB_ERROR_IO;
continue;
}
convertUniToAscii(buffer);
DEBUG_PRINT(("productName = \"%s\"\n", buffer));
if(strcmp(productName, buffer) != 0)
continue;
}
break; /* we have found the device we are looking for! */
}
SetupDiDestroyDeviceInfoList(deviceInfoList);
if(deviceDetails != NULL)
free(deviceDetails);
if(handle != INVALID_HANDLE_VALUE){
fdp->pfd = (void *)handle;
errorCode = 0;
}
return errorCode;
}
/* ------------------------------------------------------------------------ */
static void usbCloseDevice(union filedescriptor *fdp)
{
CloseHandle((HANDLE)fdp->pfd);
}
/* ------------------------------------------------------------------------ */
static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len)
{
HANDLE handle = (HANDLE)fdp->pfd;
BOOLEAN rval = 0;
DWORD bytesWritten;
switch(reportType){
case USB_HID_REPORT_TYPE_INPUT:
break;
case USB_HID_REPORT_TYPE_OUTPUT:
rval = WriteFile(handle, buffer, len, &bytesWritten, NULL);
break;
case USB_HID_REPORT_TYPE_FEATURE:
rval = HidD_SetFeature(handle, buffer, len);
break;
}
return rval == 0 ? USB_ERROR_IO : 0;
}
/* ------------------------------------------------------------------------ */
static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber,
char *buffer, int *len)
{
HANDLE handle = (HANDLE)fdp->pfd;
BOOLEAN rval = 0;
DWORD bytesRead;
switch(reportType){
case USB_HID_REPORT_TYPE_INPUT:
buffer[0] = reportNumber;
rval = ReadFile(handle, buffer, *len, &bytesRead, NULL);
if(rval)
*len = bytesRead;
break;
case USB_HID_REPORT_TYPE_OUTPUT:
break;
case USB_HID_REPORT_TYPE_FEATURE:
buffer[0] = reportNumber;
rval = HidD_GetFeature(handle, buffer, *len);
break;
}
return rval == 0 ? USB_ERROR_IO : 0;
}
#endif /* WIN32 */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
@ -551,4 +371,4 @@ struct serial_device avrdoper_serdev =
.flags = SERDEV_FL_NONE, .flags = SERDEV_FL_NONE,
}; };
#endif /* defined(HAVE_LIBHIDAPI) || (defined(WIN32) && defined(HAVE_LIBHID)) */ #endif /* defined(HAVE_LIBHIDAPI) */

View File

@ -28,6 +28,7 @@
#include "ac_cfg.h" #include "ac_cfg.h"
#include <ctype.h> #include <ctype.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -42,6 +43,10 @@
#include <termios.h> #include <termios.h>
#include <unistd.h> #include <unistd.h>
#ifdef __APPLE__
# include <IOKit/serial/ioss.h>
#endif
#include "avrdude.h" #include "avrdude.h"
#include "libavrdude.h" #include "libavrdude.h"
@ -78,10 +83,12 @@ static struct baud_mapping baud_lookup_table [] = {
static struct termios original_termios; static struct termios original_termios;
static int saved_original_termios; static int saved_original_termios;
static speed_t serial_baud_lookup(long baud) static speed_t serial_baud_lookup(long baud, bool *nonstandard)
{ {
struct baud_mapping *map = baud_lookup_table; struct baud_mapping *map = baud_lookup_table;
*nonstandard = false;
while (map->baud) { while (map->baud) {
if (map->baud == baud) if (map->baud == baud)
return map->speed; return map->speed;
@ -92,30 +99,20 @@ static speed_t serial_baud_lookup(long baud)
* If a non-standard BAUD rate is used, issue * If a non-standard BAUD rate is used, issue
* a warning (if we are verbose) and return the raw rate * a warning (if we are verbose) and return the raw rate
*/ */
avrdude_message(MSG_NOTICE, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld", avrdude_message(MSG_NOTICE, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld\n",
progname, baud); progname, baud);
return baud; *nonstandard = true;
}
static tcflag_t translate_flags(unsigned long cflags) return baud;
{
return ((cflags & SERIAL_CS5) ? CS5 : 0) |
((cflags & SERIAL_CS6) ? CS6 : 0) |
((cflags & SERIAL_CS7) ? CS7 : 0) |
((cflags & SERIAL_CS8) ? CS8 : 0) |
((cflags & SERIAL_CSTOPB) ? CSTOPB : 0) |
((cflags & SERIAL_CREAD) ? CREAD : 0) |
((cflags & (SERIAL_PARENB | SERIAL_PARODD)) ? PARENB : 0) |
((cflags & SERIAL_PARODD) ? PARODD : 0) |
((cflags & SERIAL_CLOCAL) ? CLOCAL : 0) ;
} }
static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cflags) static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cflags)
{ {
int rc; int rc;
struct termios termios; struct termios termios;
speed_t speed = serial_baud_lookup (baud); bool nonstandard;
speed_t speed = serial_baud_lookup (baud, &nonstandard);
if (!isatty(fd->ifd)) if (!isatty(fd->ifd))
return -ENOTTY; return -ENOTTY;
@ -137,15 +134,86 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla
original_termios = termios; original_termios = termios;
} }
termios.c_iflag = IGNBRK; if (cflags & SERIAL_CREAD) {
termios.c_oflag = 0; termios.c_cflag |= CREAD;
termios.c_lflag = 0; }
termios.c_cflag = translate_flags(cflags); if (cflags & SERIAL_CLOCAL) {
termios.c_cc[VMIN] = 1; termios.c_cflag |= CLOCAL;
termios.c_cc[VTIME] = 0; }
termios.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ISIG | IEXTEN);
#ifdef ECHOCTL
termios.c_lflag &= ~ECHOCTL;
#endif /* ECHOCTL */
#ifdef ECHOKE
termios.c_lflag &= ~ECHOKE;
#endif /* ECHOKE */
termios.c_oflag &= ~(OPOST | ONLCR | OCRNL);
termios.c_iflag &= ~(INLCR | IGNCR | ICRNL | IGNBRK);
#ifdef IUCLC
termios.c_iflag &= ~IUCLC;
#endif /* IUCLC */
#ifdef PARMRK
termios.c_iflag &= ~PARMRK;
#endif /* PARMRK */
// MacOS doesn't handle nonstandard baudrate values in
// normal tcsetattr(), sigh.
#ifdef __APPLE__
if (!nonstandard) {
#endif
cfsetospeed(&termios, speed); cfsetospeed(&termios, speed);
cfsetispeed(&termios, speed); cfsetispeed(&termios, speed);
#ifdef __APPLE__
}
#endif
termios.c_cflag &= ~CSIZE;
if (cflags & SERIAL_CS8) {
termios.c_cflag |= CS8;
}
if (cflags & SERIAL_CS7) {
termios.c_cflag |= CS7;
}
if (cflags & SERIAL_CS6) {
termios.c_cflag |= CS6;
}
if (cflags & SERIAL_CS5) {
termios.c_cflag |= CS5;
}
if (cflags & SERIAL_CSTOPB) {
termios.c_cflag |= CSTOPB;
} else {
termios.c_cflag &= ~CSTOPB;
}
termios.c_iflag &= ~(INPCK | ISTRIP);
if (cflags & (SERIAL_PARENB | SERIAL_PARODD)) {
termios.c_cflag |= PARENB;
} else {
termios.c_cflag &= ~PARENB;
}
if (cflags & SERIAL_PARODD) {
termios.c_cflag |= PARODD;
} else {
termios.c_cflag &= ~PARODD;
}
#ifdef IXANY
termios.c_iflag &= ~IXANY;
#endif /* IXANY */
termios.c_iflag &= ~(IXON | IXOFF);
#ifdef CRTSCTS
termios.c_iflag &= ~CRTSCTS;
#endif /* CRTSCTS */
#ifdef CNEW_RTSCTS
termios.c_iflag &= ~CNEW_RTSCTS;
#endif /* CRTSCTS */
rc = tcsetattr(fd->ifd, TCSANOW, &termios); rc = tcsetattr(fd->ifd, TCSANOW, &termios);
if (rc < 0) { if (rc < 0) {
@ -154,13 +222,18 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla
return -errno; return -errno;
} }
/* #ifdef __APPLE__
* Everything is now set up for a local line without modem control // handle nonstandard speed values the MacOS way
* or flow control, so clear O_NONBLOCK again. if (nonstandard) {
*/ if (ioctl(fd->ifd, IOSSIOSPEED, &speed) < 0) {
rc = fcntl(fd->ifd, F_GETFL, 0); avrdude_message(MSG_INFO, "%s: ser_setparams(): ioctrl(IOSSIOSPEED) failed\n",
if (rc != -1) progname);
fcntl(fd->ifd, F_SETFL, rc & ~O_NONBLOCK); return -errno;
}
}
#endif // __APPLE__
tcflush(fd->ifd, TCIFLUSH);
return 0; return 0;
} }
@ -520,3 +593,4 @@ struct serial_device serial_serdev =
struct serial_device *serdev = &serial_serdev; struct serial_device *serdev = &serial_serdev;
#endif /* WIN32 */ #endif /* WIN32 */

View File

@ -1613,11 +1613,11 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port)
PDATA(pgm)->pgmtype = PGMTYPE_UNKNOWN; PDATA(pgm)->pgmtype = PGMTYPE_UNKNOWN;
if(strcasecmp(port, "avrdoper") == 0){ if(strcasecmp(port, "avrdoper") == 0){
#if defined(HAVE_LIBHIDAPI) || (defined(WIN32) && defined(HAVE_LIBHID)) #if defined(HAVE_LIBHIDAPI)
serdev = &avrdoper_serdev; serdev = &avrdoper_serdev;
PDATA(pgm)->pgmtype = PGMTYPE_STK500; PDATA(pgm)->pgmtype = PGMTYPE_STK500;
#else #else
avrdude_message(MSG_INFO, "avrdoper requires avrdude with hid support.\n"); avrdude_message(MSG_INFO, "avrdoper requires avrdude with libhidapi support.\n");
return -1; return -1;
#endif #endif
} }
@ -3869,7 +3869,8 @@ static int stk600_xprog_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
* fuses. * fuses.
*/ */
need_erase = 1; need_erase = 1;
} else if (strcmp(mem->desc, "usersig") == 0) { } else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
memcode = XPRG_MEM_TYPE_USERSIG; memcode = XPRG_MEM_TYPE_USERSIG;
} else { } else {
avrdude_message(MSG_INFO, "%s: stk600_xprog_write_byte(): unknown memory \"%s\"\n", avrdude_message(MSG_INFO, "%s: stk600_xprog_write_byte(): unknown memory \"%s\"\n",
@ -3944,7 +3945,8 @@ static int stk600_xprog_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
} else if (strcmp(mem->desc, "calibration") == 0 || } else if (strcmp(mem->desc, "calibration") == 0 ||
strcmp(mem->desc, "prodsig") == 0) { strcmp(mem->desc, "prodsig") == 0) {
b[1] = XPRG_MEM_TYPE_FACTORY_CALIBRATION; b[1] = XPRG_MEM_TYPE_FACTORY_CALIBRATION;
} else if (strcmp(mem->desc, "usersig") == 0) { } else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
b[1] = XPRG_MEM_TYPE_USERSIG; b[1] = XPRG_MEM_TYPE_USERSIG;
} else { } else {
avrdude_message(MSG_INFO, "%s: stk600_xprog_read_byte(): unknown memory \"%s\"\n", avrdude_message(MSG_INFO, "%s: stk600_xprog_read_byte(): unknown memory \"%s\"\n",
@ -4019,7 +4021,8 @@ static int stk600_xprog_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
} else if (strcmp(mem->desc, "calibration") == 0 || } else if (strcmp(mem->desc, "calibration") == 0 ||
strcmp(mem->desc, "prodsig") == 0) { strcmp(mem->desc, "prodsig") == 0) {
memtype = XPRG_MEM_TYPE_FACTORY_CALIBRATION; memtype = XPRG_MEM_TYPE_FACTORY_CALIBRATION;
} else if (strcmp(mem->desc, "usersig") == 0) { } else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
memtype = XPRG_MEM_TYPE_USERSIG; memtype = XPRG_MEM_TYPE_USERSIG;
} else { } else {
avrdude_message(MSG_INFO, "%s: stk600_xprog_paged_load(): unknown paged memory \"%s\"\n", avrdude_message(MSG_INFO, "%s: stk600_xprog_paged_load(): unknown paged memory \"%s\"\n",
@ -4132,7 +4135,8 @@ static int stk600_xprog_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
} else if (strcmp(mem->desc, "calibration") == 0) { } else if (strcmp(mem->desc, "calibration") == 0) {
memtype = XPRG_MEM_TYPE_FACTORY_CALIBRATION; memtype = XPRG_MEM_TYPE_FACTORY_CALIBRATION;
writemode = (1 << XPRG_MEM_WRITE_WRITE); writemode = (1 << XPRG_MEM_WRITE_WRITE);
} else if (strcmp(mem->desc, "usersig") == 0) { } else if (strcmp(mem->desc, "usersig") == 0 ||
strcmp(mem->desc, "userrow") == 0) {
memtype = XPRG_MEM_TYPE_USERSIG; memtype = XPRG_MEM_TYPE_USERSIG;
writemode = (1 << XPRG_MEM_WRITE_WRITE); writemode = (1 << XPRG_MEM_WRITE_WRITE);
} else { } else {
@ -4290,7 +4294,8 @@ static int stk600_xprog_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
b[1] = XPRG_ERASE_BOOT_PAGE; b[1] = XPRG_ERASE_BOOT_PAGE;
} else if (strcmp(m->desc, "eeprom") == 0) { } else if (strcmp(m->desc, "eeprom") == 0) {
b[1] = XPRG_ERASE_EEPROM_PAGE; b[1] = XPRG_ERASE_EEPROM_PAGE;
} else if (strcmp(m->desc, "usersig") == 0) { } else if (strcmp(m->desc, "usersig") == 0 ||
strcmp(m->desc, "userrow") == 0) {
b[1] = XPRG_ERASE_USERSIG; b[1] = XPRG_ERASE_USERSIG;
} else { } else {
avrdude_message(MSG_INFO, "%s: stk600_xprog_page_erase(): unknown paged memory \"%s\"\n", avrdude_message(MSG_INFO, "%s: stk600_xprog_page_erase(): unknown paged memory \"%s\"\n",

View File

@ -23,6 +23,7 @@
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
@ -97,8 +98,8 @@ struct command cmd[] = {
{ "sig", cmd_sig, "display device signature bytes" }, { "sig", cmd_sig, "display device signature bytes" },
{ "part", cmd_part, "display the current part information" }, { "part", cmd_part, "display the current part information" },
{ "send", cmd_send, "send a raw command : %s <b1> <b2> <b3> <b4>" }, { "send", cmd_send, "send a raw command : %s <b1> <b2> <b3> <b4>" },
{ "parms", cmd_parms, "display adjustable parameters (STK500 only)" }, { "parms", cmd_parms, "display adjustable parameters (STK500 and Curiosity Nano only)" },
{ "vtarg", cmd_vtarg, "set <V[target]> (STK500 only)" }, { "vtarg", cmd_vtarg, "set <V[target]> (STK500 and Curiosity Nano only)" },
{ "varef", cmd_varef, "set <V[aref]> (STK500 only)" }, { "varef", cmd_varef, "set <V[aref]> (STK500 only)" },
{ "fosc", cmd_fosc, "set <oscillator frequency> (STK500 only)" }, { "fosc", cmd_fosc, "set <oscillator frequency> (STK500 only)" },
{ "sck", cmd_sck, "set <SCK period> (STK500 only)" }, { "sck", cmd_sck, "set <SCK period> (STK500 only)" },
@ -125,9 +126,15 @@ static int nexttok(char * buf, char ** tok, char ** next)
q++; q++;
/* isolate first token */ /* isolate first token */
n = q+1; n = q;
while (*n && !isspace((int)*n)) uint8_t quotes = 0;
while (*n && (!isspace((int)*n) || quotes)) {
if (*n == '\"')
quotes++;
else if (isspace((int)*n) && *(n-1) == '\"')
break;
n++; n++;
}
if (*n) { if (*n) {
*n = 0; *n = 0;
@ -148,12 +155,10 @@ static int nexttok(char * buf, char ** tok, char ** next)
static int hexdump_line(char * buffer, unsigned char * p, int n, int pad) static int hexdump_line(char * buffer, unsigned char * p, int n, int pad)
{ {
char * hexdata = "0123456789abcdef"; char * hexdata = "0123456789abcdef";
char * b; char * b = buffer;
int i, j; int32_t i = 0;
int32_t j = 0;
b = buffer;
j = 0;
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
if (i && ((i % 8) == 0)) if (i && ((i % 8) == 0))
b[j++] = ' '; b[j++] = ' ';
@ -182,7 +187,7 @@ static int chardump_line(char * buffer, unsigned char * p, int n, int pad)
int i; int i;
char b [ 128 ]; char b [ 128 ];
for (i=0; i<n; i++) { for (int32_t i = 0; i < n; i++) {
memcpy(b, p, n); memcpy(b, p, n);
buffer[i] = '.'; buffer[i] = '.';
if (isalpha((int)(b[i])) || isdigit((int)(b[i])) || ispunct((int)(b[i]))) if (isalpha((int)(b[i])) || isdigit((int)(b[i])) || ispunct((int)(b[i])))
@ -202,16 +207,13 @@ static int chardump_line(char * buffer, unsigned char * p, int n, int pad)
static int hexdump_buf(FILE * f, int startaddr, unsigned char * buf, int len) static int hexdump_buf(FILE * f, int startaddr, unsigned char * buf, int len)
{ {
int addr;
int n;
unsigned char * p;
char dst1[80]; char dst1[80];
char dst2[80]; char dst2[80];
addr = startaddr; int32_t addr = startaddr;
p = (unsigned char *)buf; unsigned char * p = (unsigned char *)buf;
while (len) { while (len) {
n = 16; int32_t n = 16;
if (n > len) if (n > len)
n = len; n = len;
hexdump_line(dst1, p, n, 48); hexdump_line(dst1, p, n, 48);
@ -229,80 +231,86 @@ static int hexdump_buf(FILE * f, int startaddr, unsigned char * buf, int len)
static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
int argc, char * argv[]) int argc, char * argv[])
{ {
static char prevmem[128] = {0}; if (argc < 2) {
char * e; avrdude_message(MSG_INFO, "Usage: %s <memtype> [<start addr> <len>]\n"
unsigned char * buf; " %s <memtype> [<start addr> <...>]\n"
int maxsize; " %s <memtype> <...>\n"
unsigned long i; " %s <memtype>\n",
static unsigned long addr=0; argv[0], argv[0], argv[0], argv[0]);
static int len=64;
AVRMEM * mem;
char * memtype = NULL;
int rc;
if (!((argc == 2) || (argc == 4))) {
avrdude_message(MSG_INFO, "Usage: dump <memtype> [<addr> <len>]\n");
return -1; return -1;
} }
memtype = argv[1]; enum { read_size = 256 };
static char prevmem[128] = {0x00};
if (strncmp(prevmem, memtype, strlen(memtype)) != 0) { char * memtype = argv[1];
addr = 0; AVRMEM * mem = avr_locate_mem(p, memtype);
len = 64;
strncpy(prevmem, memtype, sizeof(prevmem)-1);
prevmem[sizeof(prevmem)-1] = 0;
}
mem = avr_locate_mem(p, memtype);
if (mem == NULL) { if (mem == NULL) {
avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n", avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n",
memtype, p->desc); memtype, p->desc);
return -1; return -1;
} }
uint32_t maxsize = mem->size;
// Get start address if present
char * end_ptr;
static uint32_t addr = 0;
if (argc == 4) { if (argc == 4) {
addr = strtoul(argv[2], &e, 0); addr = strtoul(argv[2], &end_ptr, 0);
if (*e || (e == argv[2])) { if (*end_ptr || (end_ptr == argv[2])) {
avrdude_message(MSG_INFO, "%s (dump): can't parse address \"%s\"\n", avrdude_message(MSG_INFO, "%s (%s): can't parse address \"%s\"\n",
progname, argv[2]); progname, argv[0], argv[2]);
return -1; return -1;
} } else if (addr >= maxsize) {
avrdude_message(MSG_INFO, "%s (%s): address 0x%05lx is out of range for %s memory\n",
len = strtol(argv[3], &e, 0); progname, argv[0], addr, mem->desc);
if (*e || (e == argv[3])) {
avrdude_message(MSG_INFO, "%s (dump): can't parse length \"%s\"\n",
progname, argv[3]);
return -1; return -1;
} }
} }
maxsize = mem->size; // Get no. bytes to read if present
static int32_t len = read_size;
if (addr >= maxsize) { if (argc >= 3) {
if (argc == 2) { memset(prevmem, 0x00, sizeof(prevmem));
/* wrap around */ if (strcmp(argv[argc - 1], "...") == 0) {
if (argc == 3)
addr = 0; addr = 0;
} len = maxsize - addr;
else { } else if (argc == 4) {
avrdude_message(MSG_INFO, "%s (dump): address 0x%05lx is out of range for %s memory\n", len = strtol(argv[3], &end_ptr, 0);
progname, addr, mem->desc); if (*end_ptr || (end_ptr == argv[3])) {
avrdude_message(MSG_INFO, "%s (%s): can't parse length \"%s\"\n",
progname, argv[0], argv[3]);
return -1; return -1;
} }
} else {
len = read_size;
}
}
// No address or length specified
else if (argc == 2) {
if (strncmp(prevmem, memtype, strlen(memtype)) != 0) {
addr = 0;
len = read_size;
strncpy(prevmem, memtype, sizeof(prevmem) - 1);
prevmem[sizeof(prevmem) - 1] = 0;
}
if (addr >= maxsize)
addr = 0; // Wrap around
} }
/* trim len if nessary to not read past the end of memory */ // Trim len if nessary to not read past the end of memory
if ((addr + len) > maxsize) if ((addr + len) > maxsize)
len = maxsize - addr; len = maxsize - addr;
buf = malloc(len); uint8_t * buf = malloc(len);
if (buf == NULL) { if (buf == NULL) {
avrdude_message(MSG_INFO, "%s (dump): out of memory\n", progname); avrdude_message(MSG_INFO, "%s (dump): out of memory\n", progname);
return -1; return -1;
} }
for (i=0; i<len; i++) { report_progress(0, 1, "Reading");
rc = pgm->read_byte(pgm, p, mem, addr+i, &buf[i]); for (uint32_t i = 0; i < len; i++) {
int32_t rc = pgm->read_byte(pgm, p, mem, addr + i, &buf[i]);
if (rc != 0) { if (rc != 0) {
avrdude_message(MSG_INFO, "error reading %s address 0x%05lx of part %s\n", avrdude_message(MSG_INFO, "error reading %s address 0x%05lx of part %s\n",
mem->desc, addr + i, p->desc); mem->desc, addr + i, p->desc);
@ -311,10 +319,11 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
mem->desc); mem->desc);
return -1; return -1;
} }
report_progress(i, len, NULL);
} }
report_progress(1, 1, NULL);
hexdump_buf(stdout, addr, buf, len); hexdump_buf(stdout, addr, buf, len);
fprintf(stdout, "\n"); fprintf(stdout, "\n");
free(buf); free(buf);
@ -328,35 +337,31 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p,
static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
int argc, char * argv[]) int argc, char * argv[])
{ {
char * e;
int len, maxsize;
char * memtype;
unsigned long addr, i;
unsigned char * buf;
unsigned char b;
int rc;
int werror;
AVRMEM * mem;
if (argc < 4) { if (argc < 4) {
avrdude_message(MSG_INFO, "Usage: write <memtype> <addr> <byte1> " avrdude_message(MSG_INFO,
"<byte2> ... <byteN>\n"); "Usage: write <memtype> <start addr> <data1> <data2> <dataN>\n"
" write <memtype> <start addr> <no. bytes> <data1> <dataN> <...>\n\n"
" Add a suffix to manually specify the size for each field:\n"
" HH/hh: 8-bit, H/h/S/s: 16-bit, L/l: 32-bit, LL/ll: 64-bit, F/f: 32-bit float\n");
return -1; return -1;
} }
memtype = argv[1]; int32_t i;
uint8_t write_mode; // Operation mode, "standard" or "fill"
mem = avr_locate_mem(p, memtype); uint8_t start_offset; // Which argc argument
int32_t len; // Number of bytes to write to memory
char * memtype = argv[1]; // Memory name string
AVRMEM * mem = avr_locate_mem(p, memtype);
if (mem == NULL) { if (mem == NULL) {
avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n", avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n",
memtype, p->desc); memtype, p->desc);
return -1; return -1;
} }
uint32_t maxsize = mem->size;
maxsize = mem->size; char * end_ptr;
int32_t addr = strtoul(argv[2], &end_ptr, 0);
addr = strtoul(argv[2], &e, 0); if (*end_ptr || (end_ptr == argv[2])) {
if (*e || (e == argv[2])) {
avrdude_message(MSG_INFO, "%s (write): can't parse address \"%s\"\n", avrdude_message(MSG_INFO, "%s (write): can't parse address \"%s\"\n",
progname, argv[2]); progname, argv[2]);
return -1; return -1;
@ -368,61 +373,228 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p,
return -1; return -1;
} }
/* number of bytes to write at the specified address */ // Allocate a buffer guaranteed to be large enough
len = argc - 3; uint8_t * buf = calloc(mem->size + 0x10 + strlen(argv[argc - 2]), sizeof(uint8_t));
if ((addr + len) > maxsize) {
avrdude_message(MSG_INFO, "%s (write): selected address and # bytes exceed "
"range for %s memory\n",
progname, memtype);
return -1;
}
buf = malloc(len);
if (buf == NULL) { if (buf == NULL) {
avrdude_message(MSG_INFO, "%s (write): out of memory\n", progname); avrdude_message(MSG_INFO, "%s (write): out of memory\n", progname);
return -1; return -1;
} }
for (i=3; i<argc; i++) { // Find the first argument to write to flash and how many arguments to parse and write
buf[i-3] = strtoul(argv[i], &e, 0); if (strcmp(argv[argc - 1], "...") == 0) {
if (*e || (e == argv[i])) { write_mode = WRITE_MODE_FILL;
avrdude_message(MSG_INFO, "%s (write): can't parse byte \"%s\"\n", start_offset = 4;
progname, argv[i]); len = strtoul(argv[3], &end_ptr, 0);
if (*end_ptr || (end_ptr == argv[3])) {
avrdude_message(MSG_INFO, "%s (write ...): can't parse address \"%s\"\n",
progname, argv[3]);
free(buf); free(buf);
return -1; return -1;
} }
} else {
write_mode = WRITE_MODE_STANDARD;
start_offset = 3;
len = argc - start_offset;
} }
pgm->err_led(pgm, OFF); // Structure related to data that is being written to memory
for (werror=0, i=0; i<len; i++) { struct Data {
// Data info
int32_t bytes_grown;
uint8_t size;
bool is_float;
bool is_signed;
char * str_ptr;
// Data union
union {
float f;
int64_t ll;
uint8_t a[8];
};
} data = {
.bytes_grown = 0,
.size = 0,
.is_float = false,
.is_signed = false,
.str_ptr = NULL,
.ll = 0
};
rc = avr_write_byte(pgm, p, mem, addr+i, buf[i]); for (i = start_offset; i < len + start_offset; i++) {
data.is_float = false;
data.size = 0;
// Handle the next argument
if (i < argc - start_offset + 3) {
// Free string pointer if already allocated
if(data.str_ptr) {
free(data.str_ptr);
data.str_ptr = NULL;
}
// Get suffix if present
char suffix = argv[i][strlen(argv[i]) - 1];
char lsuffix = argv[i][strlen(argv[i]) - 2];
if ((suffix == 'L' && lsuffix == 'L') || (suffix == 'l' && lsuffix == 'l')) {
argv[i][strlen(argv[i]) - 2] = '\0';
data.size = 8;
} else if (suffix == 'L' || suffix == 'l') {
argv[i][strlen(argv[i]) - 1] = '\0';
data.size = 4;
} else if ((suffix == 'F' || suffix == 'f') &&
strncmp(argv[i], "0x", 2) != 0 && strncmp(argv[i], "-0x", 3) != 0) {
argv[i][strlen(argv[i]) - 1] = '\0';
data.size = 4;
} else if ((suffix == 'H' && lsuffix == 'H') || (suffix == 'h' && lsuffix == 'h')) {
argv[i][strlen(argv[i]) - 2] = '\0';
data.size = 1;
} else if (suffix == 'H' || suffix == 'h' || suffix == 'S' || suffix == 's') {
argv[i][strlen(argv[i]) - 1] = '\0';
data.size = 2;
} else if (suffix == '\'') {
data.size = 1;
}
// Try integers
data.ll = strtoll(argv[i], &end_ptr, 0);
if (*end_ptr || (end_ptr == argv[i])) {
// Try float
data.f = strtof(argv[i], &end_ptr);
data.is_float = true;
if (*end_ptr || (end_ptr == argv[i])) {
data.is_float = false;
// Try single character
if (argv[i][0] == '\'' && argv[i][2] == '\'') {
data.ll = argv[i][1];
} else {
// Try string that starts and ends with quotes
if (argv[i][0] == '\"' && argv[i][strlen(argv[i]) - 1] == '\"') {
data.str_ptr = calloc(strlen(argv[i]), sizeof(char));
if (data.str_ptr == NULL) {
avrdude_message(MSG_INFO, "%s (write str): out of memory\n", progname);
return -1;
}
// Strip start and end quotes
strncpy(data.str_ptr, argv[i] + 1, strlen(argv[i]) - 2);
} else {
avrdude_message(MSG_INFO, "\n%s (write): can't parse data '%s'\n",
progname, argv[i]);
free(buf);
if(data.str_ptr != NULL)
free(data.str_ptr);
return -1;
}
}
}
}
// Print warning if data size might be ambiguous
bool is_hex = (strncmp(argv[i], "0x", 2) == 0);
bool is_neg_hex = (strncmp(argv[i], "-0x", 3) == 0);
bool leading_zero = (strncmp(argv[i], "0x0", 3) == 0);
int8_t hex_digits = (strlen(argv[i]) - 2);
if(!data.size // No pre-defined size
&& (is_neg_hex // Hex with - sign in front
|| (is_hex && leading_zero && (hex_digits & (hex_digits - 1))) // Hex with 3, 5, 6 or 7 digits
|| (!is_hex && !data.is_float && llabs(data.ll) > 0xFF && strlen(argv[i]) > 2))) // Base10 int greater than 255
{
avrdude_message(MSG_INFO, "Warning: no size suffix specified for \"%s\". "
"Writing %d byte(s)\n",
argv[i],
llabs(data.ll) > UINT32_MAX ? 8 :
llabs(data.ll) > UINT16_MAX || data.is_float ? 4 : \
llabs(data.ll) > UINT8_MAX ? 2 : 1);
}
// Flag if signed integer and adjust size
if (data.ll < 0 && !data.is_float) {
data.is_signed = true;
if (data.ll < INT32_MIN)
data.size = 8;
else if (data.ll < INT16_MIN)
data.size = 4;
else if (data.ll < INT8_MIN)
data.size = 2;
else
data.size = 1;
}
}
if(data.str_ptr) {
for(int16_t j = 0; j < strlen(data.str_ptr); j++)
buf[i - start_offset + data.bytes_grown++] = (uint8_t)data.str_ptr[j];
} else {
buf[i - start_offset + data.bytes_grown] = data.a[0];
if (llabs(data.ll) > 0x000000FF || data.size >= 2 || data.is_float)
buf[i - start_offset + ++data.bytes_grown] = data.a[1];
if (llabs(data.ll) > 0x0000FFFF || data.size >= 4 || data.is_float) {
buf[i - start_offset + ++data.bytes_grown] = data.a[2];
buf[i - start_offset + ++data.bytes_grown] = data.a[3];
}
if (llabs(data.ll) > 0xFFFFFFFF || data.size == 8) {
buf[i - start_offset + ++data.bytes_grown] = data.a[4];
buf[i - start_offset + ++data.bytes_grown] = data.a[5];
buf[i - start_offset + ++data.bytes_grown] = data.a[6];
buf[i - start_offset + ++data.bytes_grown] = data.a[7];
}
}
// Make sure buf does not overflow
if (i - start_offset + data.bytes_grown > maxsize)
break;
}
// When in "fill" mode, the maximum size is already predefined
if (write_mode == WRITE_MODE_FILL)
data.bytes_grown = 0;
if ((addr + len + data.bytes_grown) > maxsize) {
avrdude_message(MSG_INFO, "%s (write): selected address and # bytes exceed "
"range for %s memory\n",
progname, memtype);
free(buf);
return -1;
}
if(data.str_ptr)
free(data.str_ptr);
avrdude_message(MSG_NOTICE, "\nInfo: Writing %d bytes starting from address 0x%02x",
len + data.bytes_grown, addr);
if (write_mode == WRITE_MODE_FILL)
avrdude_message(MSG_NOTICE, ". Remaining space filled with %s", argv[argc - 2]);
avrdude_message(MSG_NOTICE, "\n");
pgm->err_led(pgm, OFF);
bool werror = false;
report_progress(0, 1, "Writing");
for (i = 0; i < (len + data.bytes_grown); i++) {
int32_t rc = avr_write_byte(pgm, p, mem, addr+i, buf[i]);
if (rc) { if (rc) {
avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n", avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n",
progname, buf[i], addr+i, rc); progname, buf[i], addr+i, rc);
if (rc == -1) if (rc == -1)
avrdude_message(MSG_INFO, "write operation not supported on memory type \"%s\"\n", avrdude_message(MSG_INFO, "write operation not supported on memory type \"%s\"\n",
mem->desc); mem->desc);
werror = 1; werror = true;
} }
uint8_t b;
rc = pgm->read_byte(pgm, p, mem, addr+i, &b); rc = pgm->read_byte(pgm, p, mem, addr+i, &b);
if (b != buf[i]) { if (b != buf[i]) {
avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n", avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n",
progname, buf[i], addr+i, b); progname, buf[i], addr+i, b);
werror = 1; werror = true;
} }
if (werror) { if (werror) {
pgm->err_led(pgm, ON); pgm->err_led(pgm, ON);
} }
report_progress(i, (len + data.bytes_grown), NULL);
} }
report_progress(1, 1, NULL);
free(buf); free(buf);
fprintf(stdout, "\n");
return 0; return 0;
} }

View File

@ -27,6 +27,11 @@
extern "C" { extern "C" {
#endif #endif
typedef enum {
WRITE_MODE_STANDARD = 0,
WRITE_MODE_FILL = 1,
} mode;
int terminal_mode(PROGRAMMER * pgm, struct avrpart * p); int terminal_mode(PROGRAMMER * pgm, struct avrpart * p);
char * terminal_get_input(const char *prompt); char * terminal_get_input(const char *prompt);

View File

@ -227,6 +227,13 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
return -1; return -1;
} }
AVRMEM_ALIAS * alias_mem = avr_find_memalias(p, mem);
char alias_mem_desc[AVR_DESCLEN + 1] = "";
if(alias_mem) {
strcat(alias_mem_desc, "/");
strcat(alias_mem_desc, alias_mem->desc);
}
if (upd->op == DEVICE_READ) { if (upd->op == DEVICE_READ) {
/* /*
* read out the specified device memory and write it to a file * read out the specified device memory and write it to a file
@ -238,14 +245,14 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
return -1; return -1;
} }
if (quell_progress < 2) { if (quell_progress < 2) {
avrdude_message(MSG_INFO, "%s: reading %s memory:\n", avrdude_message(MSG_INFO, "%s: reading %s%s memory:\n",
progname, mem->desc); progname, mem->desc, alias_mem_desc);
} }
report_progress(0,1,"Reading"); report_progress(0,1,"Reading");
rc = avr_read(pgm, p, upd->memtype, 0); rc = avr_read(pgm, p, upd->memtype, 0);
if (rc < 0) { if (rc < 0) {
avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n", avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n",
progname, mem->desc, rc); progname, mem->desc, alias_mem_desc, rc);
return -1; return -1;
} }
report_progress(1,1,NULL); report_progress(1,1,NULL);
@ -288,8 +295,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
* write the buffer contents to the selected memory type * write the buffer contents to the selected memory type
*/ */
if (quell_progress < 2) { if (quell_progress < 2) {
avrdude_message(MSG_INFO, "%s: writing %s (%d bytes):\n", avrdude_message(MSG_INFO, "%s: writing %s%s (%d bytes):\n",
progname, mem->desc, size); progname, mem->desc, alias_mem_desc, size);
} }
if (!(flags & UF_NOWRITE)) { if (!(flags & UF_NOWRITE)) {
@ -306,16 +313,16 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
} }
if (rc < 0) { if (rc < 0) {
avrdude_message(MSG_INFO, "%s: failed to write %s memory, rc=%d\n", avrdude_message(MSG_INFO, "%s: failed to write %s%s memory, rc=%d\n",
progname, mem->desc, rc); progname, mem->desc, alias_mem_desc, rc);
return -1; return -1;
} }
vsize = rc; vsize = rc;
if (quell_progress < 2) { if (quell_progress < 2) {
avrdude_message(MSG_INFO, "%s: %d bytes of %s written\n", progname, avrdude_message(MSG_INFO, "%s: %d bytes of %s%s written\n", progname,
vsize, mem->desc); vsize, mem->desc, alias_mem_desc);
} }
} }
@ -327,11 +334,11 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
pgm->vfy_led(pgm, ON); pgm->vfy_led(pgm, ON);
if (quell_progress < 2) { if (quell_progress < 2) {
avrdude_message(MSG_INFO, "%s: verifying %s memory against %s:\n", avrdude_message(MSG_INFO, "%s: verifying %s%s memory against %s:\n",
progname, mem->desc, upd->filename); progname, mem->desc, alias_mem_desc, upd->filename);
avrdude_message(MSG_NOTICE2, "%s: load data %s data from input file %s:\n", avrdude_message(MSG_NOTICE2, "%s: load data %s%s data from input file %s:\n",
progname, mem->desc, upd->filename); progname, mem->desc, alias_mem_desc, upd->filename);
} }
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1); rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1);
@ -345,15 +352,15 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
if (quell_progress < 2) { if (quell_progress < 2) {
avrdude_message(MSG_NOTICE2, "%s: input file %s contains %d bytes\n", avrdude_message(MSG_NOTICE2, "%s: input file %s contains %d bytes\n",
progname, upd->filename, size); progname, upd->filename, size);
avrdude_message(MSG_NOTICE2, "%s: reading on-chip %s data:\n", avrdude_message(MSG_NOTICE2, "%s: reading on-chip %s%s data:\n",
progname, mem->desc); progname, mem->desc, alias_mem_desc);
} }
report_progress (0,1,"Reading"); report_progress (0,1,"Reading");
rc = avr_read(pgm, p, upd->memtype, v); rc = avr_read(pgm, p, upd->memtype, v);
if (rc < 0) { if (rc < 0) {
avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n", avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n",
progname, mem->desc, rc); progname, mem->desc, alias_mem_desc, rc);
pgm->err_led(pgm, ON); pgm->err_led(pgm, ON);
avr_free_part(v); avr_free_part(v);
return -1; return -1;
@ -375,8 +382,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
} }
if (quell_progress < 2) { if (quell_progress < 2) {
avrdude_message(MSG_INFO, "%s: %d bytes of %s verified\n", avrdude_message(MSG_INFO, "%s: %d bytes of %s%s verified\n",
progname, rc, mem->desc); progname, rc, mem->desc, alias_mem_desc);
} }
pgm->vfy_led(pgm, OFF); pgm->vfy_led(pgm, OFF);

View File

@ -53,7 +53,7 @@ static void updi_set_rtsdtr_mode(PROGRAMMER* pgm)
static int updi_physical_open(PROGRAMMER* pgm, int baudrate, unsigned long cflags) static int updi_physical_open(PROGRAMMER* pgm, int baudrate, unsigned long cflags)
{ {
serial_recv_timeout = 100; serial_recv_timeout = 1000;
union pinfo pinfo; union pinfo pinfo;
pinfo.serialinfo.baud = baudrate; pinfo.serialinfo.baud = baudrate;
@ -155,12 +155,19 @@ static int updi_physical_send_double_break(PROGRAMMER * pgm)
serial_send(&pgm->fd, buffer, 1); serial_send(&pgm->fd, buffer, 1);
serial_recv(&pgm->fd, buffer, 1); serial_recv(&pgm->fd, buffer, 1);
serial_drain(&pgm->fd, 0);
if (serial_setparams(&pgm->fd, pgm->baudrate? pgm->baudrate: 115200, SERIAL_8E2) < 0) { if (serial_setparams(&pgm->fd, pgm->baudrate? pgm->baudrate: 115200, SERIAL_8E2) < 0) {
return -1; return -1;
} }
updi_set_rtsdtr_mode(pgm); updi_set_rtsdtr_mode(pgm);
/*
* drain any extraneous input
*/
serial_drain(&pgm->fd, 0);
return 0; return 0;
} }
@ -191,10 +198,14 @@ int updi_physical_sib(PROGRAMMER * pgm, unsigned char * buffer, uint8_t size)
int updi_link_open(PROGRAMMER * pgm) int updi_link_open(PROGRAMMER * pgm)
{ {
unsigned char init_buffer[1];
if (updi_physical_open(pgm, pgm->baudrate? pgm->baudrate: 115200, SERIAL_8E2) < 0) { if (updi_physical_open(pgm, pgm->baudrate? pgm->baudrate: 115200, SERIAL_8E2) < 0) {
return -1; return -1;
} }
return updi_physical_send_double_break(pgm);
init_buffer[0]=UPDI_BREAK;
return updi_physical_send(pgm, init_buffer, 1);
} }
void updi_link_close(PROGRAMMER * pgm) void updi_link_close(PROGRAMMER * pgm)

View File

@ -291,7 +291,7 @@ static int usbhid_recv(union filedescriptor *fd, unsigned char *buf, size_t nbyt
if (udev == NULL) if (udev == NULL)
return -1; return -1;
rv = i = hid_read_timeout(udev, buf, nbytes, 300); rv = i = hid_read_timeout(udev, buf, nbytes, 10000);
if (i != nbytes) if (i != nbytes)
avrdude_message(MSG_INFO, avrdude_message(MSG_INFO,
"%s: Short read, read only %d out of %u bytes\n", "%s: Short read, read only %d out of %u bytes\n",