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 e3d6f8dd..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() # ------------------------------------- @@ -212,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 f2ec51a2..78f59f95 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,39 @@ 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 + - [bug #43898] atmega644p remains stopped after JTAG transaction #366 + + * 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 + - Dragon JTAG fix #979 + - adding support for all Linux baud rates v.2 #993 + - Replace internal knowledge in jtag3.c by a public API #996 + - JTAG3 UPDI EEPROM fix #1013 + - Treat x bits in .conf SPI commands as 0 #943 + - Fix avrftdi support for ATmega2560 et al #474 + - Fix avrdude.conf timings for ATmega328PB and other parts #976 + + * Internals: + +Changes in version 7.0: * Major changes compared to the previous version: @@ -52,6 +84,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: @@ -88,6 +122,9 @@ Changes since version 6.4: 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: @@ -175,6 +212,8 @@ Changes since version 6.4: - 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: 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 a8e0262b..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() # ===================================== @@ -216,6 +214,7 @@ add_library(libavrdude xbee.c ${FLEX_Parser_OUTPUTS} ${BISON_Parser_OUTPUTS} + "${EXTRA_WINDOWS_SOURCES}" ) set_target_properties(libavrdude PROPERTIES @@ -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,8 +263,8 @@ 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 "${CMAKE_CURRENT_BINARY_DIR}/avrdude.conf" TYPE SYSCONF) diff --git a/src/avr.c b/src/avr.c index a6d621b7..7f91e9a1 100644 --- a/src/avr.c +++ b/src/avr.c @@ -234,7 +234,7 @@ int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (readop == NULL) { #if DEBUG - avrdude_message(MSG_INFO, "avr_read_byte(): operation not supported on memory type \"%s\"\n", + avrdude_message(MSG_INFO, "avr_read_byte_default(): operation not supported on memory type \"%s\"\n", mem->desc); #endif return -1; @@ -450,16 +450,16 @@ int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, (vmem->tags[i] & TAG_ALLOCATED) != 0) { rc = pgm->read_byte(pgm, p, mem, i, mem->buf + i); - if (rc != 0) { + if (rc != LIBAVRDUDE_SUCCESS) { avrdude_message(MSG_INFO, "avr_read(): error reading address 0x%04lx\n", i); - if (rc == -1) { + if (rc == LIBAVRDUDE_GENERAL_FAILURE) { avrdude_message(MSG_INFO, " read operation not supported for memory \"%s\"\n", memtype); - return -2; + return LIBAVRDUDE_NOTSUPPORTED; } avrdude_message(MSG_INFO, " read operation failed for memory \"%s\"\n", memtype); - return rc; + return LIBAVRDUDE_SOFTFAIL; } } report_progress(i, mem->size, NULL); @@ -655,7 +655,7 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, if (writeop == NULL) { #if DEBUG - avrdude_message(MSG_INFO, "avr_write_byte(): write not supported for memory type \"%s\"\n", + avrdude_message(MSG_INFO, "avr_write_byte_default(): write not supported for memory type \"%s\"\n", mem->desc); #endif return -1; @@ -1040,14 +1040,14 @@ int avr_signature(PROGRAMMER * pgm, AVRPART * p) report_progress (0,1,"Reading"); rc = avr_read(pgm, p, "signature", 0); - if (rc < 0) { + if (rc < LIBAVRDUDE_SUCCESS) { avrdude_message(MSG_INFO, "%s: error reading signature data for part \"%s\", rc=%d\n", progname, p->desc, rc); return rc; } report_progress (1,1,NULL); - return 0; + return LIBAVRDUDE_SUCCESS; } static uint8_t get_fuse_bitmask(AVRMEM * m) { diff --git a/src/avrdude.1 b/src/avrdude.1 index 48082d00..c4fc850f 100644 --- a/src/avrdude.1 +++ b/src/avrdude.1 @@ -18,7 +18,7 @@ .\" .\" $Id$ .\" -.Dd DATE April 28, 2022 +.Dd July 12, 2022 .Os .Dt AVRDUDE 1 .Sh NAME diff --git a/src/avrdude.conf.in b/src/avrdude.conf.in index 096751d0..1728497f 100644 --- a/src/avrdude.conf.in +++ b/src/avrdude.conf.in @@ -593,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"; @@ -915,9 +947,10 @@ programmer ; # commercial version of USBtiny, using a separate VID/PID +# https://github.com/IowaScaledEngineering/ckt-avrprogrammer programmer id = "iseavrprog"; - desc = "USBtiny-based USB programmer, https://github.com/IowaScaledEngineering/ckt-avrprogrammer"; + desc = "USBtiny-based programmer, https://iascaled.com"; type = "usbtiny"; connection_type = usb; usbvid = 0x1209; @@ -4741,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; ; + ; #------------------------------------------------------------ @@ -5728,6 +5824,8 @@ part memory "efuse" size = 1; + min_write_delay = 2000; + max_write_delay = 2000; 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"; @@ -5907,7 +6005,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"; @@ -6161,7 +6259,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"; @@ -8118,6 +8216,7 @@ part parent "m48" id = "m48pb"; desc = "ATmega48PB"; signature = 0x1e 0x92 0x10; + chip_erase_delay = 10500; ; #------------------------------------------------------------ @@ -8345,6 +8444,7 @@ part parent "m88" id = "m88pb"; desc = "ATmega88PB"; signature = 0x1e 0x93 0x16; + chip_erase_delay = 10500; ; #------------------------------------------------------------ @@ -8574,6 +8674,7 @@ part parent "m168" id = "m168pb"; desc = "ATmega168PB"; signature = 0x1e 0x94 0x15; + chip_erase_delay = 10500; ; #------------------------------------------------------------ @@ -8846,7 +8947,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", @@ -8854,8 +8955,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; @@ -9033,7 +9134,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", @@ -9041,8 +9142,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; @@ -9730,6 +9831,7 @@ part parent "m328" id = "m328pb"; desc = "ATmega328PB"; signature = 0x1e 0x95 0x16; + chip_erase_delay = 10500; memory "efuse" size = 1; @@ -9757,6 +9859,8 @@ part parent "m328" memory "efuse" size = 1; + min_write_delay = 4500; + max_write_delay = 4500; 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"; write = "1 0 1 0 1 1 0 0 1 0 1 0 0 1 0 0", @@ -9777,8 +9881,37 @@ part parent "m328" 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" @@ -9786,6 +9919,40 @@ part parent "m328" 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" @@ -10259,7 +10426,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"; @@ -12127,7 +12294,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; @@ -12319,8 +12486,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; @@ -12621,7 +12788,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"; @@ -12690,6 +12857,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; ; @@ -12728,7 +12897,7 @@ 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"; ; @@ -12803,23 +12972,23 @@ part readback_p1 = 0x00; readback_p2 = 0x00; read = " 1 0 1 0 0 0 0 0", - " x x x x x a10 a9 a8", + " 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 a10 a9 a8", + " 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 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", + " 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; @@ -13005,12 +13174,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; @@ -13404,7 +13573,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"; @@ -16463,28 +16632,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; diff --git a/src/avrftdi.c b/src/avrftdi.c index e41d775e..f0c07a6a 100644 --- a/src/avrftdi.c +++ b/src/avrftdi.c @@ -917,8 +917,19 @@ static int avrftdi_chip_erase(PROGRAMMER * pgm, AVRPART * p) static int avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, unsigned int address) { + /* nothing to do if load extended address command unavailable */ + if(m->op[AVR_OP_LOAD_EXT_ADDR] == NULL) + return 0; + + avrftdi_t *pdata = to_pdata(pgm); unsigned char buf[] = { 0x00, 0x00, 0x00, 0x00 }; + /* only send load extended address command if high byte changed */ + if(pdata->lext_byte == (uint8_t) (address>>16)) + return 0; + + pdata->lext_byte = (uint8_t) (address>>16); + avr_set_bits(m->op[AVR_OP_LOAD_EXT_ADDR], buf); avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], buf, address); @@ -983,8 +994,6 @@ static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned int page_size, unsigned int addr, unsigned int len) { - int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; - unsigned int word; unsigned int poll_index; @@ -1013,22 +1022,12 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, page_size = m->page_size; - /* if we do cross a 64k word boundary (or write the - * first page), we need to issue a 'load extended - * address byte' command, which is defined as 0x4d - * 0x00
0x00. As far as i know, this - * is only available on 256k parts. 64k word is 128k - * bytes. - * write the command only once. - */ - if(use_lext_address && (((addr/2) & 0xffff0000))) { - if (0 > avrftdi_lext(pgm, p, m, addr/2)) - return -1; - } + /* on large-flash devices > 128k issue extended address command when needed */ + if(avrftdi_lext(pgm, p, m, addr/2) < 0) + return -1; /* prepare the command stream for the whole page */ - /* addr is in bytes, but we program in words. addr/2 should be something - * like addr >> WORD_SHIFT, though */ + /* addr is in bytes, but we program in words. */ for(word = addr/2; word < (len + addr)/2; word++) { log_debug("-< bytes = %d of %d\n", word * 2, len + addr); @@ -1107,8 +1106,6 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, { OPCODE * readop; int byte, word; - int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL; - unsigned int address = addr/2; unsigned int buf_size = 4 * len + 4; unsigned char* o_buf = alloca(buf_size); @@ -1128,10 +1125,8 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, return -1; } - if(use_lext_address && ((address & 0xffff0000))) { - if (0 > avrftdi_lext(pgm, p, m, address)) - return -1; - } + if(avrftdi_lext(pgm, p, m, addr/2) < 0) + return -1; /* word addressing! */ for(word = addr/2, index = 0; word < (addr + len)/2; word++) @@ -1210,7 +1205,11 @@ avrftdi_setup(PROGRAMMER * pgm) { avrftdi_t* pdata; - pgm->cookie = malloc(sizeof(avrftdi_t)); + + if(!(pgm->cookie = calloc(sizeof(avrftdi_t), 1))) { + log_err("Error allocating memory.\n"); + exit(1); + } pdata = to_pdata(pgm); pdata->ftdic = ftdi_new(); @@ -1224,6 +1223,7 @@ avrftdi_setup(PROGRAMMER * pgm) pdata->pin_value = 0; pdata->pin_direction = 0; pdata->led_mask = 0; + pdata->lext_byte = 0xff; } static void diff --git a/src/avrftdi_private.h b/src/avrftdi_private.h index 3c965ed8..15b9caec 100644 --- a/src/avrftdi_private.h +++ b/src/avrftdi_private.h @@ -81,6 +81,8 @@ typedef struct avrftdi_s { int tx_buffer_size; /* use bitbanging instead of mpsse spi */ bool use_bitbanging; + /* bits 16-23 of extended 24-bit word flash address for parts with flash > 128k */ + uint8_t lext_byte; } avrftdi_t; void avrftdi_log(int level, const char * func, int line, const char * fmt, ...); diff --git a/src/avrpart.c b/src/avrpart.c index dc6def44..fdff0f78 100644 --- a/src/avrpart.c +++ b/src/avrpart.c @@ -82,11 +82,11 @@ int avr_set_bits(OPCODE * op, unsigned char * cmd) unsigned char mask; for (i=0; i<32; i++) { - if (op->bit[i].type == AVR_CMDBIT_VALUE) { + if (op->bit[i].type == AVR_CMDBIT_VALUE || op->bit[i].type == AVR_CMDBIT_IGNORE) { j = 3 - i / 8; bit = i % 8; mask = 1 << bit; - if (op->bit[i].value) + if (op->bit[i].value && op->bit[i].type == AVR_CMDBIT_VALUE) cmd[j] = cmd[j] | mask; else cmd[j] = cmd[j] & ~mask; 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/avrdude.texi b/src/doc/avrdude.texi index a7901361..d99b0a85 100644 --- a/src/doc/avrdude.texi +++ b/src/doc/avrdude.texi @@ -1572,7 +1572,7 @@ 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| +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 diff --git a/src/ft245r.c b/src/ft245r.c index d5af4ca9..874167ac 100644 --- a/src/ft245r.c +++ b/src/ft245r.c @@ -107,10 +107,10 @@ void ft245r_initpgm(PROGRAMMER * pgm) { #else -#define FT245R_CYCLES 2 -#define FT245R_FRAGMENT_SIZE 512 -#define REQ_OUTSTANDINGS 10 -//#define USE_INLINE_WRITE_PAGE +#define FT245R_CYCLES 2 +#define FT245R_CMD_SIZE (4 * 8*FT245R_CYCLES) +#define FT245R_FRAGMENT_SIZE (8 * FT245R_CMD_SIZE) +#define REQ_OUTSTANDINGS 10 #define FT245R_DEBUG 0 /* @@ -992,40 +992,18 @@ static void ft245r_display(PROGRAMMER * pgm, const char * p) { pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS); } -static int ft245r_paged_write_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, - unsigned int n_bytes) { - unsigned long i, pa; - int rc; - for (i=0; ibuf[addr]); - if (rc != 0) { +static int ft245r_paged_write_gen(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { + + for(int i=0; i < (int) n_bytes; i++, addr++) + if(avr_write_byte_default(pgm, p, m, addr, m->buf[addr]) != 0) return -2; - } - if (m->paged) { - // Can this piece of code ever be activated?? Do AVRs exist that - // have paged non-flash memories? -- REW - // XXX Untested code below. - /* - * check to see if it is time to flush the page with a page - * write - */ - - if (((addr % m->page_size) == m->page_size-1) || (i == n_bytes-1)) { - pa = addr - (addr % m->page_size); - - rc = avr_write_page(pgm, p, m, pa); - if (rc != 0) { - return -2; - } - } - } - } - return i; + return n_bytes; } + static struct ft245r_request { int addr; int bytes; @@ -1081,178 +1059,185 @@ static int do_request(PROGRAMMER * pgm, AVRMEM *m) { return 1; } -static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - int page_size, int addr, int n_bytes) { - unsigned int i,j; - int addr_save,buf_pos,do_page_write,req_count; - unsigned char buf[FT245R_FRAGMENT_SIZE+1+128]; - req_count = 0; - for (i=0; i> 9) & 0xff ); - buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff ); - buf_pos += set_data(pgm, buf+buf_pos, m->buf[addr]); - addr ++; - i++; - if ( (m->paged) && - (((i % m->page_size) == 0) || (i == n_bytes))) { - do_page_write = 1; - break; - } - } -#if defined(USE_INLINE_WRITE_PAGE) - if (do_page_write) { - int addr_wk = addr_save - (addr_save % m->page_size); - /* If this device has a "load extended address" command, issue it. */ - if (m->op[AVR_OP_LOAD_EXT_ADDR]) { - unsigned char cmd[4]; - OPCODE *lext = m->op[AVR_OP_LOAD_EXT_ADDR]; +static int ft245r_paged_write_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { - memset(cmd, 0, 4); - avr_set_bits(lext, cmd); - avr_set_addr(lext, cmd, addr_wk/2); - buf_pos += set_data(pgm, buf+buf_pos, cmd[0]); - buf_pos += set_data(pgm, buf+buf_pos, cmd[1]); - buf_pos += set_data(pgm, buf+buf_pos, cmd[2]); - buf_pos += set_data(pgm, buf+buf_pos, cmd[3]); + int i, j, addr_save, buf_pos, req_count, do_page_write; + unsigned char buf[FT245R_FRAGMENT_SIZE+1]; + unsigned char cmd[4]; + + if(m->op[AVR_OP_LOADPAGE_LO] == NULL || m->op[AVR_OP_LOADPAGE_HI] == NULL) { + avrdude_message(MSG_INFO, "AVR_OP_LOADPAGE_HI/LO command not defined for %s\n", p->desc); + return -1; + } + + do_page_write = req_count = i = j = buf_pos = 0; + addr_save = addr; + while(i < (int) n_bytes) { + int spi = addr&1? AVR_OP_LOADPAGE_HI: AVR_OP_LOADPAGE_LO; + + // put the SPI loadpage command as FT245R_CMD_SIZE bytes into buffer + memset(cmd, 0, sizeof cmd); + avr_set_bits(m->op[spi], cmd); + avr_set_addr(m->op[spi], cmd, addr/2); + avr_set_input(m->op[spi], cmd, m->buf[addr]); + for(int k=0; kpaged && (i%m->page_size == 0 || i >= (int) n_bytes)) + do_page_write = 1; + + // page boundary, finished or buffer exhausted? queue up requests + if(do_page_write || i >= (int) n_bytes || j >= FT245R_FRAGMENT_SIZE/FT245R_CMD_SIZE) { + if(i >= n_bytes) { + ft245r_out = SET_BITS_0(ft245r_out, pgm, PIN_AVR_SCK, 0); // SCK down + buf[buf_pos++] = ft245r_out; + } else { + // stretch sequence to allow correct readout, see extract_data() + buf[buf_pos] = buf[buf_pos - 1]; + buf_pos++; } - buf_pos += set_data(pgm, buf+buf_pos, 0x4C); /* Issue Page Write */ - buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 9) & 0xff); - buf_pos += set_data(pgm, buf+buf_pos,(addr_wk >> 1) & 0xff); - buf_pos += set_data(pgm, buf+buf_pos, 0); - } -#endif - if (i >= n_bytes) { - ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down - buf[buf_pos++] = ft245r_out; - } - else { - /* stretch sequence to allow correct readout, see extract_data() */ - buf[buf_pos] = buf[buf_pos - 1]; - buf_pos++; - } - ft245r_send(pgm, buf, buf_pos); - put_request(addr_save, buf_pos, 0); - //ft245r_sync(pgm); -#if 0 - avrdude_message(MSG_INFO, "send addr 0x%04x bufsize %d [%02x %02x] page_write %d\n", - addr_save,buf_pos, - extract_data_out(pgm, buf , (0*4 + 3) ), - extract_data_out(pgm, buf , (1*4 + 3) ), - do_page_write); -#endif - req_count++; - if (req_count > REQ_OUTSTANDINGS) - do_request(pgm, m); - if (do_page_write) { -#if defined(USE_INLINE_WRITE_PAGE) - while (do_request(pgm, m)) - ; - ft245r_usleep(pgm, m->max_write_delay); -#else - int addr_wk = addr_save - (addr_save % m->page_size); - int rc; - while (do_request(pgm, m)) - ; - rc = avr_write_page(pgm, p, m, addr_wk); - if (rc != 0) { - return -2; + ft245r_send(pgm, buf, buf_pos); + put_request(addr_save, buf_pos, 0); + + if(++req_count > REQ_OUTSTANDINGS) + do_request(pgm, m); + + if(do_page_write) { + while(do_request(pgm, m)) + continue; + if(avr_write_page(pgm, p, m, addr_save - (addr_save % m->page_size)) != 0) + return -2; + do_page_write = req_count = 0; } -#endif - req_count = 0; + + // reset buffer variables + j = buf_pos = 0; + addr_save = addr; } } - while (do_request(pgm, m)) - ; - return i; + + while(do_request(pgm, m)) + continue; + + return n_bytes; } static int ft245r_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, unsigned int n_bytes) { - if (strcmp(m->desc, "flash") == 0) { + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { + + if(!n_bytes) + return 0; + + if(strcmp(m->desc, "flash") == 0) return ft245r_paged_write_flash(pgm, p, m, page_size, addr, n_bytes); - } else if (strcmp(m->desc, "eeprom") == 0) { + + if(strcmp(m->desc, "eeprom") == 0) return ft245r_paged_write_gen(pgm, p, m, page_size, addr, n_bytes); - } else { - return -2; - } + + return -2; } -static int ft245r_paged_load_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, - int n_bytes) { - unsigned char rbyte; - unsigned long i; - int rc; +static int ft245r_paged_load_gen(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { - for (i=0; ibuf[i+addr] = rbyte; + + m->buf[addr+i] = rbyte; } + return 0; } -static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, - unsigned int n_bytes) { - unsigned long i,j,n; - int addr_save,buf_pos; - int req_count = 0; + +static int ft245r_paged_load_flash(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { + + int i, j, addr_save, buf_pos, req_count; unsigned char buf[FT245R_FRAGMENT_SIZE+1]; + unsigned char cmd[4]; - for (i=0; i= n_bytes) break; - buf_pos += set_data(pgm, buf+buf_pos, (addr & 1)?0x28:0x20 ); - buf_pos += set_data(pgm, buf+buf_pos, (addr >> 9) & 0xff ); - buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff ); - buf_pos += set_data(pgm, buf+buf_pos, 0); - addr ++; - i++; - } - if (i >= n_bytes) { - ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down - buf[buf_pos++] = ft245r_out; - } - else { - /* stretch sequence to allow correct readout, see extract_data() */ - buf[buf_pos] = buf[buf_pos - 1]; - buf_pos++; - } - n = j; - ft245r_send(pgm, buf, buf_pos); - put_request(addr_save, buf_pos, n); - req_count++; - if (req_count > REQ_OUTSTANDINGS) - do_request(pgm, m); - + if(m->op[AVR_OP_READ_LO] == NULL || m->op[AVR_OP_READ_HI] == NULL) { + avrdude_message(MSG_INFO, "AVR_OP_READ_HI/LO command not defined for %s\n", p->desc); + return -1; } - while (do_request(pgm, m)) - ; + + // always called with addr at page boundary, and n_bytes == m->page_size; + // hence, OK to prepend load extended address command (at most) once + if(m->op[AVR_OP_LOAD_EXT_ADDR]) { + memset(cmd, 0, sizeof cmd); + avr_set_bits(m->op[AVR_OP_LOAD_EXT_ADDR], cmd); + avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], cmd, addr/2); + + buf_pos = 0; + for(int k=0; kop[spi], cmd); + avr_set_addr(m->op[spi], cmd, addr/2); + for(int k=0; k= (int) n_bytes || j >= FT245R_FRAGMENT_SIZE/FT245R_CMD_SIZE) { + if(i >= (int) n_bytes) { + ft245r_out = SET_BITS_0(ft245r_out, pgm, PIN_AVR_SCK, 0); // SCK down + buf[buf_pos++] = ft245r_out; + } else { + // stretch sequence to allow correct readout, see extract_data() + buf[buf_pos] = buf[buf_pos - 1]; + buf_pos++; + } + ft245r_send(pgm, buf, buf_pos); + put_request(addr_save, buf_pos, j); + + if(++req_count > REQ_OUTSTANDINGS) + do_request(pgm, m); + + // reset buffer variables + j = buf_pos = 0; + addr_save = addr; + } + } + + while(do_request(pgm, m)) + continue; + return 0; } -static int ft245r_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, - unsigned int page_size, unsigned int addr, - unsigned int n_bytes) { - if (strcmp(m->desc, "flash") == 0) { +static int ft245r_paged_load(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, + unsigned int page_size, unsigned int addr, unsigned int n_bytes) { + + if(!n_bytes) + return 0; + + if(strcmp(m->desc, "flash") == 0) return ft245r_paged_load_flash(pgm, p, m, page_size, addr, n_bytes); - } else if (strcmp(m->desc, "eeprom") == 0) { + + if(strcmp(m->desc, "eeprom") == 0) return ft245r_paged_load_gen(pgm, p, m, page_size, addr, n_bytes); - } else { - return -2; - } + + return -2; } void ft245r_initpgm(PROGRAMMER * pgm) { diff --git a/src/jtag3.c b/src/jtag3.c index 6d358dfa..6a4004f3 100644 --- a/src/jtag3.c +++ b/src/jtag3.c @@ -313,6 +313,14 @@ static void jtag3_prmsg(PROGRAMMER * pgm, unsigned char * data, size_t len) } } +static int jtag3_errcode(int reason) +{ + if (reason == RSP3_FAIL_OCD_LOCKED || + reason == RSP3_FAIL_CRC_FAILURE) + return LIBAVRDUDE_SOFTFAIL; + return LIBAVRDUDE_GENERAL_FAILURE; +} + static void jtag3_prevent(PROGRAMMER * pgm, unsigned char * data, size_t len) { int i; @@ -834,7 +842,7 @@ int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) { } } - int jtag3_command(PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen, +int jtag3_command(PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen, unsigned char **resp, const char *descr) { int status; @@ -850,7 +858,7 @@ int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) { putc('\n', stderr); avrdude_message(MSG_NOTICE2, "%s: %s command: timeout/error communicating with programmer (status %d)\n", progname, descr, status); - return -1; + return LIBAVRDUDE_GENERAL_FAILURE; } else if (verbose >= 3) { putc('\n', stderr); jtag3_prmsg(pgm, *resp, status); @@ -858,9 +866,10 @@ int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) { avrdude_message(MSG_NOTICE2, "0x%02x (%d bytes msg)\n", (*resp)[1], status); } - c = (*resp)[1]; - if ((c & RSP3_STATUS_MASK) != RSP3_OK) { - if ((c == RSP3_FAILED) && ((*resp)[3] == RSP3_FAIL_OCD_LOCKED)) { + c = (*resp)[1] & RSP3_STATUS_MASK; + if (c != RSP3_OK) { + if ((c == RSP3_FAILED) && ((*resp)[3] == RSP3_FAIL_OCD_LOCKED || + (*resp)[3] == RSP3_FAIL_CRC_FAILURE)) { avrdude_message(MSG_INFO, "%s: Device is locked! Chip erase required to unlock.\n", progname); @@ -871,7 +880,7 @@ int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg) { status = (*resp)[3]; free(*resp); resp = 0; - return -status; + return jtag3_errcode(status); } return status; @@ -987,7 +996,7 @@ static int jtag3_program_enable(PROGRAMMER * pgm) free(resp); PDATA(pgm)->prog_enabled = 1; - return 0; + return LIBAVRDUDE_SUCCESS; } return status; @@ -1761,7 +1770,7 @@ static int jtag3_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, free(cmd); return n_bytes; } - cmd[3] = ( p->flags & AVRPART_HAS_PDI ) ? MTYPE_EEPROM_XMEGA : MTYPE_EEPROM_PAGE; + cmd[3] = ( p->flags & AVRPART_HAS_PDI || p->flags & AVRPART_HAS_UPDI ) ? MTYPE_EEPROM_XMEGA : MTYPE_EEPROM_PAGE; PDATA(pgm)->eeprom_pageaddr = (unsigned long)-1L; } else if (strcmp(m->desc, "usersig") == 0 || strcmp(m->desc, "userrow") == 0) { diff --git a/src/jtag3_private.h b/src/jtag3_private.h index a3e7fb08..7d0cbb74 100644 --- a/src/jtag3_private.h +++ b/src/jtag3_private.h @@ -144,6 +144,7 @@ # define RSP3_FAIL_WRONG_MODE 0x32 /* progmode vs. non-prog */ # define RSP3_FAIL_UNSUPP_MEMORY 0x34 /* unsupported memory type */ # define RSP3_FAIL_WRONG_LENGTH 0x35 /* wrong lenth for mem access */ +# define RSP3_FAIL_CRC_FAILURE 0x43 /* CRC failure in device */ # define RSP3_FAIL_OCD_LOCKED 0x44 /* device is locked */ # define RSP3_FAIL_NOT_UNDERSTOOD 0x91 diff --git a/src/jtagmkII.c b/src/jtagmkII.c index fc06301c..b1024b53 100644 --- a/src/jtagmkII.c +++ b/src/jtagmkII.c @@ -1840,8 +1840,8 @@ void jtagmkII_close(PROGRAMMER * pgm) avrdude_message(MSG_NOTICE2, "%s: jtagmkII_close()\n", progname); - if (pgm->flag & PGM_FL_IS_PDI) { - /* When in PDI mode, restart target. */ + if (pgm->flag & (PGM_FL_IS_PDI | PGM_FL_IS_JTAG)) { + /* When in PDI or JTAG mode, restart target. */ buf[0] = CMND_GO; avrdude_message(MSG_NOTICE2, "%s: jtagmkII_close(): Sending GO command: ", progname); diff --git a/src/libavrdude.h b/src/libavrdude.h index 73083932..7088b108 100644 --- a/src/libavrdude.h +++ b/src/libavrdude.h @@ -27,6 +27,16 @@ #include typedef uint32_t pinmask_t; +/* + * Values returned by library functions. + * Some library functions also return a count, i.e. a positive + * number greater than 0. + */ +#define LIBAVRDUDE_SUCCESS 0 +#define LIBAVRDUDE_GENERAL_FAILURE (-1) +#define LIBAVRDUDE_NOTSUPPORTED (-2) // operation not supported +#define LIBAVRDUDE_SOFTFAIL (-3) // returned by avr_signature() if caller + // might proceed with chip erase /* formerly lists.h */ 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 f5381834..1d00ae67 100644 --- a/src/main.c +++ b/src/main.c @@ -1121,9 +1121,8 @@ int main(int argc, char * argv []) usleep(waittime); if (init_ok) { rc = avr_signature(pgm, p); - if (rc != 0) { - // -68 == -(0x44) == -(RSP3_FAIL_OCD_LOCKED) - if ((rc == -68) && (p->flags & AVRPART_HAS_UPDI) && (attempt < 1)) { + if (rc != LIBAVRDUDE_SUCCESS) { + if ((rc == LIBAVRDUDE_SOFTFAIL) && (p->flags & AVRPART_HAS_UPDI) && (attempt < 1)) { attempt++; if (pgm->read_sib) { // Read SIB and compare FamilyID 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/pickit2.c b/src/pickit2.c index 9e4be94c..ac3781f5 100644 --- a/src/pickit2.c +++ b/src/pickit2.c @@ -491,18 +491,15 @@ static int pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem, pgm->pgm_led(pgm, ON); + if (lext) { + memset(cmd, 0, sizeof(cmd)); + avr_set_bits(lext, cmd); + avr_set_addr(lext, cmd, addr/2); + pgm->cmd(pgm, cmd, res); + } + for (addr_base = addr; addr_base < max_addr; ) { - if ((addr_base == 0 || (addr_base % /*ext_address_boundary*/ 65536) == 0) - && lext != NULL) - { - memset(cmd, 0, sizeof(cmd)); - - avr_set_bits(lext, cmd); - avr_set_addr(lext, cmd, addr_base); - pgm->cmd(pgm, cmd, res); - } - // bytes to send in the next packet -- not necessary as pickit2_spi() handles breaking up // the data into packets -- but we need to keep transfers frequent so that we can update the // status indicator bar diff --git a/src/ser_posix.c b/src/ser_posix.c index 2c5d45b5..53d8cd15 100644 --- a/src/ser_posix.c +++ b/src/ser_posix.c @@ -76,6 +76,45 @@ static struct baud_mapping baud_lookup_table [] = { #endif #ifdef B230400 { 230400, B230400 }, +#endif +#ifdef B250000 + { 250000, B250000 }, +#endif +#ifdef B460800 + { 460800, B460800 }, +#endif +#ifdef B500000 + { 500000, B500000 }, +#endif +#ifdef B576000 + { 576000, B576000 }, +#endif +#ifdef B921600 + { 921600, B921600 }, +#endif +#ifdef B1000000 + { 1000000, B1000000 }, +#endif +#ifdef B1152000 + { 1152000, B1152000 }, +#endif +#ifdef B1500000 + { 1500000, B1500000 }, +#endif +#ifdef B2000000 + { 2000000, B2000000 }, +#endif +#ifdef B2500000 + { 2500000, B2500000 }, +#endif +#ifdef B3000000 + { 3000000, B3000000 }, +#endif +#ifdef B3500000 + { 3500000, B3500000 }, +#endif +#ifdef B4000000 + { 4000000, B4000000 }, #endif { 0, 0 } /* Terminator. */ };