diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7951592c..01a23f7e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,7 +20,11 @@ name: Build on: push: + branches-ignore: + - 'onlinedocs' pull_request: + branches-ignore: + - 'onlinedocs' workflow_call: env: diff --git a/CMakeLists.txt b/CMakeLists.txt index bfd4ab24..19897c72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,7 @@ # cmake --build build 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_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(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(CheckSymbolExists) include(FetchContent) @@ -110,14 +117,14 @@ endif() # Detect installed libraries # ===================================== -# Prefer static libraries over DLLs on Windows -if(WIN32) +if(USE_STATIC_LIBS) set(PREFERRED_LIBELF libelf.a elf) set(PREFERRED_LIBUSB libusb.a usb) 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_LIBFTDI libftdi.a ftdi) set(PREFERRED_LIBFTDI1 libftdi1.a ftdi1) + set(PREFERRED_LIBREADLINE libreadline.a) else() set(PREFERRED_LIBELF elf) set(PREFERRED_LIBUSB usb) @@ -125,6 +132,7 @@ else() set(PREFERRED_LIBHIDAPI hidapi hidapi-libusb hidapi-hidraw) set(PREFERRED_LIBFTDI ftdi) set(PREFERRED_LIBFTDI1 ftdi1) + set(PREFERRED_LIBREADLINE readline) endif() # ------------------------------------- @@ -182,6 +190,9 @@ endif() # Find libhidapi find_library(HAVE_LIBHID NAMES hid) +if(HAVE_LIBHID) + set(LIB_LIBHID ${HAVE_LIBHID}) +endif() find_library(HAVE_LIBHIDAPI NAMES ${PREFERRED_LIBHIDAPI}) if(HAVE_LIBHIDAPI) @@ -209,7 +220,7 @@ endif() # ------------------------------------- # Find libreadline -find_library(HAVE_LIBREADLINE NAMES readline) +find_library(HAVE_LIBREADLINE NAMES ${PREFERRED_LIBREADLINE}) if(HAVE_LIBREADLINE) set(LIB_LIBREADLINE ${HAVE_LIBREADLINE}) endif() diff --git a/NEWS b/NEWS index 6b09b724..888796ca 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,31 @@ Approximate change log for AVRDUDE by version. (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: @@ -13,6 +37,17 @@ Changes since version 6.4: - Started to add CMake (by now, parallel with autoconf/automake) - New-architecture devices (AVR8X mega and tiny) can access all 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: @@ -30,6 +65,7 @@ Changes since version 6.4: - ATtiny3224, ATtiny3226 and ATtiny3227 - 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 + - ATmega16U4 * New programmers supported: @@ -40,6 +76,8 @@ Changes since version 6.4: - Teensy bootloader (PR #802) - Micronucleus bootloader (PR #786) - ft232h (generic variant, PR #842) + - Kristech KT-LINK FT2232H interface with IO switching and voltage + buffers (PR #930) * Issues fixed: @@ -63,6 +101,22 @@ Changes since version 6.4: - Segmentation fault when writing ATtiny104 fuse #823 - USBasp returns ERANGE for unknown error #848 - 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: @@ -119,10 +173,45 @@ Changes since version 6.4: - Fix libusb-1.0 error strings #850 - Assign proper type to msg[] in errstr() #857 - 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: - Development moved to Github + - Addition of "alias" keyword to avrdude.conf.in syntax; used + for fuse name aliases right now Version 6.4: diff --git a/README.md b/README.md index 5c0c05ff..19bbabf4 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,10 @@ with the help of [various contributors](./AUTHORS). The latest version of AVRDUDE is always available here:\ +## Documentation + +Documentation for current and previous releases is [on Github Pages](https://avrdudes.github.io/avrdude/). + ## Getting AVRDUDE for Windows 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. -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/). diff --git a/build.sh b/build.sh index baea4516..0b664807 100755 --- a/build.sh +++ b/build.sh @@ -50,7 +50,13 @@ case "${ostype}" in then build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/local/lib" else - build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar" + # 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 + build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar" + fi fi ;; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b32934f5..bd3c6dee 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -51,15 +51,10 @@ include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) add_compile_definitions(CONFIG_DIR=\"${CONFIG_DIR}\") 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) endif() -if(NOT WIN32) - set(LIB_MATH m) - add_compile_options(-Wall) # -Wextra -endif() - if(MSVC) add_compile_definitions(_CRT_SECURE_NO_WARNINGS=1) add_compile_definitions(_CRT_NONSTDC_NO_WARNINGS=1) @@ -79,6 +74,9 @@ if(MSVC) set(EXTRA_WINDOWS_INCLUDES ${EXTRA_WINDOWS_INCLUDES} "msvc" ) +else() + set(LIB_MATH m) + add_compile_options(-Wall) # -Wextra endif() # ===================================== @@ -173,7 +171,6 @@ add_library(libavrdude ppi.c ppi.h ppiwin.c - safemode.c serbb.h serbb_posix.c serbb_win32.c @@ -217,6 +214,7 @@ add_library(libavrdude xbee.c ${FLEX_Parser_OUTPUTS} ${BISON_Parser_OUTPUTS} + "${EXTRA_WINDOWS_SOURCES}" ) set_target_properties(libavrdude PROPERTIES @@ -240,6 +238,7 @@ target_link_libraries(libavrdude ${LIB_LIBELF} ${LIB_LIBUSB} ${LIB_LIBUSB_1_0} + ${LIB_LIBHID} ${LIB_LIBHIDAPI} ${LIB_LIBFTDI} ${LIB_LIBFTDI1} @@ -253,7 +252,7 @@ add_executable(avrdude term.h whereami.c whereami.h - "${EXTRA_WINDOWS_SOURCES}" + "${EXTRA_WINDOWS_RESOURCES}" ) target_link_libraries(avrdude PUBLIC libavrdude) @@ -264,9 +263,9 @@ target_link_libraries(avrdude PUBLIC libavrdude) install(TARGETS avrdude DESTINATION bin) install(TARGETS libavrdude - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 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) diff --git a/src/Makefile.am b/src/Makefile.am index dd7adb57..15162224 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -148,7 +148,6 @@ libavrdude_a_SOURCES = \ ppi.c \ ppi.h \ ppiwin.c \ - safemode.c \ serbb.h \ serbb_posix.c \ serbb_win32.c \ diff --git a/src/avr.c b/src/avr.c index 68ecc9a4..d6e78bb5 100644 --- a/src/avr.c +++ b/src/avr.c @@ -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, 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); } diff --git a/src/avrdude.1 b/src/avrdude.1 index f73a4689..81834d30 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -18,7 +18,7 @@ .\" .\" $Id$ .\" -.Dd DATE November 22, 2021 +.Dd November 22, 2021 .Os .Dt AVRDUDE 1 .Sh NAME @@ -607,40 +607,11 @@ Posix systems (by now). .It Fl q Disable (or quell) output of the progress bar while reading or writing to the device. Specify it a second time for even quieter operation. -.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 Tells .Nm to enter the interactive ``terminal'' mode instead of up- or downloading 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 .Ar \&: Ns Ar op Ns .Ar \&: Ns Ar filename Ns diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 46076088..ba7f4f8e 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -339,10 +339,6 @@ default_parallel = "@DEFAULT_PAR_PORT@"; default_serial = "@DEFAULT_SER_PORT@"; # default_bitclock = 2.5; -# Turn off safemode by default -#default_safemode = no; - - # # PROGRAMMER DEFINITIONS # @@ -597,6 +593,38 @@ programmer 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 id = "serialupdi"; desc = "SerialUPDI"; @@ -890,6 +918,24 @@ programmer 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 programmer id = "ehajo-isp"; @@ -900,6 +946,17 @@ programmer 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 id = "micronucleus"; desc = "Micronucleus Bootloader"; @@ -918,16 +975,6 @@ programmer 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 id = "butterfly"; desc = "Atmel Butterfly Development Board"; @@ -4727,16 +4774,79 @@ part parent "m324p" signature = 0x1e 0x94 0x0a; memory "eeprom" + paged = no; /* leave this "no" */ size = 512; 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" paged = yes; size = 16384; page_size = 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"; 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", " x x x x x x x x"; @@ -5966,7 +6076,7 @@ part part parent "m329" id = "m329a"; - desc = "ATmega329a"; + desc = "ATmega329A"; ; #------------------------------------------------------------ @@ -6147,7 +6257,7 @@ part " i i i i i i i i"; 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", " 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"; 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", " 0 0 0 0 0 0 0 0", @@ -8840,8 +8950,8 @@ part " i i i i i i i i"; writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " 0 0 a5 a4 a3 a2 0 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; @@ -9019,7 +9129,7 @@ part "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", - "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", " 0 0 0 0 0 0 0 0", @@ -9027,8 +9137,8 @@ part " i i i i i i i i"; writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " 0 0 a5 a4 a3 a2 0 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; @@ -9762,6 +9872,81 @@ part parent "m328" signature = 0x1e 0x96 0x84; 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" size = 1; min_write_delay = 4500; @@ -10233,7 +10418,7 @@ part " i i i i i i i i"; 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", " x x x x x x x x"; @@ -12101,7 +12286,7 @@ part writepage = " 1 1 0 0 0 0 1 0", " 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"; mode = 0x41; @@ -12293,8 +12478,8 @@ part " i i i i i i i i"; writepage = " 1 1 0 0 0 0 1 0", - " 0 0 x x x x x x", - " x a6 a5 a4 a3 a2 0 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; @@ -12535,7 +12720,7 @@ part parent "t84" part id = "t43u"; - desc = "ATtiny43u"; + desc = "ATtiny43U"; has_debugwire = yes; flash_instr = 0xB4, 0x07, 0x17; eeprom_instr = 0xBB, 0xFF, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D, @@ -12595,7 +12780,7 @@ part readback_p1 = 0xff; readback_p2 = 0xff; 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", "0 0 a5 a4 a3 a2 a1 a0 i i i i i i i i"; @@ -12664,6 +12849,8 @@ part size = 1; 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"; + 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; max_write_delay = 4500; ; @@ -12702,12 +12889,203 @@ part ; memory "calibration" - size = 2; + size = 1; 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"; ; ; +#------------------------------------------------------------ +# 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 #------------------------------------------------------------ @@ -12788,12 +13166,12 @@ part 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", + " 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 0 0 0", + " a7 a6 a5 a4 a3 a2 0 0", " x x x x x x x x"; mode = 0x41; @@ -12867,7 +13245,7 @@ part 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 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", "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"; 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", " x x x x x x x x"; @@ -14249,7 +14627,7 @@ part part id = "m165"; desc = "ATmega165"; - signature = 0x1e 0x94 0x07; + signature = 0x1e 0x94 0x10; has_jtag = yes; # stk500_devcode = 0x??; # avr910_devcode = 0x??; @@ -14423,7 +14801,7 @@ part memory "signature" 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"; ; @@ -15431,6 +15809,13 @@ part parent "x128c3" id = "x128d4"; desc = "ATxmega128D4"; signature = 0x1e 0x97 0x47; + + memory "flash" + size = 0x22000; + offset = 0x800000; + page_size = 0x100; + readsize = 0x100; + ; ; #------------------------------------------------------------ @@ -16239,28 +16624,28 @@ part readback_p1 = 0xff; readback_p2 = 0xff; 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", " o o o o o o o o"; 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", " 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 x a5 a4 a3 a2 a1 a0", + " x x x x 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 x a5 a4 a3 a2 a1 a0", + " x x x x a3 a2 a1 a0", " i i i i i i i i"; writepage = " 0 1 0 0 1 1 0 0", - " 0 0 0 a12 a11 a10 a9 a8", - " a7 a6 x x x x x x", + " 0 0 a13 a12 a11 a10 a9 a8", + " a7 a6 a5 a4 x x x x", " x x x x x x x x"; mode = 0x41; @@ -16499,7 +16884,7 @@ part parent ".reduced_core_tiny" part id = "m406"; - desc = "ATMEGA406"; + desc = "ATmega406"; has_jtag = yes; signature = 0x1e 0x95 0x07; @@ -16632,9 +17017,7 @@ part ; memory "wdtcfg" - size = 1; - offset = 0x1280; - readsize = 1; + alias "fuse0"; ; memory "fuse1" @@ -16644,9 +17027,7 @@ part ; memory "bodcfg" - size = 1; - offset = 0x1281; - readsize = 1; + alias "fuse1"; ; memory "fuse2" @@ -16656,9 +17037,7 @@ part ; memory "osccfg" - size = 1; - offset = 0x1282; - readsize = 1; + alias "fuse2"; ; memory "fuse4" @@ -16668,9 +17047,7 @@ part ; memory "tcd0cfg" - size = 1; - offset = 0x1284; - readsize = 1; + alias "fuse4"; ; memory "fuse5" @@ -16680,9 +17057,7 @@ part ; memory "syscfg0" - size = 1; - offset = 0x1285; - readsize = 1; + alias "fuse5"; ; memory "fuse6" @@ -16692,9 +17067,7 @@ part ; memory "syscfg1" - size = 1; - offset = 0x1286; - readsize = 1; + alias "fuse6"; ; memory "fuse7" @@ -16704,9 +17077,11 @@ part ; memory "append" - size = 1; - offset = 0x1287; - readsize = 1; + alias "fuse7"; + ; + + memory "codesize" + alias "fuse7"; ; memory "fuse8" @@ -16716,9 +17091,11 @@ part ; memory "bootend" - size = 1; - offset = 0x1288; - readsize = 1; + alias "fuse8"; + ; + + memory "bootsize" + alias "fuse8"; ; memory "lock" @@ -16742,12 +17119,16 @@ part parent ".avr8x" desc = "AVR8X tiny family common values"; family_id = "tinyAVR"; - memory "usersig" + memory "userrow" size = 0x20; offset = 0x1300; page_size = 0x20; readsize = 0x100; ; + + memory "usersig" + alias "userrow"; + ; ; #------------------------------------------------------------ @@ -16759,12 +17140,16 @@ part parent ".avr8x" desc = "AVR8X mega family common values"; family_id = "megaAVR"; - memory "usersig" + memory "userrow" size = 0x40; offset = 0x1300; page_size = 0x40; readsize = 0x100; ; + + memory "usersig" + alias "userrow"; + ; ; #------------------------------------------------------------ @@ -17900,9 +18285,7 @@ part ; memory "wdtcfg" - size = 1; - offset = 0x1050; - readsize = 1; + alias "fuse0"; ; memory "fuse1" @@ -17912,9 +18295,7 @@ part ; memory "bodcfg" - size = 1; - offset = 0x1051; - readsize = 1; + alias "fuse1"; ; memory "fuse2" @@ -17924,9 +18305,7 @@ part ; memory "osccfg" - size = 1; - offset = 0x1052; - readsize = 1; + alias "fuse2"; ; memory "fuse4" @@ -17936,9 +18315,7 @@ part ; memory "tcd0cfg" - size = 1; - offset = 0x1054; - readsize = 1; + alias "fuse4"; ; memory "fuse5" @@ -17948,9 +18325,7 @@ part ; memory "syscfg0" - size = 1; - offset = 0x1055; - readsize = 1; + alias "fuse5"; ; memory "fuse6" @@ -17960,9 +18335,7 @@ part ; memory "syscfg1" - size = 1; - offset = 0x1056; - readsize = 1; + alias "fuse6"; ; memory "fuse7" @@ -17972,15 +18345,11 @@ part ; memory "codesize" - size = 1; - offset = 0x1057; - readsize = 1; + alias "fuse7"; ; memory "append" - size = 1; - offset = 0x1057; - readsize = 1; + alias "fuse7"; ; memory "fuse8" @@ -17990,15 +18359,11 @@ part ; memory "bootsize" - size = 1; - offset = 0x1058; - readsize = 1; + alias "fuse8"; ; memory "bootend" - size = 1; - offset = 0x1058; - readsize = 1; + alias "fuse8"; ; memory "lock" @@ -18015,6 +18380,10 @@ part readsize = 0x20; ; + memory "usersig" + alias "userrow"; + ; + memory "data" # SRAM, only used to supply the offset offset = 0x1000000; @@ -18851,6 +19220,10 @@ part parent ".avrdx" page_size = 0x40; readsize = 0x40; ; + + memory "usersig" + alias "userrow"; + ; ; #------------------------------------------------------------ diff --git a/src/avrpart.c b/src/avrpart.c index 13b89e2d..dc6def44 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -260,6 +260,21 @@ AVRMEM * avr_new_memtype(void) 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 @@ -326,6 +341,17 @@ AVRMEM * avr_dup_mem(AVRMEM * m) 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) { int i; @@ -348,7 +374,36 @@ void avr_free_mem(AVRMEM * 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; 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, int type, int verbose) { - static LNODEID ln; - static AVRMEM * n; static unsigned int prev_mem_offset, prev_mem_size; int i, j; char * optr; @@ -398,25 +496,14 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p, 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 if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) { prev_mem_offset = m->offset; 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 and size, we're not out of band and a family_id is present */ - char * mem_desc_alias = m->offset == n->offset && \ - m->size == n->size && \ - ln != NULL && \ - strcmp(p->family_id, "") != 0 ? - n->desc : ""; + char * mem_desc_alias = ap? ap->desc: ""; fprintf(f, "%s%-11s %-8s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n", prefix, @@ -488,6 +575,7 @@ AVRPART * avr_new_part(void) p->ocdrev = -1; p->mem = lcreat(NULL, 0); + p->mem_alias = lcreat(NULL, 0); return p; } @@ -496,19 +584,35 @@ AVRPART * avr_new_part(void) AVRPART * avr_dup_part(AVRPART * d) { AVRPART * p; - LISTID save; - LNODEID ln; + LISTID save, save2; + LNODEID ln, ln2; int i; p = avr_new_part(); save = p->mem; + save2 = p->mem_alias; *p = *d; p->mem = save; + p->mem_alias = save2; 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++) { @@ -523,6 +627,8 @@ void avr_free_part(AVRPART * d) int i; ldestroy_cb(d->mem, (void(*)(void *))avr_free_mem); d->mem = NULL; + ldestroy_cb(d->mem_alias, (void(*)(void *))avr_free_memalias); + d->mem_alias = NULL; for(i=0;iop)/sizeof(d->op[0]);i++) { if (d->op[i] != NULL) diff --git a/src/config.c b/src/config.c index 9402e4bb..3d8a760e 100644 --- a/src/config.c +++ b/src/config.c @@ -36,7 +36,6 @@ char default_programmer[MAX_STR_CONST]; char default_parallel[PATH_MAX]; char default_serial[PATH_MAX]; double default_bitclock; -int default_safemode; char string_buf[MAX_STR_CONST]; char *string_buf_ptr; @@ -48,6 +47,7 @@ AVRPART * current_part; AVRMEM * current_mem; LISTID part_list; LISTID programmers; +bool is_alias; int lineno; const char * infile; @@ -73,6 +73,7 @@ int init_config(void) current_mem = NULL; part_list = lcreat(NULL, 0); programmers = lcreat(NULL, 0); + is_alias = false; lineno = 1; infile = NULL; diff --git a/src/config.h b/src/config.h index d0d65ae2..914dda54 100644 --- a/src/config.h +++ b/src/config.h @@ -54,6 +54,7 @@ extern int lineno; extern const char * infile; extern LISTID string_list; extern LISTID number_list; +extern bool is_alias; // current entry is alias #if !defined(HAS_YYSTYPE) diff --git a/src/config_gram.y b/src/config_gram.y index e2a935cf..a8416162 100644 --- a/src/config_gram.y +++ b/src/config_gram.y @@ -68,6 +68,7 @@ static int pin_name; %token K_PAGE_SIZE %token K_PAGED +%token K_ALIAS %token K_BAUDRATE %token K_BS2 %token K_BUFF @@ -77,7 +78,6 @@ static int pin_name; %token K_DEFAULT_BITCLOCK %token K_DEFAULT_PARALLEL %token K_DEFAULT_PROGRAMMER -%token K_DEFAULT_SAFEMODE %token K_DEFAULT_SERIAL %token K_DESC %token K_FAMILY_ID @@ -257,14 +257,6 @@ def : K_DEFAULT_BITCLOCK TKN_EQUAL number_real TKN_SEMI { default_bitclock = $3->value.number_real; 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; - 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) { lrmv_d(current_part->mem, existing_mem); avr_free_mem(existing_mem); } - ladd(current_part->mem, current_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); + } current_mem = NULL; } | @@ -1290,6 +1287,7 @@ yesno : mem_specs : mem_spec TKN_SEMI | + mem_alias 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); + } +; %% diff --git a/src/configure.ac b/src/configure.ac index 5527ad6c..e6629c73 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -23,7 +23,7 @@ # Process this file with autoconf to produce a configure script. 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_HOST diff --git a/src/doc/Makefile.am b/src/doc/Makefile.am index bee799f7..4e644557 100644 --- a/src/doc/Makefile.am +++ b/src/doc/Makefile.am @@ -40,7 +40,7 @@ all-local: info html ps pdf html: avrdude-html/avrdude.html 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 \ mkdir -p avrdude-html ; \ mv -f *.html avrdude-html ; \ diff --git a/src/doc/avrdude.css b/src/doc/avrdude.css new file mode 100644 index 00000000..c5cba5ba --- /dev/null +++ b/src/doc/avrdude.css @@ -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; +} diff --git a/src/doc/avrdude.texi b/src/doc/avrdude.texi index 5761b908..92cf4df4 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -28,9 +28,7 @@ This file documents the avrdude program. For avrdude version @value{VERSION}, @value{UPDATED}. -Copyright @copyright{} 2003, 2005 Brian Dean - -Copyright @copyright{} 2006 - 2021 J@"org Wunsch +Copyright @copyright{} Brian Dean, J@"org Wunsch Permission is granted to make and distribute verbatim copies of 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 @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{} 2006 - 2013 J@"org Wunsch +Copyright @copyright{} Brian S. Dean, J@"org Wunsch @sp 2 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}. -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{} 2003,2005 Brian S. Dean - -Copyright @copyright{} 2006 J@"org Wunsch +Copyright @copyright{} Brian S. Dean, J@"org Wunsch @end ifinfo @menu @@ -119,6 +110,7 @@ Copyright @copyright{} 2006 J@"org Wunsch * Programmer Specific Information:: * Platform Dependent Information:: * Troubleshooting:: +* Index:: @end menu @c @@ -127,7 +119,7 @@ Copyright @copyright{} 2006 J@"org Wunsch @node Introduction, Command Line Options, Top, Top @comment node-name, next, previous, up @chapter Introduction -@cindex introduction +@cindex Introduction AVRDUDE - AVR Downloader Uploader - is a program for downloading and 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, programming fuse/lock bits, etc. +@cindex Programmers supported + AVRDUDE supports the following basic programmer types: Atmel's STK500, Atmel's AVRISP and AVRISP mkII devices, Atmel's STK600, @@ -345,6 +339,7 @@ below for Teensy specific options. @c Node @c @node History, , Introduction, Introduction +@cindex History @section History and Credits 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 Windows programming software. -The AVRDUDE source now resides in the public CVS repository on -savannah.gnu.org (@url{http://savannah.gnu.org/projects/avrdude/}), -where it continues to be enhanced and ported to other systems. In +For many years, the AVRDUDE source resided in public repositories on +savannah.nongnu.org, +where it continued to be enhanced and ported to other systems. In addition to FreeBSD, AVRDUDE now runs on Linux and Windows. The developers behind the porting effort primarily were Ted Roth, Eric 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 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 @@ -374,7 +371,6 @@ Roth. @c @node Command Line Options, Terminal Mode Operation, Introduction, Top @chapter Command Line Options -@cindex options @menu * Option Descriptions:: @@ -386,6 +382,7 @@ Roth. @c Node @c @node Option Descriptions, Programmers accepting extended parameters, Command Line Options, Command Line Options +@cindex Options (command-line) @section Option Descriptions @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. Currently, the following MCU types are understood: +@cindex Device support + @multitable @columnfractions .15 .3 @include parts.texi @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. Currently, the following programmer ids are understood and supported: +@cindex Programmer support + @multitable @columnfractions .2 .6 @include programmers.texi @end multitable @@ -681,32 +682,6 @@ Posix systems (by now). Disable (or quell) output of the progress bar while reading or writing 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 Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up- or downloading files. See below for a detailed description of the @@ -864,7 +839,7 @@ accepting extended parameters. @c @node Programmers accepting extended parameters, Example Command Line Invocations, Option Descriptions, Command Line Options @section Programmers accepting extended parameters - +@cindex @code{-x} AVR Dragon @table @code @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. @end table +@cindex @code{-x} AVR910 @item AVR910 The AVR910 programmer type accepts the following extended parameter: @@ -901,13 +877,16 @@ Use programmer creates errors during initial sequence. @end table +@cindex @code{-x} Arduino @item Arduino The Arduino programmer type accepts the following extended parameter: @table @code @item @samp{attemps=VALUE} Overide the default number of connection retry attempt by using @var{VALUE}. +@end table +@cindex @code{-x} Buspirate @item BusPirate 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 +@cindex @code{-x} Micronucleus bootloader @item Micronucleus bootloader 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. @end table +@cindex @code{-x} Teensy bootloader @item Teensy bootloader 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. @end table +@cindex @code{-x} Wiring @item Wiring 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. @end table +@cindex @code{-x} PICkit2 @item PICkit2 Connection to the PICkit2 programmer: @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). @end table +@cindex @code{-x} USBasp @item USBasp Extended parameters: @table @code @@ -1062,6 +1046,7 @@ rather than entire chip. Only applicable to TPI devices (ATtiny 4/5/9/10/20/40). @end table +@cindex @code{-x} xbee @item xbee Extended parameters: @table @code @@ -1078,6 +1063,7 @@ The remaining two necessary XBee-to-MCU connections are not selectable the MCU's ‘TXD’ line. @end table +@cindex @code{-x} serialupdi @item serialupdi Extended parameters: @table @code @@ -1133,8 +1119,6 @@ Reading | ################################################## | 100% 6.83s avrdude: verifying ... avrdude: 19278 bytes of flash verified -avrdude: safemode: Fuses OK - avrdude done. Thank you. % @@ -1162,8 +1146,6 @@ Reading | ################################################## | 100% 46.10s avrdude: writing output file "c:/diag flash.bin" -avrdude: safemode: Fuses OK - avrdude done. Thank you. % @@ -1284,6 +1266,7 @@ commands can be recalled and edited. @end menu @node Terminal Mode Commands, Terminal Mode Examples, Terminal Mode Operation, Terminal Mode Operation +@cindex Terminal Mode @section Terminal Mode Commands @noindent @@ -1291,20 +1274,83 @@ The following commands are implemented: @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 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 previous dump command left off. -@item write @var{memtype} @var{addr} @var{byte1} @dots{} @var{byteN} -Manually program the respective memory cells, starting at address addr, -using the values @var{byte1} through @var{byteN}. This feature is not +@item write @var{memtype} @var{start_addr} @var{data1} @var{data2} @dots{} @var{dataN} +Manually program the respective memory cells, starting at address @var{start_addr}, +using the values @var{data1} through @var{dataN}. This feature is not implemented for bank-addressed memories such as the flash memory of 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 Perform a chip erase. @@ -1397,6 +1443,7 @@ Display the current target supply voltage and JTAG bit clock rate/period. @c Node @c @node Terminal Mode Examples, , Terminal Mode Commands, Terminal Mode Operation +@cindex Terminal Mode @section Terminal Mode Examples @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: Device signature = 0x1e9702 -avrdude: current erase-rewrite cycle count is 52 (if being tracked) avrdude> part >>> part @@ -1470,7 +1516,6 @@ display the factory defaults, then reprogram: avrdude: AVR device initialized and ready to accept instructions avrdude: Device signature = 0x1e9702 -avrdude: current erase-rewrite cycle count is 52 (if being tracked) avrdude> d efuse >>> d efuse 0000 fd |. | @@ -1496,11 +1541,56 @@ avrdude> @end cartouche @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 Node @c @node Configuration File, Programmer Specific Information, Terminal Mode Operation, Top +@cindex Configuration File +@cindex @code{avrdude.conf} @chapter Configuration File @noindent @@ -1845,9 +1935,6 @@ flash pages of the application section. Reading fuse and lock bits is fully supported. -Note that due to the inability to write the fuse bits, the safemode -functionality does not make sense for these boot loaders. - @end itemize @c @@ -1866,6 +1953,7 @@ functionality does not make sense for these boot loaders. @c Node @c @node Atmel STK600, Atmel DFU bootloader using FLIP version 1, Programmer Specific Information, Programmer Specific Information +@cindex STK600 @section Atmel STK600 @c @@ -1962,6 +2050,7 @@ least 4.5 V in order to work. This can be done using @c Node @c @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 Bootloaders using the FLIP protocol version 1 experience some very @@ -1990,6 +2079,7 @@ versions of the bootloader. @c Node @c @node SerialUPDI programmer, , Atmel DFU bootloader using FLIP version 1, Programmer Specific Information +@cindex SerialUPDI @section SerialUPDI programmer 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 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 and 2, but there is also experimental implementation of model 3 - not yet tested. @@ -2243,6 +2330,8 @@ configuration file will be always be @code{/etc/avrdude.conf}. @noindent 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. @multitable @columnfractions .30 .30 .30 @@ -2475,13 +2564,13 @@ such as @option{--prefix} and @option{--datadir}. @c @c Node @c -@node Troubleshooting, ,Platform Dependent Information ,Top +@node Troubleshooting,Index ,Platform Dependent Information ,Top @appendix Troubleshooting @noindent 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 @@ -2786,7 +2875,11 @@ erase cycle. @end itemize +@node Index, , Troubleshooting, Top +@unnumbered Concept Index + +@printindex cp @bye diff --git a/src/jtag3.c b/src/jtag3.c index b0815986..4e3ef8c2 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -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) { - 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); 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)) { /* 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]); } data += this_len; @@ -596,36 +596,36 @@ static int jtag3_edbg_signoff(PROGRAMMER * pgm) buf[1] = CMSISDAP_LED_CONNECT; buf[2] = 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); return -1; } rv = serial_recv(&pgm->fd, status, 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); return -1; } if (status[0] != CMSISDAP_CMD_LED || 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]); buf[0] = CMSISDAP_CMD_DISCONNECT; 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); return -1; } rv = serial_recv(&pgm->fd, status, 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); return -1; } if (status[0] != CMSISDAP_CMD_DISCONNECT || 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]); 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); 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); return -1; } 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); free(buf); return -1; @@ -706,7 +706,7 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) { request[0] = EDBG_VENDOR_AVR_RSP; if (serial_send(&pgm->fd, request, pgm->fd.usb.max_xfer) != 0) { - avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n", + avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): error sending CMSIS-DAP vendor command\n", progname); free(request); free(*msg); @@ -725,7 +725,7 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) { } 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]); free(*msg); free(request); @@ -736,7 +736,7 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) { // Documentation says: // "FragmentInfo 0x00 indicates that no response data is // available, and the rest of the packet is ignored." - avrdude_message(MSG_INFO, + avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): " "No response available\n", progname); @@ -752,7 +752,7 @@ static int jtag3_edbg_recv_frame(PROGRAMMER * pgm, unsigned char **msg) { thisfrag = 1; } else { if (nfrags != (buf[1] & 0x0F)) { - avrdude_message(MSG_INFO, + avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): " "Inconsistent # of fragments; had %d, now %d\n", 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)) { - avrdude_message(MSG_INFO, + avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): " "Inconsistent fragment number; expect %d, got %d\n", 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]; 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); thislen = rv + 4; } if (len + thislen > USBDEV_MAX_XFER_3) { - avrdude_message(MSG_INFO, "%s: jtag3_edbg_recv(): Length exceeds max size (%d > %d)\n", + avrdude_message(MSG_NOTICE, "%s: jtag3_edbg_recv(): Length exceeds max size (%d > %d)\n", progname, len + thislen, USBDEV_MAX_XFER_3); 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", progname); } 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); } status = (*resp)[3]; @@ -1129,7 +1129,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p) if (PDATA(pgm)->set_sck(pgm, parm) < 0) return -1; } - + jtag3_print_parms1(pgm, progbuf); if (conn == PARM3_CONN_JTAG) { 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); } else if (matches(m->desc, "lock")) { 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); } else if (strcmp(m->desc, "prodsig") == 0) { 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_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_base, m->offset); @@ -1269,7 +1271,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p) "xd->flash_page_size=%x\n\t" "xd->eeprom_page_size=%x\n\t" "xd->nvmctrl=%x %x\n\t" - "xd->ocd=%x %x\n\t", + "xd->ocd=%x %x\n\t" "xd->address_mode=%x\n", xd.prog_base_msb, xd.prog_base[0], xd.prog_base[1], @@ -1355,13 +1357,14 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p) if ((status = jtag3_command(pgm, cmd, 4, &resp, "AVR sign-on")) >= 0) break; - avrdude_message(MSG_INFO, "%s: retrying with external reset applied\n", + avrdude_message(MSG_NOTICE, "%s: retrying with external reset applied\n", progname); } if (use_ext_reset > 1) { - avrdude_message(MSG_INFO, "%s: JTAGEN fuse disabled?\n", progname); - return -1; + if(strcmp(pgm->type, "JTAGICE3") == 0 && p->flags & AVRPART_HAS_JTAG) + avrdude_message(MSG_INFO, "%s: JTAGEN fuse disabled?\n", progname); + return -1; } /* @@ -1689,9 +1692,10 @@ static int jtag3_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, cmd[3] = XMEGA_ERASE_BOOT_PAGE; } else if (strcmp(m->desc, "eeprom") == 0) { 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; - } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { + } else if (strcmp(m->desc, "boot") == 0) { cmd[3] = XMEGA_ERASE_BOOT_PAGE; } else { 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; 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; - } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { + } else if (strcmp(m->desc, "boot") == 0) { cmd[3] = MTYPE_BOOT_FLASH; } else if ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) { 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; if (pgm->flag & PGM_FL_IS_DW) return -1; - } else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) { + } else if (strcmp(m->desc, "prodsig") == 0) { 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; - } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { + } else if (strcmp(m->desc, "boot") == 0) { cmd[3] = MTYPE_BOOT_FLASH; } else if ( p->flags & AVRPART_HAS_PDI ) { cmd[3] = MTYPE_FLASH; @@ -1968,10 +1974,23 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, cmd[3] = MTYPE_FUSE_BITS; if (!(p->flags & AVRPART_HAS_UPDI)) 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; } else if (strcmp(mem->desc, "prodsig") == 0) { 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) { cmd[3] = MTYPE_OSCCAL_BYTE; 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; if (!(p->flags & AVRPART_HAS_UPDI)) 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; } else if (strcmp(mem->desc, "prodsig") == 0) { cmd[3] = MTYPE_PRODSIG; @@ -2232,7 +2252,7 @@ int jtag3_getparm(PROGRAMMER * pgm, unsigned char scope, c = resp[1]; 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", progname, descr); free(resp); @@ -2317,9 +2337,8 @@ static int jtag3_set_vtarget(PROGRAMMER * pgm, double v) utarg = (unsigned)(v * 1000); 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); - return -1; } 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", 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 0; } @@ -2368,14 +2390,12 @@ static void jtag3_display(PROGRAMMER * pgm, const char * p) memmove(resp, resp + 3, status - 3); resp[status - 3] = 0; - avrdude_message(MSG_INFO, "%sICE hardware version: %d\n", p, parms[0]); - avrdude_message(MSG_INFO, "%sICE firmware version: %d.%02d (rel. %d)\n", p, + avrdude_message(MSG_INFO, "%sICE HW version : %d\n", p, parms[0]); + avrdude_message(MSG_INFO, "%sICE FW version : %d.%02d (rel. %d)\n", p, parms[1], parms[2], (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); - - jtag3_print_parms1(pgm, p); } @@ -2386,28 +2406,40 @@ static void jtag3_print_parms1(PROGRAMMER * pgm, const char * p) if (jtag3_getparm(pgm, SCOPE_GENERAL, 1, PARM3_VTARGET, buf, 2) < 0) return; - avrdude_message(MSG_INFO, "%sVtarget : %.2f V\n", p, - b2_to_u16(buf) / 1000.0); + avrdude_message(MSG_INFO, "%sVtarget %s: %.2f V\n", p, + verbose ? "" : " ", b2_to_u16(buf) / 1000.0); if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0) return; - avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/program: %u kHz\n", p, - b2_to_u16(buf)); + + if (b2_to_u16(buf) > 0) { + avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/program : %u kHz\n", p, + b2_to_u16(buf)); + } if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0) return; - avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/debug: %u kHz\n", p, - b2_to_u16(buf)); + + if (b2_to_u16(buf) > 0) { + avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/debug : %u kHz\n", p, + b2_to_u16(buf)); + } if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0) return; - avrdude_message(MSG_INFO, "%sJTAG clock Xmega: %u kHz\n", p, - b2_to_u16(buf)); + + if (b2_to_u16(buf) > 0) { + avrdude_message(MSG_INFO, "%sJTAG clock Xmega : %u kHz\n", p, + b2_to_u16(buf)); + } if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0) return; - avrdude_message(MSG_INFO, "%sPDI clock Xmega : %u kHz\n", p, - b2_to_u16(buf)); + + if (b2_to_u16(buf) > 0) { + avrdude_message(MSG_INFO, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n\n", p, + b2_to_u16(buf)); + } } static void jtag3_print_parms(PROGRAMMER * pgm) @@ -2444,14 +2476,14 @@ static unsigned int jtag3_memaddr(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, uns * Non-Xmega device. */ if (p->flags & AVRPART_HAS_UPDI) { - if (strcmp(m->desc, "fuses") == 0) { - addr += m->offset; + if (strcmp(m->desc, "flash") == 0) { + return addr; } - else if (matches(m->desc, "fuse")) { - addr = m->offset; + else if (m->size == 1) { + addr = m->offset; } - else if (strcmp(m->desc, "flash") != 0) { - addr += m->offset; + else if (m->size > 1) { + addr += m->offset; } } return addr; diff --git a/src/jtagmkI.c b/src/jtagmkI.c index 2d4d83cd..7a97217b 100644 --- a/src/jtagmkI.c +++ b/src/jtagmkI.c @@ -1275,8 +1275,8 @@ static void jtagmkI_display(PROGRAMMER * pgm, const char * p) jtagmkI_getparm(pgm, PARM_SW_VERSION, &fw) < 0) return; - avrdude_message(MSG_INFO, "%sICE hardware version: 0x%02x\n", p, hw); - avrdude_message(MSG_INFO, "%sICE firmware version: 0x%02x\n", p, fw); + avrdude_message(MSG_INFO, "%sICE HW version: 0x%02x\n", p, hw); + avrdude_message(MSG_INFO, "%sICE FW version: 0x%02x\n", p, fw); jtagmkI_print_parms1(pgm, p); @@ -1320,9 +1320,9 @@ static void jtagmkI_print_parms1(PROGRAMMER * pgm, const char * p) clk = 1e6; } - avrdude_message(MSG_INFO, "%sVtarget : %.1f V\n", p, + avrdude_message(MSG_INFO, "%sVtarget : %.1f V\n", p, 6.25 * (unsigned)vtarget / 255.0); - avrdude_message(MSG_INFO, "%sJTAG clock : %s (%.1f us)\n", p, clkstr, + avrdude_message(MSG_INFO, "%sJTAG clock : %s (%.1f us)\n", p, clkstr, 1.0e6 / clk); return; diff --git a/src/jtagmkII.c b/src/jtagmkII.c index 2886642e..fc06301c 100644 --- a/src/jtagmkII.c +++ b/src/jtagmkII.c @@ -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); } else if (strncmp(m->desc, "lock", 4) == 0) { 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); } else if (strcmp(m->desc, "prodsig") == 0) { 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; } else if (strcmp(m->desc, "eeprom") == 0) { 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; - } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { + } else if (strcmp(m->desc, "boot") == 0) { cmd[1] = XMEGA_ERASE_BOOT_PAGE; } else { cmd[1] = XMEGA_ERASE_APP_PAGE; @@ -2044,13 +2046,14 @@ static int jtagmkII_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, free(cmd); return n_bytes; } - 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; - } else if ( ( strcmp(m->desc, "usersig") == 0 ) ) { + } else if (strcmp(m->desc, "usersig") == 0 || + strcmp(m->desc, "userrow") == 0) { cmd[1] = MTYPE_USERSIG; - } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { + } else if (strcmp(m->desc, "boot") == 0) { 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; } else { cmd[1] = MTYPE_SPM; @@ -2156,16 +2159,17 @@ static int jtagmkII_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, /* dynamically decide between flash/boot memtype */ dynamic_memtype = 1; } else if (strcmp(m->desc, "eeprom") == 0) { - cmd[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) return -1; - } else if ( ( strcmp(m->desc, "prodsig") == 0 ) ) { + } else if (strcmp(m->desc, "prodsig") == 0) { 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; - } else if ( ( strcmp(m->desc, "boot") == 0 ) ) { + } else if (strcmp(m->desc, "boot") == 0) { 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; } else { cmd[1] = MTYPE_SPM; @@ -2291,7 +2295,8 @@ static int jtagmkII_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsupp = 1; } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { 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; } else if (strcmp(mem->desc, "prodsig") == 0) { cmd[1] = MTYPE_PRODSIG; @@ -2460,7 +2465,8 @@ static int jtagmkII_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, unsupp = 1; } else if (strncmp(mem->desc, "fuse", strlen("fuse")) == 0) { 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; } else if (strcmp(mem->desc, "prodsig") == 0) { cmd[1] = MTYPE_PRODSIG; @@ -2688,11 +2694,11 @@ static void jtagmkII_display(PROGRAMMER * pgm, const char * p) jtagmkII_getparm(pgm, PAR_FW_VERSION, fw) < 0) return; - avrdude_message(MSG_INFO, "%sM_MCU hardware 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, "%sS_MCU hardware 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, "%sSerial number: %02x:%02x:%02x:%02x:%02x:%02x\n", + avrdude_message(MSG_INFO, "%sM_MCU HW version: %d\n", p, hw[0]); + avrdude_message(MSG_INFO, "%sM_MCU FW version: %d.%02d\n", p, fw[1], fw[0]); + avrdude_message(MSG_INFO, "%sS_MCU HW version: %d\n", p, hw[1]); + 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", 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]); jtagmkII_print_parms1(pgm, p); diff --git a/src/lexer.l b/src/lexer.l index 2e27a5d4..0b31eb21 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -117,6 +117,7 @@ SIGN [+-] \n { yyerror("unterminated character constant"); return YYERRCODE; } +alias { yylval=NULL; return K_ALIAS; } allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; } avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; } 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_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; } default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; } -default_safemode { yylval=NULL; return K_DEFAULT_SAFEMODE; } default_serial { yylval=NULL; return K_DEFAULT_SERIAL; } delay { yylval=NULL; return K_DELAY; } desc { yylval=NULL; return K_DESC; } diff --git a/src/libavrdude.h b/src/libavrdude.h index eebdf5a9..ddb72b48 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -261,6 +261,7 @@ typedef struct avrpart { OPCODE * op[AVR_OP_MAX]; /* opcodes */ LISTID mem; /* avr memory definitions */ + LISTID mem_alias; /* memory alias definitions */ char config_file[PATH_MAX]; /* config file where defined */ int lineno; /* config file line number */ } AVRPART; @@ -292,6 +293,11 @@ typedef struct avrmem { OPCODE * op[AVR_OP_MAX]; /* opcodes */ } AVRMEM; +typedef struct avrmem_alias { + char desc[AVR_MEMDESCLEN]; /* alias name ("syscfg0" etc.) */ + AVRMEM *aliased_mem; +} AVRMEM_ALIAS; + #ifdef __cplusplus extern "C" { #endif @@ -307,10 +313,15 @@ int avr_get_output_index(OPCODE * op); /* Functions for AVRMEM structures */ AVRMEM * avr_new_memtype(void); +AVRMEM_ALIAS * avr_new_memalias(void); int avr_initmem(AVRPART * p); AVRMEM * avr_dup_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_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, int type, int verbose); @@ -831,30 +842,6 @@ int fileio(int op, char * filename, FILEFMT format, #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 */ enum { @@ -926,7 +913,6 @@ extern char default_programmer[]; extern char default_parallel[]; extern char default_serial[]; extern double default_bitclock; -extern int default_safemode; /* This name is fixed, it's only here for symmetry with * default_parallel and default_serial. */ diff --git a/src/linuxspi.c b/src/linuxspi.c index d0912e1a..df497057 100644 --- a/src/linuxspi.c +++ b/src/linuxspi.c @@ -223,7 +223,7 @@ static int linuxspi_open(PROGRAMMER *pgm, char *port) avrdude_message(MSG_INFO, "%s: obsolete use of -b option for bit clock; use -B \n", progname); - pgm->bitclock = 1E6 / pgm->baudrate; + pgm->bitclock = 1.0 / pgm->baudrate; } if (pgm->bitclock == 0) { avrdude_message(MSG_NOTICE, diff --git a/src/main.c b/src/main.c index 35cdb1d5..253c6e51 100644 --- a/src/main.c +++ b/src/main.c @@ -122,9 +122,6 @@ static void usage(void) " is performed in the order specified.\n" " -n Do not write anything to the device.\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" " -E [,] List programmer exit specifications.\n" " -x Pass to programmer.\n" @@ -349,19 +346,11 @@ int main(int argc, char * argv []) int baudrate; /* override default programmer baud rate */ double bitclock; /* Specify programmer bit clock (JTAG ICE) */ 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 is_open; /* Device open succeeded */ char * logfile; /* Use logfile rather than stderr for diagnostics */ 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) char * homedir; #endif @@ -394,7 +383,6 @@ int main(int argc, char * argv []) default_parallel[0] = 0; default_serial[0] = 0; default_bitclock = 0.0; - default_safemode = -1; init_config(); @@ -434,8 +422,6 @@ int main(int argc, char * argv []) baudrate = 0; bitclock = 0.0; ispdelay = 0; - safemode = 1; /* Safemode on by default */ - silentsafe = 0; /* Ask by default */ is_open = 0; logfile = NULL; @@ -581,17 +567,13 @@ int main(int argc, char * argv []) quell_progress++ ; break; - case 's' : /* Silent safemode */ - silentsafe = 1; - safemode = 1; - break; - case 't': /* enter terminal mode */ terminal = 1; break; - case 'u' : /* Disable safemode */ - safemode = 0; + case 'u': + avrdude_message(MSG_INFO, "%s: \"safemode\" feature no longer supported\n", + progname); break; 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) { 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 ((p->flags & AVRPART_HAS_PDI) && pgm->page_erase != NULL && 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: /* diff --git a/src/micronucleus.c b/src/micronucleus.c index b3c25341..c3dd007d 100644 --- a/src/micronucleus.c +++ b/src/micronucleus.c @@ -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) { struct usb_device* device = usb_device(pdata->usb_handle); @@ -696,6 +712,7 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port) usb_init(); bool show_retry_message = true; + bool show_unresponsive_device_message = true; time_t start_time = time(NULL); for (;;) @@ -717,6 +734,19 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port) pdata->major_version = (uint8_t)(device->descriptor.bcdDevice >> 8); 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", progname, pdata->major_version, pdata->minor_version, diff --git a/src/safemode.c b/src/safemode.c deleted file mode 100644 index 41012c12..00000000 --- a/src/safemode.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * avrdude - A Downloader/Uploader for AVR device programmers - * avrdude is Copyright (C) 2000-2004 Brian S. Dean - * - * This file: Copyright (C) 2005-2007 Colin O'Flynn - * - * 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 . - */ - - -#include - -#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; -} diff --git a/src/ser_avrdoper.c b/src/ser_avrdoper.c index 2e90f0eb..a8414403 100644 --- a/src/ser_avrdoper.c +++ b/src/ser_avrdoper.c @@ -26,11 +26,12 @@ #include "ac_cfg.h" -#if defined(HAVE_LIBHIDAPI) || (defined(WIN32) && defined(HAVE_LIBHID)) +#if defined(HAVE_LIBHIDAPI) #include #include #include +#include #include "avrdude.h" #include "libavrdude.h" @@ -64,12 +65,6 @@ static int avrdoperRxPosition = 0; /* amount of bytes already consu /* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */ -#if defined(HAVE_LIBHIDAPI) - -#include - -/* ------------------------------------------------------------------------- */ - static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName, 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 -#include -#include -#include - -#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, }; -#endif /* defined(HAVE_LIBHIDAPI) || (defined(WIN32) && defined(HAVE_LIBHID)) */ +#endif /* defined(HAVE_LIBHIDAPI) */ diff --git a/src/ser_posix.c b/src/ser_posix.c index 96d665f0..2c5d45b5 100644 --- a/src/ser_posix.c +++ b/src/ser_posix.c @@ -28,6 +28,7 @@ #include "ac_cfg.h" #include +#include #include #include #include @@ -42,6 +43,10 @@ #include #include +#ifdef __APPLE__ +# include +#endif + #include "avrdude.h" #include "libavrdude.h" @@ -78,10 +83,12 @@ static struct baud_mapping baud_lookup_table [] = { static struct termios 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; + *nonstandard = false; + while (map->baud) { if (map->baud == baud) return map->speed; @@ -92,30 +99,20 @@ static speed_t serial_baud_lookup(long baud) * If a non-standard BAUD rate is used, issue * 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); - return baud; -} + *nonstandard = true; -static tcflag_t translate_flags(unsigned long cflags) -{ - 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) ; + return baud; } static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cflags) { int rc; struct termios termios; - speed_t speed = serial_baud_lookup (baud); + bool nonstandard; + speed_t speed = serial_baud_lookup (baud, &nonstandard); if (!isatty(fd->ifd)) return -ENOTTY; @@ -137,15 +134,86 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla original_termios = termios; } - termios.c_iflag = IGNBRK; - termios.c_oflag = 0; - termios.c_lflag = 0; - termios.c_cflag = translate_flags(cflags); - termios.c_cc[VMIN] = 1; - termios.c_cc[VTIME] = 0; + if (cflags & SERIAL_CREAD) { + termios.c_cflag |= CREAD; + } + if (cflags & SERIAL_CLOCAL) { + termios.c_cflag |= CLOCAL; + } + 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); + 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 */ - cfsetospeed(&termios, speed); - cfsetispeed(&termios, speed); rc = tcsetattr(fd->ifd, TCSANOW, &termios); if (rc < 0) { @@ -154,14 +222,19 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla return -errno; } - /* - * Everything is now set up for a local line without modem control - * or flow control, so clear O_NONBLOCK again. - */ - rc = fcntl(fd->ifd, F_GETFL, 0); - if (rc != -1) - fcntl(fd->ifd, F_SETFL, rc & ~O_NONBLOCK); +#ifdef __APPLE__ + // handle nonstandard speed values the MacOS way + if (nonstandard) { + if (ioctl(fd->ifd, IOSSIOSPEED, &speed) < 0) { + avrdude_message(MSG_INFO, "%s: ser_setparams(): ioctrl(IOSSIOSPEED) failed\n", + progname); + return -errno; + } + } +#endif // __APPLE__ + tcflush(fd->ifd, TCIFLUSH); + return 0; } @@ -520,3 +593,4 @@ struct serial_device serial_serdev = struct serial_device *serdev = &serial_serdev; #endif /* WIN32 */ + diff --git a/src/stk500v2.c b/src/stk500v2.c index 11aa9a94..523d6539 100644 --- a/src/stk500v2.c +++ b/src/stk500v2.c @@ -1613,11 +1613,11 @@ static int stk500v2_open(PROGRAMMER * pgm, char * port) PDATA(pgm)->pgmtype = PGMTYPE_UNKNOWN; if(strcasecmp(port, "avrdoper") == 0){ -#if defined(HAVE_LIBHIDAPI) || (defined(WIN32) && defined(HAVE_LIBHID)) +#if defined(HAVE_LIBHIDAPI) serdev = &avrdoper_serdev; PDATA(pgm)->pgmtype = PGMTYPE_STK500; #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; #endif } @@ -3869,7 +3869,8 @@ static int stk600_xprog_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, * fuses. */ 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; } else { 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 || strcmp(mem->desc, "prodsig") == 0) { 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; } else { 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 || strcmp(mem->desc, "prodsig") == 0) { 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; } else { 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) { memtype = XPRG_MEM_TYPE_FACTORY_CALIBRATION; 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; writemode = (1 << XPRG_MEM_WRITE_WRITE); } else { @@ -4290,7 +4294,8 @@ static int stk600_xprog_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, b[1] = XPRG_ERASE_BOOT_PAGE; } else if (strcmp(m->desc, "eeprom") == 0) { 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; } else { avrdude_message(MSG_INFO, "%s: stk600_xprog_page_erase(): unknown paged memory \"%s\"\n", diff --git a/src/term.c b/src/term.c index 5c91931c..dc771273 100644 --- a/src/term.c +++ b/src/term.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -97,8 +98,8 @@ struct command cmd[] = { { "sig", cmd_sig, "display device signature bytes" }, { "part", cmd_part, "display the current part information" }, { "send", cmd_send, "send a raw command : %s " }, - { "parms", cmd_parms, "display adjustable parameters (STK500 only)" }, - { "vtarg", cmd_vtarg, "set (STK500 only)" }, + { "parms", cmd_parms, "display adjustable parameters (STK500 and Curiosity Nano only)" }, + { "vtarg", cmd_vtarg, "set (STK500 and Curiosity Nano only)" }, { "varef", cmd_varef, "set (STK500 only)" }, { "fosc", cmd_fosc, "set (STK500 only)" }, { "sck", cmd_sck, "set (STK500 only)" }, @@ -125,9 +126,15 @@ static int nexttok(char * buf, char ** tok, char ** next) q++; /* isolate first token */ - n = q+1; - while (*n && !isspace((int)*n)) + n = q; + uint8_t quotes = 0; + while (*n && (!isspace((int)*n) || quotes)) { + if (*n == '\"') + quotes++; + else if (isspace((int)*n) && *(n-1) == '\"') + break; n++; + } if (*n) { *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) { char * hexdata = "0123456789abcdef"; - char * b; - int i, j; + char * b = buffer; + int32_t i = 0; + int32_t j = 0; - b = buffer; - - j = 0; for (i=0; i len) n = len; hexdump_line(dst1, p, n, 48); @@ -229,92 +231,99 @@ static int hexdump_buf(FILE * f, int startaddr, unsigned char * buf, int len) static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, int argc, char * argv[]) { - static char prevmem[128] = {0}; - char * e; - unsigned char * buf; - int maxsize; - unsigned long i; - static unsigned long addr=0; - static int len=64; - AVRMEM * mem; - char * memtype = NULL; - int rc; - - if (!((argc == 2) || (argc == 4))) { - avrdude_message(MSG_INFO, "Usage: dump [ ]\n"); - return -1; + if (argc < 2) { + avrdude_message(MSG_INFO, "Usage: %s [ ]\n" + " %s [ <...>]\n" + " %s <...>\n" + " %s \n", + argv[0], argv[0], argv[0], argv[0]); + return -1; } - memtype = argv[1]; - - if (strncmp(prevmem, memtype, strlen(memtype)) != 0) { - addr = 0; - len = 64; - strncpy(prevmem, memtype, sizeof(prevmem)-1); - prevmem[sizeof(prevmem)-1] = 0; - } - - mem = avr_locate_mem(p, memtype); + enum { read_size = 256 }; + static char prevmem[128] = {0x00}; + char * memtype = argv[1]; + AVRMEM * mem = avr_locate_mem(p, memtype); if (mem == NULL) { avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n", memtype, p->desc); return -1; } + uint32_t maxsize = mem->size; + // Get start address if present + char * end_ptr; + static uint32_t addr = 0; if (argc == 4) { - addr = strtoul(argv[2], &e, 0); - if (*e || (e == argv[2])) { - avrdude_message(MSG_INFO, "%s (dump): can't parse address \"%s\"\n", - progname, argv[2]); + addr = strtoul(argv[2], &end_ptr, 0); + if (*end_ptr || (end_ptr == argv[2])) { + avrdude_message(MSG_INFO, "%s (%s): can't parse address \"%s\"\n", + progname, argv[0], argv[2]); return -1; - } - - len = strtol(argv[3], &e, 0); - if (*e || (e == argv[3])) { - avrdude_message(MSG_INFO, "%s (dump): can't parse length \"%s\"\n", - progname, argv[3]); + } else if (addr >= maxsize) { + avrdude_message(MSG_INFO, "%s (%s): address 0x%05lx is out of range for %s memory\n", + progname, argv[0], addr, mem->desc); return -1; } } - maxsize = mem->size; - - if (addr >= maxsize) { - if (argc == 2) { - /* wrap around */ + // Get no. bytes to read if present + static int32_t len = read_size; + if (argc >= 3) { + memset(prevmem, 0x00, sizeof(prevmem)); + if (strcmp(argv[argc - 1], "...") == 0) { + if (argc == 3) + addr = 0; + len = maxsize - addr; + } else if (argc == 4) { + len = strtol(argv[3], &end_ptr, 0); + 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; + } + } 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; } - else { - avrdude_message(MSG_INFO, "%s (dump): address 0x%05lx is out of range for %s memory\n", - progname, addr, mem->desc); - return -1; - } + 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) len = maxsize - addr; - buf = malloc(len); + uint8_t * buf = malloc(len); if (buf == NULL) { avrdude_message(MSG_INFO, "%s (dump): out of memory\n", progname); return -1; } - for (i=0; iread_byte(pgm, p, mem, addr+i, &buf[i]); + report_progress(0, 1, "Reading"); + for (uint32_t i = 0; i < len; i++) { + int32_t rc = pgm->read_byte(pgm, p, mem, addr + i, &buf[i]); if (rc != 0) { 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); if (rc == -1) avrdude_message(MSG_INFO, "read operation not supported on memory type \"%s\"\n", mem->desc); return -1; } + report_progress(i, len, NULL); } + report_progress(1, 1, NULL); hexdump_buf(stdout, addr, buf, len); - fprintf(stdout, "\n"); free(buf); @@ -328,35 +337,31 @@ static int cmd_dump(PROGRAMMER * pgm, struct avrpart * p, static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, 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) { - avrdude_message(MSG_INFO, "Usage: write " - " ... \n"); + avrdude_message(MSG_INFO, + "Usage: write \n" + " write <...>\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; } - memtype = argv[1]; - - mem = avr_locate_mem(p, memtype); + int32_t i; + uint8_t write_mode; // Operation mode, "standard" or "fill" + 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) { avrdude_message(MSG_INFO, "\"%s\" memory type not defined for part \"%s\"\n", memtype, p->desc); return -1; } + uint32_t maxsize = mem->size; - maxsize = mem->size; - - addr = strtoul(argv[2], &e, 0); - if (*e || (e == argv[2])) { + char * end_ptr; + int32_t addr = strtoul(argv[2], &end_ptr, 0); + if (*end_ptr || (end_ptr == argv[2])) { avrdude_message(MSG_INFO, "%s (write): can't parse address \"%s\"\n", progname, argv[2]); return -1; @@ -368,61 +373,228 @@ static int cmd_write(PROGRAMMER * pgm, struct avrpart * p, return -1; } - /* number of bytes to write at the specified address */ - len = argc - 3; - - 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); + // Allocate a buffer guaranteed to be large enough + uint8_t * buf = calloc(mem->size + 0x10 + strlen(argv[argc - 2]), sizeof(uint8_t)); if (buf == NULL) { avrdude_message(MSG_INFO, "%s (write): out of memory\n", progname); return -1; } - for (i=3; ierr_led(pgm, OFF); - for (werror=0, i=0; i 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) { avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx, rc=%d\n", progname, buf[i], addr+i, rc); if (rc == -1) avrdude_message(MSG_INFO, "write operation not supported on memory type \"%s\"\n", mem->desc); - werror = 1; + werror = true; } + uint8_t b; rc = pgm->read_byte(pgm, p, mem, addr+i, &b); if (b != buf[i]) { avrdude_message(MSG_INFO, "%s (write): error writing 0x%02x at 0x%05lx cell=0x%02x\n", progname, buf[i], addr+i, b); - werror = 1; + werror = true; } if (werror) { pgm->err_led(pgm, ON); } + + report_progress(i, (len + data.bytes_grown), NULL); } + report_progress(1, 1, NULL); free(buf); - fprintf(stdout, "\n"); - return 0; } diff --git a/src/term.h b/src/term.h index fca3aac8..f114d4b0 100644 --- a/src/term.h +++ b/src/term.h @@ -27,6 +27,11 @@ extern "C" { #endif +typedef enum { + WRITE_MODE_STANDARD = 0, + WRITE_MODE_FILL = 1, +} mode; + int terminal_mode(PROGRAMMER * pgm, struct avrpart * p); char * terminal_get_input(const char *prompt); diff --git a/src/update.c b/src/update.c index e6360896..15002549 100644 --- a/src/update.c +++ b/src/update.c @@ -227,6 +227,13 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f 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) { /* * 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; } if (quell_progress < 2) { - avrdude_message(MSG_INFO, "%s: reading %s memory:\n", - progname, mem->desc); + avrdude_message(MSG_INFO, "%s: reading %s%s memory:\n", + progname, mem->desc, alias_mem_desc); } report_progress(0,1,"Reading"); rc = avr_read(pgm, p, upd->memtype, 0); if (rc < 0) { - avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n", - progname, mem->desc, rc); + avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n", + progname, mem->desc, alias_mem_desc, rc); return -1; } 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 */ if (quell_progress < 2) { - avrdude_message(MSG_INFO, "%s: writing %s (%d bytes):\n", - progname, mem->desc, size); + avrdude_message(MSG_INFO, "%s: writing %s%s (%d bytes):\n", + progname, mem->desc, alias_mem_desc, size); } if (!(flags & UF_NOWRITE)) { @@ -306,16 +313,16 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f } if (rc < 0) { - avrdude_message(MSG_INFO, "%s: failed to write %s memory, rc=%d\n", - progname, mem->desc, rc); + avrdude_message(MSG_INFO, "%s: failed to write %s%s memory, rc=%d\n", + progname, mem->desc, alias_mem_desc, rc); return -1; } vsize = rc; if (quell_progress < 2) { - avrdude_message(MSG_INFO, "%s: %d bytes of %s written\n", progname, - vsize, mem->desc); + avrdude_message(MSG_INFO, "%s: %d bytes of %s%s written\n", progname, + 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); if (quell_progress < 2) { - avrdude_message(MSG_INFO, "%s: verifying %s memory against %s:\n", - progname, mem->desc, upd->filename); + avrdude_message(MSG_INFO, "%s: verifying %s%s memory against %s:\n", + progname, mem->desc, alias_mem_desc, upd->filename); - avrdude_message(MSG_NOTICE2, "%s: load data %s data from input file %s:\n", - progname, mem->desc, upd->filename); + avrdude_message(MSG_NOTICE2, "%s: load data %s%s data from input file %s:\n", + progname, mem->desc, alias_mem_desc, upd->filename); } 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) { avrdude_message(MSG_NOTICE2, "%s: input file %s contains %d bytes\n", progname, upd->filename, size); - avrdude_message(MSG_NOTICE2, "%s: reading on-chip %s data:\n", - progname, mem->desc); + avrdude_message(MSG_NOTICE2, "%s: reading on-chip %s%s data:\n", + progname, mem->desc, alias_mem_desc); } report_progress (0,1,"Reading"); rc = avr_read(pgm, p, upd->memtype, v); if (rc < 0) { - avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n", - progname, mem->desc, rc); + avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n", + progname, mem->desc, alias_mem_desc, rc); pgm->err_led(pgm, ON); avr_free_part(v); return -1; @@ -375,8 +382,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f } if (quell_progress < 2) { - avrdude_message(MSG_INFO, "%s: %d bytes of %s verified\n", - progname, rc, mem->desc); + avrdude_message(MSG_INFO, "%s: %d bytes of %s%s verified\n", + progname, rc, mem->desc, alias_mem_desc); } pgm->vfy_led(pgm, OFF); diff --git a/src/updi_link.c b/src/updi_link.c index f87f8a83..1f179398 100644 --- a/src/updi_link.c +++ b/src/updi_link.c @@ -53,7 +53,7 @@ static void updi_set_rtsdtr_mode(PROGRAMMER* pgm) static int updi_physical_open(PROGRAMMER* pgm, int baudrate, unsigned long cflags) { - serial_recv_timeout = 100; + serial_recv_timeout = 1000; union pinfo pinfo; pinfo.serialinfo.baud = baudrate; @@ -155,12 +155,19 @@ static int updi_physical_send_double_break(PROGRAMMER * pgm) serial_send(&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) { return -1; } updi_set_rtsdtr_mode(pgm); + /* + * drain any extraneous input + */ + serial_drain(&pgm->fd, 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) { + unsigned char init_buffer[1]; + if (updi_physical_open(pgm, pgm->baudrate? pgm->baudrate: 115200, SERIAL_8E2) < 0) { 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) diff --git a/src/usb_hidapi.c b/src/usb_hidapi.c index d23c628e..5ceca60a 100644 --- a/src/usb_hidapi.c +++ b/src/usb_hidapi.c @@ -291,7 +291,7 @@ static int usbhid_recv(union filedescriptor *fd, unsigned char *buf, size_t nbyt if (udev == NULL) return -1; - rv = i = hid_read_timeout(udev, buf, nbytes, 300); + rv = i = hid_read_timeout(udev, buf, nbytes, 10000); if (i != nbytes) avrdude_message(MSG_INFO, "%s: Short read, read only %d out of %u bytes\n",