Merge main branch
This commit is contained in:
commit
8b147b4bcd
|
@ -34,9 +34,11 @@ jobs:
|
||||||
linux-x86_64:
|
linux-x86_64:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Install prerequisites
|
- name: Install prerequisites
|
||||||
run: >-
|
run: >-
|
||||||
|
sudo apt-get update
|
||||||
|
|
||||||
sudo apt-get install -y
|
sudo apt-get install -y
|
||||||
build-essential
|
build-essential
|
||||||
cmake
|
cmake
|
||||||
|
@ -47,9 +49,14 @@ jobs:
|
||||||
libusb-1.0-0-dev
|
libusb-1.0-0-dev
|
||||||
libhidapi-dev
|
libhidapi-dev
|
||||||
libftdi1-dev
|
libftdi1-dev
|
||||||
|
libreadline-dev
|
||||||
|
texinfo
|
||||||
|
texlive
|
||||||
|
texi2html
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: >-
|
run: >-
|
||||||
cmake
|
cmake
|
||||||
|
-D BUILD_DOC=1
|
||||||
-D DEBUG_CMAKE=1
|
-D DEBUG_CMAKE=1
|
||||||
-D HAVE_LINUXGPIO=1
|
-D HAVE_LINUXGPIO=1
|
||||||
-D HAVE_LINUXSPI=1
|
-D HAVE_LINUXSPI=1
|
||||||
|
@ -59,7 +66,7 @@ jobs:
|
||||||
run: cmake --build build
|
run: cmake --build build
|
||||||
- name: Archive build artifacts
|
- name: Archive build artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: build-linux-x86_64
|
name: build-linux-x86_64
|
||||||
path: |
|
path: |
|
||||||
|
@ -67,7 +74,7 @@ jobs:
|
||||||
!**/*.d
|
!**/*.d
|
||||||
!**/*.o
|
!**/*.o
|
||||||
- name: Archive executables
|
- name: Archive executables
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: avrdude-linux-x86_64
|
name: avrdude-linux-x86_64
|
||||||
path: |
|
path: |
|
||||||
|
@ -84,13 +91,15 @@ jobs:
|
||||||
- { arch: armhf, processor: armhf, prefix: arm-linux-gnueabihf, inc-lib: arm-linux-gnueabihf }
|
- { arch: armhf, processor: armhf, prefix: arm-linux-gnueabihf, inc-lib: arm-linux-gnueabihf }
|
||||||
- { arch: arm64, processor: aarch64, prefix: aarch64-linux-gnu, inc-lib: aarch64-linux-gnu }
|
- { arch: arm64, processor: aarch64, prefix: aarch64-linux-gnu, inc-lib: aarch64-linux-gnu }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Add architecture
|
- name: Add architecture
|
||||||
run: |
|
run: |
|
||||||
dpkg --add-architecture ${{matrix.arch}}
|
dpkg --add-architecture ${{matrix.arch}}
|
||||||
apt-get update
|
apt-get update
|
||||||
- name: Install prerequisites
|
- name: Install prerequisites
|
||||||
run: >-
|
run: >-
|
||||||
|
apt-get update
|
||||||
|
|
||||||
apt-get install -y
|
apt-get install -y
|
||||||
git
|
git
|
||||||
cmake
|
cmake
|
||||||
|
@ -102,6 +111,7 @@ jobs:
|
||||||
libusb-1.0-0-dev:${{matrix.arch}}
|
libusb-1.0-0-dev:${{matrix.arch}}
|
||||||
libhidapi-dev:${{matrix.arch}}
|
libhidapi-dev:${{matrix.arch}}
|
||||||
libftdi1-dev:${{matrix.arch}}
|
libftdi1-dev:${{matrix.arch}}
|
||||||
|
libreadline-dev:${{matrix.arch}}
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: >-
|
run: >-
|
||||||
cmake
|
cmake
|
||||||
|
@ -120,7 +130,7 @@ jobs:
|
||||||
run: cmake --build build
|
run: cmake --build build
|
||||||
- name: Archive build artifacts
|
- name: Archive build artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: build-linux-${{matrix.processor}}
|
name: build-linux-${{matrix.processor}}
|
||||||
path: |
|
path: |
|
||||||
|
@ -128,7 +138,7 @@ jobs:
|
||||||
!**/*.d
|
!**/*.d
|
||||||
!**/*.o
|
!**/*.o
|
||||||
- name: Archive executables
|
- name: Archive executables
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: avrdude-linux-${{matrix.processor}}
|
name: avrdude-linux-${{matrix.processor}}
|
||||||
path: |
|
path: |
|
||||||
|
@ -138,9 +148,11 @@ jobs:
|
||||||
macos-x86_64:
|
macos-x86_64:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Install prerequisites
|
- name: Install prerequisites
|
||||||
run: >-
|
run: >-
|
||||||
|
# brew update
|
||||||
|
|
||||||
brew install
|
brew install
|
||||||
cmake
|
cmake
|
||||||
flex
|
flex
|
||||||
|
@ -149,6 +161,7 @@ jobs:
|
||||||
libusb
|
libusb
|
||||||
hidapi
|
hidapi
|
||||||
libftdi
|
libftdi
|
||||||
|
readline
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: >-
|
run: >-
|
||||||
cmake
|
cmake
|
||||||
|
@ -161,7 +174,7 @@ jobs:
|
||||||
run: cmake --build build
|
run: cmake --build build
|
||||||
- name: Archive build artifacts
|
- name: Archive build artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: build-macos-x86_64
|
name: build-macos-x86_64
|
||||||
path: |
|
path: |
|
||||||
|
@ -169,7 +182,7 @@ jobs:
|
||||||
!**/*.d
|
!**/*.d
|
||||||
!**/*.o
|
!**/*.o
|
||||||
- name: Archive executables
|
- name: Archive executables
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: avrdude-macos-x86_64
|
name: avrdude-macos-x86_64
|
||||||
path: |
|
path: |
|
||||||
|
@ -185,7 +198,7 @@ jobs:
|
||||||
- { arch: x64, platform: x64 }
|
- { arch: x64, platform: x64 }
|
||||||
- { arch: arm64, platform: ARM64 }
|
- { arch: arm64, platform: ARM64 }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- name: Install prerequisites
|
- name: Install prerequisites
|
||||||
# As Chocolatey is notoriously unreliable, install winflexbison3 directly from GitHub.
|
# As Chocolatey is notoriously unreliable, install winflexbison3 directly from GitHub.
|
||||||
# run: choco install winflexbison3
|
# run: choco install winflexbison3
|
||||||
|
@ -202,14 +215,15 @@ jobs:
|
||||||
-D CMAKE_C_FLAGS_RELWITHDEBINFO="/MT /GL /Zi /O2 /Ob1 /DNDEBUG"
|
-D CMAKE_C_FLAGS_RELWITHDEBINFO="/MT /GL /Zi /O2 /Ob1 /DNDEBUG"
|
||||||
-D CMAKE_CXX_FLAGS_RELWITHDEBINFO="/MT /GL /Zi /O2 /Ob1 /DNDEBUG"
|
-D CMAKE_CXX_FLAGS_RELWITHDEBINFO="/MT /GL /Zi /O2 /Ob1 /DNDEBUG"
|
||||||
-D CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO="/DEBUG /INCREMENTAL:NO /LTCG /OPT:REF /OPT:ICF"
|
-D CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO="/DEBUG /INCREMENTAL:NO /LTCG /OPT:REF /OPT:ICF"
|
||||||
|
-D HAVE_LIBREADLINE=HAVE_LIBREADLINE-NOTFOUND
|
||||||
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
||||||
-D USE_EXTERNAL=1
|
-D USE_EXTERNAL_LIBS=1
|
||||||
-B build
|
-B build
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build --config ${{env.BUILD_TYPE}}
|
run: cmake --build build --config ${{env.BUILD_TYPE}}
|
||||||
- name: Archive build artifacts
|
- name: Archive build artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: build-msvc-${{matrix.arch}}
|
name: build-msvc-${{matrix.arch}}
|
||||||
path: |
|
path: |
|
||||||
|
@ -221,7 +235,7 @@ jobs:
|
||||||
mv build/src/RelWithDebInfo/avrdude.exe build/src
|
mv build/src/RelWithDebInfo/avrdude.exe build/src
|
||||||
mv build/src/RelWithDebInfo/avrdude.pdb build/src
|
mv build/src/RelWithDebInfo/avrdude.pdb build/src
|
||||||
- name: Archive executables
|
- name: Archive executables
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: avrdude-msvc-${{matrix.arch}}
|
name: avrdude-msvc-${{matrix.arch}}
|
||||||
path: |
|
path: |
|
||||||
|
@ -240,7 +254,7 @@ jobs:
|
||||||
- { sys: mingw32, env: i686 }
|
- { sys: mingw32, env: i686 }
|
||||||
- { sys: mingw64, env: x86_64 }
|
- { sys: mingw64, env: x86_64 }
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
- uses: msys2/setup-msys2@v2
|
- uses: msys2/setup-msys2@v2
|
||||||
with:
|
with:
|
||||||
msystem: ${{matrix.sys}}
|
msystem: ${{matrix.sys}}
|
||||||
|
@ -265,13 +279,13 @@ jobs:
|
||||||
run: cmake --build build
|
run: cmake --build build
|
||||||
- name: Archive build artifacts
|
- name: Archive build artifacts
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: build-mingw-${{matrix.env}}
|
name: build-mingw-${{matrix.env}}
|
||||||
path: |
|
path: |
|
||||||
build/
|
build/
|
||||||
- name: Archive executables
|
- name: Archive executables
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: avrdude-mingw-${{matrix.env}}
|
name: avrdude-mingw-${{matrix.env}}
|
||||||
path: |
|
path: |
|
||||||
|
|
|
@ -76,10 +76,3 @@ jobs:
|
||||||
asset_path: ./asset.zip
|
asset_path: ./asset.zip
|
||||||
asset_name: avrdude-${{github.ref_name}}-windows-${{matrix.arch}}.zip
|
asset_name: avrdude-${{github.ref_name}}-windows-${{matrix.arch}}.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
|
||||||
#deploy:
|
|
||||||
# needs: [asset-msvc]
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# steps:
|
|
||||||
# - name: Create package (Chocolatey)
|
|
||||||
# run: echo TODO
|
|
||||||
|
|
12
AUTHORS
12
AUTHORS
|
@ -2,6 +2,14 @@ AVRDUDE was written by:
|
||||||
|
|
||||||
Brian S. Dean <bsd@bdmicro.com>
|
Brian S. Dean <bsd@bdmicro.com>
|
||||||
|
|
||||||
|
AVRDUDE is currently maintained by:
|
||||||
|
|
||||||
|
Hans Eirik Bull
|
||||||
|
Stefan Rueger
|
||||||
|
Xiaofan Chen
|
||||||
|
Marius Greuel
|
||||||
|
Joerg Wunsch
|
||||||
|
|
||||||
Contributors:
|
Contributors:
|
||||||
|
|
||||||
Joerg Wunsch <j@uriah.heep.sax.de>
|
Joerg Wunsch <j@uriah.heep.sax.de>
|
||||||
|
@ -29,6 +37,8 @@ Contributors:
|
||||||
Marius Greuel <greuelm@mgtek.com>
|
Marius Greuel <greuelm@mgtek.com>
|
||||||
Dawid Buchwald <dawid.buchwald@hotmail.com>
|
Dawid Buchwald <dawid.buchwald@hotmail.com>
|
||||||
Hans Eirik Bull
|
Hans Eirik Bull
|
||||||
|
Stefan Rueger
|
||||||
|
Xiaofan Chen
|
||||||
|
|
||||||
Contributors to code no longer present:
|
Contributors to code no longer present:
|
||||||
|
|
||||||
|
@ -36,5 +46,5 @@ Contributors to code no longer present:
|
||||||
Paula Tomlinson for the loaddrv sources
|
Paula Tomlinson for the loaddrv sources
|
||||||
Chris Liechti for loaddrv modifications
|
Chris Liechti for loaddrv modifications
|
||||||
|
|
||||||
For minor contributions, please see the ChangeLog files.
|
For minor contributions, please see the ChangeLog files / Git log.
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
# cmake -B build
|
# cmake -B build
|
||||||
# cmake --build build
|
# cmake --build build
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.12)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(avrdude VERSION 7.0)
|
project(avrdude VERSION 7.1 LANGUAGES C)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
set(CMAKE_C_STANDARD 11)
|
||||||
set(CMAKE_C_STANDARD_REQUIRED True)
|
set(CMAKE_C_STANDARD_REQUIRED True)
|
||||||
|
@ -30,11 +30,18 @@ option(BUILD_DOC "Enable building documents" OFF)
|
||||||
option(HAVE_LINUXGPIO "Enable Linux sysfs GPIO support" OFF)
|
option(HAVE_LINUXGPIO "Enable Linux sysfs GPIO support" OFF)
|
||||||
option(HAVE_LINUXSPI "Enable Linux SPI support" OFF)
|
option(HAVE_LINUXSPI "Enable Linux SPI support" OFF)
|
||||||
option(HAVE_PARPORT "Enable parallel port support" OFF)
|
option(HAVE_PARPORT "Enable parallel port support" OFF)
|
||||||
option(USE_EXTERNAL "Use external libraries from AVRDUDE GitHub repositories" OFF)
|
option(USE_EXTERNAL_LIBS "Use external libraries from AVRDUDE GitHub repositories" OFF)
|
||||||
option(USE_LIBUSBWIN32 "Prefer libusb-win32 over libusb" OFF)
|
option(USE_LIBUSBWIN32 "Prefer libusb-win32 over libusb" OFF)
|
||||||
option(DEBUG_CMAKE "Enable debugging output for this CMake project" OFF)
|
option(DEBUG_CMAKE "Enable debugging output for this CMake project" OFF)
|
||||||
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
# Prefer static libraries over DLLs on Windows
|
||||||
|
option(USE_STATIC_LIBS "Use static libraries" ON)
|
||||||
|
else()
|
||||||
|
option(USE_STATIC_LIBS "Use static libraries" OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
include(CheckIncludeFile)
|
include(CheckIncludeFile)
|
||||||
include(CheckSymbolExists)
|
include(CheckSymbolExists)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
@ -110,14 +117,14 @@ endif()
|
||||||
# Detect installed libraries
|
# Detect installed libraries
|
||||||
# =====================================
|
# =====================================
|
||||||
|
|
||||||
# Prefer static libraries over DLLs on Windows
|
if(USE_STATIC_LIBS)
|
||||||
if(WIN32)
|
|
||||||
set(PREFERRED_LIBELF libelf.a elf)
|
set(PREFERRED_LIBELF libelf.a elf)
|
||||||
set(PREFERRED_LIBUSB libusb.a usb)
|
set(PREFERRED_LIBUSB libusb.a usb)
|
||||||
set(PREFERRED_LIBUSB_1_0 libusb-1.0.a usb-1.0)
|
set(PREFERRED_LIBUSB_1_0 libusb-1.0.a usb-1.0)
|
||||||
set(PREFERRED_LIBHIDAPI libhidapi.a libhidapi-libusb.a libhidapi-hidraw.a hidapi hidapi-libusb hidapi-hidraw)
|
set(PREFERRED_LIBHIDAPI libhidapi.a libhidapi-libusb.a libhidapi-hidraw.a hidapi hidapi-libusb hidapi-hidraw)
|
||||||
set(PREFERRED_LIBFTDI libftdi.a ftdi)
|
set(PREFERRED_LIBFTDI libftdi.a ftdi)
|
||||||
set(PREFERRED_LIBFTDI1 libftdi1.a ftdi1)
|
set(PREFERRED_LIBFTDI1 libftdi1.a ftdi1)
|
||||||
|
set(PREFERRED_LIBREADLINE libreadline.a)
|
||||||
else()
|
else()
|
||||||
set(PREFERRED_LIBELF elf)
|
set(PREFERRED_LIBELF elf)
|
||||||
set(PREFERRED_LIBUSB usb)
|
set(PREFERRED_LIBUSB usb)
|
||||||
|
@ -125,6 +132,7 @@ else()
|
||||||
set(PREFERRED_LIBHIDAPI hidapi hidapi-libusb hidapi-hidraw)
|
set(PREFERRED_LIBHIDAPI hidapi hidapi-libusb hidapi-hidraw)
|
||||||
set(PREFERRED_LIBFTDI ftdi)
|
set(PREFERRED_LIBFTDI ftdi)
|
||||||
set(PREFERRED_LIBFTDI1 ftdi1)
|
set(PREFERRED_LIBFTDI1 ftdi1)
|
||||||
|
set(PREFERRED_LIBREADLINE readline)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# -------------------------------------
|
# -------------------------------------
|
||||||
|
@ -212,16 +220,18 @@ endif()
|
||||||
# -------------------------------------
|
# -------------------------------------
|
||||||
# Find libreadline
|
# Find libreadline
|
||||||
|
|
||||||
find_library(HAVE_LIBREADLINE NAMES readline)
|
find_library(HAVE_LIBREADLINE NAMES ${PREFERRED_LIBREADLINE})
|
||||||
if(HAVE_LIBREADLINE)
|
if(HAVE_LIBREADLINE)
|
||||||
set(LIB_LIBREADLINE ${HAVE_LIBREADLINE})
|
set(LIB_LIBREADLINE ${HAVE_LIBREADLINE})
|
||||||
|
elseif(MSVC)
|
||||||
|
set(HAVE_LIBREADLINE 1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# =====================================
|
# =====================================
|
||||||
# Use external libraries if requested
|
# Use external libraries if requested
|
||||||
# =====================================
|
# =====================================
|
||||||
|
|
||||||
if(USE_EXTERNAL)
|
if(USE_EXTERNAL_LIBS)
|
||||||
FetchContent_Declare(libelf
|
FetchContent_Declare(libelf
|
||||||
GIT_REPOSITORY https://github.com/avrdudes/libelf.git
|
GIT_REPOSITORY https://github.com/avrdudes/libelf.git
|
||||||
GIT_TAG e5a39bf19bd6598c42e09172be5a78ceec2a065c
|
GIT_TAG e5a39bf19bd6598c42e09172be5a78ceec2a065c
|
||||||
|
@ -234,12 +244,12 @@ if(USE_EXTERNAL)
|
||||||
|
|
||||||
FetchContent_Declare(libhidapi
|
FetchContent_Declare(libhidapi
|
||||||
GIT_REPOSITORY https://github.com/avrdudes/libhidapi.git
|
GIT_REPOSITORY https://github.com/avrdudes/libhidapi.git
|
||||||
GIT_TAG e3700e951f762ef92871ff4fc94586e4d1c042a6
|
GIT_TAG d1307487973c857bc158e27ecc99644b2f5e68ea
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_Declare(libftdi
|
FetchContent_Declare(libftdi
|
||||||
GIT_REPOSITORY https://github.com/avrdudes/libftdi.git
|
GIT_REPOSITORY https://github.com/avrdudes/libftdi.git
|
||||||
GIT_TAG f3a54da710002a7d25a32a69e667a69ef84cc120
|
GIT_TAG f9fe6e96b97c3a08efd081632c1859cb83aa14e3
|
||||||
)
|
)
|
||||||
|
|
||||||
message(STATUS "Fetching external libraries, please wait...")
|
message(STATUS "Fetching external libraries, please wait...")
|
||||||
|
@ -273,25 +283,8 @@ endif()
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
||||||
# =====================================
|
if(BUILD_DOC)
|
||||||
# Setup default port names
|
add_subdirectory(src/doc)
|
||||||
# =====================================
|
|
||||||
|
|
||||||
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|
||||||
set(DEFAULT_PAR_PORT "/dev/parport0")
|
|
||||||
set(DEFAULT_SER_PORT "/dev/ttyS0")
|
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
|
||||||
set(DEFAULT_PAR_PORT "/dev/ppi0")
|
|
||||||
set(DEFAULT_SER_PORT "/dev/cuad0")
|
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Solaris")
|
|
||||||
set(DEFAULT_PAR_PORT "/dev/printers/0")
|
|
||||||
set(DEFAULT_SER_PORT "/dev/term/a")
|
|
||||||
elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
|
||||||
set(DEFAULT_PAR_PORT "lpt1")
|
|
||||||
set(DEFAULT_SER_PORT "com1")
|
|
||||||
else()
|
|
||||||
set(DEFAULT_PAR_PORT "unknown")
|
|
||||||
set(DEFAULT_SER_PORT "unknown")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# =====================================
|
# =====================================
|
||||||
|
@ -308,7 +301,7 @@ if (DEBUG_CMAKE)
|
||||||
message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
|
message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
|
||||||
message(STATUS "CONFIG_DIR: ${CONFIG_DIR}")
|
message(STATUS "CONFIG_DIR: ${CONFIG_DIR}")
|
||||||
message(STATUS "AVRDUDE_FULL_VERSION: ${AVRDUDE_FULL_VERSION}")
|
message(STATUS "AVRDUDE_FULL_VERSION: ${AVRDUDE_FULL_VERSION}")
|
||||||
message(STATUS "USE_EXTERNAL: ${USE_EXTERNAL}")
|
message(STATUS "USE_EXTERNAL_LIBS: ${USE_EXTERNAL_LIBS}")
|
||||||
message(STATUS "USE_LIBUSBWIN32: ${USE_LIBUSBWIN32}")
|
message(STATUS "USE_LIBUSBWIN32: ${USE_LIBUSBWIN32}")
|
||||||
message(STATUS "HAVE_LIBELF: ${HAVE_LIBELF}")
|
message(STATUS "HAVE_LIBELF: ${HAVE_LIBELF}")
|
||||||
message(STATUS "HAVE_LIBUSB: ${HAVE_LIBUSB}")
|
message(STATUS "HAVE_LIBUSB: ${HAVE_LIBUSB}")
|
||||||
|
@ -370,6 +363,12 @@ else()
|
||||||
message(STATUS "DON'T HAVE libftdi1")
|
message(STATUS "DON'T HAVE libftdi1")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_LIBREADLINE)
|
||||||
|
message(STATUS "DO HAVE libreadline")
|
||||||
|
else()
|
||||||
|
message(STATUS "DON'T HAVE libreadline")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(BUILD_DOC)
|
if(BUILD_DOC)
|
||||||
message(STATUS "ENABLED doc")
|
message(STATUS "ENABLED doc")
|
||||||
else()
|
else()
|
||||||
|
|
|
@ -1,85 +1,19 @@
|
||||||
{
|
{
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
|
||||||
"name": "x86-Debug",
|
|
||||||
"generator": "Visual Studio 17 2022",
|
|
||||||
"configurationType": "Debug",
|
|
||||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
|
||||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
|
||||||
"cmakeCommandArgs": "",
|
|
||||||
"buildCommandArgs": "",
|
|
||||||
"ctestCommandArgs": "",
|
|
||||||
"inheritEnvironments": [ "msvc_x86" ],
|
|
||||||
"variables": [
|
|
||||||
{
|
|
||||||
"name": "DEBUG_CMAKE",
|
|
||||||
"value": "True",
|
|
||||||
"type": "BOOL"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "USE_EXTERNAL",
|
|
||||||
"value": "True",
|
|
||||||
"type": "BOOL"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "x86-Release",
|
|
||||||
"generator": "Ninja",
|
|
||||||
"configurationType": "RelWithDebInfo",
|
|
||||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
|
||||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
|
||||||
"cmakeCommandArgs": "",
|
|
||||||
"buildCommandArgs": "",
|
|
||||||
"ctestCommandArgs": "",
|
|
||||||
"inheritEnvironments": [ "msvc_x86" ],
|
|
||||||
"variables": [
|
|
||||||
{
|
|
||||||
"name": "DEBUG_CMAKE",
|
|
||||||
"value": "True",
|
|
||||||
"type": "BOOL"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "USE_EXTERNAL",
|
|
||||||
"value": "True",
|
|
||||||
"type": "BOOL"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CMAKE_C_FLAGS_RELWITHDEBINFO",
|
|
||||||
"value": "/MT /GL /Zi /O2 /Ob1 /DNDEBUG",
|
|
||||||
"type": "STRING"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
|
|
||||||
"value": "/MT /GL /Zi /O2 /Ob1 /DNDEBUG",
|
|
||||||
"type": "STRING"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO",
|
|
||||||
"value": "/debug /INCREMENTAL:NO /LTCG /OPT:REF /OPT:ICF",
|
|
||||||
"type": "STRING"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "x64-Debug",
|
"name": "x64-Debug",
|
||||||
"generator": "Visual Studio 17 2022 Win64",
|
"generator": "Ninja",
|
||||||
"configurationType": "Debug",
|
"configurationType": "Debug",
|
||||||
|
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
"cmakeCommandArgs": "",
|
"cmakeCommandArgs": "",
|
||||||
"buildCommandArgs": "",
|
"buildCommandArgs": "",
|
||||||
"ctestCommandArgs": "",
|
"ctestCommandArgs": "",
|
||||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
|
||||||
"variables": [
|
"variables": [
|
||||||
{
|
{
|
||||||
"name": "DEBUG_CMAKE",
|
"name": "USE_EXTERNAL_LIBS",
|
||||||
"value": "True",
|
"value": "true",
|
||||||
"type": "BOOL"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "USE_EXTERNAL",
|
|
||||||
"value": "True",
|
|
||||||
"type": "BOOL"
|
"type": "BOOL"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -96,29 +30,45 @@
|
||||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||||
"variables": [
|
"variables": [
|
||||||
{
|
{
|
||||||
"name": "DEBUG_CMAKE",
|
"name": "USE_EXTERNAL_LIBS",
|
||||||
"value": "True",
|
"value": "true",
|
||||||
"type": "BOOL"
|
"type": "BOOL"
|
||||||
},
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-Debug",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "Debug",
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"buildCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "msvc_x86" ],
|
||||||
|
"variables": [
|
||||||
{
|
{
|
||||||
"name": "USE_EXTERNAL",
|
"name": "USE_EXTERNAL_LIBS",
|
||||||
"value": "True",
|
"value": "true",
|
||||||
"type": "BOOL"
|
"type": "BOOL"
|
||||||
},
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-Release",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "RelWithDebInfo",
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"buildCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "msvc_x86" ],
|
||||||
|
"variables": [
|
||||||
{
|
{
|
||||||
"name": "CMAKE_C_FLAGS_RELWITHDEBINFO",
|
"name": "USE_EXTERNAL_LIBS",
|
||||||
"value": "/MT /GL /Zi /O2 /Ob1 /DNDEBUG",
|
"value": "true",
|
||||||
"type": "STRING"
|
"type": "BOOL"
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
|
|
||||||
"value": "/MT /GL /Zi /O2 /Ob1 /DNDEBUG",
|
|
||||||
"type": "STRING"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO",
|
|
||||||
"value": "/debug /INCREMENTAL:NO /LTCG /OPT:REF /OPT:ICF",
|
|
||||||
"type": "STRING"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
311
NEWS
311
NEWS
|
@ -5,6 +5,317 @@ Approximate change log for AVRDUDE by version.
|
||||||
(For detailed changes, see the version control system logs.)
|
(For detailed changes, see the version control system logs.)
|
||||||
|
|
||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
|
Changes since version 7.1:
|
||||||
|
|
||||||
|
* Major changes compared to the previous version:
|
||||||
|
|
||||||
|
* New devices supported: none
|
||||||
|
|
||||||
|
* New programmers supported:
|
||||||
|
|
||||||
|
* Issues fixed:
|
||||||
|
|
||||||
|
* Pull requests:
|
||||||
|
|
||||||
|
* Internals:
|
||||||
|
|
||||||
|
|
||||||
|
Changes in version 7.1:
|
||||||
|
|
||||||
|
* Major changes compared to the previous version:
|
||||||
|
|
||||||
|
- Provide a new programmer -c urclock for bootloader urprotocol
|
||||||
|
+ Urclock fully supports vector bootloaders at no extra code size
|
||||||
|
+ Uprotocol
|
||||||
|
https://github.com/stefanrueger/urboot/blob/main/urprotocol.md
|
||||||
|
allows programming much shorter bootloaders with more features:
|
||||||
|
* Exports a pgm_write_page(sram, progmem) function that the
|
||||||
|
application can call at FLASHEND-4+1 to use flash as storage
|
||||||
|
* Supports EEPROM reads/writes
|
||||||
|
* Protects itself from overwriting
|
||||||
|
* Vector bootloaders: can protect the reset vector
|
||||||
|
* Offers Chip Erase function (quicker than uploading 0xff's)
|
||||||
|
+ Urclock when compiled with libreadline supports bootloaders in
|
||||||
|
terminal mode (preventing them from WDT timeout)
|
||||||
|
+ The -c urclock programmer provides a metadata interface that
|
||||||
|
allows unused flash to be used as storage
|
||||||
|
+ avrdude -c urclock is backward compatible with avrdude -c arduino
|
||||||
|
|
||||||
|
- Add TPI support for Microchip tools #1205
|
||||||
|
|
||||||
|
- Add C-strings, C characters and double to terminal write
|
||||||
|
|
||||||
|
- Provide write flash in the terminal (using a cache)
|
||||||
|
|
||||||
|
- Provide page erase in the terminal as pgerase
|
||||||
|
|
||||||
|
- Add support for NetBSD and OpenBSD to build.sh
|
||||||
|
|
||||||
|
* New devices supported: none
|
||||||
|
|
||||||
|
* New programmers supported:
|
||||||
|
|
||||||
|
- urclock = Urclock programmer for bootloaders using urprotocol
|
||||||
|
- xplainedmini_tpi = Atmel AVR XplainedMini in TPI mode
|
||||||
|
- xplainedpro_pdi = Atmel AVR XplainedPro in PDI mode
|
||||||
|
- atmelice_tpi = Atmel-ICE (ARM/AVR) in TPI mode
|
||||||
|
- powerdebugger_tpi = Atmel PowerDebugger (ARM/AVR) in TPI mode
|
||||||
|
- pickit4 = MPLAB(R) PICkit 4 in JTAG mode
|
||||||
|
- pickit4_tpi = MPLAB(R) PICkit 4 in TPI mode
|
||||||
|
- snap = MPLAB(R) SNAP in JTAG mode
|
||||||
|
- snap_tpi = MPLAB(R) SNAP in TPI mode
|
||||||
|
- arduino_gemma = Arduino Gemma bootloader disguised as USBtiny
|
||||||
|
- adafruit_gemma = Adafruit Trinket Gemma bootloader disguised as USBtiny
|
||||||
|
- digilent-hs2 = Digilient JTAG HS2 (MPSSE)
|
||||||
|
- tigard = Tigard interface board
|
||||||
|
|
||||||
|
* 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
|
||||||
|
- Wrong timings for ATmega328PB and other parts in avrdude.conf
|
||||||
|
#976
|
||||||
|
- FT232R based programmer ATmega2560 Flash Reading Problem #995
|
||||||
|
also #474
|
||||||
|
- Enable avrdude to send full input file incl trailing 0xff
|
||||||
|
#936
|
||||||
|
- Portname default for linuxspi programmer not recognized #926
|
||||||
|
- JTAG1 unable to write fuse and lock bits #443
|
||||||
|
- Unknown option '-s' on command line (legacy) #1032
|
||||||
|
- STK500/arduino/xbee programmers fail EEPROM r/w for some
|
||||||
|
parts #967 also #421
|
||||||
|
- Design issue: jtag2updi is hardcoded to fail for parts with
|
||||||
|
has_pdi = yes #1037
|
||||||
|
- Option parse error: after -U flash:w:program_to_upload.hex,
|
||||||
|
subsequent -V ignored #441
|
||||||
|
- Automatic verification is designed to fail for stdin #1044
|
||||||
|
- Display correct number of bytes when input file has holes
|
||||||
|
#1005
|
||||||
|
- Cmake installs avrdude.1 in the wrong place on Linux #1064
|
||||||
|
- avr910 -qq prompt too verbose #1081
|
||||||
|
- avrftdi.c: paged write can fail at addr 0 #1073
|
||||||
|
- Permission denied accessing /sys/class/gpio/gpioX/direction
|
||||||
|
would leave pin exported #472 also #372
|
||||||
|
- Raspberry Pi sysfs bug workaround for linuxgpio driver #386
|
||||||
|
- Fix CMake avrdude.conf dependency to avrdude.conf.in #1035
|
||||||
|
- CMake infrastructure does not handle documentation #947
|
||||||
|
- New feature: ability to reset FLIPv2 targets #733
|
||||||
|
- Fix Extended address not sent with avr109/butterfly #360
|
||||||
|
and #454
|
||||||
|
- Enable AVR JTAG ICE mkI program EEPROM in terminal mode
|
||||||
|
#1054
|
||||||
|
- Make flash writes work in terminal mode #1020
|
||||||
|
- Add support for XMEGA specific AVR109 protocol extensions
|
||||||
|
used by XBoot #200
|
||||||
|
- jtag2updi can not write EEPROM in terminal mode #1116
|
||||||
|
- Make UPDI programmers less verbose during initialization
|
||||||
|
#1084
|
||||||
|
- Quell mode isn't handled systematically #1114
|
||||||
|
- Mixing the progress bar with warning messages #1136
|
||||||
|
- Inconsistent terminal output re stdout and stderr #1130
|
||||||
|
- Supress the warning for Microchip SNAP #1135
|
||||||
|
- ATtiny85 communication problem with default bitclock #1133
|
||||||
|
- [Regression] Optiboot for "modern AVRs" no longer works #1120
|
||||||
|
- Cannot access EEPROM on some bootloader/part combos #970
|
||||||
|
- -U writes sometimes more bytes to flash/memory than input
|
||||||
|
file has #1050
|
||||||
|
- debugWire using dragon_dw and jtag2dw not working #1168
|
||||||
|
- && echo OK does not work after -c urclock #1192
|
||||||
|
- Serial drain timeout needs calibrating for -c urclock #1193
|
||||||
|
- avrdude -U file.elf misses second and following suitable
|
||||||
|
sections in elf segements #1204
|
||||||
|
- Avrdude on macOS has problems with libedit #1173
|
||||||
|
- urclock support for optiboot_x and optiboot_dx #1200
|
||||||
|
- Terminal does not continue read/dump correctly #1201
|
||||||
|
- JTAG3 programmer info not available in ISP mode #1212
|
||||||
|
- Extra avrdude> prompt with -qqt in terminal mode #1214
|
||||||
|
- PICkit4 and SNAP serial numbers not read by Avrdude #1038
|
||||||
|
- Optiboot EEPROM support cannot be detected by avrdude #1224
|
||||||
|
- megaAVR JTAG programming doesn't work for SNAP and PICkit4
|
||||||
|
#1052
|
||||||
|
- urclock/FTDI communication issues #1245
|
||||||
|
- stk500v2.c dumps core on open #1254
|
||||||
|
- linuxgpio cannot use pin 0 #1228
|
||||||
|
- Remove non-working butterfly page erase function
|
||||||
|
- linuxgpio and linuxspi: input files with unset bytes don't program
|
||||||
|
correctly #1263 #455
|
||||||
|
|
||||||
|
* 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 #998
|
||||||
|
- Fix avrdude.conf timings for ATmega328PB and other parts #1001
|
||||||
|
- Fix PICKit2 ATmega2560 flash paged flash read #1023
|
||||||
|
- Fix ft245r paged read for ATmega2560 et al #1018
|
||||||
|
- Add option -A that supresses trailing 0xff optimisation
|
||||||
|
and automatically do so for -c arduino #936
|
||||||
|
- Fix linuxspi default port #933
|
||||||
|
- Add support for high-voltage UPDI im jtag3.c #1015
|
||||||
|
- Fix terminal write edge cases; add one read mode; add quell
|
||||||
|
command #1025
|
||||||
|
- Fix usbtiny read for parts with more than 64 kB flash #1029
|
||||||
|
- CMakeLists.txt: fix build without C++ #1016
|
||||||
|
- Provide file format I: Intel HEX with comments that ignores
|
||||||
|
checksum errors #1030
|
||||||
|
- Enable writing fuse and lock bits for AVR-JTAGICE #1031
|
||||||
|
- Ignore -s flag as safemode is no longer supported #1033
|
||||||
|
- Developer options to describe parts and
|
||||||
|
extend avrdude.conf syntax #1040
|
||||||
|
- Deprecate original STK500 v1 protocol in favour of optiboot
|
||||||
|
and Arduino as ISP #1046
|
||||||
|
- Add jtagmkii_updi programmer option #1048
|
||||||
|
- Enable stdin verification, display correct number of bytes
|
||||||
|
written/verified, check -U memory names against spelling
|
||||||
|
errors and exit but skip -U memory updates with known
|
||||||
|
memories that the part lacks #1053
|
||||||
|
- Handle invalid -U file format specifiers for input #1042
|
||||||
|
- Implement a dry run for -U updates before opening the
|
||||||
|
programmer #1056
|
||||||
|
- Implement -c <wildcard>/dev_options for printing avrdude.conf
|
||||||
|
show comments with -p*/s or -c*/s; Reduce -p */r raw output;
|
||||||
|
specifying the full memory name now always works; stop
|
||||||
|
listing programmers where id starts with dot #1059
|
||||||
|
- Fix logfile short option in man-page; fix install dir for man
|
||||||
|
page #1063
|
||||||
|
- Use const for programmer functions where useful; add second
|
||||||
|
argument for programmer enable interface function
|
||||||
|
void (*enable)(PROGRAMMER *pgm, const AVRPART *p) #1078
|
||||||
|
- Make avr910 programmer initialize() less verbose #1083
|
||||||
|
- Fix flash paged write for avrftdi.c #1074
|
||||||
|
- Fix 4 parts wrt to their interfaces in avrdude.conf; rewrite
|
||||||
|
avrdude.conf.in file from avrdude -c* -p* output; reformat
|
||||||
|
conditional programmers in avrdude.conf.in using -c*; fix
|
||||||
|
reset=dedicated|io; entries #1086
|
||||||
|
- Add prog_modes, a bitwise or of prgramming modes, to part and
|
||||||
|
programmer definitions; add to part definition
|
||||||
|
+ mcuid, a unique id in 0..2039 for 8-bit AVR
|
||||||
|
+ n_interrupts, the number of interrupts
|
||||||
|
+ n_page_erase, if set, the # of pages erased for NVM erase
|
||||||
|
implement a simple calculator in config_gram.y for numeric
|
||||||
|
values; set part prog_modes, mcuid, n_interrupts and
|
||||||
|
n_page_erase in avrdude.conf.in; add external intelligence
|
||||||
|
about AVRs avrintel.[ch] to the project and warn during
|
||||||
|
parsing if mcuid is incompatible with it #1091
|
||||||
|
- Fix permission denied error in linuxgpio programmer #917
|
||||||
|
- Add a programmer arduino_gemma for the Arduino Gemma
|
||||||
|
bootloader and another one, adafruit_gemma, for the Adafruit
|
||||||
|
Trinket Gemma bootloader in avrdude.conf; #1093
|
||||||
|
- Add digilent-hs2 programmer in avrdude.conf #1094
|
||||||
|
- Fix dependency chain between avrdude.conf.in and
|
||||||
|
avrdude.conf #1095
|
||||||
|
- Build docs with CMake #1096
|
||||||
|
- New feature so user can print all compatible parts for a
|
||||||
|
programmer using -p\? -c programmer and vice versa #1099
|
||||||
|
- Add extended parameter disable_no_cs for linuxspi programmer
|
||||||
|
#1100
|
||||||
|
- Fix avr109 extended address #1101
|
||||||
|
- Add support for Flip 2 reset on exit #1102
|
||||||
|
- Support for Power Debugger analog readings in terminal mode
|
||||||
|
#1105
|
||||||
|
- Provide cached byte-wise read/write API #1106
|
||||||
|
- AVR109: support for prodsig read and usersig read/write #1108
|
||||||
|
- Add missing AVR variants the original JTAG ICE supports #1109
|
||||||
|
- Improve help message in terminal and provide new command
|
||||||
|
pgerase #1113
|
||||||
|
- Fix pointer truncation for Windows x64 #1119
|
||||||
|
- Fix jtag3_page_erase for targets with UPDI #1112
|
||||||
|
- Fix writing of last word on DWORD TPI parts #1115
|
||||||
|
- Use byte-wise read/write when page size is 1 in terminal
|
||||||
|
cache #1121
|
||||||
|
- Suppress Teensy USB communication error message on reboot #1122
|
||||||
|
- Fix UPDI erase when target is locked #1125
|
||||||
|
- Review and overhaul AVRDUDE's messaging system #1126
|
||||||
|
- Look for ~/.config/avrdude/avrdude.rc then ~/.avrduderc #1131
|
||||||
|
- Revamp terminal output (progress bar, callback and
|
||||||
|
stdout/stderr) #1132
|
||||||
|
- Detect PICkit4 and SNAP in PIC mode #1138
|
||||||
|
- Mention -B in the error message #1139
|
||||||
|
- Support optiboot, optiboot_dx and optiboot_x bootloaders for
|
||||||
|
-c arduino #1140
|
||||||
|
- Always use paged access for programmers that serve
|
||||||
|
bootloaders #1141
|
||||||
|
- Add libreadline-dev for Linux github action build #1146
|
||||||
|
- Implementation of SerialUPDI page erase operation #1151
|
||||||
|
- Fix Type 2 HV UPDI #1164
|
||||||
|
- Rewrite authors/copyrights #1182
|
||||||
|
- Add fallback for EM_AVR #1181
|
||||||
|
- Add a workaround for issue 1173 #1185
|
||||||
|
- Add xplainedpro_pdi programmer #1147
|
||||||
|
- Provide Urclock programmer #1171
|
||||||
|
- Fix JTAGICE mkII (not initializing after chip erase) #1172
|
||||||
|
- Ensure default_programmer from config files is used #1174
|
||||||
|
- Make terminal write's automatic number width less surprising
|
||||||
|
#1175
|
||||||
|
- Print HAVE_LIBREADLINE status when making the project #1184
|
||||||
|
- Pad pages with input file contents before avr_write() #1188
|
||||||
|
- Deprecate mosi/miso in favour of sdo/sdi #1189
|
||||||
|
- Provide bootloader-hash tool #1190
|
||||||
|
- Fix JTAGICE mkII parameters for parts with bootloaders #1191
|
||||||
|
- Fix shell exit value when chip erase is delayed #1194
|
||||||
|
- Support autobaud for urclock programmer #1198
|
||||||
|
- Fix userrow size and page_size for ATtiny3216/7 #1199
|
||||||
|
- Added TPI support for Microchip tools #1205
|
||||||
|
- Fix reading of .elf files #1206
|
||||||
|
- Use libedit only in interactive mode #1207
|
||||||
|
- Add urclock support for bootloaders in low flash #1208
|
||||||
|
- Terminal read improvements #1209
|
||||||
|
- Print meaningful error when a too slow ISP clock is detected #1216
|
||||||
|
- Check alternative USB PID for PICkit4/SNAP in PIC mode #1219
|
||||||
|
- Remove extraneous avrdude> prompt at end of terminal session #1220
|
||||||
|
- Read programmer serial number from libusb or hidusb #1223
|
||||||
|
- Hint at -xeepromrw option in EEPROM error messages #1226
|
||||||
|
- Add JTAG support for PICkit4 and Snap. #1233
|
||||||
|
- Mention developer options in documentation and Usage() #1234
|
||||||
|
- Print expected signature on signature mismatch #1237
|
||||||
|
- To work around Issue #1107 #1240
|
||||||
|
- Update build.sh for NetBSD #1241
|
||||||
|
- Add FT2232H support for Windows, Tigard programmer #1242
|
||||||
|
- Modify recv timeouts to accommodate urclock sync with ftdi
|
||||||
|
#1246
|
||||||
|
- CMake updates #1243
|
||||||
|
- Silence conf path detection debug output #1247
|
||||||
|
- Make WIN32 ser_recv() fail on time-out #1248
|
||||||
|
- Guard urclock_getsync() against initial spurious input #1251
|
||||||
|
- Change definition of NO_PIN to 1+PIN_MAX #1231
|
||||||
|
- Fix partial matches for locate_mem() and do_cmd() #1256
|
||||||
|
- Add abbreviated q command in terminal
|
||||||
|
- Move static usbsn into serdev struct and remove serno #1258
|
||||||
|
- Clean up avrdude.conf.in fixing a couple of bugs #1260
|
||||||
|
- Add readline library replacement for MSVC #1264
|
||||||
|
- Ensure full words are loaded for ISP programming #1265
|
||||||
|
- Silence page erase in cache code #1266
|
||||||
|
- Update to latest MSVC fork of hidapi to include bug fixes
|
||||||
|
#1269
|
||||||
|
|
||||||
|
* Internals:
|
||||||
|
|
||||||
|
- Implement -c <wildcard>/dev_opts and -p <wildcard>/dev_opts
|
||||||
|
for printing avrdude.conf programmer and part entries
|
||||||
|
|
||||||
|
- Added shorter alternative ISP commands for avrdude.conf
|
||||||
|
|
||||||
|
- Reformatted avrdude.conf to canonical form
|
||||||
|
|
||||||
|
- Reviewed API for prgrammer functions: use const for
|
||||||
|
programmer functions where useful; add second argument for
|
||||||
|
void (*enable)(PROGRAMMER *pgm, const AVRPART *p) #1078
|
||||||
|
|
||||||
|
- Reviewed messaging system making warnings and errors explicit
|
||||||
|
and treat them systematically
|
||||||
|
|
||||||
|
|
||||||
Changes in version 7.0:
|
Changes in version 7.0:
|
||||||
|
|
||||||
* Major changes compared to the previous version:
|
* Major changes compared to the previous version:
|
||||||
|
|
23
build.sh
23
build.sh
|
@ -29,7 +29,12 @@ ostype=$(uname | tr '[A-Z]' '[a-z]')
|
||||||
build_type=RelWithDebInfo
|
build_type=RelWithDebInfo
|
||||||
# build_type=Release # no debug info
|
# build_type=Release # no debug info
|
||||||
|
|
||||||
|
# See CMakeLists.txt for all options
|
||||||
|
#
|
||||||
|
# Use this to enable (historical) parallel-port based programmers:
|
||||||
|
#extra_enable="-D HAVE_PARPORT=1"
|
||||||
extra_enable=""
|
extra_enable=""
|
||||||
|
|
||||||
build_flags=""
|
build_flags=""
|
||||||
|
|
||||||
case "${ostype}" in
|
case "${ostype}" in
|
||||||
|
@ -37,9 +42,9 @@ case "${ostype}" in
|
||||||
# try to find out whether this is an Embedded Linux
|
# try to find out whether this is an Embedded Linux
|
||||||
# platform (e.g. Raspberry Pi)
|
# platform (e.g. Raspberry Pi)
|
||||||
machine=$(uname -m)
|
machine=$(uname -m)
|
||||||
if expr "${machine}" : 'arm' >/dev/null
|
if expr "${machine}" : '^\(arm\|aarch\)' >/dev/null
|
||||||
then
|
then
|
||||||
extra_enable="${extra_enable} -D HAVE_LINUXGPIO=ON -D HAVE_LINUXSPI=ON"
|
extra_enable="${extra_enable} -D HAVE_LINUXGPIO=1 -D HAVE_LINUXSPI=1"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
@ -50,11 +55,21 @@ case "${ostype}" in
|
||||||
then
|
then
|
||||||
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/local/lib"
|
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/local/lib"
|
||||||
else
|
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
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
freebsd)
|
netbsd)
|
||||||
|
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/pkg/include -D CMAKE_EXE_LINKER_FLAGS=-R/usr/pkg/lib -D CMAKE_INSTALL_PREFIX:PATH=/usr/pkg"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*bsd)
|
||||||
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/lib"
|
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/lib"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -51,16 +51,13 @@ include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
add_compile_definitions(CONFIG_DIR=\"${CONFIG_DIR}\")
|
add_compile_definitions(CONFIG_DIR=\"${CONFIG_DIR}\")
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(EXTRA_WINDOWS_SOURCES "${PROJECT_BINARY_DIR}/src/windows.rc")
|
set(EXTRA_WINDOWS_RESOURCES "${PROJECT_BINARY_DIR}/src/windows.rc")
|
||||||
set(EXTRA_WINDOWS_LIBRARIES setupapi ws2_32)
|
set(EXTRA_WINDOWS_LIBRARIES setupapi ws2_32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT WIN32)
|
|
||||||
set(LIB_MATH m)
|
|
||||||
add_compile_options(-Wall) # -Wextra
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS=1)
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS=1)
|
||||||
add_compile_definitions(_CRT_NONSTDC_NO_WARNINGS=1)
|
add_compile_definitions(_CRT_NONSTDC_NO_WARNINGS=1)
|
||||||
add_compile_definitions(_WINSOCK_DEPRECATED_NO_WARNINGS=1)
|
add_compile_definitions(_WINSOCK_DEPRECATED_NO_WARNINGS=1)
|
||||||
|
@ -68,45 +65,69 @@ if(MSVC)
|
||||||
add_compile_options(/wd4018) # warning C4018: signed/unsigned mismatch
|
add_compile_options(/wd4018) # warning C4018: signed/unsigned mismatch
|
||||||
add_compile_options(/wd4244) # warning C4244: conversion from '...' to '...', possible loss of data
|
add_compile_options(/wd4244) # warning C4244: conversion from '...' to '...', possible loss of data
|
||||||
add_compile_options(/wd4267) # warning C4267: conversion from '...' to '...', possible loss of data
|
add_compile_options(/wd4267) # warning C4267: conversion from '...' to '...', possible loss of data
|
||||||
add_compile_options(/wd5105) # warning C5105: macro expansion producing 'xxx' has undefined behavior
|
|
||||||
add_compile_options(/wd6255) # warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
|
|
||||||
|
|
||||||
set(EXTRA_WINDOWS_SOURCES ${EXTRA_WINDOWS_SOURCES}
|
set(EXTRA_WINDOWS_SOURCES ${EXTRA_WINDOWS_SOURCES}
|
||||||
"msvc/getopt.c"
|
"msvc/getopt.c"
|
||||||
"msvc/gettimeofday.c"
|
"msvc/gettimeofday.c"
|
||||||
"msvc/usleep.cpp"
|
"msvc/usleep.cpp"
|
||||||
|
"msvc/readline.cpp"
|
||||||
"msvc/usb_com_helper.cpp"
|
"msvc/usb_com_helper.cpp"
|
||||||
)
|
)
|
||||||
set(EXTRA_WINDOWS_INCLUDES ${EXTRA_WINDOWS_INCLUDES}
|
set(EXTRA_WINDOWS_INCLUDES ${EXTRA_WINDOWS_INCLUDES}
|
||||||
"msvc"
|
"msvc"
|
||||||
)
|
)
|
||||||
|
else()
|
||||||
|
set(LIB_MATH m)
|
||||||
|
add_compile_options(-Wall) # -Wextra
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# Setup default port names
|
||||||
|
# =====================================
|
||||||
|
|
||||||
|
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
||||||
|
set(DEFAULT_PAR_PORT "/dev/parport0")
|
||||||
|
set(DEFAULT_SER_PORT "/dev/ttyS0")
|
||||||
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||||
|
set(DEFAULT_PAR_PORT "/dev/ppi0")
|
||||||
|
set(DEFAULT_SER_PORT "/dev/cuad0")
|
||||||
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "Solaris")
|
||||||
|
set(DEFAULT_PAR_PORT "/dev/printers/0")
|
||||||
|
set(DEFAULT_SER_PORT "/dev/term/a")
|
||||||
|
elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||||
|
set(DEFAULT_PAR_PORT "lpt1")
|
||||||
|
set(DEFAULT_SER_PORT "com1")
|
||||||
|
else()
|
||||||
|
set(DEFAULT_PAR_PORT "unknown")
|
||||||
|
set(DEFAULT_SER_PORT "unknown")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# =====================================
|
# =====================================
|
||||||
# Configure files
|
# Configure files
|
||||||
# =====================================
|
# =====================================
|
||||||
|
|
||||||
macro(configure_option option)
|
|
||||||
if(${${option}})
|
|
||||||
string(REGEX REPLACE "(.*)@${option}_BEGIN@(.*)@${option}_END@(.*)" "\\1\\2\\3" conf_file "${conf_file}")
|
|
||||||
else()
|
|
||||||
string(REGEX REPLACE "(.*)@${option}_BEGIN@(.*)@${option}_END@(.*)" "\\1\\3" conf_file "${conf_file}")
|
|
||||||
endif()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
file(READ avrdude.conf.in conf_file)
|
|
||||||
configure_option(HAVE_PARPORT)
|
|
||||||
configure_option(HAVE_LINUXGPIO)
|
|
||||||
configure_option(HAVE_LINUXSPI)
|
|
||||||
file(WRITE "${PROJECT_BINARY_DIR}/avrdude.conf.in" "${conf_file}")
|
|
||||||
|
|
||||||
configure_file(cmake_config.h.in ac_cfg.h)
|
configure_file(cmake_config.h.in ac_cfg.h)
|
||||||
configure_file("${PROJECT_BINARY_DIR}/avrdude.conf.in" avrdude.conf)
|
|
||||||
configure_file(avrdude.spec.in avrdude.spec)
|
configure_file(avrdude.spec.in avrdude.spec)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
configure_file(windows.rc.in windows.rc)
|
configure_file(windows.rc.in windows.rc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT avrdude.conf
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/avrdude.conf.in" avrdude.conf.in
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-D HAVE_PARPORT=${HAVE_PARPORT}
|
||||||
|
-D HAVE_LINUXSPI=${HAVE_LINUXSPI}
|
||||||
|
-D HAVE_LINUXGPIO=${HAVE_LINUXGPIO}
|
||||||
|
-D DEFAULT_PAR_PORT=${DEFAULT_PAR_PORT}
|
||||||
|
-D DEFAULT_SER_PORT=${DEFAULT_SER_PORT}
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/configure.cmake"
|
||||||
|
DEPENDS avrdude.conf.in
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(conf ALL DEPENDS avrdude.conf)
|
||||||
|
|
||||||
# =====================================
|
# =====================================
|
||||||
# Project
|
# Project
|
||||||
# =====================================
|
# =====================================
|
||||||
|
@ -118,6 +139,7 @@ add_library(libavrdude
|
||||||
avr.c
|
avr.c
|
||||||
avr910.c
|
avr910.c
|
||||||
avr910.h
|
avr910.h
|
||||||
|
avrcache.c
|
||||||
avrdude.h
|
avrdude.h
|
||||||
avrftdi.c
|
avrftdi.c
|
||||||
avrftdi.h
|
avrftdi.h
|
||||||
|
@ -203,6 +225,10 @@ add_library(libavrdude
|
||||||
updi_readwrite.h
|
updi_readwrite.h
|
||||||
updi_state.c
|
updi_state.c
|
||||||
updi_state.h
|
updi_state.h
|
||||||
|
urclock.c
|
||||||
|
urclock.h
|
||||||
|
urclock_hash.h
|
||||||
|
urclock_private.h
|
||||||
usbasp.c
|
usbasp.c
|
||||||
usbasp.h
|
usbasp.h
|
||||||
usbdevs.h
|
usbdevs.h
|
||||||
|
@ -217,6 +243,7 @@ add_library(libavrdude
|
||||||
xbee.c
|
xbee.c
|
||||||
${FLEX_Parser_OUTPUTS}
|
${FLEX_Parser_OUTPUTS}
|
||||||
${BISON_Parser_OUTPUTS}
|
${BISON_Parser_OUTPUTS}
|
||||||
|
"${EXTRA_WINDOWS_SOURCES}"
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties(libavrdude PROPERTIES
|
set_target_properties(libavrdude PROPERTIES
|
||||||
|
@ -252,9 +279,14 @@ add_executable(avrdude
|
||||||
main.c
|
main.c
|
||||||
term.c
|
term.c
|
||||||
term.h
|
term.h
|
||||||
|
avrintel.c
|
||||||
|
avrintel.h
|
||||||
|
developer_opts.c
|
||||||
|
developer_opts.h
|
||||||
|
developer_opts_private.h
|
||||||
whereami.c
|
whereami.c
|
||||||
whereami.h
|
whereami.h
|
||||||
"${EXTRA_WINDOWS_SOURCES}"
|
"${EXTRA_WINDOWS_RESOURCES}"
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(avrdude PUBLIC libavrdude)
|
target_link_libraries(avrdude PUBLIC libavrdude)
|
||||||
|
@ -265,9 +297,11 @@ target_link_libraries(avrdude PUBLIC libavrdude)
|
||||||
|
|
||||||
install(TARGETS avrdude DESTINATION bin)
|
install(TARGETS avrdude DESTINATION bin)
|
||||||
install(TARGETS libavrdude
|
install(TARGETS libavrdude
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
PUBLIC_HEADER DESTINATION include COMPONENT dev
|
PUBLIC_HEADER DESTINATION include COMPONENT dev
|
||||||
)
|
)
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/avrdude.conf" TYPE SYSCONF)
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/avrdude.conf" TYPE SYSCONF)
|
||||||
install(FILES avrdude.1 TYPE MAN)
|
install(FILES "avrdude.1"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
|
||||||
|
)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
|
||||||
#
|
#
|
||||||
# avrdude - A Downloader/Uploader for AVR device programmers
|
# avrdude - A Downloader/Uploader for AVR device programmers
|
||||||
# Copyright (C) 2003, 2004 Theodore A. Roth <troth@openavr.org>
|
# Copyright (C) 2003, 2004 Theodore A. Roth <troth@openavr.org>
|
||||||
|
@ -92,6 +93,7 @@ libavrdude_a_SOURCES = \
|
||||||
avr.c \
|
avr.c \
|
||||||
avr910.c \
|
avr910.c \
|
||||||
avr910.h \
|
avr910.h \
|
||||||
|
avrcache.c \
|
||||||
avrdude.h \
|
avrdude.h \
|
||||||
avrftdi.c \
|
avrftdi.c \
|
||||||
avrftdi.h \
|
avrftdi.h \
|
||||||
|
@ -179,6 +181,10 @@ libavrdude_a_SOURCES = \
|
||||||
updi_readwrite.h \
|
updi_readwrite.h \
|
||||||
updi_nvm.c \
|
updi_nvm.c \
|
||||||
updi_nvm.h \
|
updi_nvm.h \
|
||||||
|
urclock.c \
|
||||||
|
urclock.h \
|
||||||
|
urclock_hash.h \
|
||||||
|
urclock_private.h \
|
||||||
usbdevs.h \
|
usbdevs.h \
|
||||||
usb_hidapi.c \
|
usb_hidapi.c \
|
||||||
usb_libusb.c \
|
usb_libusb.c \
|
||||||
|
@ -198,6 +204,11 @@ avrdude_SOURCES = \
|
||||||
main.c \
|
main.c \
|
||||||
whereami.c \
|
whereami.c \
|
||||||
whereami.h \
|
whereami.h \
|
||||||
|
avrintel.c \
|
||||||
|
avrintel.h \
|
||||||
|
developer_opts.c \
|
||||||
|
developer_opts.h \
|
||||||
|
developer_opts_private.h \
|
||||||
term.c \
|
term.c \
|
||||||
term.h
|
term.h
|
||||||
|
|
||||||
|
|
|
@ -38,14 +38,13 @@
|
||||||
#include "arduino.h"
|
#include "arduino.h"
|
||||||
|
|
||||||
/* read signature bytes - arduino version */
|
/* read signature bytes - arduino version */
|
||||||
static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
static int arduino_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m) {
|
||||||
{
|
|
||||||
unsigned char buf[32];
|
unsigned char buf[32];
|
||||||
|
|
||||||
/* Signature byte reads are always 3 bytes. */
|
/* Signature byte reads are always 3 bytes. */
|
||||||
|
|
||||||
if (m->size < 3) {
|
if (m->size < 3) {
|
||||||
avrdude_message(MSG_INFO, "%s: memsize too small for sig byte read", progname);
|
pmsg_error("memsize too small for sig byte read");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,19 +56,16 @@ static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||||
if (serial_recv(&pgm->fd, buf, 5) < 0)
|
if (serial_recv(&pgm->fd, buf, 5) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (buf[0] == Resp_STK_NOSYNC) {
|
if (buf[0] == Resp_STK_NOSYNC) {
|
||||||
avrdude_message(MSG_INFO, "%s: stk500_cmd(): programmer is out of sync\n",
|
pmsg_error("programmer is out of sync\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
} else if (buf[0] != Resp_STK_INSYNC) {
|
} else if (buf[0] != Resp_STK_INSYNC) {
|
||||||
avrdude_message(MSG_INFO, "\n%s: arduino_read_sig_bytes(): (a) protocol error, "
|
msg_error("\n");
|
||||||
"expect=0x%02x, resp=0x%02x\n",
|
pmsg_error("protocol expects sync byte 0x%02x but got 0x%02x\n", Resp_STK_INSYNC, buf[0]);
|
||||||
progname, Resp_STK_INSYNC, buf[0]);
|
return -2;
|
||||||
return -2;
|
|
||||||
}
|
}
|
||||||
if (buf[4] != Resp_STK_OK) {
|
if (buf[4] != Resp_STK_OK) {
|
||||||
avrdude_message(MSG_INFO, "\n%s: arduino_read_sig_bytes(): (a) protocol error, "
|
msg_error("\n");
|
||||||
"expect=0x%02x, resp=0x%02x\n",
|
pmsg_error("protocol expects OK byte 0x%02x but got 0x%02x\n", Resp_STK_OK, buf[4]);
|
||||||
progname, Resp_STK_OK, buf[4]);
|
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +76,7 @@ static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int arduino_open(PROGRAMMER * pgm, char * port)
|
static int arduino_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
union pinfo pinfo;
|
union pinfo pinfo;
|
||||||
strcpy(pgm->port, port);
|
strcpy(pgm->port, port);
|
||||||
pinfo.serialinfo.baud = pgm->baudrate? pgm->baudrate: 115200;
|
pinfo.serialinfo.baud = pgm->baudrate? pgm->baudrate: 115200;
|
||||||
|
@ -118,8 +113,7 @@ static void arduino_close(PROGRAMMER * pgm)
|
||||||
|
|
||||||
const char arduino_desc[] = "Arduino programmer";
|
const char arduino_desc[] = "Arduino programmer";
|
||||||
|
|
||||||
void arduino_initpgm(PROGRAMMER * pgm)
|
void arduino_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* This is mostly a STK500; just the signature is read
|
/* This is mostly a STK500; just the signature is read
|
||||||
differently than on real STK500v1
|
differently than on real STK500v1
|
||||||
and the DTR signal is set when opening the serial port
|
and the DTR signal is set when opening the serial port
|
||||||
|
@ -130,4 +124,6 @@ void arduino_initpgm(PROGRAMMER * pgm)
|
||||||
pgm->read_sig_bytes = arduino_read_sig_bytes;
|
pgm->read_sig_bytes = arduino_read_sig_bytes;
|
||||||
pgm->open = arduino_open;
|
pgm->open = arduino_open;
|
||||||
pgm->close = arduino_close;
|
pgm->close = arduino_close;
|
||||||
|
|
||||||
|
disable_trailing_ff_removal(); /* so that arduino bootloader can ignore chip erase */
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#define arduino_h__
|
#define arduino_h__
|
||||||
|
|
||||||
extern const char arduino_desc[];
|
extern const char arduino_desc[];
|
||||||
void arduino_initpgm (PROGRAMMER * pgm);
|
void arduino_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
123
src/avr910.c
123
src/avr910.c
|
@ -57,8 +57,7 @@ struct pdata
|
||||||
static void avr910_setup(PROGRAMMER * pgm)
|
static void avr910_setup(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
|
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: avr910_setup(): Out of memory allocating private data\n",
|
pmsg_error("out of memory allocating private data\n");
|
||||||
progname);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
memset(pgm->cookie, 0, sizeof(struct pdata));
|
memset(pgm->cookie, 0, sizeof(struct pdata));
|
||||||
|
@ -71,40 +70,34 @@ static void avr910_teardown(PROGRAMMER * pgm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len)
|
static int avr910_send(const PROGRAMMER *pgm, char *buf, size_t len) {
|
||||||
{
|
|
||||||
return serial_send(&pgm->fd, (unsigned char *)buf, len);
|
return serial_send(&pgm->fd, (unsigned char *)buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len)
|
static int avr910_recv(const PROGRAMMER *pgm, char *buf, size_t len) {
|
||||||
{
|
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
|
rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: avr910_recv(): programmer is not responding\n",
|
pmsg_error("programmer is not responding\n");
|
||||||
progname);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_drain(PROGRAMMER * pgm, int display)
|
static int avr910_drain(const PROGRAMMER *pgm, int display) {
|
||||||
{
|
|
||||||
return serial_drain(&pgm->fd, display);
|
return serial_drain(&pgm->fd, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg)
|
static int avr910_vfy_cmd_sent(const PROGRAMMER *pgm, char *errmsg) {
|
||||||
{
|
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
avr910_recv(pgm, &c, 1);
|
avr910_recv(pgm, &c, 1);
|
||||||
if (c != '\r') {
|
if (c != '\r') {
|
||||||
avrdude_message(MSG_INFO, "%s: error: programmer did not respond to command: %s\n",
|
pmsg_error("programmer did not respond to command: %s\n", errmsg);
|
||||||
progname, errmsg);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -114,8 +107,7 @@ static int avr910_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg)
|
||||||
/*
|
/*
|
||||||
* issue the 'chip erase' command to the AVR device
|
* issue the 'chip erase' command to the AVR device
|
||||||
*/
|
*/
|
||||||
static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
static int avr910_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
avr910_send(pgm, "e", 1);
|
avr910_send(pgm, "e", 1);
|
||||||
if (avr910_vfy_cmd_sent(pgm, "chip erase") < 0)
|
if (avr910_vfy_cmd_sent(pgm, "chip erase") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -129,15 +121,13 @@ static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_enter_prog_mode(PROGRAMMER * pgm)
|
static int avr910_enter_prog_mode(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
avr910_send(pgm, "P", 1);
|
avr910_send(pgm, "P", 1);
|
||||||
return avr910_vfy_cmd_sent(pgm, "enter prog mode");
|
return avr910_vfy_cmd_sent(pgm, "enter prog mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_leave_prog_mode(PROGRAMMER * pgm)
|
static int avr910_leave_prog_mode(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
avr910_send(pgm, "L", 1);
|
avr910_send(pgm, "L", 1);
|
||||||
return avr910_vfy_cmd_sent(pgm, "leave prog mode");
|
return avr910_vfy_cmd_sent(pgm, "leave prog mode");
|
||||||
}
|
}
|
||||||
|
@ -146,8 +136,7 @@ static int avr910_leave_prog_mode(PROGRAMMER * pgm)
|
||||||
/*
|
/*
|
||||||
* issue the 'program enable' command to the AVR device
|
* issue the 'program enable' command to the AVR device
|
||||||
*/
|
*/
|
||||||
static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
static int avr910_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +144,7 @@ static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||||
/*
|
/*
|
||||||
* initialize the AVR device and prepare it to accept commands
|
* initialize the AVR device and prepare it to accept commands
|
||||||
*/
|
*/
|
||||||
static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
static int avr910_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
char id[8];
|
char id[8];
|
||||||
char sw[2];
|
char sw[2];
|
||||||
char hw[2];
|
char hw[2];
|
||||||
|
@ -185,16 +173,16 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
avr910_send(pgm, "p", 1);
|
avr910_send(pgm, "p", 1);
|
||||||
avr910_recv(pgm, &type, 1);
|
avr910_recv(pgm, &type, 1);
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "Found programmer: Id = \"%s\"; type = %c\n", id, type);
|
msg_notice("Programmer id = %s; type = %c\n", id, type);
|
||||||
avrdude_message(MSG_INFO, " Software Version = %c.%c; ", sw[0], sw[1]);
|
msg_notice("Software version = %c.%c; ", sw[0], sw[1]);
|
||||||
avrdude_message(MSG_INFO, "Hardware Version = %c.%c\n", hw[0], hw[1]);
|
msg_notice("Hardware version = %c.%c\n", hw[0], hw[1]);
|
||||||
|
|
||||||
/* See if programmer supports autoincrement of address. */
|
/* See if programmer supports autoincrement of address. */
|
||||||
|
|
||||||
avr910_send(pgm, "a", 1);
|
avr910_send(pgm, "a", 1);
|
||||||
avr910_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1);
|
avr910_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1);
|
||||||
if (PDATA(pgm)->has_auto_incr_addr == 'Y')
|
if (PDATA(pgm)->has_auto_incr_addr == 'Y')
|
||||||
avrdude_message(MSG_INFO, "Programmer supports auto addr increment.\n");
|
msg_notice("programmer supports auto addr increment\n");
|
||||||
|
|
||||||
/* Check support for buffered memory access, ignore if not available */
|
/* Check support for buffered memory access, ignore if not available */
|
||||||
|
|
||||||
|
@ -206,8 +194,8 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8;
|
PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8;
|
||||||
avr910_recv(pgm, &c, 1);
|
avr910_recv(pgm, &c, 1);
|
||||||
PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c;
|
PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c;
|
||||||
avrdude_message(MSG_INFO, "Programmer supports buffered memory access with "
|
msg_notice("programmer supports buffered memory access with "
|
||||||
"buffersize = %u bytes.\n",
|
"buffersize = %u bytes\n",
|
||||||
PDATA(pgm)->buffersize);
|
PDATA(pgm)->buffersize);
|
||||||
PDATA(pgm)->use_blockmode = 1;
|
PDATA(pgm)->use_blockmode = 1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -224,7 +212,7 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
/* Get list of devices that the programmer supports. */
|
/* Get list of devices that the programmer supports. */
|
||||||
|
|
||||||
avr910_send(pgm, "t", 1);
|
avr910_send(pgm, "t", 1);
|
||||||
avrdude_message(MSG_INFO, "\nProgrammer supports the following devices:\n");
|
msg_notice2("\nProgrammer supports the following devices:\n");
|
||||||
devtype_1st = 0;
|
devtype_1st = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
avr910_recv(pgm, &c, 1);
|
avr910_recv(pgm, &c, 1);
|
||||||
|
@ -234,20 +222,22 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
break;
|
break;
|
||||||
part = locate_part_by_avr910_devcode(part_list, c);
|
part = locate_part_by_avr910_devcode(part_list, c);
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, " Device code: 0x%02x = %s\n", c, part ? part->desc : "(unknown)");
|
msg_notice2(" Device code: 0x%02x = %s\n", c & 0xff, part? part->desc: "(unknown)");
|
||||||
|
|
||||||
/* FIXME: Need to lookup devcode and report the device. */
|
/* FIXME: Need to lookup devcode and report the device. */
|
||||||
|
|
||||||
if (p->avr910_devcode == c)
|
if (p->avr910_devcode == c)
|
||||||
dev_supported = 1;
|
dev_supported = 1;
|
||||||
};
|
};
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_notice2("\n");
|
||||||
|
|
||||||
if (!dev_supported) {
|
if (!dev_supported) {
|
||||||
avrdude_message(MSG_INFO, "%s: %s: selected device is not supported by programmer: %s\n",
|
if(ovsigck)
|
||||||
progname, ovsigck? "warning": "error", p->id);
|
pmsg_warning("selected device is not supported by programmer %s\n", p->id);
|
||||||
if (!ovsigck)
|
else {
|
||||||
|
pmsg_error("selected device is not supported by programmer %s\n", p->id);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* If the user forced the selection, use the first device
|
/* If the user forced the selection, use the first device
|
||||||
type that is supported by the programmer. */
|
type that is supported by the programmer. */
|
||||||
|
@ -264,8 +254,7 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
avr910_send(pgm, buf, 2);
|
avr910_send(pgm, buf, 2);
|
||||||
avr910_vfy_cmd_sent(pgm, "select device");
|
avr910_vfy_cmd_sent(pgm, "select device");
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE, "%s: avr910_devcode selected: 0x%02x\n",
|
pmsg_notice("avr910_devcode selected: 0x%02x\n", (unsigned) buf[1]);
|
||||||
progname, (unsigned)buf[1]);
|
|
||||||
|
|
||||||
avr910_enter_prog_mode(pgm);
|
avr910_enter_prog_mode(pgm);
|
||||||
|
|
||||||
|
@ -273,16 +262,14 @@ static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void avr910_disable(PROGRAMMER * pgm)
|
static void avr910_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void avr910_enable(PROGRAMMER * pgm)
|
static void avr910_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -293,7 +280,7 @@ static void avr910_enable(PROGRAMMER * pgm)
|
||||||
* transmit an AVR device command and return the results; 'cmd' and
|
* transmit an AVR device command and return the results; 'cmd' and
|
||||||
* 'res' must point to at least a 4 byte data buffer
|
* 'res' must point to at least a 4 byte data buffer
|
||||||
*/
|
*/
|
||||||
static int avr910_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
|
static int avr910_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
unsigned char *res)
|
unsigned char *res)
|
||||||
{
|
{
|
||||||
char buf[5];
|
char buf[5];
|
||||||
|
@ -318,8 +305,7 @@ static int avr910_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_parseextparms(PROGRAMMER * pgm, LISTID extparms)
|
static int avr910_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||||
{
|
|
||||||
LNODEID ln;
|
LNODEID ln;
|
||||||
const char *extended_param;
|
const char *extended_param;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
@ -331,27 +317,23 @@ static int avr910_parseextparms(PROGRAMMER * pgm, LISTID extparms)
|
||||||
int devcode;
|
int devcode;
|
||||||
if (sscanf(extended_param, "devcode=%i", &devcode) != 1 ||
|
if (sscanf(extended_param, "devcode=%i", &devcode) != 1 ||
|
||||||
devcode <= 0 || devcode > 255) {
|
devcode <= 0 || devcode > 255) {
|
||||||
avrdude_message(MSG_INFO, "%s: avr910_parseextparms(): invalid devcode '%s'\n",
|
pmsg_error("invalid devcode '%s'\n", extended_param);
|
||||||
progname, extended_param);
|
|
||||||
rv = -1;
|
rv = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_NOTICE2, "%s: avr910_parseextparms(): devcode overwritten as 0x%02x\n",
|
pmsg_notice2("avr910_parseextparms(): devcode overwritten as 0x%02x\n", devcode);
|
||||||
progname, devcode);
|
|
||||||
PDATA(pgm)->devcode = devcode;
|
PDATA(pgm)->devcode = devcode;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (strncmp(extended_param, "no_blockmode", strlen("no_blockmode")) == 0) {
|
if (strncmp(extended_param, "no_blockmode", strlen("no_blockmode")) == 0) {
|
||||||
avrdude_message(MSG_NOTICE2, "%s: avr910_parseextparms(-x): no testing for Blockmode\n",
|
pmsg_notice2("avr910_parseextparms(-x): no testing for Blockmode\n");
|
||||||
progname);
|
|
||||||
PDATA(pgm)->test_blockmode = 0;
|
PDATA(pgm)->test_blockmode = 0;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: avr910_parseextparms(): invalid extended parameter '%s'\n",
|
pmsg_error("invalid extended parameter '%s'\n", extended_param);
|
||||||
progname, extended_param);
|
|
||||||
rv = -1;
|
rv = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,8 +341,7 @@ static int avr910_parseextparms(PROGRAMMER * pgm, LISTID extparms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_open(PROGRAMMER * pgm, char * port)
|
static int avr910_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
union pinfo pinfo;
|
union pinfo pinfo;
|
||||||
/*
|
/*
|
||||||
* If baudrate was not specified use 19.200 Baud
|
* If baudrate was not specified use 19.200 Baud
|
||||||
|
@ -393,14 +374,12 @@ static void avr910_close(PROGRAMMER * pgm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void avr910_display(PROGRAMMER * pgm, const char * p)
|
static void avr910_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void avr910_set_addr(PROGRAMMER * pgm, unsigned long addr)
|
static void avr910_set_addr(const PROGRAMMER *pgm, unsigned long addr) {
|
||||||
{
|
|
||||||
char cmd[3];
|
char cmd[3];
|
||||||
|
|
||||||
cmd[0] = 'A';
|
cmd[0] = 'A';
|
||||||
|
@ -412,7 +391,7 @@ static void avr910_set_addr(PROGRAMMER * pgm, unsigned long addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avr910_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned long addr, unsigned char value)
|
unsigned long addr, unsigned char value)
|
||||||
{
|
{
|
||||||
char cmd[2];
|
char cmd[2];
|
||||||
|
@ -445,7 +424,7 @@ static int avr910_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avr910_read_byte_flash(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned long addr, unsigned char * value)
|
unsigned long addr, unsigned char * value)
|
||||||
{
|
{
|
||||||
char buf[2];
|
char buf[2];
|
||||||
|
@ -468,7 +447,7 @@ static int avr910_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avr910_read_byte_eeprom(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned long addr, unsigned char * value)
|
unsigned long addr, unsigned char * value)
|
||||||
{
|
{
|
||||||
avr910_set_addr(pgm, addr);
|
avr910_set_addr(pgm, addr);
|
||||||
|
@ -479,7 +458,7 @@ static int avr910_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avr910_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned long addr, unsigned char * value)
|
unsigned long addr, unsigned char * value)
|
||||||
{
|
{
|
||||||
if (strcmp(m->desc, "flash") == 0) {
|
if (strcmp(m->desc, "flash") == 0) {
|
||||||
|
@ -494,7 +473,7 @@ static int avr910_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avr910_paged_write_flash(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
|
@ -553,8 +532,8 @@ static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p,
|
static int avr910_paged_write_eeprom(const PROGRAMMER *pgm, const AVRPART *p,
|
||||||
AVRMEM * m,
|
const AVRMEM * m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
|
@ -582,7 +561,7 @@ static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avr910_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
|
@ -642,7 +621,7 @@ static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avr910_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
|
@ -719,12 +698,11 @@ static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
|
|
||||||
/* Signature byte reads are always 3 bytes. */
|
/* Signature byte reads are always 3 bytes. */
|
||||||
|
|
||||||
static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
static int avr910_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m) {
|
||||||
{
|
|
||||||
unsigned char tmp;
|
unsigned char tmp;
|
||||||
|
|
||||||
if (m->size < 3) {
|
if (m->size < 3) {
|
||||||
avrdude_message(MSG_INFO, "%s: memsize too small for sig byte read", progname);
|
pmsg_error("memsize too small for sig byte read");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,8 +718,7 @@ static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||||
|
|
||||||
const char avr910_desc[] = "Serial programmers using protocol described in application note AVR910";
|
const char avr910_desc[] = "Serial programmers using protocol described in application note AVR910";
|
||||||
|
|
||||||
void avr910_initpgm(PROGRAMMER * pgm)
|
void avr910_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "avr910");
|
strcpy(pgm->type, "avr910");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char avr910_desc[];
|
extern const char avr910_desc[];
|
||||||
void avr910_initpgm (PROGRAMMER * pgm);
|
void avr910_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,774 @@
|
||||||
|
/*
|
||||||
|
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||||
|
* Copyright (C) 2022 Stefan Rueger <stefan.rueger@urclocks.c>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
#include "ac_cfg.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "avrdude.h"
|
||||||
|
#include "libavrdude.h"
|
||||||
|
#include "avrintel.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Provides an API for cached bytewise access
|
||||||
|
*
|
||||||
|
* int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
|
||||||
|
* AVRMEM *mem, unsigned long addr, unsigned char *value);
|
||||||
|
*
|
||||||
|
* int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const
|
||||||
|
* AVRMEM *mem, unsigned long addr, unsigned char data);
|
||||||
|
*
|
||||||
|
* int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
*
|
||||||
|
* int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
*
|
||||||
|
* int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const
|
||||||
|
* AVRMEM *mem, unsigned int baseaddr);
|
||||||
|
*
|
||||||
|
* int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
*
|
||||||
|
* avr_read_byte_cached() and avr_write_byte_cached() use a cache if paged
|
||||||
|
* routines are available and if the device memory is EEPROM or flash,
|
||||||
|
* otherwise they fall back to pgm->read_byte() and pgm->write_byte(),
|
||||||
|
* respectively. Bytewise cached read always gets its data from the cache,
|
||||||
|
* possibly after reading a page from the device memory. Bytewise cached
|
||||||
|
* write with an address in memory range only ever modifies the cache. Any
|
||||||
|
* modifications are written to the device after calling avr_flush_cache() or
|
||||||
|
* when attempting to read or write from a location outside the address range
|
||||||
|
* of the device memory.
|
||||||
|
*
|
||||||
|
* avr_flush_cache() synchronises pending writes to EEPROM and flash with the
|
||||||
|
* device. With some programmer and part combinations, flash (and sometimes
|
||||||
|
* EEPROM, too) looks like a NOR memory, ie, one can only write 0 bits, not 1
|
||||||
|
* bits. When this is detected, either page erase is deployed (eg, with parts
|
||||||
|
* that have PDI/UPDI interfaces), or if that is not available, both EEPROM
|
||||||
|
* and flash caches are fully read in, a pgm->chip_erase() command is issued
|
||||||
|
* and both EEPROM and flash are written back to the device. Hence, it can
|
||||||
|
* take minutes to ensure that a single previously cleared bit is set and,
|
||||||
|
* therefore, this routine should be called sparingly.
|
||||||
|
*
|
||||||
|
* avr_chip_erase_cached() erases the chip and discards pending writes() to
|
||||||
|
* flash or EEPROM. It presets the flash cache to all 0xff alleviating the
|
||||||
|
* need to read from the device flash. However, if the programmer serves
|
||||||
|
* bootloaders (pgm->prog_modes & PM_SPM) then the flash cache is reset
|
||||||
|
* instead, necessitating flash memory be fetched from the device on first
|
||||||
|
* read; the reason for this is that bootloaders emulate chip erase and they
|
||||||
|
* won't overwrite themselves (some bootloaders, eg, optiboot ignore chip
|
||||||
|
* erase commands) making it truly unknowable what the flash contents on
|
||||||
|
* device is after a chip erase.
|
||||||
|
*
|
||||||
|
* For EEPROM avr_chip_erase_cached() concludes that it has been deleted if a
|
||||||
|
* previously cached EEPROM page that contained cleared bits now no longer
|
||||||
|
* has these clear bits on the device. Only with this evidence is the EEPROM
|
||||||
|
* cache preset to all 0xff otherwise the cache discards all pending writes
|
||||||
|
* to EEPROM and is left unchanged otherwise.
|
||||||
|
*
|
||||||
|
* The avr_page_erase_cached() function erases a page and synchronises it
|
||||||
|
* with the cache.
|
||||||
|
*
|
||||||
|
* Finally, avr_reset_cache() resets the cache without synchronising pending
|
||||||
|
* writes() to the device.
|
||||||
|
*
|
||||||
|
* This file also holds the following utility functions
|
||||||
|
*
|
||||||
|
* // Does the programmer/memory combo have paged memory access?
|
||||||
|
* int avr_has_paged_access(const PROGRAMMER *pgm, const AVRMEM *mem);
|
||||||
|
*
|
||||||
|
* // Read the page containing addr from the device into buf
|
||||||
|
* int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, unsigned char *buf);
|
||||||
|
*
|
||||||
|
* // Write the data page to the device into the page containing addr
|
||||||
|
* int avr_write_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, unsigned char *data);
|
||||||
|
*
|
||||||
|
* // Could memory region s1 be the result of a NOR-memory copy of s3 onto s2?
|
||||||
|
* int avr_is_and(const unsigned char *s1, const unsigned char *s2, const unsigned char *s3, size_t n);
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Paged access?
|
||||||
|
* - Programmer must have paged routines
|
||||||
|
* - Memory has positive page size, which is a power of two
|
||||||
|
* - Memory has positive size, which is a multiple of the page size
|
||||||
|
* - Memory is flash type or eeprom type
|
||||||
|
*
|
||||||
|
* Note that in this definition the page size can be 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
int avr_has_paged_access(const PROGRAMMER *pgm, const AVRMEM *mem) {
|
||||||
|
return pgm->paged_load && pgm->paged_write &&
|
||||||
|
mem->page_size > 0 && (mem->page_size & (mem->page_size-1)) == 0 &&
|
||||||
|
mem->size > 0 && mem->size % mem->page_size == 0 &&
|
||||||
|
(avr_mem_is_flash_type(mem) || avr_mem_is_eeprom_type(mem));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define fallback_read_byte (pgm->read_byte != avr_read_byte_cached? pgm->read_byte: avr_read_byte_default)
|
||||||
|
#define fallback_write_byte (pgm->write_byte != avr_write_byte_cached? pgm->write_byte: avr_write_byte_default)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the page containing addr from the device into buf
|
||||||
|
* - Caller to ensure buf has mem->page_size bytes
|
||||||
|
* - Part memory buffer mem is unaffected by this (though temporarily changed)
|
||||||
|
* - Uses read_byte() if memory page size is one, otherwise paged_load()
|
||||||
|
* - Fall back to bytewise read if paged_load() returned an error
|
||||||
|
* - On failure returns a negative value, on success a non-negative value, which is either
|
||||||
|
* + The number of bytes read by pgm->paged_load() if that succeeded
|
||||||
|
* + LIBAVRDUDE_SUCCESS (0) if the fallback of bytewise read succeeded
|
||||||
|
*/
|
||||||
|
int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, unsigned char *buf) {
|
||||||
|
if(!avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
int rc, pgsize = mem->page_size, base = addr & ~(pgsize-1);
|
||||||
|
unsigned char *pagecopy = cfg_malloc("avr_read_page_default()", pgsize);
|
||||||
|
|
||||||
|
if(pgsize == 1)
|
||||||
|
return fallback_read_byte(pgm, p, mem, addr, buf);
|
||||||
|
|
||||||
|
memcpy(pagecopy, mem->buf + base, pgsize);
|
||||||
|
if((rc = pgm->paged_load(pgm, p, mem, pgsize, base, pgsize)) >= 0)
|
||||||
|
memcpy(buf, mem->buf + base, pgsize);
|
||||||
|
memcpy(mem->buf + base, pagecopy, pgsize);
|
||||||
|
|
||||||
|
if(rc < 0 && pgm->read_byte != avr_read_byte_cached) {
|
||||||
|
rc = LIBAVRDUDE_SUCCESS;
|
||||||
|
for(int i=0; i<pgsize; i++) {
|
||||||
|
if(pgm->read_byte(pgm, p, mem, base+i, pagecopy+i) < 0) {
|
||||||
|
rc = LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(rc == LIBAVRDUDE_SUCCESS)
|
||||||
|
memcpy(buf, pagecopy, pgsize);
|
||||||
|
}
|
||||||
|
free(pagecopy);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write the data page to the device into the page containing addr
|
||||||
|
* - Caller to provide all mem->page_size bytes incl padding if any
|
||||||
|
* - Part memory buffer mem is unaffected by this (though temporarily changed)
|
||||||
|
* - Uses write_byte() if memory page size is one, otherwise paged_write()
|
||||||
|
*/
|
||||||
|
int avr_write_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, unsigned char *data) {
|
||||||
|
if(!avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
int rc, pgsize = mem->page_size, base = addr & ~(pgsize-1);
|
||||||
|
unsigned char *pagecopy = cfg_malloc("avr_write_page_default()", pgsize);
|
||||||
|
|
||||||
|
if(pgsize == 1)
|
||||||
|
return fallback_write_byte(pgm, p, mem, addr, *data);
|
||||||
|
|
||||||
|
memcpy(pagecopy, mem->buf + base, pgsize);
|
||||||
|
memcpy(mem->buf + base, data, pgsize);
|
||||||
|
rc = pgm->paged_write(pgm, p, mem, pgsize, base, pgsize);
|
||||||
|
memcpy(mem->buf + base, pagecopy, pgsize);
|
||||||
|
free(pagecopy);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Could memory region s1 be the result of a NOR-memory copy of s3 onto s2?
|
||||||
|
int avr_is_and(const unsigned char *s1, const unsigned char *s2, const unsigned char *s3, size_t n) {
|
||||||
|
while(n--)
|
||||||
|
if(*s1++ != (*s2++ & *s3++))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cacheAddress(int addr, const AVR_Cache *cp, const AVRMEM *mem) {
|
||||||
|
int cacheaddr = addr + (int) (mem->offset - cp->offset);
|
||||||
|
|
||||||
|
if(cacheaddr < 0 || cacheaddr >= cp->size) { // Should never happen (unless offsets wrong in avrdude.conf)
|
||||||
|
pmsg_error("%s cache address 0x%04x out of range [0, 0x%04x]\n", mem->desc, cacheaddr, cp->size-1);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mem->page_size != cp->page_size) { // Should never happen (unless incompatible page sizes in avrdude.conf)
|
||||||
|
pmsg_error("%s page size %d incompatible with cache page size %d\n", mem->desc, mem->page_size, cp->page_size);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cacheaddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int loadCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, int cacheaddr, int nlOnErr) {
|
||||||
|
int pgno = cacheaddr/cp->page_size;
|
||||||
|
|
||||||
|
if(!cp->iscached[pgno]) {
|
||||||
|
// Read cached section from device
|
||||||
|
int cachebase = cacheaddr & ~(cp->page_size-1);
|
||||||
|
if(avr_read_page_default(pgm, p, mem, addr & ~(cp->page_size-1), cp->cont + cachebase) < 0) {
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
if(nlOnErr && quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("unable to read %s page at addr 0x%04x\n", mem->desc, addr);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy last read device page, so we can later check for changes
|
||||||
|
memcpy(cp->copy + cachebase, cp->cont + cachebase, cp->page_size);
|
||||||
|
cp->iscached[pgno] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int initCache(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
|
AVRMEM *basemem = avr_locate_mem(p, cp == pgm->cp_flash? "flash": "eeprom");
|
||||||
|
|
||||||
|
if(!basemem || !avr_has_paged_access(pgm, basemem))
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
cp->size = basemem->size;
|
||||||
|
cp->page_size = basemem->page_size;
|
||||||
|
cp->offset = basemem->offset;
|
||||||
|
cp->cont = cfg_malloc("initCache()", cp->size);
|
||||||
|
cp->copy = cfg_malloc("initCache()", cp->size);
|
||||||
|
cp->iscached = cfg_malloc("initCache()", cp->size/cp->page_size);
|
||||||
|
|
||||||
|
if((pgm->prog_modes & PM_SPM) && avr_mem_is_flash_type(basemem)) { // Could be vector bootloader
|
||||||
|
// Caching the vector page gives control to the progammer that then can patch the reset vector
|
||||||
|
if(loadCachePage(cp, pgm, p, basemem, 0, 0, 0) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int writeCachePage(AVR_Cache *cp, const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int base, int nlOnErr) {
|
||||||
|
// Write modified page cont to device; if unsuccessful try bytewise access
|
||||||
|
if(avr_write_page_default(pgm, p, mem, base, cp->cont + base) < 0) {
|
||||||
|
if(pgm->read_byte != avr_read_byte_cached && pgm->write_byte != avr_write_byte_cached) {
|
||||||
|
for(int i=0; i < cp->page_size; i++)
|
||||||
|
if(cp->cont[base+i] != cp->copy[base+i])
|
||||||
|
if(pgm->write_byte(pgm, p, mem, base+i, cp->cont[base+i]) < 0 ||
|
||||||
|
pgm->read_byte(pgm, p, mem, base+i, cp->copy+base+i) < 0) {
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
if(nlOnErr && quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("%s access error at addr 0x%04x\n", mem->desc, base+i);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS; // Bytewise writes & reads successful
|
||||||
|
}
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
if(nlOnErr && quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("write %s page error at addr 0x%04x\n", mem->desc, base);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
// Read page back from device and update copy to what is on device
|
||||||
|
if(avr_read_page_default(pgm, p, mem, base, cp->copy + base) < 0) {
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
if(nlOnErr && quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("unable to read %s page at addr 0x%04x\n", mem->desc, base);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Does the memory region only haxe 0xff?
|
||||||
|
static int _is_all_0xff(const void *p, size_t n) {
|
||||||
|
const unsigned char *q = (const unsigned char *) p;
|
||||||
|
return n <= 0 || (*q == 0xff && memcmp(q, q+1, n-1) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// A coarse guess where any bootloader might start (prob underestimates the start)
|
||||||
|
static int guessBootStart(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
|
int bootstart = 0;
|
||||||
|
const AVR_Cache *cp = pgm->cp_flash;
|
||||||
|
|
||||||
|
if(p->prog_modes & PM_UPDI) // Modern AVRs put the bootloader at 0
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(p->n_boot_sections > 0 && p->boot_section_size > 0)
|
||||||
|
bootstart = cp->size - (p->boot_section_size<<(p->n_boot_sections-1));
|
||||||
|
|
||||||
|
if(bootstart <= cp->size/2 || bootstart >= cp->size)
|
||||||
|
bootstart = cp->size > 32768? cp->size - 16384: cp->size*3/4;
|
||||||
|
|
||||||
|
return bootstart & ~(cp->page_size-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Page erase but without error messages if it does not work
|
||||||
|
static int silent_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, unsigned int a) {
|
||||||
|
int bakverb = verbose;
|
||||||
|
verbose = -123;
|
||||||
|
int ret = pgm->page_erase? pgm->page_erase(pgm, p, m, a): -1;
|
||||||
|
verbose = bakverb;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
AVRMEM *mem;
|
||||||
|
AVR_Cache *cp;
|
||||||
|
int isflash, zopaddr, pgerase;
|
||||||
|
} CacheDesc_t;
|
||||||
|
|
||||||
|
|
||||||
|
// Write both EEPROM and flash caches to device and free them
|
||||||
|
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
|
CacheDesc_t mems[2] = {
|
||||||
|
{ avr_locate_mem(p, "flash"), pgm->cp_flash, 1, -1, 0 },
|
||||||
|
{ avr_locate_mem(p, "eeprom"), pgm->cp_eeprom, 0, -1, 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
int chpages = 0;
|
||||||
|
bool chiperase = 0;
|
||||||
|
// Count page changes and find a page that needs a clear bit set
|
||||||
|
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||||
|
AVRMEM *mem = mems[i].mem;
|
||||||
|
AVR_Cache *cp = mems[i].cp;
|
||||||
|
if(!mem || !cp->cont)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) {
|
||||||
|
if(cp->iscached[pgno])
|
||||||
|
if(memcmp(cp->copy + n, cp->cont + n, cp->page_size)) {
|
||||||
|
chpages++;
|
||||||
|
if(mems[i].zopaddr == -1 && !avr_is_and(cp->cont + n, cp->copy + n, cp->cont + n, cp->page_size))
|
||||||
|
mems[i].zopaddr = n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!chpages)
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
|
||||||
|
pmsg_info("synching cache to device ... ");
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
// Check whether page erase needed and working and whether chip erase needed
|
||||||
|
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||||
|
AVRMEM *mem = mems[i].mem;
|
||||||
|
AVR_Cache *cp = mems[i].cp;
|
||||||
|
|
||||||
|
if(!mem)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!cp->cont) // Ensure cache is initialised from now on
|
||||||
|
if(initCache(cp, pgm, p) < 0) {
|
||||||
|
if(quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("unable to initialise the cache\n");
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chiperase || mems[i].zopaddr < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int n=mems[i].zopaddr;
|
||||||
|
|
||||||
|
if(writeCachePage(cp, pgm, p, mem, n, 1) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
// Same? OK, can set cleared bit to one, "normal" memory
|
||||||
|
if(!memcmp(cp->copy + n, cp->cont + n, cp->page_size)) {
|
||||||
|
chpages--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Probably NOR memory, check out page erase
|
||||||
|
if(silent_page_erase(pgm, p, mem, n) >= 0) {
|
||||||
|
if(writeCachePage(cp, pgm, p, mem, n, 1) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
// Worked OK? Can use page erase on this memory
|
||||||
|
if(!memcmp(cp->copy + n, cp->cont + n, cp->page_size)) {
|
||||||
|
mems[i].pgerase = 1;
|
||||||
|
chpages--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
chiperase = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!chpages) {
|
||||||
|
msg_info("done\n");
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chiperase) {
|
||||||
|
if(quell_progress) {
|
||||||
|
msg_info("reading/chip erase/writing cycle needed ... ");
|
||||||
|
fflush(stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nrd = 0;
|
||||||
|
// Count read operations needed
|
||||||
|
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||||
|
AVRMEM *mem = mems[i].mem;
|
||||||
|
AVR_Cache *cp = mems[i].cp;
|
||||||
|
if(!mem)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size)
|
||||||
|
if(!cp->iscached[pgno])
|
||||||
|
nrd++;
|
||||||
|
}
|
||||||
|
|
||||||
|
report_progress(0, 1, "Reading");
|
||||||
|
if(nrd) {
|
||||||
|
// Read full flash and EEPROM
|
||||||
|
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||||
|
AVRMEM *mem = mems[i].mem;
|
||||||
|
AVR_Cache *cp = mems[i].cp;
|
||||||
|
if(!mem)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for(int ird = 0, pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) {
|
||||||
|
if(!cp->iscached[pgno]) {
|
||||||
|
report_progress(ird++, nrd, NULL);
|
||||||
|
if(loadCachePage(cp, pgm, p, mem, n, n, 1) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
report_progress(1, 0, NULL);
|
||||||
|
|
||||||
|
report_progress(0, 1, "Erasing");
|
||||||
|
if(avr_chip_erase(pgm, p) < 0) {
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
if(quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("chip erase failed\n");
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update cache copies after chip erase so that writing back is efficient
|
||||||
|
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||||
|
AVRMEM *mem = mems[i].mem;
|
||||||
|
AVR_Cache *cp = mems[i].cp;
|
||||||
|
if(!mem)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(mems[i].isflash) { // flash
|
||||||
|
memset(cp->copy, 0xff, cp->size); // record device memory as erased
|
||||||
|
if(pgm->prog_modes & PM_SPM) { // Bootloaders will not overwrite themselves
|
||||||
|
// Read back generously estimated bootloader section to avoid verification errors
|
||||||
|
int bootstart = guessBootStart(pgm, p);
|
||||||
|
int nbo = (cp->size - bootstart)/cp->page_size;
|
||||||
|
|
||||||
|
for(int ibo = 0, n = bootstart; n < cp->size; n += cp->page_size) {
|
||||||
|
report_progress(1+ibo++, nbo+2, NULL);
|
||||||
|
if(avr_read_page_default(pgm, p, mem, n, cp->copy + n) < 0) {
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
if(quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("flash read failed at addr 0x%04x\n", n);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { // EEPROM
|
||||||
|
// Don't know whether chip erase has zapped EEPROM
|
||||||
|
for(int n = 0; n < cp->size; n += cp->page_size) {
|
||||||
|
if(!_is_all_0xff(cp->copy + n, cp->page_size)) { // First page that had EEPROM data
|
||||||
|
if(avr_read_page_default(pgm, p, mem, n, cp->copy + n) < 0) {
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
if(quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("EEPROM read failed at addr 0x%04x\n", n);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
// EEPROM zapped by chip erase? Set all copy to 0xff
|
||||||
|
if(_is_all_0xff(cp->copy + n, cp->page_size))
|
||||||
|
memset(cp->copy, 0xff, cp->size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
report_progress(1, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nwr = 0;
|
||||||
|
// Count number of writes
|
||||||
|
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||||
|
AVRMEM *mem = mems[i].mem;
|
||||||
|
AVR_Cache *cp = mems[i].cp;
|
||||||
|
if(!mem)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size)
|
||||||
|
if(cp->iscached[pgno] && memcmp(cp->copy + n, cp->cont + n, cp->page_size))
|
||||||
|
nwr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
report_progress(0, 1, "Writing");
|
||||||
|
if(nwr) {
|
||||||
|
// Write all modified pages to the device
|
||||||
|
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||||
|
AVRMEM *mem = mems[i].mem;
|
||||||
|
AVR_Cache *cp = mems[i].cp;
|
||||||
|
if(!mem || !cp->cont)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for(int iwr = 0, pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) {
|
||||||
|
if(cp->iscached[pgno] && memcmp(cp->copy + n, cp->cont + n, cp->page_size)) {
|
||||||
|
if(!chiperase && mems[i].pgerase)
|
||||||
|
pgm->page_erase(pgm, p, mem, n);
|
||||||
|
if(writeCachePage(cp, pgm, p, mem, n, 1) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
if(memcmp(cp->copy + n, cp->cont + n, cp->page_size)) {
|
||||||
|
report_progress(1, -1, NULL);
|
||||||
|
if(quell_progress)
|
||||||
|
msg_info("\n");
|
||||||
|
pmsg_error("verification mismatch at %s page addr 0x%04x\n", mem->desc, n);
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
report_progress(iwr++, nwr, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
report_progress(1, 0, NULL);
|
||||||
|
|
||||||
|
msg_info(quell_progress? "done\n": "\n");
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read byte via a read/write cache
|
||||||
|
* - Used if paged routines available and if memory is EEPROM or flash
|
||||||
|
* - Otherwise fall back to pgm->read_byte()
|
||||||
|
* - Out of memory addr: synchronise cache and, if successful, pretend reading a zero
|
||||||
|
* - Cache is automagically created and initialised if needed
|
||||||
|
*/
|
||||||
|
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
|
unsigned long addr, unsigned char *value) {
|
||||||
|
|
||||||
|
// Use pgm->read_byte() if not EEPROM/flash or no paged access
|
||||||
|
if(!avr_has_paged_access(pgm, mem))
|
||||||
|
return fallback_read_byte(pgm, p, mem, addr, value);
|
||||||
|
|
||||||
|
// If address is out of range synchronise cache and, if successful, pretend reading a zero
|
||||||
|
if(addr >= (unsigned long) mem->size) {
|
||||||
|
if(avr_flush_cache(pgm, p) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
*value = 0;
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVR_Cache *cp = avr_mem_is_eeprom_type(mem)? pgm->cp_eeprom: pgm->cp_flash;
|
||||||
|
|
||||||
|
if(!cp->cont) // Init cache if needed
|
||||||
|
if(initCache(cp, pgm, p) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
int cacheaddr = cacheAddress((int) addr, cp, mem);
|
||||||
|
if(cacheaddr < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
// Ensure cache page is there
|
||||||
|
if(loadCachePage(cp, pgm, p, mem, addr, cacheaddr, 0) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
*value = cp->cont[cacheaddr];
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write byte via a read/write cache
|
||||||
|
* - Used if paged routines available and if memory is EEPROM or flash
|
||||||
|
* - Otherwise fall back to pgm->write_byte()
|
||||||
|
* - Out of memory addr: synchronise cache with device and return whether successful
|
||||||
|
* - If programmer indicates a readonly spot, return LIBAVRDUDE_SOFTFAIL
|
||||||
|
* - Cache is automagically created and initialised if needed
|
||||||
|
*/
|
||||||
|
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
|
unsigned long addr, unsigned char data) {
|
||||||
|
|
||||||
|
if(pgm->readonly && pgm->readonly(pgm, p, mem, addr))
|
||||||
|
return LIBAVRDUDE_SOFTFAIL;
|
||||||
|
|
||||||
|
// Use pgm->write_byte() if not EEPROM/flash or no paged access
|
||||||
|
if(!avr_has_paged_access(pgm, mem))
|
||||||
|
return fallback_write_byte(pgm, p, mem, addr, data);
|
||||||
|
|
||||||
|
// If address is out of range synchronise caches with device and return whether successful
|
||||||
|
if(addr >= (unsigned long) mem->size)
|
||||||
|
return avr_flush_cache(pgm, p);
|
||||||
|
|
||||||
|
AVR_Cache *cp = avr_mem_is_eeprom_type(mem)? pgm->cp_eeprom: pgm->cp_flash;
|
||||||
|
|
||||||
|
if(!cp->cont) // Init cache if needed
|
||||||
|
if(initCache(cp, pgm, p) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
int cacheaddr = cacheAddress((int) addr, cp, mem);
|
||||||
|
if(cacheaddr < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
// Ensure cache page is there
|
||||||
|
if(loadCachePage(cp, pgm, p, mem, addr, cacheaddr, 0) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
cp->cont[cacheaddr] = data;
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Erase the chip and set the cache accordingly
|
||||||
|
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
|
CacheDesc_t mems[2] = {
|
||||||
|
{ avr_locate_mem(p, "flash"), pgm->cp_flash, 1, -1, 0 },
|
||||||
|
{ avr_locate_mem(p, "eeprom"), pgm->cp_eeprom, 0, -1, 0 },
|
||||||
|
};
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if((rc = pgm->chip_erase(pgm, p)) < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||||
|
AVRMEM *mem = mems[i].mem;
|
||||||
|
AVR_Cache *cp = mems[i].cp;
|
||||||
|
|
||||||
|
if(!mem || !avr_has_paged_access(pgm, mem))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!cp->cont) // Init cache if needed
|
||||||
|
if(initCache(cp, pgm, p) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
if(mems[i].isflash) { // flash
|
||||||
|
if(pgm->prog_modes & PM_SPM) { // reset cache to unknown
|
||||||
|
memset(cp->iscached, 0, cp->size/cp->page_size);
|
||||||
|
} else { // preset all pages as erased
|
||||||
|
memset(cp->copy, 0xff, cp->size);
|
||||||
|
memset(cp->cont, 0xff, cp->size);
|
||||||
|
memset(cp->iscached, 1, cp->size/cp->page_size);
|
||||||
|
}
|
||||||
|
} else { // EEPROM: test whether cached pages were zapped
|
||||||
|
bool erasedee = 0;
|
||||||
|
for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size) {
|
||||||
|
if(cp->iscached[pgno]) {
|
||||||
|
if(!_is_all_0xff(cp->copy + n, cp->page_size)) { // Page has EEPROM data?
|
||||||
|
if(avr_read_page_default(pgm, p, mem, n, cp->copy + n) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
erasedee = _is_all_0xff(cp->copy + n, cp->page_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(erasedee) { // EEPROM was erased, set cache correspondingly
|
||||||
|
memset(cp->copy, 0xff, cp->size);
|
||||||
|
memset(cp->cont, 0xff, cp->size);
|
||||||
|
memset(cp->iscached, 1, cp->size/cp->page_size);
|
||||||
|
} else { // discard previous writes, but leave cache
|
||||||
|
for(int pgno = 0, n = 0; n < cp->size; pgno++, n += cp->page_size)
|
||||||
|
if(cp->iscached[pgno])
|
||||||
|
memcpy(cp->cont + n, cp->copy + n, cp->page_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Erase a page and synchronise it with the cache
|
||||||
|
int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
|
unsigned int uaddr) {
|
||||||
|
|
||||||
|
int addr = uaddr;
|
||||||
|
|
||||||
|
if(!avr_has_paged_access(pgm, mem) || addr < 0 || addr >= mem->size)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
if(mem->page_size == 1) {
|
||||||
|
if(fallback_write_byte(pgm, p, mem, uaddr, 0xff) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
} else {
|
||||||
|
if(silent_page_erase(pgm, p, mem, uaddr) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
AVR_Cache *cp = avr_mem_is_eeprom_type(mem)? pgm->cp_eeprom: pgm->cp_flash;
|
||||||
|
|
||||||
|
if(!cp->cont) // Init cache if needed
|
||||||
|
if(initCache(cp, pgm, p) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
int cacheaddr = cacheAddress(addr, cp, mem);
|
||||||
|
if(cacheaddr < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
// Invalidate this cache page and read back, ie, we don't trust the page_erase() routine
|
||||||
|
cp->iscached[cacheaddr/cp->page_size] = 0;
|
||||||
|
|
||||||
|
// Reload cache page
|
||||||
|
if(loadCachePage(cp, pgm, p, mem, (int) addr, cacheaddr, 0) < 0)
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
if(!_is_all_0xff(cp->cont + (cacheaddr & ~(cp->page_size-1)), cp->page_size))
|
||||||
|
return LIBAVRDUDE_GENERAL_FAILURE;
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Free cache(s) discarding any pending writes
|
||||||
|
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p_unused) {
|
||||||
|
AVR_Cache *mems[2] = { pgm->cp_flash, pgm->cp_eeprom, };
|
||||||
|
|
||||||
|
for(size_t i = 0; i < sizeof mems/sizeof*mems; i++) {
|
||||||
|
AVR_Cache *cp = mems[i];
|
||||||
|
if(cp->cont)
|
||||||
|
free(cp->cont);
|
||||||
|
if(cp->copy)
|
||||||
|
free(cp->copy);
|
||||||
|
if(cp->iscached)
|
||||||
|
free(cp->iscached);
|
||||||
|
memset(cp, 0, sizeof*cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LIBAVRDUDE_SUCCESS;
|
||||||
|
}
|
482
src/avrdude.1
482
src/avrdude.1
|
@ -18,7 +18,7 @@
|
||||||
.\"
|
.\"
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.Dd DATE November 22, 2021
|
.Dd July 12, 2022
|
||||||
.Os
|
.Os
|
||||||
.Dt AVRDUDE 1
|
.Dt AVRDUDE 1
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -31,6 +31,7 @@
|
||||||
.Op Fl B Ar bitclock
|
.Op Fl B Ar bitclock
|
||||||
.Op Fl c Ar programmer-id
|
.Op Fl c Ar programmer-id
|
||||||
.Op Fl C Ar config-file
|
.Op Fl C Ar config-file
|
||||||
|
.Op Fl A
|
||||||
.Op Fl D
|
.Op Fl D
|
||||||
.Op Fl e
|
.Op Fl e
|
||||||
.Oo Fl E Ar exitspec Ns
|
.Oo Fl E Ar exitspec Ns
|
||||||
|
@ -38,14 +39,12 @@
|
||||||
.Oc
|
.Oc
|
||||||
.Op Fl F
|
.Op Fl F
|
||||||
.Op Fl i Ar delay
|
.Op Fl i Ar delay
|
||||||
.Op Fl n logfile
|
.Op Fl l Ar logfile
|
||||||
.Op Fl n
|
.Op Fl n
|
||||||
.Op Fl O
|
.Op Fl O
|
||||||
.Op Fl P Ar port
|
.Op Fl P Ar port
|
||||||
.Op Fl q
|
.Op Fl q
|
||||||
.Op Fl s
|
|
||||||
.Op Fl t
|
.Op Fl t
|
||||||
.Op Fl u
|
|
||||||
.Op Fl U Ar memtype:op:filename:filefmt
|
.Op Fl U Ar memtype:op:filename:filefmt
|
||||||
.Op Fl v
|
.Op Fl v
|
||||||
.Op Fl x Ar extended_param
|
.Op Fl x Ar extended_param
|
||||||
|
@ -76,10 +75,12 @@ so, for the
|
||||||
based programmer, the MCU signals
|
based programmer, the MCU signals
|
||||||
.Ql /RESET ,
|
.Ql /RESET ,
|
||||||
.Ql SCK ,
|
.Ql SCK ,
|
||||||
.Ql MISO
|
.Ql SDI
|
||||||
and
|
and
|
||||||
.Ql MOSI
|
.Ql SDO
|
||||||
need to be connected to the parallel port. Optionally, some otherwise
|
of the AVR's SPI interface need to be connected to the
|
||||||
|
parallel port; older boards might use the labels MOSI for SDO or MISO for SDI.
|
||||||
|
Optionally, some otherwise
|
||||||
unused output pins of the parallel port can be used to supply power
|
unused output pins of the parallel port can be used to supply power
|
||||||
for the MCU part, so it is also possible to construct a passive
|
for the MCU part, so it is also possible to construct a passive
|
||||||
stand-alone programming device. Some status LEDs indicating the
|
stand-alone programming device. Some status LEDs indicating the
|
||||||
|
@ -99,10 +100,10 @@ work at all, or to work abysmally slow.
|
||||||
.Pp
|
.Pp
|
||||||
If you happen to have a Linux system with at least 4 hardware GPIOs
|
If you happen to have a Linux system with at least 4 hardware GPIOs
|
||||||
available (like almost all embedded Linux boards) you can do without
|
available (like almost all embedded Linux boards) you can do without
|
||||||
any additional hardware - just connect them to the MOSI, MISO, RESET
|
any additional hardware - just connect them to the SDO, SDI, RESET
|
||||||
and SCK pins on the AVR and use the linuxgpio programmer type. It bitbangs
|
and SCK pins on the AVR and use the linuxgpio programmer type. It bitbangs
|
||||||
the lines using the Linux sysfs GPIO interface. Of course, care should
|
the lines using the Linux sysfs GPIO interface. Of course, care should
|
||||||
be taken about voltage level compatibility. Also, although not strictrly
|
be taken about voltage level compatibility. Also, although not strictly
|
||||||
required, it is strongly advisable to protect the GPIO pins from
|
required, it is strongly advisable to protect the GPIO pins from
|
||||||
overcurrent situations in some way. The simplest would be to just put
|
overcurrent situations in some way. The simplest would be to just put
|
||||||
some resistors in series or better yet use a 3-state buffer driver like
|
some resistors in series or better yet use a 3-state buffer driver like
|
||||||
|
@ -115,7 +116,7 @@ programmer type can be used to directly connect to and program a chip
|
||||||
using the built in interfaces on the computer. The requirements to use
|
using the built in interfaces on the computer. The requirements to use
|
||||||
this type are that an SPI interface is exposed along with one GPIO
|
this type are that an SPI interface is exposed along with one GPIO
|
||||||
pin. The GPIO serves as the reset output since the Linux SPI drivers
|
pin. The GPIO serves as the reset output since the Linux SPI drivers
|
||||||
do not hold slave select down when a transfer is not occurring and thus
|
do not hold chip select down when a transfer is not occurring and thus
|
||||||
it cannot be used as the reset pin. A readily available level
|
it cannot be used as the reset pin. A readily available level
|
||||||
translator should be used between the SPI bus/reset GPIO and the chip
|
translator should be used between the SPI bus/reset GPIO and the chip
|
||||||
to avoid potentially damaging the computer's SPI controller in the
|
to avoid potentially damaging the computer's SPI controller in the
|
||||||
|
@ -148,9 +149,23 @@ programming mode. The programmer type is ``wiring''. Note that the -D option
|
||||||
will likely be required in this case, because the bootloader will rewrite the
|
will likely be required in this case, because the bootloader will rewrite the
|
||||||
program memory, but no true chip erase can be performed.
|
program memory, but no true chip erase can be performed.
|
||||||
.Pp
|
.Pp
|
||||||
The Arduino (which is very similar to the STK500 1.x) is supported via
|
Serial bootloaders that run a skeleton of the STK500 1.x protocol are
|
||||||
its own programmer type specification ``arduino''. This programmer works for
|
supported via their own programmer type ``arduino''. This programmer works
|
||||||
the Arduino Uno Rev3 or any AVR that runs the Optiboot bootloader.
|
for the Arduino Uno Rev3 or any AVR that runs the Optiboot bootloader.
|
||||||
|
.Pp
|
||||||
|
Urprotocol is a leaner version of the STK500 1.x protocol that is designed
|
||||||
|
to be backwards compatible with STK500 v1.x, and allows bootloaders to be
|
||||||
|
much smaller, e.g., as implemented in the urboot project
|
||||||
|
https://github.com/stefanrueger/urboot. The programmer type ``urclock''
|
||||||
|
caters for these urboot programmers. Owing to its backward compatibility,
|
||||||
|
bootloaders that can be served by the arduino programmer can normally
|
||||||
|
also be served by the urclock programmer. This may require specifying the
|
||||||
|
size of (to avrdude) unknown bootloaders in bytes using the
|
||||||
|
.Fl x Ar bootsize=<n>
|
||||||
|
option, which is necessary for the urclock programmer to enable it to
|
||||||
|
protect the bootloader from being overwritten. If an unknown bootloader
|
||||||
|
has EEPROM read/write capability then the option -x eepromrw informs
|
||||||
|
avrdude -c urclock of that capability.
|
||||||
.Pp
|
.Pp
|
||||||
The BusPirate is a versatile tool that can also be used as an AVR programmer.
|
The BusPirate is a versatile tool that can also be used as an AVR programmer.
|
||||||
A single BusPirate can be connected to up to 3 independent AVRs. See
|
A single BusPirate can be connected to up to 3 independent AVRs. See
|
||||||
|
@ -179,7 +194,7 @@ has a revision 1 hardware and firmware version of at least 5.37 (decimal).
|
||||||
For ATxmega devices, the JTAGICE3 is supported in PDI mode.
|
For ATxmega devices, the JTAGICE3 is supported in PDI mode.
|
||||||
.Pp
|
.Pp
|
||||||
Atmel-ICE (ARM/AVR) is supported in all modes (JTAG, PDI for Xmega, debugWIRE,
|
Atmel-ICE (ARM/AVR) is supported in all modes (JTAG, PDI for Xmega, debugWIRE,
|
||||||
ISP).
|
ISP, UPDI).
|
||||||
.Pp
|
.Pp
|
||||||
Atmel's XplainedPro boards, using the EDBG protocol (CMSIS-DAP compatible),
|
Atmel's XplainedPro boards, using the EDBG protocol (CMSIS-DAP compatible),
|
||||||
are supported using the "jtag3" programmer type.
|
are supported using the "jtag3" programmer type.
|
||||||
|
@ -210,13 +225,14 @@ has been compiled in
|
||||||
.Nm avrdude ,
|
.Nm avrdude ,
|
||||||
the avrftdi device adds support for many programmers using FTDI's 2232C/D/H
|
the avrftdi device adds support for many programmers using FTDI's 2232C/D/H
|
||||||
and 4232H parts running in MPSSE mode, which hard-codes (in the chip)
|
and 4232H parts running in MPSSE mode, which hard-codes (in the chip)
|
||||||
SCK to bit 1, MOSI to bit 2, and MISO to bit 3. Reset is usually bit 4.
|
SCK to bit 1, SDO to bit 2, and SDI to bit 3. Reset is usually bit 4.
|
||||||
.Pp
|
.Pp
|
||||||
The Atmel DFU bootloader is supported in both, FLIP protocol version 1
|
The Atmel DFU bootloader is supported in both, FLIP protocol version 1
|
||||||
(AT90USB* and ATmega*U* devices), as well as version 2 (Xmega devices).
|
(AT90USB* and ATmega*U* devices), as well as version 2 (Xmega devices).
|
||||||
See below for some hints about FLIP version 1 protocol behaviour.
|
See below for some hints about FLIP version 1 protocol behaviour.
|
||||||
.Pp
|
.Pp
|
||||||
The MPLAB(R) PICkit 4 and MPLAB(R) SNAP, are supported in ISP, PDI and UPDI mode.
|
The MPLAB(R) PICkit 4 and MPLAB(R) SNAP, are supported in JTAG, TPI, ISP,
|
||||||
|
PDI and UPDI mode.
|
||||||
The Curiosity Nano board is supported in UPDI mode. It is dubbed
|
The Curiosity Nano board is supported in UPDI mode. It is dubbed
|
||||||
.Dq PICkit on Board ,
|
.Dq PICkit on Board ,
|
||||||
thus the name
|
thus the name
|
||||||
|
@ -225,7 +241,7 @@ thus the name
|
||||||
SerialUPDI programmer implementation is based on Microchip's
|
SerialUPDI programmer implementation is based on Microchip's
|
||||||
.Em pymcuprog Li https://github.com/microchip-pic-avr-tools/pymcuprog
|
.Em pymcuprog Li https://github.com/microchip-pic-avr-tools/pymcuprog
|
||||||
utility, but it also contains some performance improvements included in
|
utility, but it also contains some performance improvements included in
|
||||||
Spence Kohde's
|
Spence Konde's
|
||||||
.Em DxCore
|
.Em DxCore
|
||||||
Arduino core
|
Arduino core
|
||||||
.Li https://github.com/SpenceKonde/DxCore .
|
.Li https://github.com/SpenceKonde/DxCore .
|
||||||
|
@ -253,7 +269,7 @@ The Teensy bootloader is supported for all AVR boards.
|
||||||
As the bootloader does not support reading from flash memory,
|
As the bootloader does not support reading from flash memory,
|
||||||
use the
|
use the
|
||||||
.Fl V
|
.Fl V
|
||||||
option to prevent AVRDUDE from verifing the flash memory.
|
option to prevent AVRDUDE from verifying the flash memory.
|
||||||
See the section on
|
See the section on
|
||||||
.Em extended parameters
|
.Em extended parameters
|
||||||
for Teensy specific options.
|
for Teensy specific options.
|
||||||
|
@ -294,7 +310,7 @@ file. Finally, a ``terminal'' mode is available that allows one to
|
||||||
interactively communicate with the MCU, and to display or program
|
interactively communicate with the MCU, and to display or program
|
||||||
individual memory cells.
|
individual memory cells.
|
||||||
On the STK500 and STK600 programmer, several operational parameters (target supply
|
On the STK500 and STK600 programmer, several operational parameters (target supply
|
||||||
voltage, target Aref voltage, master clock) can be examined and changed
|
voltage, target Aref voltage, programming clock) can be examined and changed
|
||||||
from within terminal mode as well.
|
from within terminal mode as well.
|
||||||
.Ss Options
|
.Ss Options
|
||||||
In order to control all the different operation modi, a number of options
|
In order to control all the different operation modi, a number of options
|
||||||
|
@ -302,10 +318,15 @@ need to be specified to
|
||||||
.Nm avrdude .
|
.Nm avrdude .
|
||||||
.Bl -tag -offset indent -width indent
|
.Bl -tag -offset indent -width indent
|
||||||
.It Fl p Ar partno
|
.It Fl p Ar partno
|
||||||
This is the only option that is mandatory for every invocation of
|
This option specifies the MCU connected to the programmer. The MCU
|
||||||
.Nm avrdude .
|
descriptions are read from the config file. For currently supported MCUs use
|
||||||
It specifies the type of the MCU connected to the programmer. These are read from the config file.
|
? as partno, which will print a list of partno ids and official part names.
|
||||||
For currently supported MCU types use ? as partno, this will print a list of partno ids and official part names on the terminal. (Both can be used with the -p option.)
|
Both can be used with the -p option. If -p ? is specified with a specific
|
||||||
|
programmer, see -c below, then only those parts are output that the
|
||||||
|
programmer expects to be able to handle, together with the programming
|
||||||
|
interface(s) that can be used in that combination. In reality there can be
|
||||||
|
deviations from this list, particularly if programming is directly via a
|
||||||
|
bootloader.
|
||||||
.Pp
|
.Pp
|
||||||
Following parts need special attention:
|
Following parts need special attention:
|
||||||
.Bl -tag -width "ATmega1234"
|
.Bl -tag -width "ATmega1234"
|
||||||
|
@ -324,22 +345,29 @@ and bit-bang programmers.
|
||||||
The ATtiny11 can only be
|
The ATtiny11 can only be
|
||||||
programmed in high-voltage serial mode.
|
programmed in high-voltage serial mode.
|
||||||
.El
|
.El
|
||||||
|
.It Fl p Ar wildcard/flags
|
||||||
|
Run developer options for MCUs that are matched by wildcard. Whilst
|
||||||
|
their main use is for developers some flags can be of utility for users, e.g.,
|
||||||
|
avrdude -p m328p/S outputs AVRDUDE's understanding of ATmega328P MCU properties;
|
||||||
|
for more information run avrdude -p x/h.
|
||||||
.It Fl b Ar baudrate
|
.It Fl b Ar baudrate
|
||||||
Override the RS-232 connection baud rate specified in the respective
|
Override the RS-232 connection baud rate specified in the respective
|
||||||
programmer's entry of the configuration file.
|
programmer's entry of the configuration file.
|
||||||
.It Fl B Ar bitclock
|
.It Fl B Ar bitclock
|
||||||
Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only).
|
Specify the bit clock period for the JTAG, PDI, TPI, UPDI, or ISP
|
||||||
The value is a floating-point number in microseconds.
|
interface. The value is a floating-point number in microseconds.
|
||||||
Alternatively, the value might be suffixed with "Hz", "kHz", or "MHz",
|
Alternatively, the value might be suffixed with "Hz", "kHz" or
|
||||||
in order to specify the bit clock frequency, rather than a period.
|
"MHz" in order to specify the bit clock frequency rather than a
|
||||||
The default value of the JTAG ICE results in about 1 microsecond bit
|
period. Some programmers default their bit clock value to a 1
|
||||||
clock period, suitable for target MCUs running at 4 MHz clock and
|
microsecond bit clock period, suitable for target MCUs running at 4
|
||||||
above.
|
MHz clock and above. Slower MCUs need a correspondingly higher bit
|
||||||
Unlike certain parameters in the STK500, the JTAG ICE resets all its
|
clock period. Some programmers reset their bit clock value to the
|
||||||
parameters to default values when the programming software signs
|
default value when the programming software signs off, whilst others
|
||||||
off from the ICE, so for MCUs running at lower clock speeds, this
|
store the last used bit clock value. It is recommended to always
|
||||||
parameter must be specified on the command-line.
|
specify the bit clock if read/write speed is important.
|
||||||
You can use the 'default_bitclock' keyword in your
|
You can use the 'default_bitclock' keyword in your
|
||||||
|
.Pa ${HOME}/.config/avrdude/avrdude.rc
|
||||||
|
or
|
||||||
.Pa ${HOME}/.avrduderc
|
.Pa ${HOME}/.avrduderc
|
||||||
file to assign a default value to keep from having to specify this
|
file to assign a default value to keep from having to specify this
|
||||||
option on every invocation.
|
option on every invocation.
|
||||||
|
@ -353,11 +381,23 @@ through the use of a config file to make
|
||||||
work with different programmers as long as the programmer supports the
|
work with different programmers as long as the programmer supports the
|
||||||
Atmel AVR serial program method. You can use the 'default_programmer'
|
Atmel AVR serial program method. You can use the 'default_programmer'
|
||||||
keyword in your
|
keyword in your
|
||||||
|
.Pa ${HOME}/.config/avrdude/avrdude.rc
|
||||||
|
or
|
||||||
.Pa ${HOME}/.avrduderc
|
.Pa ${HOME}/.avrduderc
|
||||||
file to assign a default programmer to keep from having to specify
|
file to assign a default programmer to keep from having to specify
|
||||||
this option on every invocation.
|
this option on every invocation.
|
||||||
A full list of all supported programmers is output to the terminal
|
A full list of all supported programmers is output to the terminal
|
||||||
by using ? as programmer-id.
|
by using ? as programmer-id.
|
||||||
|
If -c ? is specified with a specific part, see
|
||||||
|
-p above, then only those programmers are output that expect
|
||||||
|
to be able to handle this part, together with the programming interface(s) that can be
|
||||||
|
used in that combination. In reality there can be deviations from this list,
|
||||||
|
particularly if programming is directly via a bootloader.
|
||||||
|
.It Fl c Ar wildcard/flags
|
||||||
|
Run developer options for programmers that are matched by wildcard. Whilst
|
||||||
|
their main use is for developers some flags can be of utility for users, e.g.,
|
||||||
|
avrdude -c usbtiny/S shows AVRDUDE's understanding of usbtiny's properties;
|
||||||
|
for more information run avrdude -c x/h.
|
||||||
.It Fl C Ar config-file
|
.It Fl C Ar config-file
|
||||||
Use the specified config file to load configuration data. This file
|
Use the specified config file to load configuration data. This file
|
||||||
contains all programmer and part definitions that
|
contains all programmer and part definitions that
|
||||||
|
@ -376,6 +416,20 @@ files. This can be used to add entries to the configuration
|
||||||
without patching your system wide configuration file. It can be used
|
without patching your system wide configuration file. It can be used
|
||||||
several times, the files are read in same order as given on the command
|
several times, the files are read in same order as given on the command
|
||||||
line.
|
line.
|
||||||
|
.It Fl A
|
||||||
|
Disable the automatic removal of trailing-0xFF sequences in file
|
||||||
|
input that is to be programmed to flash and in AVR reads from
|
||||||
|
flash memory. Normally, trailing 0xFFs can be discarded, as flash
|
||||||
|
programming requires the memory be erased to 0xFF beforehand.
|
||||||
|
.Fl A
|
||||||
|
should be used when the programmer hardware, or bootloader
|
||||||
|
software for that matter, does not carry out chip erase and
|
||||||
|
instead handles the memory erase on a page level. Popular
|
||||||
|
Arduino bootloaders exhibit this behaviour; for this reason
|
||||||
|
.Fl A
|
||||||
|
is engaged by default when specifying
|
||||||
|
. Fl c
|
||||||
|
arduino.
|
||||||
.It Fl D
|
.It Fl D
|
||||||
Disable auto erase for flash. When the
|
Disable auto erase for flash. When the
|
||||||
.Fl U
|
.Fl U
|
||||||
|
@ -389,6 +443,10 @@ use page erase before writing each page so no explicit chip erase
|
||||||
is required.
|
is required.
|
||||||
Note however that any page not affected by the current operation
|
Note however that any page not affected by the current operation
|
||||||
will retain its previous contents.
|
will retain its previous contents.
|
||||||
|
Setting
|
||||||
|
.Fl D
|
||||||
|
implies
|
||||||
|
.Fl A.
|
||||||
.It Fl e
|
.It Fl e
|
||||||
Causes a chip erase to be executed. This will reset the contents of the
|
Causes a chip erase to be executed. This will reset the contents of the
|
||||||
flash ROM and EEPROM to the value
|
flash ROM and EEPROM to the value
|
||||||
|
@ -401,7 +459,7 @@ contents would exclusively cause bits to be programmed from the value
|
||||||
.Ql 1
|
.Ql 1
|
||||||
to
|
to
|
||||||
.Ql 0 .
|
.Ql 0 .
|
||||||
Note that in order to reprogram EERPOM cells, no explicit prior chip
|
Note that in order to reprogram EEPROM cells, no explicit prior chip
|
||||||
erase is required since the MCU provides an auto-erase cycle in that
|
erase is required since the MCU provides an auto-erase cycle in that
|
||||||
case before programming the cell.
|
case before programming the cell.
|
||||||
.It Xo Fl E Ar exitspec Ns
|
.It Xo Fl E Ar exitspec Ns
|
||||||
|
@ -434,11 +492,17 @@ MCU type, a previous invocation of
|
||||||
.Nm
|
.Nm
|
||||||
with this option specified is one of the possible ways to guarantee this
|
with this option specified is one of the possible ways to guarantee this
|
||||||
condition.
|
condition.
|
||||||
|
.Em reset
|
||||||
|
is supported by the linuxspi and flip2 programmer options, as well as all
|
||||||
|
parallel port based programmers.
|
||||||
.It Ar noreset
|
.It Ar noreset
|
||||||
The
|
The
|
||||||
.Ql /RESET
|
.Ql /RESET
|
||||||
line will be deactivated at program exit, thus allowing the MCU target
|
line will be deactivated at program exit, thus allowing the MCU target
|
||||||
program to run while the programming hardware remains connected.
|
program to run while the programming hardware remains connected.
|
||||||
|
.Em noreset
|
||||||
|
is supported by the linuxspi and flip2 programmer options, as well as all
|
||||||
|
parallel port based programmers.
|
||||||
.It Ar vcc
|
.It Ar vcc
|
||||||
This option will leave those parallel port pins active
|
This option will leave those parallel port pins active
|
||||||
.Pq \&i. \&e. Em high
|
.Pq \&i. \&e. Em high
|
||||||
|
@ -474,6 +538,8 @@ actual connection to a target controller), this option can be used
|
||||||
together with
|
together with
|
||||||
.Fl t
|
.Fl t
|
||||||
to continue in terminal mode.
|
to continue in terminal mode.
|
||||||
|
Moreover, the option allows to continue despite failed initialization
|
||||||
|
of connection between a programmer and a target.
|
||||||
.It Fl i Ar delay
|
.It Fl i Ar delay
|
||||||
For bitbang-type programmers, delay for approximately
|
For bitbang-type programmers, delay for approximately
|
||||||
.Ar delay
|
.Ar delay
|
||||||
|
@ -606,7 +672,10 @@ Note: The ability to handle IPv6 hostnames and addresses is limited to
|
||||||
Posix systems (by now).
|
Posix systems (by now).
|
||||||
.It Fl q
|
.It Fl q
|
||||||
Disable (or quell) output of the progress bar while reading or writing
|
Disable (or quell) output of the progress bar while reading or writing
|
||||||
to the device. Specify it a second time for even quieter operation.
|
to the device. Specify it more often for even quieter operations.
|
||||||
|
.It Fl s, u
|
||||||
|
These options used to control the obsolete "safemode" feature which
|
||||||
|
is no longer present. They are silently ignored for backwards compatibility.
|
||||||
.It Fl t
|
.It Fl t
|
||||||
Tells
|
Tells
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -690,6 +759,8 @@ can be one of:
|
||||||
.Bl -tag -width sss
|
.Bl -tag -width sss
|
||||||
.It Ar i
|
.It Ar i
|
||||||
Intel Hex
|
Intel Hex
|
||||||
|
.It Ar I
|
||||||
|
Intel Hex with comments on download and tolerance of checksum errors on upload
|
||||||
.It Ar s
|
.It Ar s
|
||||||
Motorola S-record
|
Motorola S-record
|
||||||
.It Ar r
|
.It Ar r
|
||||||
|
@ -714,14 +785,17 @@ fuse bit settings.
|
||||||
hexadecimal; each value will get the string
|
hexadecimal; each value will get the string
|
||||||
.Em 0x
|
.Em 0x
|
||||||
prepended.
|
prepended.
|
||||||
|
Only valid on output.
|
||||||
.It Ar o
|
.It Ar o
|
||||||
octal; each value will get a
|
octal; each value will get a
|
||||||
.Em 0
|
.Em 0
|
||||||
prepended unless it is less than 8 in which case it gets no prefix.
|
prepended unless it is less than 8 in which case it gets no prefix.
|
||||||
|
Only valid on output.
|
||||||
.It Ar b
|
.It Ar b
|
||||||
binary; each value will get the string
|
binary; each value will get the string
|
||||||
.Em 0b
|
.Em 0b
|
||||||
prepended.
|
prepended.
|
||||||
|
Only valid on output.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The default is to use auto detection for input files, and raw binary
|
The default is to use auto detection for input files, and raw binary
|
||||||
|
@ -771,30 +845,128 @@ abbreviated to the shortest unambiguous form. Terminal mode provides
|
||||||
a command history using
|
a command history using
|
||||||
.Xr readline 3 ,
|
.Xr readline 3 ,
|
||||||
so previously entered command lines can be recalled and edited. The
|
so previously entered command lines can be recalled and edited. The
|
||||||
following commands are currently implemented:
|
following commands are currently implemented for all programmers:
|
||||||
.Bl -tag -offset indent -width indent
|
.Bl -tag -offset indent -width indent
|
||||||
.It Ar dump memtype addr nbytes
|
.It Ar dump memory addr len
|
||||||
Read
|
Read
|
||||||
.Ar nbytes
|
.Ar len
|
||||||
bytes from the specified memory area, and display them in the usual
|
bytes from the specified memory area, and display them in the usual
|
||||||
hexadecimal and ASCII form.
|
hexadecimal and ASCII form.
|
||||||
.It Ar dump
|
.It Ar dump memory addr ...
|
||||||
|
Read all bytes from the specified memory starting at address
|
||||||
|
.Ar addr,
|
||||||
|
and display them.
|
||||||
|
.It Ar dump memory addr
|
||||||
|
Read 256 bytes from the specified memory area, and display them.
|
||||||
|
.It Ar dump memory ...
|
||||||
|
Read all bytes from the specified memory, and display them.
|
||||||
|
.It Ar dump memory
|
||||||
Continue dumping the memory contents for another
|
Continue dumping the memory contents for another
|
||||||
.Ar nbytes
|
.Ar 256
|
||||||
where the previous
|
bytes where the previous
|
||||||
.Ar dump
|
.Ar dump
|
||||||
command left off.
|
command left off.
|
||||||
.It Ar write memtype addr byte1 ... byteN
|
.It Ar read
|
||||||
|
can be used as an alias for dump
|
||||||
|
.It Ar write memory addr data[,] {data[,]}
|
||||||
Manually program the respective memory cells, starting at address
|
Manually program the respective memory cells, starting at address
|
||||||
.Ar addr ,
|
.Ar addr ,
|
||||||
using the values
|
using the data items provided.
|
||||||
.Ar byte1
|
The terminal implements reading from and writing to flash and EEPROM type
|
||||||
through
|
memories normally through a cache and paged access functions. All other
|
||||||
.Ar byteN .
|
memories are directly written to without use of a cache. Some
|
||||||
This feature is not implemented for bank-addressed memories such as
|
older parts without paged access will also have flash and EEPROM directly
|
||||||
the flash memory of ATMega devices.
|
accessed without cache.
|
||||||
|
.Pp
|
||||||
|
.Ar data
|
||||||
|
can be hexadecimal, octal or decimal integers, floating point numbers
|
||||||
|
or C-style strings and characters. For integers, an optional case-insensitive
|
||||||
|
suffix specifies the data size: HH 8 bit, H/S 16 bit, L 32 bit, LL 64 bit.
|
||||||
|
Suffix D indicates a 64-bit double, F a 32-bit float, whilst a floating point
|
||||||
|
number without suffix defaults to 32-bit float. Hexadecimal floating point
|
||||||
|
notation is supported. An ambiguous trailing suffix, e.g., 0x1.8D, is read as
|
||||||
|
no-suffix float where D is part of the mantissa; use a zero exponent 0x1.8p0D
|
||||||
|
to clarify.
|
||||||
|
.Pp
|
||||||
|
An optional U suffix makes integers unsigned. Ordinary 0x hex integers are
|
||||||
|
always treated as unsigned. +0x or -0x hex numbers are treated as signed
|
||||||
|
unless they have a U suffix. Unsigned integers cannot be larger than 2^64-1.
|
||||||
|
If n is an unsigned integer then -n is also a valid unsigned integer as in C.
|
||||||
|
Signed integers must fall into the [-2^63, 2^63-1] range or a correspondingly
|
||||||
|
smaller range when a suffix specifies a smaller type.
|
||||||
|
.Pp
|
||||||
|
Ordinary 0x hex integers with n hex digits (counting leading zeros) use the
|
||||||
|
smallest size of one, two, four and eight bytes that can accommodate any
|
||||||
|
n-digit hex integer. If an integer suffix specifies a size explicitly the
|
||||||
|
corresponding number of least significant bytes are written, and a warning
|
||||||
|
shown if the number does not fit into the desired representation. Otherwise,
|
||||||
|
unsigned integers occupy the smallest of one, two, four or eight bytes
|
||||||
|
needed. Signed numbers are allowed to fit into the smallest signed or
|
||||||
|
smallest unsigned representation: For example, 255 is stored as one byte as
|
||||||
|
255U would fit in one byte, though as a signed number it would not fit into a
|
||||||
|
one-byte interval [-128, 127]. The number -1 is stored in one byte whilst -1U
|
||||||
|
needs eight bytes as it is the same as 0xFFFFffffFFFFffffU.
|
||||||
|
.Pp
|
||||||
|
One trailing comma at the end of
|
||||||
|
.Ar data
|
||||||
|
items is ignored to facilitate copy & paste of lists.
|
||||||
|
.It Ar write memory addr len data[,] {data[,]} ...
|
||||||
|
The ellipsis ... form writes <len> bytes padded by repeating the last
|
||||||
|
.Ar data
|
||||||
|
item.
|
||||||
|
.It Ar flush
|
||||||
|
Synchronise with the device all pending cached writes to EEPROM or flash.
|
||||||
|
With some programmer and part combinations, flash (and sometimes EEPROM,
|
||||||
|
too) looks like a NOR memory, ie, one can only write 0 bits, not 1 bits.
|
||||||
|
When this is detected, either page erase is deployed (e.g., with parts that
|
||||||
|
have PDI/UPDI interfaces), or if that is not available, both EEPROM and
|
||||||
|
flash caches are fully read in, a chip erase command is issued and both
|
||||||
|
EEPROM and flash are written back to the device. Hence, it can take
|
||||||
|
minutes to ensure that a single previously cleared bit is set and,
|
||||||
|
therefore, this command should be used sparingly.
|
||||||
|
.It Ar abort
|
||||||
|
Normally, caches are only ever
|
||||||
|
actually written to the device when using the
|
||||||
|
.Ar flush
|
||||||
|
command, at the end of the terminal session after typing
|
||||||
|
.Ar quit ,
|
||||||
|
or after EOF on input is encountered. The abort command resets
|
||||||
|
the cache discarding all previous writes to the flash and EEPROM cache.
|
||||||
.It Ar erase
|
.It Ar erase
|
||||||
Perform a chip erase.
|
Perform a chip erase and discard all pending writes to EEPROM and flash.
|
||||||
|
.It Ar sig
|
||||||
|
Display the device signature bytes.
|
||||||
|
.It Ar part
|
||||||
|
Display the current part settings and parameters. Includes chip
|
||||||
|
specific information including all memory types supported by the
|
||||||
|
device, read/write timing, etc.
|
||||||
|
.It Ar verbose Op Ar level
|
||||||
|
Change (when
|
||||||
|
.Ar level
|
||||||
|
is provided), or display the verbosity level.
|
||||||
|
The initial verbosity level is controlled by the number of
|
||||||
|
.Fl v
|
||||||
|
options given on the commandline.
|
||||||
|
.It Ar quell Op Ar level
|
||||||
|
Change (when
|
||||||
|
.Ar level
|
||||||
|
is provided), or display the quell level. 1 is used to suppress progress reports.
|
||||||
|
2 or higher yields in progressively quieter operations.
|
||||||
|
The initial quell level is controlled by the number of
|
||||||
|
.Fl q
|
||||||
|
options given on the commandline.
|
||||||
|
.It Ar \&?
|
||||||
|
.It Ar help
|
||||||
|
Give a short on-line summary of the available commands.
|
||||||
|
.It Ar quit
|
||||||
|
Leave terminal mode and thus
|
||||||
|
.Nm avrdude .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The terminal commands below may only be implemented on some specific programmers, and may therefore not be available in the help menu.
|
||||||
|
.Bl -tag -offset indent -width indent
|
||||||
|
.It pgerase memory addr
|
||||||
|
Erase one page of the memory specified.
|
||||||
.It Ar send b1 b2 b3 b4
|
.It Ar send b1 b2 b3 b4
|
||||||
Send raw instruction codes to the AVR device. If you need access to a
|
Send raw instruction codes to the AVR device. If you need access to a
|
||||||
feature of an AVR part that is not directly supported by
|
feature of an AVR part that is not directly supported by
|
||||||
|
@ -803,24 +975,18 @@ this command allows you to use it, even though
|
||||||
.Nm
|
.Nm
|
||||||
does not implement the command. When using direct SPI mode, up to 3 bytes
|
does not implement the command. When using direct SPI mode, up to 3 bytes
|
||||||
can be omitted.
|
can be omitted.
|
||||||
.It Ar sig
|
|
||||||
Display the device signature bytes.
|
|
||||||
.It Ar spi
|
.It Ar spi
|
||||||
Enter direct SPI mode. The
|
Enter direct SPI mode. The
|
||||||
.Em pgmled
|
.Em pgmled
|
||||||
pin acts as slave select.
|
pin acts as chip select.
|
||||||
.Em Only supported on parallel bitbang programmers, and partially by USBtiny.
|
.Em Supported on parallel bitbang programmers, and partially by USBtiny.
|
||||||
.It Ar part
|
|
||||||
Display the current part settings and parameters. Includes chip
|
|
||||||
specific information including all memory types supported by the
|
|
||||||
device, read/write timing, etc.
|
|
||||||
.It Ar pgm
|
.It Ar pgm
|
||||||
Return to programming mode (from direct SPI mode).
|
Return to programming mode (from direct SPI mode).
|
||||||
.It Ar vtarg voltage
|
.It Ar vtarg voltage
|
||||||
Set the target's supply voltage to
|
Set the target's supply voltage to
|
||||||
.Ar voltage
|
.Ar voltage
|
||||||
Volts.
|
Volts.
|
||||||
.Em Only supported on the STK500 and STK600 programmer.
|
.Em Supported on the STK500 and STK600 programmer.
|
||||||
.It Ar varef Oo Ar channel Oc Ar voltage
|
.It Ar varef Oo Ar channel Oc Ar voltage
|
||||||
Set the adjustable voltage source to
|
Set the adjustable voltage source to
|
||||||
.Ar voltage
|
.Ar voltage
|
||||||
|
@ -832,9 +998,9 @@ On the Atmel STK600, two reference voltages are available, which
|
||||||
can be selected by the optional
|
can be selected by the optional
|
||||||
.Ar channel
|
.Ar channel
|
||||||
argument (either 0 or 1).
|
argument (either 0 or 1).
|
||||||
.Em Only supported on the STK500 and STK600 programmer.
|
.Em Supported on the STK500 and STK600 programmer.
|
||||||
.It Ar fosc freq Ns Op M Ns \&| Ns k
|
.It Ar fosc freq Ns Op M Ns \&| Ns k
|
||||||
Set the master oscillator to
|
Set the programming oscillator to
|
||||||
.Ar freq
|
.Ar freq
|
||||||
Hz.
|
Hz.
|
||||||
An optional trailing letter
|
An optional trailing letter
|
||||||
|
@ -842,17 +1008,16 @@ An optional trailing letter
|
||||||
multiplies by 1E6, a trailing letter
|
multiplies by 1E6, a trailing letter
|
||||||
.Ar \&k
|
.Ar \&k
|
||||||
by 1E3.
|
by 1E3.
|
||||||
.Em Only supported on the STK500 and STK600 programmer.
|
.Em Supported on the STK500 and STK600 programmer.
|
||||||
.It Ar fosc off
|
.It Ar fosc off
|
||||||
Turn the master oscillator off.
|
Turn the programming oscillator off.
|
||||||
.Em Only supported on the STK500 and STK600 programmer.
|
.Em Supported on the STK500 and STK600 programmer.
|
||||||
.It Ar sck period
|
.It Ar sck period
|
||||||
.Em STK500 and STK600 programmer only:
|
.Em STK500 and STK600 programmer:
|
||||||
Set the SCK clock period to
|
Set the SCK clock period to
|
||||||
.Ar period
|
.Ar period
|
||||||
microseconds.
|
microseconds.
|
||||||
.Pp
|
.Em JTAG ICE:
|
||||||
.Em JTAG ICE only:
|
|
||||||
Set the JTAG ICE bit clock period to
|
Set the JTAG ICE bit clock period to
|
||||||
.Ar period
|
.Ar period
|
||||||
microseconds.
|
microseconds.
|
||||||
|
@ -862,24 +1027,12 @@ software signs off from the JTAG ICE.
|
||||||
This parameter can also be used on the JTAG ICE mkII, JTAGICE3, and Atmel-ICE to specify the
|
This parameter can also be used on the JTAG ICE mkII, JTAGICE3, and Atmel-ICE to specify the
|
||||||
ISP clock period when operating the ICE in ISP mode.
|
ISP clock period when operating the ICE in ISP mode.
|
||||||
.It Ar parms
|
.It Ar parms
|
||||||
.Em STK500 and STK600 programmer only:
|
.Em STK500 and STK600 programmer:
|
||||||
Display the current voltage and master oscillator parameters.
|
Display the current voltage and programming oscillator parameters.
|
||||||
.Pp
|
.Em JTAG ICE:
|
||||||
.Em JTAG ICE only:
|
|
||||||
Display the current target supply voltage and JTAG bit clock rate/period.
|
Display the current target supply voltage and JTAG bit clock rate/period.
|
||||||
.It Ar verbose Op Ar level
|
.Em Other programmers:
|
||||||
Change (when
|
Display the programmer specific parameters.
|
||||||
.Ar level
|
|
||||||
is provided), or display the verbosity level.
|
|
||||||
The initial verbosity level is controlled by the number of
|
|
||||||
.Fl v
|
|
||||||
options given on the commandline.
|
|
||||||
.It Ar \&?
|
|
||||||
.It Ar help
|
|
||||||
Give a short on-line summary of the available commands.
|
|
||||||
.It Ar quit
|
|
||||||
Leave terminal mode and thus
|
|
||||||
.Nm avrdude .
|
|
||||||
.El
|
.El
|
||||||
.Ss Default Parallel port pin connections
|
.Ss Default Parallel port pin connections
|
||||||
(these can be changed, see the
|
(these can be changed, see the
|
||||||
|
@ -891,8 +1044,8 @@ ll.
|
||||||
2-5 Vcc (optional power supply to MCU)
|
2-5 Vcc (optional power supply to MCU)
|
||||||
7 /RESET (to MCU)
|
7 /RESET (to MCU)
|
||||||
8 SCK (to MCU)
|
8 SCK (to MCU)
|
||||||
9 MOSI (to MCU)
|
9 SDO (to MCU)
|
||||||
10 MISO (from MCU)
|
10 SDI (from MCU)
|
||||||
18-25 GND
|
18-25 GND
|
||||||
.TE
|
.TE
|
||||||
.Ss debugWire limitations
|
.Ss debugWire limitations
|
||||||
|
@ -959,9 +1112,13 @@ versions of the bootloader.
|
||||||
.It Ar JTAG ICE mkII
|
.It Ar JTAG ICE mkII
|
||||||
.It Ar JTAGICE3
|
.It Ar JTAGICE3
|
||||||
.It Ar Atmel-ICE
|
.It Ar Atmel-ICE
|
||||||
|
.It Ar Power Debugger
|
||||||
|
.It Ar PICkit 4
|
||||||
|
.It Ar MPLAB SNAP
|
||||||
.It Ar AVR Dragon
|
.It Ar AVR Dragon
|
||||||
When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE or AVR Dragon in JTAG mode, the
|
When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE, PICkit 4, MPLAB SNAP,
|
||||||
following extended parameter is accepted:
|
Power Debugger or AVR Dragon in JTAG mode, the following extended parameter
|
||||||
|
is accepted:
|
||||||
.Bl -tag -offset indent -width indent
|
.Bl -tag -offset indent -width indent
|
||||||
.It Ar jtagchain=UB,UA,BB,BA
|
.It Ar jtagchain=UB,UA,BB,BA
|
||||||
Setup the JTAG scan chain for
|
Setup the JTAG scan chain for
|
||||||
|
@ -976,6 +1133,14 @@ bits after the target AVR, respectively.
|
||||||
Each AVR unit within the chain shifts by 4 bits.
|
Each AVR unit within the chain shifts by 4 bits.
|
||||||
Other JTAG units might require a different bit shift count.
|
Other JTAG units might require a different bit shift count.
|
||||||
.El
|
.El
|
||||||
|
.Pp
|
||||||
|
The PICkit 4 and the Power Debugger also supports high-voltage UPDI programming.
|
||||||
|
This is used to enable a UPDI pin that has previously been set to RESET or
|
||||||
|
GPIO mode. High-voltage UPDI can be utilized by using an extended parameter:
|
||||||
|
.Bl -tag -offset indent -width indent
|
||||||
|
.It Ar hvupdi
|
||||||
|
Enable high-voltage UPDI initialization for targets that supports this.
|
||||||
|
.El
|
||||||
.It Ar AVR910
|
.It Ar AVR910
|
||||||
.Bl -tag -offset indent -width indent
|
.Bl -tag -offset indent -width indent
|
||||||
.It Ar devcode=VALUE
|
.It Ar devcode=VALUE
|
||||||
|
@ -1007,12 +1172,119 @@ programmer creates errors during initial sequence.
|
||||||
Specify how many connection retry attemps to perform before exiting.
|
Specify how many connection retry attemps to perform before exiting.
|
||||||
Defaults to 10 if not specified.
|
Defaults to 10 if not specified.
|
||||||
.El
|
.El
|
||||||
|
.It Ar Urclock
|
||||||
|
.Bl -tag -offset indent -width indent
|
||||||
|
.It Ar showall
|
||||||
|
Show all info for the connected part, then exit. The -xshow... options
|
||||||
|
below can be used to assemble a bespoke response consisting of a subset
|
||||||
|
(or only one item) of all available relevant information about the
|
||||||
|
connected part and bootloader.
|
||||||
|
.It Ar showid
|
||||||
|
Show a unique Urclock ID stored in either flash or EEPROM of the MCU, then exit.
|
||||||
|
.It Ar id=<E|F>.<addr>.<len>
|
||||||
|
Historically, the Urclock ID was a six-byte unique little-endian number
|
||||||
|
stored in Urclock boards at EEPROM address 257. The location of this
|
||||||
|
number can be set by the -xid=<E|F>.<addr>.<len> extended parameter. E
|
||||||
|
stands for EEPROM and F stands for flash. A negative address addr counts
|
||||||
|
from the end of EEPROM and flash, respectively. The length len of the
|
||||||
|
Urclock ID can be between 1 and 8 bytes.
|
||||||
|
.It Ar showdate
|
||||||
|
Show the last-modified date of the input file for the flash application,
|
||||||
|
then exit. If the input file was stdin, the date will be that of the
|
||||||
|
programming. Date and filename are part of the metadata that the urclock
|
||||||
|
programmer stores by default in high flash just under the bootloader; see also
|
||||||
|
-xnometadata.
|
||||||
|
.It Ar showfilename
|
||||||
|
Show the input filename (or title) of the last flash writing session, then exit.
|
||||||
|
.It Ar title=<string>
|
||||||
|
When set, <string> will be used in lieu of the input filename. The maximum
|
||||||
|
string length for the title/filename field is 254 bytes including
|
||||||
|
terminating nul.
|
||||||
|
.It Ar showapp
|
||||||
|
Show the size of the programmed application, then exit.
|
||||||
|
.It Ar showstore
|
||||||
|
Show the size of the unused flash between the application and metadata, then exit.
|
||||||
|
.It Ar showmeta
|
||||||
|
Show the size of the metadata just below the bootloader, then exit.
|
||||||
|
.It Ar showboot
|
||||||
|
Show the size of the bootloader, then exit.
|
||||||
|
.It Ar showversion
|
||||||
|
Show bootloader version and capabilities, then exit.
|
||||||
|
.It Ar showvector
|
||||||
|
Show the vector number and name of the interrupt table vector used by the
|
||||||
|
bootloader for starting the application, then exit. For hardware-supported
|
||||||
|
bootloaders this will be vector 0 (Reset), and for vector bootloaders this
|
||||||
|
will be any other vector number of the interrupt vector table or the slot
|
||||||
|
just behind the vector table with the name VBL_ADDITIONAL_VECTOR.
|
||||||
|
.It Ar showpart
|
||||||
|
Show the part for which the bootloader was compiled, then exit.
|
||||||
|
.It Ar bootsize=<size>
|
||||||
|
Manual override for bootloader size. Urboot bootloaders put the number of
|
||||||
|
used bootloader pages into a table at the top of the bootloader section,
|
||||||
|
ie, typically top of flash, so the urclock programmer can look up the
|
||||||
|
bootloader size itself. In backward-compatibility mode, when programming
|
||||||
|
via other bootloaders, this option can be used to tell the programmer the
|
||||||
|
size, and therefore the location, of the bootloader.
|
||||||
|
.It Ar vectornum=<arg>
|
||||||
|
Manual override for vector number. Urboot bootloaders put the vector
|
||||||
|
number used by a vector bootloader into a table at the top of flash, so
|
||||||
|
this option is normally not needed for urboot bootloaders. However, it is
|
||||||
|
useful in backward-compatibility mode (or when the urboot bootloader does
|
||||||
|
not offer flash read). Specifying a vector number in these circumstances
|
||||||
|
implies a vector bootloader whilst the default assumption would be a
|
||||||
|
hardware-supported bootloader.
|
||||||
|
.It Ar eepromrw
|
||||||
|
Manual override for asserting EEPROM read/write capability. Not normally
|
||||||
|
needed for urboot bootloaders, but useful for in backward-compatibility
|
||||||
|
mode if the bootloader offers EEPROM read/write.
|
||||||
|
.It Ar emulate_ce
|
||||||
|
If an urboot bootloader does not offer a chip erase command it will tell
|
||||||
|
the urclock programmer so during handshake. In this case the urclock
|
||||||
|
programmer emulates a chip erase, if warranted by user command line
|
||||||
|
options, by filling the remainder of unused flash below the bootloader
|
||||||
|
with 0xff. If this option is specified, the urclock programmer will assume
|
||||||
|
that the bootloader cannot erase the chip itself. The option is useful
|
||||||
|
for backwards-compatible bootloaders that do not implement chip erase.
|
||||||
|
.It Ar restore
|
||||||
|
Upload unchanged flash input files and trim below the bootloader if
|
||||||
|
needed. This is most useful when one has a backup of the full flash and
|
||||||
|
wants to play that back onto the device. No metadata are written in this
|
||||||
|
case and no vector patching happens either if it is a vector bootloader.
|
||||||
|
However, for vector bootloaders, even under the option -xrestore an
|
||||||
|
input file will not be uploaded for which the reset vector does not point
|
||||||
|
to the vector bootloader. This is to avoid writing an input file to the
|
||||||
|
device that would render the vector bootloader not functional as it would
|
||||||
|
not be reached after reset.
|
||||||
|
.It Ar initstore
|
||||||
|
On writing to flash fill the store space between the flash application and
|
||||||
|
the metadata section with 0xff.
|
||||||
|
.It Ar nofilename
|
||||||
|
On writing to flash do not store the application input filename (nor a title).
|
||||||
|
.It Ar nodate
|
||||||
|
On writing to flash do not store the application input filename (nor a
|
||||||
|
title) and no date either.
|
||||||
|
.It Ar nometadata
|
||||||
|
On writing to flash do not store any metadata. The full flash below the
|
||||||
|
bootloader is available for the application. In particular, no data store
|
||||||
|
frame is programmed.
|
||||||
|
.It Ar delay=<n>
|
||||||
|
Add a <n> ms delay after reset. This can be useful if a board takes a
|
||||||
|
particularly long time to exit from external reset. <n> can be negative,
|
||||||
|
in which case the default 120 ms delay after issuing reset will be
|
||||||
|
shortened accordingly.
|
||||||
|
.It Ar strict
|
||||||
|
Urclock has a faster, but slightly different strategy than -c arduino to
|
||||||
|
synchronise with the bootloader; some stk500v1 bootloaders cannot cope
|
||||||
|
with this, and they need the -xstrict option.
|
||||||
|
.It Ar help
|
||||||
|
Show this help menu and exit
|
||||||
|
.El
|
||||||
.It Ar buspirate
|
.It Ar buspirate
|
||||||
.Bl -tag -offset indent -width indent
|
.Bl -tag -offset indent -width indent
|
||||||
.It Ar reset={cs,aux,aux2}
|
.It Ar reset={cs,aux,aux2}
|
||||||
The default setup assumes the BusPirate's CS output pin connected to
|
The default setup assumes the BusPirate's CS output pin connected to
|
||||||
the RESET pin on AVR side. It is however possible to have multiple AVRs
|
the RESET pin on AVR side. It is however possible to have multiple AVRs
|
||||||
connected to the same BP with MISO, MOSI and SCK lines common for all of them.
|
connected to the same BP with SDI, SDO and SCK lines common for all of them.
|
||||||
In such a case one AVR should have its RESET connected to BusPirate's
|
In such a case one AVR should have its RESET connected to BusPirate's
|
||||||
.Pa CS
|
.Pa CS
|
||||||
pin, second AVR's RESET connected to BusPirate's
|
pin, second AVR's RESET connected to BusPirate's
|
||||||
|
@ -1125,9 +1397,9 @@ Connection to the PICkit2 programmer:
|
||||||
RST - VPP/MCLR (1)
|
RST - VPP/MCLR (1)
|
||||||
VDD - VDD Target (2) -- possibly optional if AVR self powered
|
VDD - VDD Target (2) -- possibly optional if AVR self powered
|
||||||
GND - GND (3)
|
GND - GND (3)
|
||||||
MISO - PGD (4)
|
SDI - PGD (4)
|
||||||
SCLK - PDC (5)
|
SCLK - PDC (5)
|
||||||
MOSI - AUX (6)
|
SDO - AUX (6)
|
||||||
|
|
||||||
.Ed
|
.Ed
|
||||||
Extended commandline parameters:
|
Extended commandline parameters:
|
||||||
|
@ -1180,14 +1452,22 @@ specific.
|
||||||
.Pp
|
.Pp
|
||||||
When not provided, driver/OS default value will be used.
|
When not provided, driver/OS default value will be used.
|
||||||
.El
|
.El
|
||||||
|
.It Ar linuxspi
|
||||||
|
Extended parameter:
|
||||||
|
.Bl -tag -offset indent -width indent
|
||||||
|
.It Ar disable_no_cs
|
||||||
|
Ensures the programmer does not use the SPI_NO_CS bit for the SPI
|
||||||
|
driver. This parameter is useful for kernels that do not support
|
||||||
|
the CS line being managed outside the application.
|
||||||
|
.El
|
||||||
.El
|
.El
|
||||||
.Sh FILES
|
.Sh FILES
|
||||||
.Bl -tag -offset indent -width /dev/ppi0XXX
|
.Bl -tag -offset indent -width /dev/ppi0XXX
|
||||||
.It Pa /dev/ppi0
|
.It Pa /dev/ppi0
|
||||||
default device to be used for communication with the programming
|
Default device to be used for communication with the programming
|
||||||
hardware
|
hardware
|
||||||
.It Pa avrdude.conf
|
.It Pa avrdude.conf
|
||||||
programmer and parts configuration file
|
Programmer and parts configuration file
|
||||||
.Pp
|
.Pp
|
||||||
On Windows systems, this file is looked up in the same directory as the
|
On Windows systems, this file is looked up in the same directory as the
|
||||||
executable file.
|
executable file.
|
||||||
|
@ -1196,14 +1476,22 @@ On all other systems, the file is first looked up in
|
||||||
relative to the path of the executable, then in the same directory as
|
relative to the path of the executable, then in the same directory as
|
||||||
the executable itself, and finally in the system default location
|
the executable itself, and finally in the system default location
|
||||||
.Pa ${PREFIX}/etc/avrdude.conf .
|
.Pa ${PREFIX}/etc/avrdude.conf .
|
||||||
|
.It Pa ${XDG_CONFIG_HOME}/avrdude/avrdude.rc
|
||||||
|
Local programmer and parts configuration file (per-user overrides); it follows the same syntax as
|
||||||
|
.Pa avrdude.conf ;
|
||||||
|
if the
|
||||||
|
.Pa ${XDG_CONFIG_HOME}
|
||||||
|
environment variable is not set or empty, the directory
|
||||||
|
.Pa ${HOME}/.config/
|
||||||
|
is used instead.
|
||||||
.It Pa ${HOME}/.avrduderc
|
.It Pa ${HOME}/.avrduderc
|
||||||
programmer and parts configuration file (per-user overrides)
|
Alternative location of the per-user configuration file if above file does not exist
|
||||||
.It Pa ~/.inputrc
|
.It Pa ~/.inputrc
|
||||||
Initialization file for the
|
Initialization file for the
|
||||||
.Xr readline 3
|
.Xr readline 3
|
||||||
library
|
library
|
||||||
.It Pa ${PREFIX}/share/doc/avrdude/avrdude.pdf
|
.It Pa <prefix>/doc/avrdude/avrdude.pdf
|
||||||
Schematic of programming hardware
|
User manual
|
||||||
.El
|
.El
|
||||||
.\" .Sh EXAMPLES
|
.\" .Sh EXAMPLES
|
||||||
.Sh DIAGNOSTICS
|
.Sh DIAGNOSTICS
|
||||||
|
@ -1267,7 +1555,7 @@ The USBasp and USBtinyISP drivers do not offer any option to distinguish multipl
|
||||||
devices connected simultaneously, so effectively only a single device
|
devices connected simultaneously, so effectively only a single device
|
||||||
is supported.
|
is supported.
|
||||||
.Pp
|
.Pp
|
||||||
Slave Select must be externally held low for direct SPI when
|
Chip Select must be externally held low for direct SPI when
|
||||||
using USBtinyISP, and send must be a multiple of four bytes.
|
using USBtinyISP, and send must be a multiple of four bytes.
|
||||||
.Pp
|
.Pp
|
||||||
The avrftdi driver allows one to select specific devices using any combination of vid,pid
|
The avrftdi driver allows one to select specific devices using any combination of vid,pid
|
||||||
|
|
27112
src/avrdude.conf.in
27112
src/avrdude.conf.in
File diff suppressed because it is too large
Load Diff
|
@ -21,27 +21,77 @@
|
||||||
#ifndef avrdude_h
|
#ifndef avrdude_h
|
||||||
#define avrdude_h
|
#define avrdude_h
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#define SYSTEM_CONF_FILE "avrdude.conf"
|
#define SYSTEM_CONF_FILE "avrdude.conf"
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#define USER_CONF_FILE "avrdude.rc"
|
#define USER_CONF_FILE "avrdude.rc"
|
||||||
#else
|
#else
|
||||||
#define USER_CONF_FILE ".avrduderc"
|
#define USER_CONF_FILE ".avrduderc"
|
||||||
|
#define XDG_USER_CONF_FILE "avrdude/avrdude.rc"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern char * progname; /* name of program, for messages */
|
extern char *progname; // Name of program, for messages
|
||||||
extern char progbuf[]; /* spaces same length as progname */
|
extern char progbuf[]; // Spaces same length as progname
|
||||||
|
|
||||||
extern int ovsigck; /* override signature check (-F) */
|
extern int ovsigck; // Override signature check (-F)
|
||||||
extern int verbose; /* verbosity level (-v, -vv, ...) */
|
extern int verbose; // Verbosity level (-v, -vv, ...)
|
||||||
extern int quell_progress; /* quietness level (-q, -qq) */
|
extern int quell_progress; // Quell progress report -q, reduce effective verbosity level (-qq, -qqq)
|
||||||
|
extern const char *partdesc; // Part id
|
||||||
|
|
||||||
int avrdude_message(const int msglvl, const char *format, ...);
|
int avrdude_message(int msglvl, const char *format, ...);
|
||||||
|
int avrdude_message2(FILE *fp, int lno, const char *file, const char *func, int msgmode, int msglvl, const char *format, ...);
|
||||||
|
|
||||||
#define MSG_INFO (0) /* no -v option, can be suppressed with -qq */
|
#define MSG_EXT_ERROR (-3) // OS-type error, no -v option, can be suppressed with -qqqqq
|
||||||
#define MSG_NOTICE (1) /* displayed with -v */
|
#define MSG_ERROR (-2) // Avrdude error, no -v option, can be suppressed with -qqqq
|
||||||
#define MSG_NOTICE2 (2) /* displayed with -vv, used rarely */
|
#define MSG_WARNING (-1) // Warning, no -v option, can be suppressed with -qqq
|
||||||
#define MSG_DEBUG (3) /* displayed with -vvv */
|
#define MSG_INFO 0 // Commentary, no -v option, can be suppressed with -qq
|
||||||
#define MSG_TRACE (4) /* displayed with -vvvv, show trace communication */
|
#define MSG_NOTICE 1 // Displayed with -v
|
||||||
#define MSG_TRACE2 (5) /* displayed with -vvvvv */
|
#define MSG_NOTICE2 2 // Displayed with -vv
|
||||||
|
#define MSG_DEBUG 3 // Displayed with -vvv
|
||||||
|
#define MSG_TRACE 4 // Displayed with -vvvv, show trace communication
|
||||||
|
#define MSG_TRACE2 5 // Displayed with -vvvvv
|
||||||
|
|
||||||
|
#define MSG2_PROGNAME 1 // Start by printing progname
|
||||||
|
#define MSG2_FUNCTION 2 // Print calling function (1st arg) after progname if >= notice
|
||||||
|
#define MSG2_FILELINE 4 // Print source file and line number after function if >= debug
|
||||||
|
#define MSG2_TYPE 8 // Print message type after function or progname
|
||||||
|
#define MSG2_INDENT1 16 // Start by printing indentation of progname+1 blanks
|
||||||
|
#define MSG2_INDENT2 32 // Start by printing indentation of progname+2 blanks
|
||||||
|
#define MSG2_FLUSH 64 // Flush before and after printing
|
||||||
|
|
||||||
|
// Shortcuts
|
||||||
|
#define msg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_EXT_ERROR, __VA_ARGS__)
|
||||||
|
#define msg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_ERROR, __VA_ARGS__)
|
||||||
|
#define msg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_WARNING, __VA_ARGS__)
|
||||||
|
#define msg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_INFO, __VA_ARGS__)
|
||||||
|
#define msg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_NOTICE, __VA_ARGS__)
|
||||||
|
#define msg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_NOTICE2, __VA_ARGS__)
|
||||||
|
#define msg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_DEBUG, __VA_ARGS__)
|
||||||
|
#define msg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_TRACE, __VA_ARGS__)
|
||||||
|
#define msg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, 0, MSG_TRACE2, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define pmsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__)
|
||||||
|
#define pmsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__)
|
||||||
|
#define pmsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FUNCTION|MSG2_FILELINE|MSG2_TYPE|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__)
|
||||||
|
#define pmsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||||
|
#define pmsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
|
||||||
|
#define pmsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
|
||||||
|
#define pmsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
|
||||||
|
#define pmsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__)
|
||||||
|
#define pmsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_PROGNAME|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define imsg_ext_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_EXT_ERROR, __VA_ARGS__)
|
||||||
|
#define imsg_error(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_ERROR, __VA_ARGS__)
|
||||||
|
#define imsg_warning(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT1|MSG2_FLUSH, MSG_WARNING, __VA_ARGS__)
|
||||||
|
#define imsg_info(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||||
|
#define imsg_notice(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE, __VA_ARGS__)
|
||||||
|
#define imsg_notice2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_NOTICE2, __VA_ARGS__)
|
||||||
|
#define imsg_debug(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_DEBUG, __VA_ARGS__)
|
||||||
|
#define imsg_trace(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE, __VA_ARGS__)
|
||||||
|
#define imsg_trace2(...) avrdude_message2(stderr, __LINE__, __FILE__, __func__, MSG2_INDENT2|MSG2_FLUSH, MSG_TRACE2, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define term_out(...) avrdude_message2(stdout, __LINE__, __FILE__, __func__, MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||||
|
#define fmsg_out(fp, ...) avrdude_message2(fp, __LINE__, __FILE__, __func__, MSG2_FLUSH, MSG_INFO, __VA_ARGS__)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
253
src/avrftdi.c
253
src/avrftdi.c
|
@ -50,23 +50,19 @@
|
||||||
|
|
||||||
#ifdef DO_NOT_BUILD_AVRFTDI
|
#ifdef DO_NOT_BUILD_AVRFTDI
|
||||||
|
|
||||||
static int avrftdi_noftdi_open (struct programmer_t *pgm, char * name)
|
static int avrftdi_noftdi_open(PROGRAMMER *pgm, const char *name) {
|
||||||
{
|
pmsg_error("no libftdi or libusb support; install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again\n");
|
||||||
avrdude_message(MSG_INFO, "%s: Error: no libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.\n",
|
|
||||||
progname);
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void avrftdi_initpgm(PROGRAMMER * pgm)
|
void avrftdi_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "avrftdi");
|
strcpy(pgm->type, "avrftdi");
|
||||||
pgm->open = avrftdi_noftdi_open;
|
pgm->open = avrftdi_noftdi_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
enum { FTDI_SCK = 0, FTDI_MOSI, FTDI_MISO, FTDI_RESET };
|
enum { FTDI_SCK = 0, FTDI_SDO, FTDI_SDI, FTDI_RESET };
|
||||||
|
|
||||||
static int write_flush(avrftdi_t *);
|
static int write_flush(avrftdi_t *);
|
||||||
|
|
||||||
|
@ -142,14 +138,14 @@ void avrftdi_log(int level, const char * func, int line,
|
||||||
if(!skip_prefix)
|
if(!skip_prefix)
|
||||||
{
|
{
|
||||||
switch(level) {
|
switch(level) {
|
||||||
case ERR: avrdude_message(MSG_INFO, "E "); break;
|
case ERR: msg_error("E "); break;
|
||||||
case WARN: avrdude_message(MSG_INFO, "W "); break;
|
case WARN: msg_error("W "); break;
|
||||||
case INFO: avrdude_message(MSG_INFO, "I "); break;
|
case INFO: msg_error("I "); break;
|
||||||
case DEBUG: avrdude_message(MSG_INFO, "D "); break;
|
case DEBUG: msg_error("D "); break;
|
||||||
case TRACE: avrdude_message(MSG_INFO, "T "); break;
|
case TRACE: msg_error("T "); break;
|
||||||
default: avrdude_message(MSG_INFO, " "); break;
|
default: msg_error(" "); break;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_INFO, "%s(%d): ", func, line);
|
msg_error("%s(%d): ", func, line);
|
||||||
}
|
}
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vfprintf(stderr, fmt, ap);
|
vfprintf(stderr, fmt, ap);
|
||||||
|
@ -172,16 +168,16 @@ static void buf_dump(const unsigned char *buf, int len, char *desc,
|
||||||
int offset, int width)
|
int offset, int width)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
avrdude_message(MSG_INFO, "%s begin:\n", desc);
|
msg_info("%s begin:\n", desc);
|
||||||
for (i = 0; i < offset; i++)
|
for (i = 0; i < offset; i++)
|
||||||
avrdude_message(MSG_INFO, "%02x ", buf[i]);
|
msg_info("%02x ", buf[i]);
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_info("\n");
|
||||||
for (i++; i <= len; i++) {
|
for (i++; i <= len; i++) {
|
||||||
avrdude_message(MSG_INFO, "%02x ", buf[i-1]);
|
msg_info("%02x ", buf[i-1]);
|
||||||
if((i-offset) != 0 && (i-offset)%width == 0)
|
if((i-offset) != 0 && (i-offset)%width == 0)
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_info("\n");
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_INFO, "%s end\n", desc);
|
msg_info("%s end\n", desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -220,15 +216,17 @@ static int set_frequency(avrftdi_t* ftdi, uint32_t freq)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function sets or clears any pin, except SCK, MISO and MOSI. Depending
|
* This function sets or clears any pin, except SCK, SDI and SDO. Depending
|
||||||
* on the pin configuration, a non-zero value sets the pin in the 'active'
|
* on the pin configuration, a non-zero value sets the pin in the 'active'
|
||||||
* state (high active, low active) and a zero value sets the pin in the
|
* state (high active, low active) and a zero value sets the pin in the
|
||||||
* inactive state.
|
* inactive state.
|
||||||
* Because we configured the pin direction mask earlier, nothing bad can happen
|
* Because we configured the pin direction mask earlier, nothing bad can happen
|
||||||
* here.
|
* here.
|
||||||
*/
|
*/
|
||||||
static int set_pin(PROGRAMMER * pgm, int pinfunc, int value)
|
static int set_pin(const PROGRAMMER *pgm, int pinfunc, int value) {
|
||||||
{
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
avrftdi_t* pdata = to_pdata(pgm);
|
avrftdi_t* pdata = to_pdata(pgm);
|
||||||
struct pindef_t pin = pgm->pin[pinfunc];
|
struct pindef_t pin = pgm->pin[pinfunc];
|
||||||
|
|
||||||
|
@ -250,54 +248,50 @@ static int set_pin(PROGRAMMER * pgm, int pinfunc, int value)
|
||||||
/*
|
/*
|
||||||
* Mandatory callbacks which boil down to GPIO.
|
* Mandatory callbacks which boil down to GPIO.
|
||||||
*/
|
*/
|
||||||
static int set_led_pgm(struct programmer_t * pgm, int value)
|
static int set_led_pgm(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
return set_pin(pgm, PIN_LED_PGM, value);
|
return set_pin(pgm, PIN_LED_PGM, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_led_rdy(struct programmer_t * pgm, int value)
|
static int set_led_rdy(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
return set_pin(pgm, PIN_LED_RDY, value);
|
return set_pin(pgm, PIN_LED_RDY, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_led_err(struct programmer_t * pgm, int value)
|
static int set_led_err(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
return set_pin(pgm, PIN_LED_ERR, value);
|
return set_pin(pgm, PIN_LED_ERR, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_led_vfy(struct programmer_t * pgm, int value)
|
static int set_led_vfy(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
return set_pin(pgm, PIN_LED_VFY, value);
|
return set_pin(pgm, PIN_LED_VFY, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avrftdi_enable(PROGRAMMER * pgm)
|
static void avrftdi_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
set_pin(pgm, PPI_AVR_BUFF, ON);
|
set_pin(pgm, PPI_AVR_BUFF, ON);
|
||||||
|
|
||||||
|
// Switch to TPI initialisation in avrftdi_tpi.c
|
||||||
|
if(p->prog_modes & PM_TPI)
|
||||||
|
avrftdi_tpi_initpgm(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avrftdi_disable(PROGRAMMER * pgm)
|
static void avrftdi_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
set_pin(pgm, PPI_AVR_BUFF, OFF);
|
set_pin(pgm, PPI_AVR_BUFF, OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avrftdi_powerup(PROGRAMMER * pgm)
|
static void avrftdi_powerup(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
set_pin(pgm, PPI_AVR_VCC, ON);
|
set_pin(pgm, PPI_AVR_VCC, ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avrftdi_powerdown(PROGRAMMER * pgm)
|
static void avrftdi_powerdown(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
set_pin(pgm, PPI_AVR_VCC, OFF);
|
set_pin(pgm, PPI_AVR_VCC, OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int set_data(PROGRAMMER * pgm, unsigned char *buf, unsigned char data, bool read_data) {
|
static inline int set_data(const PROGRAMMER *pgm, unsigned char *buf, unsigned char data, bool read_data) {
|
||||||
int j;
|
int j;
|
||||||
int buf_pos = 0;
|
int buf_pos = 0;
|
||||||
unsigned char bit = 0x80;
|
unsigned char bit = 0x80;
|
||||||
avrftdi_t* pdata = to_pdata(pgm);
|
avrftdi_t* pdata = to_pdata(pgm);
|
||||||
|
|
||||||
for (j=0; j<8; j++) {
|
for (j=0; j<8; j++) {
|
||||||
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_MOSI,data & bit);
|
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_SDO,data & bit);
|
||||||
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_SCK,0);
|
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_SCK,0);
|
||||||
buf[buf_pos++] = SET_BITS_LOW;
|
buf[buf_pos++] = SET_BITS_LOW;
|
||||||
buf[buf_pos++] = (pdata->pin_value) & 0xff;
|
buf[buf_pos++] = (pdata->pin_value) & 0xff;
|
||||||
|
@ -324,7 +318,7 @@ static inline int set_data(PROGRAMMER * pgm, unsigned char *buf, unsigned char d
|
||||||
return buf_pos;
|
return buf_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned char extract_data(PROGRAMMER * pgm, unsigned char *buf, int offset) {
|
static inline unsigned char extract_data(const PROGRAMMER *pgm, unsigned char *buf, int offset) {
|
||||||
int j;
|
int j;
|
||||||
unsigned char bit = 0x80;
|
unsigned char bit = 0x80;
|
||||||
unsigned char r = 0;
|
unsigned char r = 0;
|
||||||
|
@ -332,7 +326,7 @@ static inline unsigned char extract_data(PROGRAMMER * pgm, unsigned char *buf, i
|
||||||
buf += offset * 16; // 2 bytes per bit, 8 bits
|
buf += offset * 16; // 2 bytes per bit, 8 bits
|
||||||
for (j=0; j<8; j++) {
|
for (j=0; j<8; j++) {
|
||||||
uint16_t in = buf[0] | (buf[1] << 8);
|
uint16_t in = buf[0] | (buf[1] << 8);
|
||||||
if (GET_BITS_0(in,pgm,PIN_AVR_MISO)) {
|
if (GET_BITS_0(in,pgm,PIN_AVR_SDI)) {
|
||||||
r |= bit;
|
r |= bit;
|
||||||
}
|
}
|
||||||
buf += 2; // 2 bytes per input
|
buf += 2; // 2 bytes per input
|
||||||
|
@ -342,7 +336,7 @@ static inline unsigned char extract_data(PROGRAMMER * pgm, unsigned char *buf, i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avrftdi_transmit_bb(PROGRAMMER * pgm, unsigned char mode, const unsigned char *buf,
|
static int avrftdi_transmit_bb(const PROGRAMMER *pgm, unsigned char mode, const unsigned char *buf,
|
||||||
unsigned char *data, int buf_size)
|
unsigned char *data, int buf_size)
|
||||||
{
|
{
|
||||||
size_t remaining = buf_size;
|
size_t remaining = buf_size;
|
||||||
|
@ -351,10 +345,10 @@ static int avrftdi_transmit_bb(PROGRAMMER * pgm, unsigned char mode, const unsig
|
||||||
size_t blocksize = pdata->rx_buffer_size/2; // we are reading 2 bytes per data byte
|
size_t blocksize = pdata->rx_buffer_size/2; // we are reading 2 bytes per data byte
|
||||||
|
|
||||||
// determine a maximum size of data block
|
// determine a maximum size of data block
|
||||||
size_t max_size = MIN(pdata->ftdic->max_packet_size,pdata->tx_buffer_size);
|
size_t max_size = MIN(pdata->ftdic->max_packet_size, (unsigned int) pdata->tx_buffer_size);
|
||||||
// select block size so that resulting commands does not exceed max_size if possible
|
// select block size so that resulting commands does not exceed max_size if possible
|
||||||
blocksize = MAX(1,(max_size-7)/((8*2*6)+(8*1*2)));
|
blocksize = MAX(1,(max_size-7)/((8*2*6)+(8*1*2)));
|
||||||
//avrdude_message(MSG_INFO, "blocksize %d \n",blocksize);
|
// msg_info("blocksize %d \n", blocksize);
|
||||||
|
|
||||||
unsigned char* send_buffer = alloca((8 * 2 * 6) * blocksize + (8 * 1 * 2) * blocksize + 7);
|
unsigned char* send_buffer = alloca((8 * 2 * 6) * blocksize + (8 * 1 * 2) * blocksize + 7);
|
||||||
unsigned char* recv_buffer = alloca(2 * 16 * blocksize);
|
unsigned char* recv_buffer = alloca(2 * 16 * blocksize);
|
||||||
|
@ -368,9 +362,8 @@ static int avrftdi_transmit_bb(PROGRAMMER * pgm, unsigned char mode, const unsig
|
||||||
// (8*1) inputs per data byte, 2 transmit bytes per input (GET_BITS_LOW/HIGH),
|
// (8*1) inputs per data byte, 2 transmit bytes per input (GET_BITS_LOW/HIGH),
|
||||||
// 1x SEND_IMMEDIATE
|
// 1x SEND_IMMEDIATE
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = 0 ; i< transfer_size; i++) {
|
for(size_t i = 0 ; i < transfer_size; i++) {
|
||||||
len += set_data(pgm, send_buffer + len, buf[written+i], (mode & MPSSE_DO_READ) != 0);
|
len += set_data(pgm, send_buffer + len, buf[written+i], (mode & MPSSE_DO_READ) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -387,14 +380,14 @@ static int avrftdi_transmit_bb(PROGRAMMER * pgm, unsigned char mode, const unsig
|
||||||
E(ftdi_write_data(pdata->ftdic, send_buffer, len) != len, pdata->ftdic);
|
E(ftdi_write_data(pdata->ftdic, send_buffer, len) != len, pdata->ftdic);
|
||||||
if (mode & MPSSE_DO_READ) {
|
if (mode & MPSSE_DO_READ) {
|
||||||
int n;
|
int n;
|
||||||
int k = 0;
|
size_t k = 0;
|
||||||
do {
|
do {
|
||||||
n = ftdi_read_data(pdata->ftdic, &recv_buffer[k], 2*16*transfer_size - k);
|
n = ftdi_read_data(pdata->ftdic, &recv_buffer[k], 2*16*transfer_size - k);
|
||||||
E(n < 0, pdata->ftdic);
|
E(n < 0, pdata->ftdic);
|
||||||
k += n;
|
k += n;
|
||||||
} while (k < transfer_size);
|
} while (k < transfer_size);
|
||||||
|
|
||||||
for(i = 0 ; i< transfer_size; i++) {
|
for(size_t i = 0 ; i< transfer_size; i++) {
|
||||||
data[written + i] = extract_data(pgm, recv_buffer, i);
|
data[written + i] = extract_data(pgm, recv_buffer, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,7 +430,7 @@ static int avrftdi_transmit_mpsse(avrftdi_t* pdata, unsigned char mode, const un
|
||||||
{
|
{
|
||||||
size_t transfer_size = (remaining > blocksize) ? blocksize : remaining;
|
size_t transfer_size = (remaining > blocksize) ? blocksize : remaining;
|
||||||
|
|
||||||
E(ftdi_write_data(pdata->ftdic, (unsigned char*)&buf[written], transfer_size) != transfer_size, pdata->ftdic);
|
E((size_t) ftdi_write_data(pdata->ftdic, (unsigned char*)&buf[written], transfer_size) != transfer_size, pdata->ftdic);
|
||||||
#if 0
|
#if 0
|
||||||
if(remaining < blocksize)
|
if(remaining < blocksize)
|
||||||
E(ftdi_write_data(pdata->ftdic, &si, sizeof(si)) != sizeof(si), pdata->ftdic);
|
E(ftdi_write_data(pdata->ftdic, &si, sizeof(si)) != sizeof(si), pdata->ftdic);
|
||||||
|
@ -445,7 +438,7 @@ static int avrftdi_transmit_mpsse(avrftdi_t* pdata, unsigned char mode, const un
|
||||||
|
|
||||||
if (mode & MPSSE_DO_READ) {
|
if (mode & MPSSE_DO_READ) {
|
||||||
int n;
|
int n;
|
||||||
int k = 0;
|
size_t k = 0;
|
||||||
do {
|
do {
|
||||||
n = ftdi_read_data(pdata->ftdic, &data[written + k], transfer_size - k);
|
n = ftdi_read_data(pdata->ftdic, &data[written + k], transfer_size - k);
|
||||||
E(n < 0, pdata->ftdic);
|
E(n < 0, pdata->ftdic);
|
||||||
|
@ -461,7 +454,7 @@ static int avrftdi_transmit_mpsse(avrftdi_t* pdata, unsigned char mode, const un
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int avrftdi_transmit(PROGRAMMER * pgm, unsigned char mode, const unsigned char *buf,
|
static inline int avrftdi_transmit(const PROGRAMMER *pgm, unsigned char mode, const unsigned char *buf,
|
||||||
unsigned char *data, int buf_size)
|
unsigned char *data, int buf_size)
|
||||||
{
|
{
|
||||||
avrftdi_t* pdata = to_pdata(pgm);
|
avrftdi_t* pdata = to_pdata(pgm);
|
||||||
|
@ -520,8 +513,7 @@ static int write_flush(avrftdi_t* pdata)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_check_pins_bb(PROGRAMMER * pgm, bool output)
|
static int avrftdi_check_pins_bb(const PROGRAMMER *pgm, bool output) {
|
||||||
{
|
|
||||||
int pin;
|
int pin;
|
||||||
|
|
||||||
/* pin checklist. */
|
/* pin checklist. */
|
||||||
|
@ -548,8 +540,7 @@ static int avrftdi_check_pins_bb(PROGRAMMER * pgm, bool output)
|
||||||
return pins_check(pgm, pin_checklist, N_PINS, output);
|
return pins_check(pgm, pin_checklist, N_PINS, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_check_pins_mpsse(PROGRAMMER * pgm, bool output)
|
static int avrftdi_check_pins_mpsse(const PROGRAMMER *pgm, bool output) {
|
||||||
{
|
|
||||||
int pin;
|
int pin;
|
||||||
|
|
||||||
/* pin checklist. */
|
/* pin checklist. */
|
||||||
|
@ -557,16 +548,16 @@ static int avrftdi_check_pins_mpsse(PROGRAMMER * pgm, bool output)
|
||||||
|
|
||||||
avrftdi_t* pdata = to_pdata(pgm);
|
avrftdi_t* pdata = to_pdata(pgm);
|
||||||
|
|
||||||
/* SCK/MOSI/MISO are fixed and not invertible?*/
|
/* SCK/SDO/SDI are fixed and not invertible? */
|
||||||
/* TODO: inverted SCK/MISO/MOSI */
|
/* TODO: inverted SCK/SDI/SDO */
|
||||||
static const struct pindef_t valid_pins_SCK = {{0x01},{0x00}} ;
|
static const struct pindef_t valid_pins_SCK = {{0x01},{0x00}};
|
||||||
static const struct pindef_t valid_pins_MOSI = {{0x02},{0x00}} ;
|
static const struct pindef_t valid_pins_SDO = {{0x02},{0x00}};
|
||||||
static const struct pindef_t valid_pins_MISO = {{0x04},{0x00}} ;
|
static const struct pindef_t valid_pins_SDI = {{0x04},{0x00}};
|
||||||
|
|
||||||
/* value for 8/12/16 bit wide interface for other pins */
|
/* value for 8/12/16 bit wide interface for other pins */
|
||||||
int valid_mask = ((1 << pdata->pin_limit) - 1);
|
int valid_mask = ((1 << pdata->pin_limit) - 1);
|
||||||
/* mask out SCK/MISO/MOSI */
|
/* mask out SCK/SDI/SDO */
|
||||||
valid_mask &= ~((1 << FTDI_SCK) | (1 << FTDI_MOSI) | (1 << FTDI_MISO));
|
valid_mask &= ~((1 << FTDI_SCK) | (1 << FTDI_SDO) | (1 << FTDI_SDI));
|
||||||
|
|
||||||
log_debug("Using valid mask mpsse: 0x%08x\n", valid_mask);
|
log_debug("Using valid mask mpsse: 0x%08x\n", valid_mask);
|
||||||
static struct pindef_t valid_pins_others;
|
static struct pindef_t valid_pins_others;
|
||||||
|
@ -583,18 +574,17 @@ static int avrftdi_check_pins_mpsse(PROGRAMMER * pgm, bool output)
|
||||||
/* now set mpsse specific pins */
|
/* now set mpsse specific pins */
|
||||||
pin_checklist[PIN_AVR_SCK].mandatory = 1;
|
pin_checklist[PIN_AVR_SCK].mandatory = 1;
|
||||||
pin_checklist[PIN_AVR_SCK].valid_pins = &valid_pins_SCK;
|
pin_checklist[PIN_AVR_SCK].valid_pins = &valid_pins_SCK;
|
||||||
pin_checklist[PIN_AVR_MOSI].mandatory = 1;
|
pin_checklist[PIN_AVR_SDO].mandatory = 1;
|
||||||
pin_checklist[PIN_AVR_MOSI].valid_pins = &valid_pins_MOSI;
|
pin_checklist[PIN_AVR_SDO].valid_pins = &valid_pins_SDO;
|
||||||
pin_checklist[PIN_AVR_MISO].mandatory = 1;
|
pin_checklist[PIN_AVR_SDI].mandatory = 1;
|
||||||
pin_checklist[PIN_AVR_MISO].valid_pins = &valid_pins_MISO;
|
pin_checklist[PIN_AVR_SDI].valid_pins = &valid_pins_SDI;
|
||||||
pin_checklist[PIN_AVR_RESET].mandatory = 1;
|
pin_checklist[PIN_AVR_RESET].mandatory = 1;
|
||||||
|
|
||||||
/* assumes all checklists above have same number of entries */
|
/* assumes all checklists above have same number of entries */
|
||||||
return pins_check(pgm, pin_checklist, N_PINS, output);
|
return pins_check(pgm, pin_checklist, N_PINS, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_pin_setup(PROGRAMMER * pgm)
|
static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
int pin;
|
int pin;
|
||||||
|
|
||||||
/*************
|
/*************
|
||||||
|
@ -612,30 +602,31 @@ static int avrftdi_pin_setup(PROGRAMMER * pgm)
|
||||||
avrftdi_check_pins_bb(pgm, true);
|
avrftdi_check_pins_bb(pgm, true);
|
||||||
log_err("Pin configuration for FTDI MPSSE must be:\n");
|
log_err("Pin configuration for FTDI MPSSE must be:\n");
|
||||||
log_err("%s: 0, %s: 1, %s: 2 (is: %s, %s, %s)\n", avr_pin_name(PIN_AVR_SCK),
|
log_err("%s: 0, %s: 1, %s: 2 (is: %s, %s, %s)\n", avr_pin_name(PIN_AVR_SCK),
|
||||||
avr_pin_name(PIN_AVR_MOSI), avr_pin_name(PIN_AVR_MISO),
|
avr_pin_name(PIN_AVR_SDO), avr_pin_name(PIN_AVR_SDI),
|
||||||
pins_to_str(&pgm->pin[PIN_AVR_SCK]),
|
pins_to_str(&pgm->pin[PIN_AVR_SCK]),
|
||||||
pins_to_str(&pgm->pin[PIN_AVR_MOSI]),
|
pins_to_str(&pgm->pin[PIN_AVR_SDO]),
|
||||||
pins_to_str(&pgm->pin[PIN_AVR_MISO]));
|
pins_to_str(&pgm->pin[PIN_AVR_SDI]));
|
||||||
log_err("If other pin configuration is used, fallback to slower bitbanging mode is used.\n");
|
log_err("If other pin configuration is used, fallback to slower bitbanging mode is used.\n");
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdata->use_bitbanging = !pin_check_mpsse;
|
pdata->use_bitbanging = !pin_check_mpsse;
|
||||||
if (pdata->use_bitbanging) log_info("Because of pin configuration fallback to bitbanging mode.\n");
|
if (pdata->use_bitbanging)
|
||||||
|
log_info("Because of pin configuration fallback to bitbanging mode.\n");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* TODO: No need to fail for a wrongly configured led or something.
|
* TODO: No need to fail for a wrongly configured led or something.
|
||||||
* Maybe we should only fail for SCK; MISO, MOSI, RST (and probably
|
* Maybe we should only fail for SCK; SDI, SDO, RST (and probably
|
||||||
* VCC and BUFF).
|
* VCC and BUFF).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* everything is an output, except MISO */
|
/* everything is an output, except SDI */
|
||||||
for(pin = 0; pin < N_PINS; ++pin) {
|
for(pin = 0; pin < N_PINS; ++pin) {
|
||||||
pdata->pin_direction |= pgm->pin[pin].mask[0];
|
pdata->pin_direction |= pgm->pin[pin].mask[0];
|
||||||
pdata->pin_value = SET_BITS_0(pdata->pin_value, pgm, pin, OFF);
|
pdata->pin_value = SET_BITS_0(pdata->pin_value, pgm, pin, OFF);
|
||||||
}
|
}
|
||||||
pdata->pin_direction &= ~pgm->pin[PIN_AVR_MISO].mask[0];
|
pdata->pin_direction &= ~pgm->pin[PIN_AVR_SDI].mask[0];
|
||||||
|
|
||||||
for(pin = PIN_LED_ERR; pin < N_PINS; ++pin) {
|
for(pin = PIN_LED_ERR; pin < N_PINS; ++pin) {
|
||||||
pdata->led_mask |= pgm->pin[pin].mask[0];
|
pdata->led_mask |= pgm->pin[pin].mask[0];
|
||||||
|
@ -648,10 +639,9 @@ static int avrftdi_pin_setup(PROGRAMMER * pgm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_open(PROGRAMMER * pgm, char *port)
|
static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
int vid, pid, interface, index, err;
|
int vid, pid, interface, index, err;
|
||||||
char * serial, *desc;
|
const char *serial, *desc;
|
||||||
|
|
||||||
avrftdi_t* pdata = to_pdata(pgm);
|
avrftdi_t* pdata = to_pdata(pgm);
|
||||||
|
|
||||||
|
@ -671,8 +661,7 @@ static int avrftdi_open(PROGRAMMER * pgm, char *port)
|
||||||
if (usbpid) {
|
if (usbpid) {
|
||||||
pid = *(int *)(ldata(usbpid));
|
pid = *(int *)(ldata(usbpid));
|
||||||
if (lnext(usbpid))
|
if (lnext(usbpid))
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: using PID 0x%04x, ignoring remaining PIDs in list\n",
|
pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid);
|
||||||
progname, pid);
|
|
||||||
} else
|
} else
|
||||||
pid = USB_DEVICE_FT2232;
|
pid = USB_DEVICE_FT2232;
|
||||||
|
|
||||||
|
@ -817,11 +806,10 @@ static void avrftdi_close(PROGRAMMER * pgm)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
static int avrftdi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
avrftdi_powerup(pgm);
|
avrftdi_powerup(pgm);
|
||||||
|
|
||||||
if(p->flags & AVRPART_HAS_TPI)
|
if(p->prog_modes & PM_TPI)
|
||||||
{
|
{
|
||||||
/* see avrftdi_tpi.c */
|
/* see avrftdi_tpi.c */
|
||||||
avrftdi_tpi_initialize(pgm, p);
|
avrftdi_tpi_initialize(pgm, p);
|
||||||
|
@ -847,21 +835,18 @@ static int avrftdi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
return pgm->program_enable(pgm, p);
|
return pgm->program_enable(pgm, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void avrftdi_display(PROGRAMMER * pgm, const char *p)
|
static void avrftdi_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
|
||||||
// print the full pin definitions as in ft245r ?
|
// print the full pin definitions as in ft245r ?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avrftdi_cmd(PROGRAMMER * pgm, const unsigned char *cmd, unsigned char *res)
|
static int avrftdi_cmd(const PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res) {
|
||||||
{
|
|
||||||
return avrftdi_transmit(pgm, MPSSE_DO_READ | MPSSE_DO_WRITE, cmd, res, 4);
|
return avrftdi_transmit(pgm, MPSSE_DO_READ | MPSSE_DO_WRITE, cmd, res, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avrftdi_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
static int avrftdi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
unsigned char buf[4];
|
unsigned char buf[4];
|
||||||
|
|
||||||
|
@ -892,8 +877,7 @@ static int avrftdi_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int avrftdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
static int avrftdi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
unsigned char cmd[4];
|
unsigned char cmd[4];
|
||||||
unsigned char res[4];
|
unsigned char res[4];
|
||||||
|
|
||||||
|
@ -915,10 +899,20 @@ static int avrftdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||||
|
|
||||||
/* Load extended address byte command */
|
/* Load extended address byte command */
|
||||||
static int
|
static int
|
||||||
avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, unsigned int address)
|
avrftdi_lext(const PROGRAMMER *pgm, const AVRPART *p, const 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 };
|
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_bits(m->op[AVR_OP_LOAD_EXT_ADDR], buf);
|
||||||
avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], buf, address);
|
avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], buf, address);
|
||||||
|
|
||||||
|
@ -932,7 +926,7 @@ avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, unsigned int address)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_eeprom_write(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
static int avrftdi_eeprom_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int len)
|
unsigned int page_size, unsigned int addr, unsigned int len)
|
||||||
{
|
{
|
||||||
unsigned char cmd[] = { 0x00, 0x00, 0x00, 0x00 };
|
unsigned char cmd[] = { 0x00, 0x00, 0x00, 0x00 };
|
||||||
|
@ -954,7 +948,7 @@ static int avrftdi_eeprom_write(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
static int avrftdi_eeprom_read(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int len)
|
unsigned int page_size, unsigned int addr, unsigned int len)
|
||||||
{
|
{
|
||||||
unsigned char cmd[4];
|
unsigned char cmd[4];
|
||||||
|
@ -980,11 +974,9 @@ static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avrftdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int len)
|
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 word;
|
||||||
unsigned int poll_index;
|
unsigned int poll_index;
|
||||||
|
|
||||||
|
@ -1006,29 +998,19 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(page_size != m->page_size) {
|
if(page_size != (unsigned int) m->page_size) {
|
||||||
log_warn("Parameter page_size is %d, ", page_size);
|
log_warn("Parameter page_size is %d, ", page_size);
|
||||||
log_warn("but m->page_size is %d. Using the latter.\n", m->page_size);
|
log_warn("but m->page_size is %d. Using the latter.\n", m->page_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
page_size = m->page_size;
|
page_size = m->page_size;
|
||||||
|
|
||||||
/* if we do cross a 64k word boundary (or write the
|
/* on large-flash devices > 128k issue extended address command when needed */
|
||||||
* first page), we need to issue a 'load extended
|
if(avrftdi_lext(pgm, p, m, addr/2) < 0)
|
||||||
* address byte' command, which is defined as 0x4d
|
return -1;
|
||||||
* 0x00 <address byte> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* prepare the command stream for the whole page */
|
/* prepare the command stream for the whole page */
|
||||||
/* addr is in bytes, but we program in words. addr/2 should be something
|
/* addr is in bytes, but we program in words. */
|
||||||
* like addr >> WORD_SHIFT, though */
|
|
||||||
for(word = addr/2; word < (len + addr)/2; word++)
|
for(word = addr/2; word < (len + addr)/2; word++)
|
||||||
{
|
{
|
||||||
log_debug("-< bytes = %d of %d\n", word * 2, len + addr);
|
log_debug("-< bytes = %d of %d\n", word * 2, len + addr);
|
||||||
|
@ -1060,12 +1042,11 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
/* find a poll byte. We cannot poll a value of 0xff, so look
|
/* find a poll byte. We cannot poll a value of 0xff, so look
|
||||||
* for a value != 0xff
|
* for a value != 0xff
|
||||||
*/
|
*/
|
||||||
for(poll_index = addr+len-1; poll_index > addr-1; poll_index--)
|
for(poll_index = addr+len-1; poll_index+1 > addr; poll_index--)
|
||||||
if(m->buf[poll_index] != 0xff)
|
if(m->buf[poll_index] != 0xff)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if((poll_index < addr + len) && m->buf[poll_index] != 0xff)
|
if(poll_index+1 > addr) {
|
||||||
{
|
|
||||||
buf_size = bufptr - buf;
|
buf_size = bufptr - buf;
|
||||||
|
|
||||||
if(verbose > TRACE)
|
if(verbose > TRACE)
|
||||||
|
@ -1102,18 +1083,15 @@ static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
/*
|
/*
|
||||||
*Reading from flash
|
*Reading from flash
|
||||||
*/
|
*/
|
||||||
static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avrftdi_flash_read(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int len)
|
unsigned int page_size, unsigned int addr, unsigned int len)
|
||||||
{
|
{
|
||||||
OPCODE * readop;
|
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 int buf_size = 4 * len + 4;
|
||||||
unsigned char* o_buf = alloca(buf_size);
|
unsigned char* o_buf = alloca(buf_size);
|
||||||
unsigned char* i_buf = alloca(buf_size);
|
unsigned char* i_buf = alloca(buf_size);
|
||||||
unsigned int index;
|
|
||||||
|
|
||||||
memset(o_buf, 0, buf_size);
|
memset(o_buf, 0, buf_size);
|
||||||
memset(i_buf, 0, buf_size);
|
memset(i_buf, 0, buf_size);
|
||||||
|
@ -1128,13 +1106,11 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(use_lext_address && ((address & 0xffff0000))) {
|
if(avrftdi_lext(pgm, p, m, addr/2) < 0)
|
||||||
if (0 > avrftdi_lext(pgm, p, m, address))
|
return -1;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* word addressing! */
|
/* word addressing! */
|
||||||
for(word = addr/2, index = 0; word < (addr + len)/2; word++)
|
for(unsigned int word = addr/2, index = 0; word < (addr + len)/2; word++)
|
||||||
{
|
{
|
||||||
/* one byte is transferred via a 4-byte opcode.
|
/* one byte is transferred via a 4-byte opcode.
|
||||||
* TODO: reduce magic numbers
|
* TODO: reduce magic numbers
|
||||||
|
@ -1165,7 +1141,7 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
memset(&m->buf[addr], 0, page_size);
|
memset(&m->buf[addr], 0, page_size);
|
||||||
|
|
||||||
/* every (read) op is 4 bytes in size and yields one byte of memory data */
|
/* every (read) op is 4 bytes in size and yields one byte of memory data */
|
||||||
for(byte = 0; byte < page_size; byte++) {
|
for(unsigned int byte = 0; byte < page_size; byte++) {
|
||||||
if(byte & 1)
|
if(byte & 1)
|
||||||
readop = m->op[AVR_OP_READ_HI];
|
readop = m->op[AVR_OP_READ_HI];
|
||||||
else
|
else
|
||||||
|
@ -1183,7 +1159,7 @@ static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avrftdi_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
if (strcmp(m->desc, "flash") == 0)
|
if (strcmp(m->desc, "flash") == 0)
|
||||||
|
@ -1194,7 +1170,7 @@ static int avrftdi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrftdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int avrftdi_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
if (strcmp(m->desc, "flash") == 0)
|
if (strcmp(m->desc, "flash") == 0)
|
||||||
|
@ -1210,7 +1186,11 @@ avrftdi_setup(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
avrftdi_t* pdata;
|
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 = to_pdata(pgm);
|
||||||
|
|
||||||
pdata->ftdic = ftdi_new();
|
pdata->ftdic = ftdi_new();
|
||||||
|
@ -1224,6 +1204,7 @@ avrftdi_setup(PROGRAMMER * pgm)
|
||||||
pdata->pin_value = 0;
|
pdata->pin_value = 0;
|
||||||
pdata->pin_direction = 0;
|
pdata->pin_direction = 0;
|
||||||
pdata->led_mask = 0;
|
pdata->led_mask = 0;
|
||||||
|
pdata->lext_byte = 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1238,9 +1219,7 @@ avrftdi_teardown(PROGRAMMER * pgm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void avrftdi_initpgm(PROGRAMMER * pgm)
|
void avrftdi_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
|
|
||||||
strcpy(pgm->type, "avrftdi");
|
strcpy(pgm->type, "avrftdi");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -29,7 +29,7 @@ extern "C" {
|
||||||
|
|
||||||
|
|
||||||
extern const char avrftdi_desc[];
|
extern const char avrftdi_desc[];
|
||||||
void avrftdi_initpgm (PROGRAMMER * pgm);
|
void avrftdi_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#elif defined(HAVE_LIBFTDI)
|
#elif defined(HAVE_LIBFTDI)
|
||||||
#include <ftdi.h>
|
#include <ftdi.h>
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma message("No libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.")
|
#pragma message("No libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.")
|
||||||
#else
|
#else
|
||||||
|
@ -30,7 +31,7 @@ enum { ERR, WARN, INFO, DEBUG, TRACE };
|
||||||
#define __log(lvl, fmt, ...) \
|
#define __log(lvl, fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
avrftdi_log(lvl, __func__, __LINE__, fmt, ##__VA_ARGS__); \
|
avrftdi_log(lvl, __func__, __LINE__, fmt, ##__VA_ARGS__); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
#define log_err(fmt, ...) __log(ERR, fmt, ##__VA_ARGS__)
|
#define log_err(fmt, ...) __log(ERR, fmt, ##__VA_ARGS__)
|
||||||
|
@ -40,47 +41,49 @@ enum { ERR, WARN, INFO, DEBUG, TRACE };
|
||||||
#define log_trace(fmt, ...) __log(TRACE, fmt, ##__VA_ARGS__)
|
#define log_trace(fmt, ...) __log(TRACE, fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
#define E(x, ftdi) \
|
#define E(x, ftdi) \
|
||||||
do { \
|
do { \
|
||||||
if ((x)) \
|
if ((x)) \
|
||||||
{ \
|
{ \
|
||||||
avrdude_message(MSG_INFO, "%s:%d %s() %s: %s (%d)\n\t%s\n", \
|
msg_error("%s:%d %s() %s: %s (%d)\n\t%s\n", \
|
||||||
__FILE__, __LINE__, __FUNCTION__, \
|
__FILE__, __LINE__, __FUNCTION__, \
|
||||||
#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); \
|
#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define E_VOID(x, ftdi) \
|
#define E_VOID(x, ftdi) \
|
||||||
do { \
|
do { \
|
||||||
if ((x)) \
|
if ((x)) \
|
||||||
{ \
|
{ \
|
||||||
avrdude_message(MSG_INFO, "%s:%d %s() %s: %s (%d)\n\t%s\n", \
|
msg_error("%s:%d %s() %s: %s (%d)\n\t%s\n", \
|
||||||
__FILE__, __LINE__, __FUNCTION__, \
|
__FILE__, __LINE__, __FUNCTION__, \
|
||||||
#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); \
|
#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
#define to_pdata(pgm) \
|
#define to_pdata(pgm) \
|
||||||
((avrftdi_t *)((pgm)->cookie))
|
((avrftdi_t *)((pgm)->cookie))
|
||||||
|
|
||||||
typedef struct avrftdi_s {
|
typedef struct avrftdi_s {
|
||||||
/* pointer to struct maintained by libftdi to identify the device */
|
/* pointer to struct maintained by libftdi to identify the device */
|
||||||
struct ftdi_context* ftdic;
|
struct ftdi_context* ftdic;
|
||||||
/* bitmask of values for pins. bit 0 represents pin 0 ([A|B]DBUS0) */
|
/* bitmask of values for pins. bit 0 represents pin 0 ([A|B]DBUS0) */
|
||||||
uint16_t pin_value;
|
uint16_t pin_value;
|
||||||
/* bitmask of pin direction. a '1' make a pin an output.
|
/* bitmask of pin direction. a '1' make a pin an output.
|
||||||
* bit 0 corresponds to pin 0. */
|
* bit 0 corresponds to pin 0. */
|
||||||
uint16_t pin_direction;
|
uint16_t pin_direction;
|
||||||
/* don't know. not useful. someone put it in. */
|
/* don't know. not useful. someone put it in. */
|
||||||
uint16_t led_mask;
|
uint16_t led_mask;
|
||||||
/* total number of pins supported by a programmer. varies with FTDI chips */
|
/* total number of pins supported by a programmer. varies with FTDI chips */
|
||||||
int pin_limit;
|
int pin_limit;
|
||||||
/* internal RX buffer of the device. needed for INOUT transfers */
|
/* internal RX buffer of the device. needed for INOUT transfers */
|
||||||
int rx_buffer_size;
|
int rx_buffer_size;
|
||||||
int tx_buffer_size;
|
int tx_buffer_size;
|
||||||
/* use bitbanging instead of mpsse spi */
|
/* use bitbanging instead of mpsse spi */
|
||||||
bool use_bitbanging;
|
bool use_bitbanging;
|
||||||
|
/* bits 16-23 of extended 24-bit word flash address for parts with flash > 128k */
|
||||||
|
uint8_t lext_byte;
|
||||||
} avrftdi_t;
|
} avrftdi_t;
|
||||||
|
|
||||||
void avrftdi_log(int level, const char * func, int line, const char * fmt, ...);
|
void avrftdi_log(int level, const char * func, int line, const char * fmt, ...);
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
|
|
||||||
#ifndef DO_NOT_BUILD_AVRFTDI
|
#ifndef DO_NOT_BUILD_AVRFTDI
|
||||||
|
|
||||||
static void avrftdi_tpi_disable(PROGRAMMER *);
|
static void avrftdi_tpi_disable(const PROGRAMMER *);
|
||||||
static int avrftdi_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p);
|
static int avrftdi_tpi_program_enable(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
|
||||||
#ifdef notyet
|
#ifdef notyet
|
||||||
static void
|
static void
|
||||||
|
@ -63,27 +63,16 @@ avrftdi_debug_frame(uint16_t frame)
|
||||||
#endif /* notyet */
|
#endif /* notyet */
|
||||||
|
|
||||||
int
|
int
|
||||||
avrftdi_tpi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
avrftdi_tpi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
avrftdi_t* pdata = to_pdata(pgm);
|
avrftdi_t* pdata = to_pdata(pgm);
|
||||||
unsigned char buf[] = { MPSSE_DO_WRITE | MPSSE_WRITE_NEG | MPSSE_LSB, 0x01, 0x00, 0xff, 0xff };
|
unsigned char buf[] = { MPSSE_DO_WRITE | MPSSE_WRITE_NEG | MPSSE_LSB, 0x01, 0x00, 0xff, 0xff };
|
||||||
|
|
||||||
log_info("Using TPI interface\n");
|
|
||||||
|
|
||||||
pgm->program_enable = avrftdi_tpi_program_enable;
|
|
||||||
pgm->cmd_tpi = avrftdi_cmd_tpi;
|
|
||||||
pgm->chip_erase = avr_tpi_chip_erase;
|
|
||||||
pgm->disable = avrftdi_tpi_disable;
|
|
||||||
|
|
||||||
pgm->paged_load = NULL;
|
|
||||||
pgm->paged_write = NULL;
|
|
||||||
|
|
||||||
log_info("Setting /Reset pin low\n");
|
log_info("Setting /Reset pin low\n");
|
||||||
pgm->setpin(pgm, PIN_AVR_RESET, OFF);
|
pgm->setpin(pgm, PIN_AVR_RESET, OFF);
|
||||||
pgm->setpin(pgm, PIN_AVR_SCK, OFF);
|
pgm->setpin(pgm, PIN_AVR_SCK, OFF);
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, ON);
|
pgm->setpin(pgm, PIN_AVR_SDO, ON);
|
||||||
usleep(20 * 1000);
|
usleep(20 * 1000);
|
||||||
|
|
||||||
pgm->setpin(pgm, PIN_AVR_RESET, ON);
|
pgm->setpin(pgm, PIN_AVR_RESET, ON);
|
||||||
|
@ -101,6 +90,20 @@ avrftdi_tpi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void avrftdi_tpi_initpgm(PROGRAMMER *pgm) {
|
||||||
|
log_info("Using TPI interface\n");
|
||||||
|
|
||||||
|
pgm->program_enable = avrftdi_tpi_program_enable;
|
||||||
|
pgm->cmd_tpi = avrftdi_cmd_tpi;
|
||||||
|
pgm->chip_erase = avr_tpi_chip_erase;
|
||||||
|
pgm->disable = avrftdi_tpi_disable;
|
||||||
|
|
||||||
|
pgm->paged_load = NULL;
|
||||||
|
pgm->paged_write = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define TPI_PARITY_MASK 0x2000
|
#define TPI_PARITY_MASK 0x2000
|
||||||
|
|
||||||
static inline int count1s(unsigned int x)
|
static inline int count1s(unsigned int x)
|
||||||
|
@ -148,8 +151,7 @@ tpi_frame2byte(uint16_t frame, uint8_t * byte)
|
||||||
|
|
||||||
#ifdef notyet
|
#ifdef notyet
|
||||||
static int
|
static int
|
||||||
avrftdi_tpi_break(PROGRAMMER * pgm)
|
avrftdi_tpi_break(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
unsigned char buffer[] = { MPSSE_DO_WRITE | MPSSE_WRITE_NEG | MPSSE_LSB, 1, 0, 0, 0 };
|
unsigned char buffer[] = { MPSSE_DO_WRITE | MPSSE_WRITE_NEG | MPSSE_LSB, 1, 0, 0, 0 };
|
||||||
E(ftdi_write_data(to_pdata(pgm)->ftdic, buffer, sizeof(buffer)) != sizeof(buffer), to_pdata(pgm)->ftdic);
|
E(ftdi_write_data(to_pdata(pgm)->ftdic, buffer, sizeof(buffer)) != sizeof(buffer), to_pdata(pgm)->ftdic);
|
||||||
|
|
||||||
|
@ -158,8 +160,7 @@ avrftdi_tpi_break(PROGRAMMER * pgm)
|
||||||
#endif /* notyet */
|
#endif /* notyet */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
avrftdi_tpi_write_byte(PROGRAMMER * pgm, unsigned char byte)
|
avrftdi_tpi_write_byte(const PROGRAMMER *pgm, unsigned char byte) {
|
||||||
{
|
|
||||||
uint16_t frame;
|
uint16_t frame;
|
||||||
|
|
||||||
struct ftdi_context* ftdic = to_pdata(pgm)->ftdic;
|
struct ftdi_context* ftdic = to_pdata(pgm)->ftdic;
|
||||||
|
@ -185,8 +186,7 @@ avrftdi_tpi_write_byte(PROGRAMMER * pgm, unsigned char byte)
|
||||||
#define TPI_IDLE_BITS 2
|
#define TPI_IDLE_BITS 2
|
||||||
|
|
||||||
static int
|
static int
|
||||||
avrftdi_tpi_read_byte(PROGRAMMER * pgm, unsigned char * byte)
|
avrftdi_tpi_read_byte(const PROGRAMMER *pgm, unsigned char *byte) {
|
||||||
{
|
|
||||||
uint16_t frame;
|
uint16_t frame;
|
||||||
|
|
||||||
/* use 2 guard bits, 2 default idle bits + 12 frame bits = 16 bits total */
|
/* use 2 guard bits, 2 default idle bits + 12 frame bits = 16 bits total */
|
||||||
|
@ -230,13 +230,12 @@ avrftdi_tpi_read_byte(PROGRAMMER * pgm, unsigned char * byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
avrftdi_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
avrftdi_tpi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
return avr_tpi_program_enable(pgm, p, TPIPCR_GT_2b);
|
return avr_tpi_program_enable(pgm, p, TPIPCR_GT_2b);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
avrftdi_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd, int cmd_len,
|
avrftdi_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd, int cmd_len,
|
||||||
unsigned char *res, int res_len)
|
unsigned char *res, int res_len)
|
||||||
{
|
{
|
||||||
int i, err = 0;
|
int i, err = 0;
|
||||||
|
@ -259,8 +258,7 @@ avrftdi_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd, int cmd_len,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
avrftdi_tpi_disable(PROGRAMMER * pgm)
|
avrftdi_tpi_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
unsigned char cmd[] = {TPI_OP_SSTCS(TPIPCR), 0};
|
unsigned char cmd[] = {TPI_OP_SSTCS(TPIPCR), 0};
|
||||||
pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);
|
pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
//int avrftdi_tpi_write_byte(PROGRAMMER * pgm, unsigned char byte);
|
//int avrftdi_tpi_write_byte(PROGRAMMER *pgm, unsigned char byte);
|
||||||
//int avrftdi_tpi_read_byte(PROGRAMMER * pgm, unsigned char * byte);
|
//int avrftdi_tpi_read_byte(PROGRAMMER *pgm, unsigned char * byte);
|
||||||
int avrftdi_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd, int cmd_len,
|
int avrftdi_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd, int cmd_len,
|
||||||
unsigned char *res, int res_len);
|
unsigned char *res, int res_len);
|
||||||
int avrftdi_tpi_initialize(PROGRAMMER * pgm, AVRPART * p);
|
int avrftdi_tpi_initialize(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
void avrftdi_tpi_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
869
src/avrpart.c
869
src/avrpart.c
File diff suppressed because it is too large
Load Diff
175
src/bitbang.c
175
src/bitbang.c
|
@ -76,8 +76,7 @@ static void bitbang_calibrate_delay(void)
|
||||||
if (QueryPerformanceFrequency(&freq))
|
if (QueryPerformanceFrequency(&freq))
|
||||||
{
|
{
|
||||||
has_perfcount = 1;
|
has_perfcount = 1;
|
||||||
avrdude_message(MSG_NOTICE2, "%s: Using performance counter for bitbang delays\n",
|
pmsg_notice2("using performance counter for bitbang delays\n");
|
||||||
progname);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -90,16 +89,14 @@ static void bitbang_calibrate_delay(void)
|
||||||
* auto-calibration figures seen on various Unix systems on
|
* auto-calibration figures seen on various Unix systems on
|
||||||
* comparable hardware.
|
* comparable hardware.
|
||||||
*/
|
*/
|
||||||
avrdude_message(MSG_NOTICE2, "%s: Using guessed per-microsecond delay count for bitbang delays\n",
|
pmsg_notice2("using guessed per-microsecond delay count for bitbang delays\n");
|
||||||
progname);
|
|
||||||
delay_decrement = 100;
|
delay_decrement = 100;
|
||||||
}
|
}
|
||||||
#else /* !WIN32 */
|
#else /* !WIN32 */
|
||||||
struct itimerval itv;
|
struct itimerval itv;
|
||||||
volatile int i;
|
volatile int i;
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: Calibrating delay loop...",
|
pmsg_notice2("calibrating delay loop ...");
|
||||||
progname);
|
|
||||||
i = 0;
|
i = 0;
|
||||||
done = 0;
|
done = 0;
|
||||||
saved_alarmhandler = signal(SIGALRM, alarmhandler);
|
saved_alarmhandler = signal(SIGALRM, alarmhandler);
|
||||||
|
@ -125,7 +122,7 @@ static void bitbang_calibrate_delay(void)
|
||||||
* Calculate back from 100 ms to 1 us.
|
* Calculate back from 100 ms to 1 us.
|
||||||
*/
|
*/
|
||||||
delay_decrement = -i / 100000;
|
delay_decrement = -i / 100000;
|
||||||
avrdude_message(MSG_NOTICE2, " calibrated to %d cycles per us\n",
|
msg_notice2(" calibrated to %d cycles per us\n",
|
||||||
delay_decrement);
|
delay_decrement);
|
||||||
#endif /* WIN32 */
|
#endif /* WIN32 */
|
||||||
}
|
}
|
||||||
|
@ -163,8 +160,7 @@ void bitbang_delay(unsigned int us)
|
||||||
/*
|
/*
|
||||||
* transmit and receive a byte of data to/from the AVR device
|
* transmit and receive a byte of data to/from the AVR device
|
||||||
*/
|
*/
|
||||||
static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
|
static unsigned char bitbang_txrx(const PROGRAMMER *pgm, unsigned char byte) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
unsigned char r, b, rbyte;
|
unsigned char r, b, rbyte;
|
||||||
|
|
||||||
|
@ -176,9 +172,9 @@ static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
|
||||||
* one pgm->setpin()-call resp. par clrpin()-call, then
|
* one pgm->setpin()-call resp. par clrpin()-call, then
|
||||||
* - SCK is high for 2T
|
* - SCK is high for 2T
|
||||||
* - SCK is low for 2T
|
* - SCK is low for 2T
|
||||||
* - MOSI setuptime is 1T
|
* - SDO setuptime is 1T
|
||||||
* - MOSI holdtime is 3T
|
* - SDO holdtime is 3T
|
||||||
* - SCK low to MISO read is 2T to 3T
|
* - SCK low to SDI read is 2T to 3T
|
||||||
* So we are within programming specs (expect for AT90S1200),
|
* So we are within programming specs (expect for AT90S1200),
|
||||||
* if and only if T>t_CLCL (t_CLCL=clock period of target system).
|
* if and only if T>t_CLCL (t_CLCL=clock period of target system).
|
||||||
*
|
*
|
||||||
|
@ -190,7 +186,7 @@ static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
|
||||||
b = (byte >> i) & 0x01;
|
b = (byte >> i) & 0x01;
|
||||||
|
|
||||||
/* set the data input line as desired */
|
/* set the data input line as desired */
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, b);
|
pgm->setpin(pgm, PIN_AVR_SDO, b);
|
||||||
|
|
||||||
pgm->setpin(pgm, PIN_AVR_SCK, 1);
|
pgm->setpin(pgm, PIN_AVR_SCK, 1);
|
||||||
|
|
||||||
|
@ -198,7 +194,7 @@ static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
|
||||||
* read the result bit (it is either valid from a previous falling
|
* read the result bit (it is either valid from a previous falling
|
||||||
* edge or it is ignored in the current context)
|
* edge or it is ignored in the current context)
|
||||||
*/
|
*/
|
||||||
r = pgm->getpin(pgm, PIN_AVR_MISO);
|
r = pgm->getpin(pgm, PIN_AVR_SDI);
|
||||||
|
|
||||||
pgm->setpin(pgm, PIN_AVR_SCK, 0);
|
pgm->setpin(pgm, PIN_AVR_SCK, 0);
|
||||||
|
|
||||||
|
@ -208,25 +204,23 @@ static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
|
||||||
return rbyte;
|
return rbyte;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bitbang_tpi_clk(PROGRAMMER * pgm)
|
static int bitbang_tpi_clk(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
unsigned char r = 0;
|
unsigned char r = 0;
|
||||||
pgm->setpin(pgm, PIN_AVR_SCK, 1);
|
pgm->setpin(pgm, PIN_AVR_SCK, 1);
|
||||||
|
|
||||||
r = pgm->getpin(pgm, PIN_AVR_MISO);
|
r = pgm->getpin(pgm, PIN_AVR_SDI);
|
||||||
|
|
||||||
pgm->setpin(pgm, PIN_AVR_SCK, 0);
|
pgm->setpin(pgm, PIN_AVR_SCK, 0);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bitbang_tpi_tx(PROGRAMMER * pgm, unsigned char byte)
|
void bitbang_tpi_tx(const PROGRAMMER *pgm, unsigned char byte) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
unsigned char b, parity;
|
unsigned char b, parity;
|
||||||
|
|
||||||
/* start bit */
|
/* start bit */
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, 0);
|
pgm->setpin(pgm, PIN_AVR_SDO, 0);
|
||||||
bitbang_tpi_clk(pgm);
|
bitbang_tpi_clk(pgm);
|
||||||
|
|
||||||
parity = 0;
|
parity = 0;
|
||||||
|
@ -235,27 +229,26 @@ void bitbang_tpi_tx(PROGRAMMER * pgm, unsigned char byte)
|
||||||
parity ^= b;
|
parity ^= b;
|
||||||
|
|
||||||
/* set the data input line as desired */
|
/* set the data input line as desired */
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, b);
|
pgm->setpin(pgm, PIN_AVR_SDO, b);
|
||||||
bitbang_tpi_clk(pgm);
|
bitbang_tpi_clk(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parity bit */
|
/* parity bit */
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, parity);
|
pgm->setpin(pgm, PIN_AVR_SDO, parity);
|
||||||
bitbang_tpi_clk(pgm);
|
bitbang_tpi_clk(pgm);
|
||||||
|
|
||||||
/* 2 stop bits */
|
/* 2 stop bits */
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, 1);
|
pgm->setpin(pgm, PIN_AVR_SDO, 1);
|
||||||
bitbang_tpi_clk(pgm);
|
bitbang_tpi_clk(pgm);
|
||||||
bitbang_tpi_clk(pgm);
|
bitbang_tpi_clk(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bitbang_tpi_rx(PROGRAMMER * pgm)
|
int bitbang_tpi_rx(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
int i;
|
int i;
|
||||||
unsigned char b, rbyte, parity;
|
unsigned char b, rbyte, parity;
|
||||||
|
|
||||||
/* make sure pin is on for "pullup" */
|
/* make sure pin is on for "pullup" */
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, 1);
|
pgm->setpin(pgm, PIN_AVR_SDO, 1);
|
||||||
|
|
||||||
/* wait for start bit (up to 10 bits) */
|
/* wait for start bit (up to 10 bits) */
|
||||||
b = 1;
|
b = 1;
|
||||||
|
@ -265,7 +258,7 @@ int bitbang_tpi_rx(PROGRAMMER * pgm)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (b != 0) {
|
if (b != 0) {
|
||||||
avrdude_message(MSG_INFO, "bitbang_tpi_rx: start bit not received correctly\n");
|
pmsg_error("start bit not received correctly\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +273,7 @@ int bitbang_tpi_rx(PROGRAMMER * pgm)
|
||||||
|
|
||||||
/* parity bit */
|
/* parity bit */
|
||||||
if (bitbang_tpi_clk(pgm) != parity) {
|
if (bitbang_tpi_clk(pgm) != parity) {
|
||||||
avrdude_message(MSG_INFO, "bitbang_tpi_rx: parity bit is wrong\n");
|
pmsg_error("parity bit is wrong\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,33 +282,29 @@ int bitbang_tpi_rx(PROGRAMMER * pgm)
|
||||||
b &= bitbang_tpi_clk(pgm);
|
b &= bitbang_tpi_clk(pgm);
|
||||||
b &= bitbang_tpi_clk(pgm);
|
b &= bitbang_tpi_clk(pgm);
|
||||||
if (b != 1) {
|
if (b != 1) {
|
||||||
avrdude_message(MSG_INFO, "bitbang_tpi_rx: stop bits not received correctly\n");
|
pmsg_error("stop bits not received correctly\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rbyte;
|
return rbyte;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bitbang_rdy_led(PROGRAMMER * pgm, int value)
|
int bitbang_rdy_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
pgm->setpin(pgm, PIN_LED_RDY, !value);
|
pgm->setpin(pgm, PIN_LED_RDY, !value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bitbang_err_led(PROGRAMMER * pgm, int value)
|
int bitbang_err_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
pgm->setpin(pgm, PIN_LED_ERR, !value);
|
pgm->setpin(pgm, PIN_LED_ERR, !value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bitbang_pgm_led(PROGRAMMER * pgm, int value)
|
int bitbang_pgm_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
pgm->setpin(pgm, PIN_LED_PGM, !value);
|
pgm->setpin(pgm, PIN_LED_PGM, !value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bitbang_vfy_led(PROGRAMMER * pgm, int value)
|
int bitbang_vfy_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
pgm->setpin(pgm, PIN_LED_VFY, !value);
|
pgm->setpin(pgm, PIN_LED_VFY, !value);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -325,7 +314,7 @@ int bitbang_vfy_led(PROGRAMMER * pgm, int value)
|
||||||
* transmit an AVR device command and return the results; 'cmd' and
|
* transmit an AVR device command and return the results; 'cmd' and
|
||||||
* 'res' must point to at least a 4 byte data buffer
|
* 'res' must point to at least a 4 byte data buffer
|
||||||
*/
|
*/
|
||||||
int bitbang_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
|
int bitbang_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
unsigned char *res)
|
unsigned char *res)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -336,21 +325,21 @@ int bitbang_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
|
||||||
|
|
||||||
if(verbose >= 2)
|
if(verbose >= 2)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE2, "bitbang_cmd(): [ ");
|
msg_notice2("bitbang_cmd(): [ ");
|
||||||
for(i = 0; i < 4; i++)
|
for(i = 0; i < 4; i++)
|
||||||
avrdude_message(MSG_NOTICE2, "%02X ", cmd[i]);
|
msg_notice2("%02X ", cmd[i]);
|
||||||
avrdude_message(MSG_NOTICE2, "] [ ");
|
msg_notice2("] [ ");
|
||||||
for(i = 0; i < 4; i++)
|
for(i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE2, "%02X ", res[i]);
|
msg_notice2("%02X ", res[i]);
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_NOTICE2, "]\n");
|
msg_notice2("]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bitbang_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd,
|
int bitbang_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
int cmd_len, unsigned char *res, int res_len)
|
int cmd_len, unsigned char *res, int res_len)
|
||||||
{
|
{
|
||||||
int i, r;
|
int i, r;
|
||||||
|
@ -371,15 +360,15 @@ int bitbang_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd,
|
||||||
|
|
||||||
if(verbose >= 2)
|
if(verbose >= 2)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE2, "bitbang_cmd_tpi(): [ ");
|
msg_notice2("bitbang_cmd_tpi(): [ ");
|
||||||
for(i = 0; i < cmd_len; i++)
|
for(i = 0; i < cmd_len; i++)
|
||||||
avrdude_message(MSG_NOTICE2, "%02X ", cmd[i]);
|
msg_notice2("%02X ", cmd[i]);
|
||||||
avrdude_message(MSG_NOTICE2, "] [ ");
|
msg_notice2("] [ ");
|
||||||
for(i = 0; i < res_len; i++)
|
for(i = 0; i < res_len; i++)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE2, "%02X ", res[i]);
|
msg_notice2("%02X ", res[i]);
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_NOTICE2, "]\n");
|
msg_notice2("]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pgm->pgm_led(pgm, OFF);
|
pgm->pgm_led(pgm, OFF);
|
||||||
|
@ -392,7 +381,7 @@ int bitbang_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd,
|
||||||
* transmit bytes via SPI and return the results; 'cmd' and
|
* transmit bytes via SPI and return the results; 'cmd' and
|
||||||
* 'res' must point to data buffers
|
* 'res' must point to data buffers
|
||||||
*/
|
*/
|
||||||
int bitbang_spi(PROGRAMMER * pgm, const unsigned char *cmd,
|
int bitbang_spi(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
unsigned char *res, int count)
|
unsigned char *res, int count)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -407,15 +396,15 @@ int bitbang_spi(PROGRAMMER * pgm, const unsigned char *cmd,
|
||||||
|
|
||||||
if(verbose >= 2)
|
if(verbose >= 2)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE2, "bitbang_cmd(): [ ");
|
msg_notice2("bitbang_cmd(): [ ");
|
||||||
for(i = 0; i < count; i++)
|
for(i = 0; i < count; i++)
|
||||||
avrdude_message(MSG_NOTICE2, "%02X ", cmd[i]);
|
msg_notice2("%02X ", cmd[i]);
|
||||||
avrdude_message(MSG_NOTICE2, "] [ ");
|
msg_notice2("] [ ");
|
||||||
for(i = 0; i < count; i++)
|
for(i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE2, "%02X ", res[i]);
|
msg_notice2("%02X ", res[i]);
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_NOTICE2, "]\n");
|
msg_notice2("]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -425,13 +414,12 @@ int bitbang_spi(PROGRAMMER * pgm, const unsigned char *cmd,
|
||||||
/*
|
/*
|
||||||
* issue the 'chip erase' command to the AVR device
|
* issue the 'chip erase' command to the AVR device
|
||||||
*/
|
*/
|
||||||
int bitbang_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
int bitbang_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
unsigned char cmd[4];
|
unsigned char cmd[4];
|
||||||
unsigned char res[4];
|
unsigned char res[4];
|
||||||
AVRMEM *mem;
|
AVRMEM *mem;
|
||||||
|
|
||||||
if (p->flags & AVRPART_HAS_TPI) {
|
if (p->prog_modes & PM_TPI) {
|
||||||
pgm->pgm_led(pgm, ON);
|
pgm->pgm_led(pgm, ON);
|
||||||
|
|
||||||
while (avr_tpi_poll_nvmbsy(pgm));
|
while (avr_tpi_poll_nvmbsy(pgm));
|
||||||
|
@ -443,8 +431,7 @@ int bitbang_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||||
/* Set Pointer Register */
|
/* Set Pointer Register */
|
||||||
mem = avr_locate_mem(p, "flash");
|
mem = avr_locate_mem(p, "flash");
|
||||||
if (mem == NULL) {
|
if (mem == NULL) {
|
||||||
avrdude_message(MSG_INFO, "No flash memory to erase for part %s\n",
|
pmsg_error("no flash memory to erase for part %s\n", p->desc);
|
||||||
p->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bitbang_tpi_tx(pgm, TPI_CMD_SSTPR | 0);
|
bitbang_tpi_tx(pgm, TPI_CMD_SSTPR | 0);
|
||||||
|
@ -464,8 +451,7 @@ int bitbang_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
|
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
|
||||||
avrdude_message(MSG_INFO, "chip erase instruction not defined for part \"%s\"\n",
|
pmsg_error("chip erase instruction not defined for part %s\n", p->desc);
|
||||||
p->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,13 +472,12 @@ int bitbang_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||||
/*
|
/*
|
||||||
* issue the 'program enable' command to the AVR device
|
* issue the 'program enable' command to the AVR device
|
||||||
*/
|
*/
|
||||||
int bitbang_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
int bitbang_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
unsigned char cmd[4];
|
unsigned char cmd[4];
|
||||||
unsigned char res[4];
|
unsigned char res[4];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (p->flags & AVRPART_HAS_TPI) {
|
if (p->prog_modes & PM_TPI) {
|
||||||
/* enable NVM programming */
|
/* enable NVM programming */
|
||||||
bitbang_tpi_tx(pgm, TPI_CMD_SKEY);
|
bitbang_tpi_tx(pgm, TPI_CMD_SKEY);
|
||||||
for (i = sizeof(tpi_skey) - 1; i >= 0; i--)
|
for (i = sizeof(tpi_skey) - 1; i >= 0; i--)
|
||||||
|
@ -505,8 +490,7 @@ int bitbang_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
|
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
|
||||||
avrdude_message(MSG_INFO, "program enable instruction not defined for part \"%s\"\n",
|
pmsg_error("program enable instruction not defined for part %s\n", p->desc);
|
||||||
p->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,8 +507,7 @@ int bitbang_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||||
/*
|
/*
|
||||||
* initialize the AVR device and prepare it to accept commands
|
* initialize the AVR device and prepare it to accept commands
|
||||||
*/
|
*/
|
||||||
int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
int bitbang_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
int rc;
|
int rc;
|
||||||
int tries;
|
int tries;
|
||||||
int i;
|
int i;
|
||||||
|
@ -534,12 +517,11 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
pgm->powerup(pgm);
|
pgm->powerup(pgm);
|
||||||
usleep(20000);
|
usleep(20000);
|
||||||
|
|
||||||
/* TPIDATA is a single line, so MISO & MOSI should be connected */
|
/* TPIDATA is a single line, so SDI & SDO should be connected */
|
||||||
if (p->flags & AVRPART_HAS_TPI) {
|
if (p->prog_modes & PM_TPI) {
|
||||||
/* make sure cmd_tpi() is defined */
|
/* make sure cmd_tpi() is defined */
|
||||||
if (pgm->cmd_tpi == NULL) {
|
if (pgm->cmd_tpi == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: %s programmer does not support TPI\n",
|
pmsg_error("%s programmer does not support TPI\n", pgm->type);
|
||||||
progname, pgm->type);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,29 +532,29 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
/* RESET must be LOW in case the existing code is driving the TPI pins: */
|
/* RESET must be LOW in case the existing code is driving the TPI pins: */
|
||||||
pgm->setpin(pgm, PIN_AVR_RESET, 0);
|
pgm->setpin(pgm, PIN_AVR_RESET, 0);
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "doing MOSI-MISO link check\n");
|
msg_notice2("doing SDO-SDI link check\n");
|
||||||
|
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, 0);
|
pgm->setpin(pgm, PIN_AVR_SDO, 0);
|
||||||
if (pgm->getpin(pgm, PIN_AVR_MISO) != 0) {
|
if (pgm->getpin(pgm, PIN_AVR_SDI) != 0) {
|
||||||
avrdude_message(MSG_INFO, "MOSI->MISO 0 failed\n");
|
pmsg_error("SDO->SDI 0 failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, 1);
|
pgm->setpin(pgm, PIN_AVR_SDO, 1);
|
||||||
if (pgm->getpin(pgm, PIN_AVR_MISO) != 1) {
|
if (pgm->getpin(pgm, PIN_AVR_SDI) != 1) {
|
||||||
avrdude_message(MSG_INFO, "MOSI->MISO 1 failed\n");
|
pmsg_error("SDO->SDI 1 failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "MOSI-MISO link present\n");
|
msg_notice2("SDO-SDI link present\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
pgm->setpin(pgm, PIN_AVR_SCK, 0);
|
pgm->setpin(pgm, PIN_AVR_SCK, 0);
|
||||||
pgm->setpin(pgm, PIN_AVR_RESET, 0);
|
pgm->setpin(pgm, PIN_AVR_RESET, 0);
|
||||||
usleep(20000);
|
usleep(20000);
|
||||||
|
|
||||||
if (p->flags & AVRPART_HAS_TPI) {
|
if (p->prog_modes & PM_TPI) {
|
||||||
/* keep TPIDATA high for 16 clock cycles */
|
/* keep TPIDATA high for 16 clock cycles */
|
||||||
pgm->setpin(pgm, PIN_AVR_MOSI, 1);
|
pgm->setpin(pgm, PIN_AVR_SDO, 1);
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
pgm->highpulsepin(pgm, PIN_AVR_SCK);
|
pgm->highpulsepin(pgm, PIN_AVR_SCK);
|
||||||
|
|
||||||
|
@ -584,7 +566,7 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
bitbang_tpi_tx(pgm, TPI_CMD_SLDCS | TPI_REG_TPIIR);
|
bitbang_tpi_tx(pgm, TPI_CMD_SLDCS | TPI_REG_TPIIR);
|
||||||
rc = bitbang_tpi_rx(pgm);
|
rc = bitbang_tpi_rx(pgm);
|
||||||
if (rc != 0x80) {
|
if (rc != 0x80) {
|
||||||
avrdude_message(MSG_INFO, "TPIIR not correct\n");
|
pmsg_error("TPIIR not correct\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -618,7 +600,7 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
* can't sync with the device, maybe it's not attached?
|
* can't sync with the device, maybe it's not attached?
|
||||||
*/
|
*/
|
||||||
if (rc) {
|
if (rc) {
|
||||||
avrdude_message(MSG_INFO, "%s: AVR device not responding\n", progname);
|
pmsg_error("AVR device not responding\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -626,11 +608,14 @@ int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int verify_pin_assigned(PROGRAMMER * pgm, int pin, char * desc)
|
static int verify_pin_assigned(const PROGRAMMER *pgm, int pinfunc, char *desc) {
|
||||||
{
|
if(pinfunc < 0 || pinfunc >= N_PINS) {
|
||||||
if (pgm->pinno[pin] == 0) {
|
pmsg_error("invalid pin function number %d\n", pinfunc);
|
||||||
avrdude_message(MSG_INFO, "%s: error: no pin has been assigned for %s\n",
|
return -1;
|
||||||
progname, desc);
|
}
|
||||||
|
|
||||||
|
if ((pgm->pinno[pinfunc] & PIN_MASK) > PIN_MAX) {
|
||||||
|
pmsg_error("no pin has been assigned for %s\n", desc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -640,21 +625,19 @@ static int verify_pin_assigned(PROGRAMMER * pgm, int pin, char * desc)
|
||||||
/*
|
/*
|
||||||
* Verify all prerequisites for a bit-bang programmer are present.
|
* Verify all prerequisites for a bit-bang programmer are present.
|
||||||
*/
|
*/
|
||||||
int bitbang_check_prerequisites(PROGRAMMER *pgm)
|
int bitbang_check_prerequisites(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
|
|
||||||
if (verify_pin_assigned(pgm, PIN_AVR_RESET, "AVR RESET") < 0)
|
if (verify_pin_assigned(pgm, PIN_AVR_RESET, "AVR RESET") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (verify_pin_assigned(pgm, PIN_AVR_SCK, "AVR SCK") < 0)
|
if (verify_pin_assigned(pgm, PIN_AVR_SCK, "AVR SCK") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (verify_pin_assigned(pgm, PIN_AVR_MISO, "AVR MISO") < 0)
|
if (verify_pin_assigned(pgm, PIN_AVR_SDI, "AVR SDI") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (verify_pin_assigned(pgm, PIN_AVR_MOSI, "AVR MOSI") < 0)
|
if (verify_pin_assigned(pgm, PIN_AVR_SDO, "AVR SDO") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (pgm->cmd == NULL) {
|
if (pgm->cmd == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: error: no cmd() method defined for bitbang programmer\n",
|
pmsg_error("no cmd() method defined for bitbang programmer\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -31,25 +31,25 @@ int bitbang_getpin(int fd, int pin);
|
||||||
int bitbang_highpulsepin(int fd, int pin);
|
int bitbang_highpulsepin(int fd, int pin);
|
||||||
void bitbang_delay(unsigned int us);
|
void bitbang_delay(unsigned int us);
|
||||||
|
|
||||||
int bitbang_check_prerequisites(PROGRAMMER *pgm);
|
int bitbang_check_prerequisites(const PROGRAMMER *pgm);
|
||||||
|
|
||||||
int bitbang_rdy_led (PROGRAMMER * pgm, int value);
|
int bitbang_rdy_led (const PROGRAMMER *pgm, int value);
|
||||||
int bitbang_err_led (PROGRAMMER * pgm, int value);
|
int bitbang_err_led (const PROGRAMMER *pgm, int value);
|
||||||
int bitbang_pgm_led (PROGRAMMER * pgm, int value);
|
int bitbang_pgm_led (const PROGRAMMER *pgm, int value);
|
||||||
int bitbang_vfy_led (PROGRAMMER * pgm, int value);
|
int bitbang_vfy_led (const PROGRAMMER *pgm, int value);
|
||||||
int bitbang_cmd (PROGRAMMER * pgm, const unsigned char *cmd,
|
int bitbang_cmd (const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
unsigned char *res);
|
unsigned char *res);
|
||||||
int bitbang_cmd_tpi (PROGRAMMER * pgm, const unsigned char *cmd,
|
int bitbang_cmd_tpi (const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
int cmd_len, unsigned char *res, int res_len);
|
int cmd_len, unsigned char *res, int res_len);
|
||||||
int bitbang_spi (PROGRAMMER * pgm, const unsigned char *cmd,
|
int bitbang_spi (const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
unsigned char *res, int count);
|
unsigned char *res, int count);
|
||||||
int bitbang_chip_erase (PROGRAMMER * pgm, AVRPART * p);
|
int bitbang_chip_erase (const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
int bitbang_program_enable (PROGRAMMER * pgm, AVRPART * p);
|
int bitbang_program_enable (const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
void bitbang_powerup (PROGRAMMER * pgm);
|
void bitbang_powerup (const PROGRAMMER *pgm);
|
||||||
void bitbang_powerdown (PROGRAMMER * pgm);
|
void bitbang_powerdown (const PROGRAMMER *pgm);
|
||||||
int bitbang_initialize (PROGRAMMER * pgm, AVRPART * p);
|
int bitbang_initialize (const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
void bitbang_disable (PROGRAMMER * pgm);
|
void bitbang_disable (const PROGRAMMER *pgm);
|
||||||
void bitbang_enable (PROGRAMMER * pgm);
|
void bitbang_enable (PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
403
src/buspirate.c
403
src/buspirate.c
File diff suppressed because it is too large
Load Diff
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
extern const char buspirate_desc[];
|
extern const char buspirate_desc[];
|
||||||
extern const char buspirate_bb_desc[];
|
extern const char buspirate_bb_desc[];
|
||||||
void buspirate_initpgm (struct programmer_t *pgm);
|
void buspirate_initpgm(PROGRAMMER *pgm);
|
||||||
void buspirate_bb_initpgm (struct programmer_t *pgm);
|
void buspirate_bb_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
195
src/butterfly.c
195
src/butterfly.c
|
@ -63,8 +63,7 @@ struct pdata
|
||||||
static void butterfly_setup(PROGRAMMER * pgm)
|
static void butterfly_setup(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
|
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: butterfly_setup(): Out of memory allocating private data\n",
|
pmsg_error("out of memory allocating private data\n");
|
||||||
progname);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
memset(pgm->cookie, 0, sizeof(struct pdata));
|
memset(pgm->cookie, 0, sizeof(struct pdata));
|
||||||
|
@ -75,72 +74,62 @@ static void butterfly_teardown(PROGRAMMER * pgm)
|
||||||
free(pgm->cookie);
|
free(pgm->cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int butterfly_send(PROGRAMMER * pgm, char * buf, size_t len)
|
static int butterfly_send(const PROGRAMMER *pgm, char *buf, size_t len) {
|
||||||
{
|
|
||||||
return serial_send(&pgm->fd, (unsigned char *)buf, len);
|
return serial_send(&pgm->fd, (unsigned char *)buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_recv(PROGRAMMER * pgm, char * buf, size_t len)
|
static int butterfly_recv(const PROGRAMMER *pgm, char *buf, size_t len) {
|
||||||
{
|
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
|
rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
|
||||||
if (rv < 0) {
|
if (rv < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: butterfly_recv(): programmer is not responding\n",
|
pmsg_error("programmer is not responding\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_drain(PROGRAMMER * pgm, int display)
|
static int butterfly_drain(const PROGRAMMER *pgm, int display) {
|
||||||
{
|
|
||||||
return serial_drain(&pgm->fd, display);
|
return serial_drain(&pgm->fd, display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg)
|
static int butterfly_vfy_cmd_sent(const PROGRAMMER *pgm, char *errmsg) {
|
||||||
{
|
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
butterfly_recv(pgm, &c, 1);
|
butterfly_recv(pgm, &c, 1);
|
||||||
if (c != '\r') {
|
if (c != '\r') {
|
||||||
avrdude_message(MSG_INFO, "%s: error: programmer did not respond to command: %s\n",
|
pmsg_error("programmer did not respond to command: %s\n", errmsg);
|
||||||
progname, errmsg);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_rdy_led(PROGRAMMER * pgm, int value)
|
static int butterfly_rdy_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_err_led(PROGRAMMER * pgm, int value)
|
static int butterfly_err_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_pgm_led(PROGRAMMER * pgm, int value)
|
static int butterfly_pgm_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_vfy_led(PROGRAMMER * pgm, int value)
|
static int butterfly_vfy_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -150,8 +139,7 @@ static int butterfly_vfy_led(PROGRAMMER * pgm, int value)
|
||||||
/*
|
/*
|
||||||
* issue the 'chip erase' command to the butterfly board
|
* issue the 'chip erase' command to the butterfly board
|
||||||
*/
|
*/
|
||||||
static int butterfly_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
static int butterfly_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
butterfly_send(pgm, "e", 1);
|
butterfly_send(pgm, "e", 1);
|
||||||
if (butterfly_vfy_cmd_sent(pgm, "chip erase") < 0)
|
if (butterfly_vfy_cmd_sent(pgm, "chip erase") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -160,15 +148,13 @@ static int butterfly_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void butterfly_enter_prog_mode(PROGRAMMER * pgm)
|
static void butterfly_enter_prog_mode(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
butterfly_send(pgm, "P", 1);
|
butterfly_send(pgm, "P", 1);
|
||||||
butterfly_vfy_cmd_sent(pgm, "enter prog mode");
|
butterfly_vfy_cmd_sent(pgm, "enter prog mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void butterfly_leave_prog_mode(PROGRAMMER * pgm)
|
static void butterfly_leave_prog_mode(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
butterfly_send(pgm, "L", 1);
|
butterfly_send(pgm, "L", 1);
|
||||||
butterfly_vfy_cmd_sent(pgm, "leave prog mode");
|
butterfly_vfy_cmd_sent(pgm, "leave prog mode");
|
||||||
}
|
}
|
||||||
|
@ -177,8 +163,7 @@ static void butterfly_leave_prog_mode(PROGRAMMER * pgm)
|
||||||
/*
|
/*
|
||||||
* issue the 'program enable' command to the AVR device
|
* issue the 'program enable' command to the AVR device
|
||||||
*/
|
*/
|
||||||
static int butterfly_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
static int butterfly_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,8 +171,7 @@ static int butterfly_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
||||||
/*
|
/*
|
||||||
* apply power to the AVR processor
|
* apply power to the AVR processor
|
||||||
*/
|
*/
|
||||||
static void butterfly_powerup(PROGRAMMER * pgm)
|
static void butterfly_powerup(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -197,8 +181,7 @@ static void butterfly_powerup(PROGRAMMER * pgm)
|
||||||
/*
|
/*
|
||||||
* remove power from the AVR processor
|
* remove power from the AVR processor
|
||||||
*/
|
*/
|
||||||
static void butterfly_powerdown(PROGRAMMER * pgm)
|
static void butterfly_powerdown(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -209,8 +192,7 @@ static void butterfly_powerdown(PROGRAMMER * pgm)
|
||||||
/*
|
/*
|
||||||
* initialize the AVR device and prepare it to accept commands
|
* initialize the AVR device and prepare it to accept commands
|
||||||
*/
|
*/
|
||||||
static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
char id[8];
|
char id[8];
|
||||||
char sw[2];
|
char sw[2];
|
||||||
char hw[2];
|
char hw[2];
|
||||||
|
@ -222,13 +204,13 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
* Send some ESC to activate butterfly bootloader. This is not needed
|
* Send some ESC to activate butterfly bootloader. This is not needed
|
||||||
* for plain avr109 bootloaders but does not harm there either.
|
* for plain avr109 bootloaders but does not harm there either.
|
||||||
*/
|
*/
|
||||||
avrdude_message(MSG_INFO, "Connecting to programmer: ");
|
msg_notice("connecting to programmer: ");
|
||||||
if (pgm->flag & IS_BUTTERFLY_MK)
|
if (pgm->flag & IS_BUTTERFLY_MK)
|
||||||
{
|
{
|
||||||
char mk_reset_cmd[6] = {"#aR@S\r"};
|
char mk_reset_cmd[6] = {"#aR@S\r"};
|
||||||
unsigned char mk_timeout = 0;
|
unsigned char mk_timeout = 0;
|
||||||
|
|
||||||
putc('.', stderr);
|
msg_notice(".");
|
||||||
butterfly_send(pgm, mk_reset_cmd, sizeof(mk_reset_cmd));
|
butterfly_send(pgm, mk_reset_cmd, sizeof(mk_reset_cmd));
|
||||||
usleep(20000);
|
usleep(20000);
|
||||||
|
|
||||||
|
@ -240,13 +222,15 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
c = 0xaa;
|
c = 0xaa;
|
||||||
usleep(80000);
|
usleep(80000);
|
||||||
butterfly_send(pgm, &c, 1);
|
butterfly_send(pgm, &c, 1);
|
||||||
if (mk_timeout % 10 == 0) putc('.', stderr);
|
if (mk_timeout % 10 == 0)
|
||||||
|
msg_notice(".");
|
||||||
} while (mk_timeout++ < 10);
|
} while (mk_timeout++ < 10);
|
||||||
|
|
||||||
butterfly_recv(pgm, &c, 1);
|
butterfly_recv(pgm, &c, 1);
|
||||||
if ( c != 'M' && c != '?')
|
if ( c != 'M' && c != '?')
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "\nConnection FAILED.");
|
msg_error("\n");
|
||||||
|
pmsg_error("connection failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -257,13 +241,13 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
putc('.', stderr);
|
msg_notice(".");
|
||||||
butterfly_send(pgm, "\033", 1);
|
butterfly_send(pgm, "\033", 1);
|
||||||
butterfly_drain(pgm, 0);
|
butterfly_drain(pgm, 0);
|
||||||
butterfly_send(pgm, "S", 1);
|
butterfly_send(pgm, "S", 1);
|
||||||
butterfly_recv(pgm, &c, 1);
|
butterfly_recv(pgm, &c, 1);
|
||||||
if (c != '?') {
|
if (c != '?') {
|
||||||
putc('\n', stderr);
|
msg_notice("\n");
|
||||||
/*
|
/*
|
||||||
* Got a useful response, continue getting the programmer
|
* Got a useful response, continue getting the programmer
|
||||||
* identifier. Programmer returns exactly 7 chars _without_
|
* identifier. Programmer returns exactly 7 chars _without_
|
||||||
|
@ -293,12 +277,12 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
butterfly_send(pgm, "p", 1);
|
butterfly_send(pgm, "p", 1);
|
||||||
butterfly_recv(pgm, &type, 1);
|
butterfly_recv(pgm, &type, 1);
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "Found programmer: Id = \"%s\"; type = %c\n", id, type);
|
msg_notice("Programmer id = %s; type = %c\n", id, type);
|
||||||
avrdude_message(MSG_INFO, " Software Version = %c.%c; ", sw[0], sw[1]);
|
msg_notice("Software version = %c.%c; ", sw[0], sw[1]);
|
||||||
if (hw[0]=='?') {
|
if (hw[0]=='?') {
|
||||||
avrdude_message(MSG_INFO, "No Hardware Version given.\n");
|
msg_notice("no hardware version given\n");
|
||||||
} else {
|
} else {
|
||||||
avrdude_message(MSG_INFO, "Hardware Version = %c.%c\n", hw[0], hw[1]);
|
msg_notice("Hardware version = %c.%c\n", hw[0], hw[1]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* See if programmer supports autoincrement of address. */
|
/* See if programmer supports autoincrement of address. */
|
||||||
|
@ -306,28 +290,28 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
butterfly_send(pgm, "a", 1);
|
butterfly_send(pgm, "a", 1);
|
||||||
butterfly_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1);
|
butterfly_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1);
|
||||||
if (PDATA(pgm)->has_auto_incr_addr == 'Y')
|
if (PDATA(pgm)->has_auto_incr_addr == 'Y')
|
||||||
avrdude_message(MSG_INFO, "Programmer supports auto addr increment.\n");
|
msg_notice("programmer supports auto addr increment\n");
|
||||||
|
|
||||||
/* Check support for buffered memory access, abort if not available */
|
/* Check support for buffered memory access, abort if not available */
|
||||||
|
|
||||||
butterfly_send(pgm, "b", 1);
|
butterfly_send(pgm, "b", 1);
|
||||||
butterfly_recv(pgm, &c, 1);
|
butterfly_recv(pgm, &c, 1);
|
||||||
if (c != 'Y') {
|
if (c != 'Y') {
|
||||||
avrdude_message(MSG_INFO, "%s: error: buffered memory access not supported. Maybe it isn't\n"\
|
pmsg_notice("buffered memory access not supported; maybe it isn't\n"\
|
||||||
"a butterfly/AVR109 but a AVR910 device?\n", progname);
|
"a butterfly/AVR109 but a AVR910 device?\n");
|
||||||
return -1;
|
return -1;
|
||||||
};
|
};
|
||||||
butterfly_recv(pgm, &c, 1);
|
butterfly_recv(pgm, &c, 1);
|
||||||
PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8;
|
PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8;
|
||||||
butterfly_recv(pgm, &c, 1);
|
butterfly_recv(pgm, &c, 1);
|
||||||
PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c;
|
PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c;
|
||||||
avrdude_message(MSG_INFO, "Programmer supports buffered memory access with buffersize=%i bytes.\n",
|
msg_notice("programmer supports buffered memory access with buffersize=%i bytes\n",
|
||||||
PDATA(pgm)->buffersize);
|
PDATA(pgm)->buffersize);
|
||||||
|
|
||||||
/* Get list of devices that the programmer supports. */
|
/* Get list of devices that the programmer supports. */
|
||||||
|
|
||||||
butterfly_send(pgm, "t", 1);
|
butterfly_send(pgm, "t", 1);
|
||||||
avrdude_message(MSG_INFO, "\nProgrammer supports the following devices:\n");
|
msg_notice2("\nProgrammer supports the following devices:\n");
|
||||||
devtype_1st = 0;
|
devtype_1st = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
butterfly_recv(pgm, &c, 1);
|
butterfly_recv(pgm, &c, 1);
|
||||||
|
@ -336,9 +320,9 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
|
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
break;
|
break;
|
||||||
avrdude_message(MSG_INFO, " Device code: 0x%02x\n", (unsigned int)(unsigned char)c);
|
msg_notice2(" Device code: 0x%02x\n", (unsigned int) (unsigned char) c);
|
||||||
};
|
};
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_notice2("\n");
|
||||||
|
|
||||||
/* Tell the programmer which part we selected.
|
/* Tell the programmer which part we selected.
|
||||||
According to the AVR109 code, this is ignored by the bootloader. As
|
According to the AVR109 code, this is ignored by the bootloader. As
|
||||||
|
@ -355,9 +339,7 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
if (butterfly_vfy_cmd_sent(pgm, "select device") < 0)
|
if (butterfly_vfy_cmd_sent(pgm, "select device") < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (verbose)
|
pmsg_notice("devcode selected: 0x%02x\n", (unsigned) buf[1]);
|
||||||
avrdude_message(MSG_INFO, "%s: devcode selected: 0x%02x\n",
|
|
||||||
progname, (unsigned)buf[1]);
|
|
||||||
|
|
||||||
butterfly_enter_prog_mode(pgm);
|
butterfly_enter_prog_mode(pgm);
|
||||||
butterfly_drain(pgm, 0);
|
butterfly_drain(pgm, 0);
|
||||||
|
@ -367,22 +349,19 @@ static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void butterfly_disable(PROGRAMMER * pgm)
|
static void butterfly_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
butterfly_leave_prog_mode(pgm);
|
butterfly_leave_prog_mode(pgm);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void butterfly_enable(PROGRAMMER * pgm)
|
static void butterfly_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_open(PROGRAMMER * pgm, char * port)
|
static int butterfly_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
union pinfo pinfo;
|
union pinfo pinfo;
|
||||||
strcpy(pgm->port, port);
|
strcpy(pgm->port, port);
|
||||||
/*
|
/*
|
||||||
|
@ -417,27 +396,36 @@ static void butterfly_close(PROGRAMMER * pgm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void butterfly_display(PROGRAMMER * pgm, const char * p)
|
static void butterfly_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void butterfly_set_addr(PROGRAMMER * pgm, unsigned long addr)
|
static void butterfly_set_addr(const PROGRAMMER *pgm, unsigned long addr) {
|
||||||
{
|
if( addr < 0x10000 ) {
|
||||||
char cmd[3];
|
char cmd[3];
|
||||||
|
|
||||||
cmd[0] = 'A';
|
cmd[0] = 'A';
|
||||||
cmd[1] = (addr >> 8) & 0xff;
|
cmd[1] = (addr >> 8) & 0xff;
|
||||||
cmd[2] = addr & 0xff;
|
cmd[2] = addr & 0xff;
|
||||||
|
|
||||||
butterfly_send(pgm, cmd, sizeof(cmd));
|
butterfly_send(pgm, cmd, sizeof(cmd));
|
||||||
butterfly_vfy_cmd_sent(pgm, "set addr");
|
butterfly_vfy_cmd_sent(pgm, "set addr");
|
||||||
|
} else {
|
||||||
|
char cmd[4];
|
||||||
|
|
||||||
|
cmd[0] = 'H';
|
||||||
|
cmd[1] = (addr >> 16) & 0xff;
|
||||||
|
cmd[2] = (addr >> 8) & 0xff;
|
||||||
|
cmd[3] = addr & 0xff;
|
||||||
|
|
||||||
|
butterfly_send(pgm, cmd, sizeof(cmd));
|
||||||
|
butterfly_vfy_cmd_sent(pgm, "set extaddr");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void butterfly_set_extaddr(PROGRAMMER * pgm, unsigned long addr)
|
static void butterfly_set_extaddr(const PROGRAMMER *pgm, unsigned long addr) {
|
||||||
{
|
|
||||||
char cmd[4];
|
char cmd[4];
|
||||||
|
|
||||||
cmd[0] = 'H';
|
cmd[0] = 'H';
|
||||||
|
@ -451,7 +439,7 @@ static void butterfly_set_extaddr(PROGRAMMER * pgm, unsigned long addr)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int butterfly_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned long addr, unsigned char value)
|
unsigned long addr, unsigned char value)
|
||||||
{
|
{
|
||||||
char cmd[6];
|
char cmd[6];
|
||||||
|
@ -495,7 +483,7 @@ static int butterfly_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int butterfly_read_byte_flash(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned long addr, unsigned char * value)
|
unsigned long addr, unsigned char * value)
|
||||||
{
|
{
|
||||||
static int cached = 0;
|
static int cached = 0;
|
||||||
|
@ -515,9 +503,13 @@ static int butterfly_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
} else {
|
} else {
|
||||||
butterfly_set_addr(pgm, addr >> 1);
|
butterfly_set_addr(pgm, addr >> 1);
|
||||||
}
|
}
|
||||||
|
// Defaults to flash read ('F')
|
||||||
butterfly_send(pgm, "g\000\002F", 4);
|
char msg[4] = {'g', 0x00, 0x02, 'F'};
|
||||||
|
if (strcmp(m->desc, "prodsig") == 0)
|
||||||
|
msg[3] = 'P';
|
||||||
|
else if (strcmp(m->desc, "usersig") == 0)
|
||||||
|
msg[3] = 'U';
|
||||||
|
butterfly_send(pgm, msg, 4);
|
||||||
/* Read back the program mem word (MSB first) */
|
/* Read back the program mem word (MSB first) */
|
||||||
butterfly_recv(pgm, buf, sizeof(buf));
|
butterfly_recv(pgm, buf, sizeof(buf));
|
||||||
|
|
||||||
|
@ -536,7 +528,7 @@ static int butterfly_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int butterfly_read_byte_eeprom(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned long addr, unsigned char * value)
|
unsigned long addr, unsigned char * value)
|
||||||
{
|
{
|
||||||
butterfly_set_addr(pgm, addr);
|
butterfly_set_addr(pgm, addr);
|
||||||
|
@ -545,23 +537,14 @@ static int butterfly_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int butterfly_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned int addr)
|
static int butterfly_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
{
|
|
||||||
if (strcmp(m->desc, "flash") == 0)
|
|
||||||
return -1; /* not supported */
|
|
||||||
if (strcmp(m->desc, "eeprom") == 0)
|
|
||||||
return 0; /* nothing to do */
|
|
||||||
avrdude_message(MSG_INFO, "%s: butterfly_page_erase() called on memory type \"%s\"\n",
|
|
||||||
progname, m->desc);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int butterfly_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
|
||||||
unsigned long addr, unsigned char * value)
|
unsigned long addr, unsigned char * value)
|
||||||
{
|
{
|
||||||
char cmd;
|
char cmd;
|
||||||
|
|
||||||
if (strcmp(m->desc, "flash") == 0) {
|
if (strcmp(m->desc, "flash") == 0 ||
|
||||||
|
strcmp(m->desc, "prodsig") == 0 ||
|
||||||
|
strcmp(m->desc, "usersig") == 0) {
|
||||||
return butterfly_read_byte_flash(pgm, p, m, addr, value);
|
return butterfly_read_byte_flash(pgm, p, m, addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,7 +575,7 @@ static int butterfly_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int butterfly_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
|
@ -602,7 +585,9 @@ static int butterfly_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
|
int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
|
||||||
unsigned int wr_size = 2;
|
unsigned int wr_size = 2;
|
||||||
|
|
||||||
if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom"))
|
if (strcmp(m->desc, "flash") &&
|
||||||
|
strcmp(m->desc, "eeprom") &&
|
||||||
|
strcmp(m->desc, "usersig"))
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
if (m->desc[0] == 'e')
|
if (m->desc[0] == 'e')
|
||||||
|
@ -647,7 +632,7 @@ static int butterfly_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int butterfly_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int butterfly_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
|
@ -656,8 +641,10 @@ static int butterfly_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
int blocksize = PDATA(pgm)->buffersize;
|
int blocksize = PDATA(pgm)->buffersize;
|
||||||
int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
|
int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
|
||||||
|
|
||||||
/* check parameter syntax: only "flash" or "eeprom" is allowed */
|
/* check parameter syntax: only "flash", "eeprom" or "usersig" is allowed */
|
||||||
if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom"))
|
if (strcmp(m->desc, "flash") &&
|
||||||
|
strcmp(m->desc, "eeprom") &&
|
||||||
|
strcmp(m->desc, "usersig"))
|
||||||
return -2;
|
return -2;
|
||||||
|
|
||||||
if (m->desc[0] == 'e')
|
if (m->desc[0] == 'e')
|
||||||
|
@ -693,12 +680,11 @@ static int butterfly_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
|
|
||||||
|
|
||||||
/* Signature byte reads are always 3 bytes. */
|
/* Signature byte reads are always 3 bytes. */
|
||||||
static int butterfly_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
static int butterfly_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m) {
|
||||||
{
|
|
||||||
unsigned char tmp;
|
unsigned char tmp;
|
||||||
|
|
||||||
if (m->size < 3) {
|
if (m->size < 3) {
|
||||||
avrdude_message(MSG_INFO, "%s: memsize too small for sig byte read", progname);
|
pmsg_error("memsize too small for sig byte read");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -714,8 +700,7 @@ static int butterfly_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
|
||||||
|
|
||||||
const char butterfly_desc[] = "Atmel Butterfly evaluation board; Atmel AppNotes AVR109, AVR911";
|
const char butterfly_desc[] = "Atmel Butterfly evaluation board; Atmel AppNotes AVR109, AVR911";
|
||||||
|
|
||||||
void butterfly_initpgm(PROGRAMMER * pgm)
|
void butterfly_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "butterfly");
|
strcpy(pgm->type, "butterfly");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -742,7 +727,6 @@ void butterfly_initpgm(PROGRAMMER * pgm)
|
||||||
* optional functions
|
* optional functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pgm->page_erase = butterfly_page_erase;
|
|
||||||
pgm->paged_write = butterfly_paged_write;
|
pgm->paged_write = butterfly_paged_write;
|
||||||
pgm->paged_load = butterfly_paged_load;
|
pgm->paged_load = butterfly_paged_load;
|
||||||
|
|
||||||
|
@ -755,8 +739,7 @@ void butterfly_initpgm(PROGRAMMER * pgm)
|
||||||
|
|
||||||
const char butterfly_mk_desc[] = "Mikrokopter.de Butterfly";
|
const char butterfly_mk_desc[] = "Mikrokopter.de Butterfly";
|
||||||
|
|
||||||
void butterfly_mk_initpgm(PROGRAMMER * pgm)
|
void butterfly_mk_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
butterfly_initpgm(pgm);
|
butterfly_initpgm(pgm);
|
||||||
strcpy(pgm->type, "butterfly_mk");
|
strcpy(pgm->type, "butterfly_mk");
|
||||||
pgm->flag = IS_BUTTERFLY_MK;
|
pgm->flag = IS_BUTTERFLY_MK;
|
||||||
|
|
|
@ -27,8 +27,8 @@ extern "C" {
|
||||||
|
|
||||||
extern const char butterfly_desc[];
|
extern const char butterfly_desc[];
|
||||||
extern const char butterfly_mk_desc[];
|
extern const char butterfly_mk_desc[];
|
||||||
void butterfly_initpgm (PROGRAMMER * pgm);
|
void butterfly_initpgm(PROGRAMMER *pgm);
|
||||||
void butterfly_mk_initpgm (PROGRAMMER * pgm);
|
void butterfly_mk_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
742
src/config.c
742
src/config.c
|
@ -24,36 +24,65 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
#include "avrdude.h"
|
#include "avrdude.h"
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "avrintel.h"
|
||||||
|
|
||||||
#include "config_gram.h"
|
#include "config_gram.h"
|
||||||
|
|
||||||
char default_programmer[MAX_STR_CONST];
|
const char *default_programmer;
|
||||||
char default_parallel[PATH_MAX];
|
const char *default_parallel;
|
||||||
char default_serial[PATH_MAX];
|
const char *default_serial;
|
||||||
|
const char *default_spi;
|
||||||
double default_bitclock;
|
double default_bitclock;
|
||||||
|
|
||||||
char string_buf[MAX_STR_CONST];
|
|
||||||
char *string_buf_ptr;
|
|
||||||
|
|
||||||
LISTID string_list;
|
LISTID string_list;
|
||||||
LISTID number_list;
|
LISTID number_list;
|
||||||
PROGRAMMER * current_prog;
|
PROGRAMMER * current_prog;
|
||||||
AVRPART * current_part;
|
AVRPART * current_part;
|
||||||
AVRMEM * current_mem;
|
AVRMEM * current_mem;
|
||||||
|
int current_strct;
|
||||||
LISTID part_list;
|
LISTID part_list;
|
||||||
LISTID programmers;
|
LISTID programmers;
|
||||||
bool is_alias;
|
bool is_alias;
|
||||||
|
|
||||||
int lineno;
|
int cfg_lineno;
|
||||||
const char * infile;
|
char * cfg_infile;
|
||||||
|
|
||||||
extern char * yytext;
|
extern char * yytext;
|
||||||
|
|
||||||
|
#define pgm_comp_desc(x, type) { #x, COMP_PROGRAMMER, offsetof(PROGRAMMER, x), sizeof(((PROGRAMMER *) NULL)->x), type }
|
||||||
|
#define part_comp_desc(x, type) { #x, COMP_AVRPART, offsetof(AVRPART, x), sizeof(((AVRPART *) NULL)->x), type }
|
||||||
|
#define mem_comp_desc(x, type) { #x, COMP_AVRMEM, offsetof(AVRMEM, x), sizeof(((AVRMEM *) NULL)->x), type }
|
||||||
|
|
||||||
|
// Component description for config_gram.y, will be sorted appropriately on first use
|
||||||
|
Component_t avr_comp[] = {
|
||||||
|
// PROGRAMMER
|
||||||
|
pgm_comp_desc(prog_modes, COMP_INT),
|
||||||
|
|
||||||
|
// AVRPART
|
||||||
|
part_comp_desc(prog_modes, COMP_INT),
|
||||||
|
part_comp_desc(mcuid, COMP_INT),
|
||||||
|
part_comp_desc(n_interrupts, COMP_INT),
|
||||||
|
part_comp_desc(n_page_erase, COMP_INT),
|
||||||
|
part_comp_desc(n_boot_sections, COMP_INT),
|
||||||
|
part_comp_desc(boot_section_size, COMP_INT),
|
||||||
|
part_comp_desc(autobaud_sync, COMP_CHAR),
|
||||||
|
part_comp_desc(idr, COMP_CHAR),
|
||||||
|
part_comp_desc(rampz, COMP_CHAR),
|
||||||
|
part_comp_desc(spmcr, COMP_CHAR),
|
||||||
|
part_comp_desc(eecr, COMP_CHAR),
|
||||||
|
part_comp_desc(eind, COMP_CHAR),
|
||||||
|
|
||||||
|
// AVRMEM
|
||||||
|
mem_comp_desc(n_word_writes, COMP_INT),
|
||||||
|
};
|
||||||
|
|
||||||
#define DEBUG 0
|
#define DEBUG 0
|
||||||
|
|
||||||
void cleanup_config(void)
|
void cleanup_config(void)
|
||||||
|
@ -75,12 +104,42 @@ int init_config(void)
|
||||||
programmers = lcreat(NULL, 0);
|
programmers = lcreat(NULL, 0);
|
||||||
is_alias = false;
|
is_alias = false;
|
||||||
|
|
||||||
lineno = 1;
|
cfg_lineno = 1;
|
||||||
infile = NULL;
|
cfg_infile = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *cfg_malloc(const char *funcname, size_t n) {
|
||||||
|
void *ret = malloc(n);
|
||||||
|
if(!ret) {
|
||||||
|
pmsg_error("out of memory in %s (needed %lu bytes)\n", funcname, (unsigned long) n);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(ret, 0, n);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cfg_realloc(const char *funcname, void *p, size_t n) {
|
||||||
|
void *ret;
|
||||||
|
|
||||||
|
if(!(ret = p? realloc(p, n): calloc(1, n))) {
|
||||||
|
pmsg_error("out of memory in %s (needed %lu bytes)\n", funcname, (unsigned long) n);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *cfg_strdup(const char *funcname, const char *s) {
|
||||||
|
char *ret = strdup(s);
|
||||||
|
if(!ret) {
|
||||||
|
pmsg_error("out of memory in %s\n", funcname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int yywrap()
|
int yywrap()
|
||||||
|
@ -98,7 +157,7 @@ int yyerror(char * errmsg, ...)
|
||||||
va_start(args, errmsg);
|
va_start(args, errmsg);
|
||||||
|
|
||||||
vsnprintf(message, sizeof(message), errmsg, args);
|
vsnprintf(message, sizeof(message), errmsg, args);
|
||||||
avrdude_message(MSG_INFO, "%s: error at %s:%d: %s\n", progname, infile, lineno, message);
|
pmsg_error("%s [%s:%d]\n", message, cfg_infile, cfg_lineno);
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
@ -115,7 +174,7 @@ int yywarning(char * errmsg, ...)
|
||||||
va_start(args, errmsg);
|
va_start(args, errmsg);
|
||||||
|
|
||||||
vsnprintf(message, sizeof(message), errmsg, args);
|
vsnprintf(message, sizeof(message), errmsg, args);
|
||||||
avrdude_message(MSG_INFO, "%s: warning at %s:%d: %s\n", progname, infile, lineno, message);
|
pmsg_warning("%s [%s:%d]\n", message, cfg_infile, cfg_lineno);
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
|
@ -123,20 +182,9 @@ int yywarning(char * errmsg, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TOKEN * new_token(int primary)
|
TOKEN * new_token(int primary) {
|
||||||
{
|
TOKEN * tkn = (TOKEN *) cfg_malloc("new_token()", sizeof(TOKEN));
|
||||||
TOKEN * tkn;
|
|
||||||
|
|
||||||
tkn = (TOKEN *)malloc(sizeof(TOKEN));
|
|
||||||
if (tkn == NULL) {
|
|
||||||
yyerror("new_token(): out of memory");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(tkn, 0, sizeof(TOKEN));
|
|
||||||
|
|
||||||
tkn->primary = primary;
|
tkn->primary = primary;
|
||||||
|
|
||||||
return tkn;
|
return tkn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,100 +220,98 @@ void free_tokens(int n, ...)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
TOKEN * number(char * text)
|
TOKEN *new_number(const char *text) {
|
||||||
{
|
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||||
struct token_t * tkn;
|
|
||||||
|
|
||||||
tkn = new_token(TKN_NUMBER);
|
|
||||||
if (tkn == NULL) {
|
|
||||||
return NULL; /* yyerror already called */
|
|
||||||
}
|
|
||||||
tkn->value.type = V_NUM;
|
tkn->value.type = V_NUM;
|
||||||
tkn->value.number = atoi(text);
|
tkn->value.number = atoi(text);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
avrdude_message(MSG_INFO, "NUMBER(%d)\n", tkn->value.number);
|
msg_info("NUMBER(%d)\n", tkn->value.number);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return tkn;
|
return tkn;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN * number_real(char * text)
|
TOKEN *new_number_real(const char *text) {
|
||||||
{
|
struct token_t * tkn = new_token(TKN_NUMBER);
|
||||||
struct token_t * tkn;
|
|
||||||
|
|
||||||
tkn = new_token(TKN_NUMBER);
|
|
||||||
tkn->value.type = V_NUM_REAL;
|
tkn->value.type = V_NUM_REAL;
|
||||||
tkn->value.number_real = atof(text);
|
tkn->value.number_real = atof(text);
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
avrdude_message(MSG_INFO, "NUMBER(%g)\n", tkn->value.number_real);
|
msg_info("NUMBER(%g)\n", tkn->value.number_real);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return tkn;
|
return tkn;
|
||||||
}
|
}
|
||||||
|
|
||||||
TOKEN * hexnumber(char * text)
|
TOKEN *new_hexnumber(const char *text) {
|
||||||
{
|
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||||
struct token_t * tkn;
|
|
||||||
char * e;
|
char * e;
|
||||||
|
|
||||||
tkn = new_token(TKN_NUMBER);
|
|
||||||
if (tkn == NULL) {
|
|
||||||
return NULL; /* yyerror already called */
|
|
||||||
}
|
|
||||||
tkn->value.type = V_NUM;
|
tkn->value.type = V_NUM;
|
||||||
tkn->value.number = strtoul(text, &e, 16);
|
tkn->value.number = strtoul(text, &e, 16);
|
||||||
if ((e == text) || (*e != 0)) {
|
if ((e == text) || (*e != 0)) {
|
||||||
yyerror("can't scan hex number \"%s\"", text);
|
yyerror("cannot scan hex number %s", text);
|
||||||
free_token(tkn);
|
free_token(tkn);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
avrdude_message(MSG_INFO, "HEXNUMBER(%g)\n", tkn->value.number);
|
msg_info("HEXNUMBER(%d)\n", tkn->value.number);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return tkn;
|
return tkn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TOKEN *new_constant(const char *con) {
|
||||||
|
struct token_t *tkn = new_token(TKN_NUMBER);
|
||||||
|
int assigned = 1;
|
||||||
|
|
||||||
TOKEN * string(char * text)
|
tkn->value.type = V_NUM;
|
||||||
{
|
tkn->value.number =
|
||||||
struct token_t * tkn;
|
!strcmp("PM_SPM", con)? PM_SPM:
|
||||||
int len;
|
!strcmp("PM_TPI", con)? PM_TPI:
|
||||||
|
!strcmp("PM_ISP", con)? PM_ISP:
|
||||||
|
!strcmp("PM_PDI", con)? PM_PDI:
|
||||||
|
!strcmp("PM_UPDI", con)? PM_UPDI:
|
||||||
|
!strcmp("PM_HVSP", con)? PM_HVSP:
|
||||||
|
!strcmp("PM_HVPP", con)? PM_HVPP:
|
||||||
|
!strcmp("PM_debugWIRE", con)? PM_debugWIRE:
|
||||||
|
!strcmp("PM_JTAG", con)? PM_JTAG:
|
||||||
|
!strcmp("PM_JTAGmkI", con)? PM_JTAGmkI:
|
||||||
|
!strcmp("PM_XMEGAJTAG", con)? PM_XMEGAJTAG:
|
||||||
|
!strcmp("PM_AVR32JTAG", con)? PM_AVR32JTAG:
|
||||||
|
!strcmp("PM_aWire", con)? PM_aWire:
|
||||||
|
(assigned = 0);
|
||||||
|
|
||||||
tkn = new_token(TKN_STRING);
|
if(!assigned) {
|
||||||
if (tkn == NULL) {
|
yyerror("can't identify constant %s", con);
|
||||||
return NULL; /* yyerror already called */
|
free_token(tkn);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = strlen(text);
|
#if DEBUG
|
||||||
|
msg_info("CONSTANT(%s=%d)\n", con, tkn->value.number);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return tkn;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOKEN *new_string(const char *text) {
|
||||||
|
struct token_t *tkn = new_token(TKN_STRING);
|
||||||
tkn->value.type = V_STR;
|
tkn->value.type = V_STR;
|
||||||
tkn->value.string = (char *) malloc(len+1);
|
tkn->value.string = cfg_strdup("new_string()", text);
|
||||||
if (tkn->value.string == NULL) {
|
|
||||||
yyerror("string(): out of memory");
|
|
||||||
free_token(tkn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
strcpy(tkn->value.string, text);
|
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
avrdude_message(MSG_INFO, "STRING(%s)\n", tkn->value.string);
|
msg_info("STRING(%s)\n", tkn->value.string);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return tkn;
|
return tkn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TOKEN * keyword(int primary)
|
TOKEN *new_keyword(int primary) {
|
||||||
{
|
return new_token(primary);
|
||||||
struct token_t * tkn;
|
|
||||||
|
|
||||||
tkn = new_token(primary);
|
|
||||||
|
|
||||||
return tkn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -274,50 +320,37 @@ void print_token(TOKEN * tkn)
|
||||||
if (!tkn)
|
if (!tkn)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "token = %d = ", tkn->primary);
|
msg_info("token = %d = ", tkn->primary);
|
||||||
switch (tkn->value.type) {
|
switch (tkn->value.type) {
|
||||||
case V_NUM:
|
case V_NUM:
|
||||||
avrdude_message(MSG_INFO, "NUMBER, value=%d", tkn->value.number);
|
msg_info("NUMBER, value=%d", tkn->value.number);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V_NUM_REAL:
|
case V_NUM_REAL:
|
||||||
avrdude_message(MSG_INFO, "NUMBER, value=%g", tkn->value.number_real);
|
msg_info("NUMBER, value=%g", tkn->value.number_real);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case V_STR:
|
case V_STR:
|
||||||
avrdude_message(MSG_INFO, "STRING, value=%s", tkn->value.string);
|
msg_info("STRING, value=%s", tkn->value.string);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
avrdude_message(MSG_INFO, "<other>");
|
msg_info("<other>");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_info("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pyytext(void)
|
void pyytext(void)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
avrdude_message(MSG_INFO, "TOKEN: \"%s\"\n", yytext);
|
msg_info("TOKEN: %s\n", yytext);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
char * dup_string(const char * str)
|
|
||||||
{
|
|
||||||
char * s;
|
|
||||||
|
|
||||||
s = strdup(str);
|
|
||||||
if (s == NULL) {
|
|
||||||
yyerror("dup_string(): out of memory");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_YYLEX_DESTROY
|
#ifdef HAVE_YYLEX_DESTROY
|
||||||
/* reset lexer and free any allocated memory */
|
/* reset lexer and free any allocated memory */
|
||||||
extern int yylex_destroy(void);
|
extern int yylex_destroy(void);
|
||||||
|
@ -328,15 +361,20 @@ int read_config(const char * file)
|
||||||
FILE * f;
|
FILE * f;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
f = fopen(file, "r");
|
if(!(cfg_infile = realpath(file, NULL))) {
|
||||||
if (f == NULL) {
|
pmsg_ext_error("cannot determine realpath() of config file %s: %s\n", file, strerror(errno));
|
||||||
avrdude_message(MSG_INFO, "%s: can't open config file \"%s\": %s\n",
|
|
||||||
progname, file, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lineno = 1;
|
f = fopen(cfg_infile, "r");
|
||||||
infile = file;
|
if (f == NULL) {
|
||||||
|
pmsg_ext_error("cannot open config file %s: %s\n", cfg_infile, strerror(errno));
|
||||||
|
free(cfg_infile);
|
||||||
|
cfg_infile = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg_lineno = 1;
|
||||||
yyin = f;
|
yyin = f;
|
||||||
|
|
||||||
r = yyparse();
|
r = yyparse();
|
||||||
|
@ -348,5 +386,513 @@ int read_config(const char * file)
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
if(cfg_infile) {
|
||||||
|
free(cfg_infile);
|
||||||
|
cfg_infile = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Adapted version of a neat empirical hash function from comp.lang.c by Daniel Bernstein
|
||||||
|
unsigned strhash(const char *str) {
|
||||||
|
unsigned c, hash = 5381, n = 0;
|
||||||
|
|
||||||
|
while((c = (unsigned char) *str++) && n++ < 20)
|
||||||
|
hash = 33*hash ^ c;
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char **hstrings[1<<12];
|
||||||
|
|
||||||
|
// Return a copy of the argument as hashed string
|
||||||
|
const char *cache_string(const char *p) {
|
||||||
|
int h, k;
|
||||||
|
char **hs;
|
||||||
|
|
||||||
|
if(!p)
|
||||||
|
p = "(NULL)";
|
||||||
|
|
||||||
|
h = strhash(p) % (sizeof hstrings/sizeof*hstrings);
|
||||||
|
if(!(hs=hstrings[h]))
|
||||||
|
hs = hstrings[h] = (char **) cfg_realloc("cache_string()", NULL, (16+1)*sizeof**hstrings);
|
||||||
|
|
||||||
|
for(k=0; hs[k]; k++)
|
||||||
|
if(*p == *hs[k] && !strcmp(p, hs[k]))
|
||||||
|
return hs[k];
|
||||||
|
|
||||||
|
if(k && k%16 == 0)
|
||||||
|
hstrings[h] = (char **) cfg_realloc("cache_string()", hstrings[h], (k+16+1)*sizeof**hstrings);
|
||||||
|
|
||||||
|
hstrings[h][k+1]=NULL;
|
||||||
|
|
||||||
|
return hstrings[h][k] = cfg_strdup("cache_string()", p);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static LISTID cfg_comms; // A chain of comment lines
|
||||||
|
static LISTID cfg_prologue; // Comment lines at start of avrdude.conf
|
||||||
|
static char *lkw; // Last seen keyword
|
||||||
|
static int lkw_lineno; // Line number of that
|
||||||
|
|
||||||
|
static LISTID cfg_strctcomms; // Passed on to config_gram.y
|
||||||
|
static LISTID cfg_pushedcomms; // Temporarily pushed main comments
|
||||||
|
static int cfg_pushed; // ... for memory sections
|
||||||
|
|
||||||
|
COMMENT *locate_comment(const LISTID comments, const char *where, int rhs) {
|
||||||
|
if(comments)
|
||||||
|
for(LNODEID ln=lfirst(comments); ln; ln=lnext(ln)) {
|
||||||
|
COMMENT *n = ldata(ln);
|
||||||
|
if(n && rhs == n->rhs && n->kw && strcmp(where, n->kw) == 0)
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addcomment(int rhs) {
|
||||||
|
if(lkw) {
|
||||||
|
COMMENT *node = cfg_malloc("addcomment()", sizeof(*node));
|
||||||
|
node->rhs = rhs;
|
||||||
|
node->kw = cfg_strdup("addcomment()", lkw);
|
||||||
|
node->comms = cfg_comms;
|
||||||
|
cfg_comms = NULL;
|
||||||
|
if(!cfg_strctcomms)
|
||||||
|
cfg_strctcomms = lcreat(NULL, 0);
|
||||||
|
ladd(cfg_strctcomms, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture prologue during parsing (triggered by lexer.l)
|
||||||
|
void cfg_capture_prologue(void) {
|
||||||
|
cfg_prologue = cfg_comms;
|
||||||
|
cfg_comms = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LISTID cfg_get_prologue(void) {
|
||||||
|
return cfg_prologue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Captures comments during parsing
|
||||||
|
void capture_comment_str(const char *com, int lineno) {
|
||||||
|
if(!cfg_comms)
|
||||||
|
cfg_comms = lcreat(NULL, 0);
|
||||||
|
ladd(cfg_comms, cfg_strdup("capture_comment_str()", com));
|
||||||
|
|
||||||
|
// Last keyword lineno is the same as this comment's
|
||||||
|
if(lkw && lkw_lineno == lineno)
|
||||||
|
addcomment(1); // Register comms to show right of lkw = ...;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture assignments (keywords left of =) and associate comments to them
|
||||||
|
void capture_lvalue_kw(const char *kw, int lineno) {
|
||||||
|
if(!strcmp(kw, "memory")) { // Push part comments and start memory comments
|
||||||
|
if(!cfg_pushed) { // config_gram.y pops the part comments
|
||||||
|
cfg_pushed = 1;
|
||||||
|
cfg_pushedcomms = cfg_strctcomms;
|
||||||
|
cfg_strctcomms = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strcmp(kw, "programmer") || !strcmp(kw, "part") || !strcmp(kw, "memory"))
|
||||||
|
kw = "*"; // Show comment before programmer/part/memory
|
||||||
|
|
||||||
|
if(lkw)
|
||||||
|
free(lkw);
|
||||||
|
lkw = cfg_strdup("capture_lvalue_kw()", kw);
|
||||||
|
lkw_lineno = lineno;
|
||||||
|
if(cfg_comms) // Accrued list of # one-line comments
|
||||||
|
addcomment(0); // Register comment to appear before lkw assignment
|
||||||
|
}
|
||||||
|
|
||||||
|
// config_gram.y calls this once for each programmer/part/memory structure
|
||||||
|
LISTID cfg_move_comments(void) {
|
||||||
|
capture_lvalue_kw(";", -1);
|
||||||
|
|
||||||
|
LISTID ret = cfg_strctcomms;
|
||||||
|
cfg_strctcomms = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// config_gram.y calls this after ingressing the memory structure
|
||||||
|
void cfg_pop_comms(void) {
|
||||||
|
if(cfg_pushed) {
|
||||||
|
cfg_pushed = 0;
|
||||||
|
cfg_strctcomms = cfg_pushedcomms;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the next n hex digits of s to a hex number
|
||||||
|
static unsigned int tohex(const unsigned char *s, unsigned int n) {
|
||||||
|
int ret, c;
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
while(n--) {
|
||||||
|
ret *= 16;
|
||||||
|
c = *s++;
|
||||||
|
ret += c >= '0' && c <= '9'? c - '0': c >= 'a' && c <= 'f'? c - 'a' + 10: c - 'A' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a utf-8 character sequence from a single unicode character.
|
||||||
|
* Permissive for some invalid unicode sequences but not for those with
|
||||||
|
* high bit set). Returns numbers of characters written (0-6).
|
||||||
|
*/
|
||||||
|
static int wc_to_utf8str(unsigned int wc, unsigned char *str) {
|
||||||
|
if(!(wc & ~0x7fu)) {
|
||||||
|
*str = (char) wc;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0x7ffu)) {
|
||||||
|
*str++ = (char) ((wc >> 6) | 0xc0);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0xffffu)) {
|
||||||
|
*str++ = (char) ((wc >> 12) | 0xe0);
|
||||||
|
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0x1fffffu)) {
|
||||||
|
*str++ = (char) ((wc >> 18) | 0xf0);
|
||||||
|
*str++ = (char) (((wc >> 12) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0x3ffffffu)) {
|
||||||
|
*str++ = (char) ((wc >> 24) | 0xf8);
|
||||||
|
*str++ = (char) (((wc >> 18) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 12) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
if(!(wc & ~0x7fffffffu)) {
|
||||||
|
*str++ = (char) ((wc >> 30) | 0xfc);
|
||||||
|
*str++ = (char) (((wc >> 24) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 18) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 12) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) (((wc >> 6) & 0x3f) | 0x80);
|
||||||
|
*str++ = (char) ((wc & 0x3f) | 0x80);
|
||||||
|
return 6;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unescape C-style strings, destination d must hold enough space (and can be source s)
|
||||||
|
unsigned char *cfg_unescapeu(unsigned char *d, const unsigned char *s) {
|
||||||
|
unsigned char *ret = d;
|
||||||
|
int n, k;
|
||||||
|
|
||||||
|
while(*s) {
|
||||||
|
switch (*s) {
|
||||||
|
case '\\':
|
||||||
|
switch (*++s) {
|
||||||
|
case '\n': // String continuation over new line
|
||||||
|
#if '\n' != '\r'
|
||||||
|
case '\r':
|
||||||
|
#endif
|
||||||
|
--d;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
*d = '\n';
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
*d = '\t';
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
*d = '\a';
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
*d = '\b';
|
||||||
|
break;
|
||||||
|
case 'e': // Non-standard ESC
|
||||||
|
*d = 27;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
*d = '\f';
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
*d = '\r';
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
*d = '\v';
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
*d = '?';
|
||||||
|
break;
|
||||||
|
case '`':
|
||||||
|
*d = '`';
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
*d = '"';
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
*d = '\'';
|
||||||
|
break;
|
||||||
|
case '\\':
|
||||||
|
*d = '\\';
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '3':
|
||||||
|
case '4':
|
||||||
|
case '5':
|
||||||
|
case '6':
|
||||||
|
case '7': // 1-3 octal digits
|
||||||
|
n = *s - '0';
|
||||||
|
for(k = 0; k < 2 && s[1] >= '0' && s[1] <= '7'; k++) // Max 2 more octal characters
|
||||||
|
n *= 8, n += s[1] - '0', s++;
|
||||||
|
*d = n;
|
||||||
|
break;
|
||||||
|
case 'x': // Unlimited hex digits
|
||||||
|
for(k = 0; isxdigit(s[k + 1]); k++)
|
||||||
|
continue;
|
||||||
|
if(k > 0) {
|
||||||
|
*d = tohex(s + 1, k);
|
||||||
|
s += k;
|
||||||
|
} else { // No hex digits after \x? copy \x
|
||||||
|
*d++ = '\\';
|
||||||
|
*d = 'x';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u': // Exactly 4 hex digits and valid unicode
|
||||||
|
if(isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) && isxdigit(s[4]) &&
|
||||||
|
(n = wc_to_utf8str(tohex(s+1, 4), d))) {
|
||||||
|
d += n - 1;
|
||||||
|
s += 4;
|
||||||
|
} else { // Invalid \u sequence? copy \u
|
||||||
|
*d++ = '\\';
|
||||||
|
*d = 'u';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'U': // Exactly 6 hex digits and valid unicode
|
||||||
|
if(isxdigit(s[1]) && isxdigit(s[2]) && isxdigit(s[3]) && isxdigit(s[4]) && isxdigit(s[5]) && isxdigit(s[6]) &&
|
||||||
|
(n = wc_to_utf8str(tohex(s+1, 6), d))) {
|
||||||
|
d += n - 1;
|
||||||
|
s += 6;
|
||||||
|
} else { // Invalid \U sequence? copy \U
|
||||||
|
*d++ = '\\';
|
||||||
|
*d = 'U';
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: // Keep the escape sequence (C would warn and remove \)
|
||||||
|
*d++ = '\\';
|
||||||
|
*d = *s;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // Not an escape sequence: just copy the character
|
||||||
|
*d = *s;
|
||||||
|
}
|
||||||
|
d++;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
*d = *s; // Terminate
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unescape C-style strings, destination d must hold enough space (and can be source s)
|
||||||
|
char *cfg_unescape(char *d, const char *s) {
|
||||||
|
return (char *) cfg_unescapeu((unsigned char *) d, (const unsigned char *) s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return an escaped string that looks like a C-style input string incl quotes, memory is malloc'd
|
||||||
|
char *cfg_escape(const char *s) {
|
||||||
|
char buf[50*1024], *d = buf;
|
||||||
|
|
||||||
|
*d++ = '"';
|
||||||
|
for(; *s && d-buf < (long) sizeof buf-7; s++) {
|
||||||
|
switch(*s) {
|
||||||
|
case '\n':
|
||||||
|
*d++ = '\\'; *d++ = 'n';
|
||||||
|
break;
|
||||||
|
case '\t':
|
||||||
|
*d++ = '\\'; *d++ = 't';
|
||||||
|
break;
|
||||||
|
case '\a':
|
||||||
|
*d++ = '\\'; *d++ = 'a';
|
||||||
|
break;
|
||||||
|
case '\b':
|
||||||
|
*d++ = '\\'; *d++ = 'b';
|
||||||
|
break;
|
||||||
|
case '\f':
|
||||||
|
*d++ = '\\'; *d++ = 'f';
|
||||||
|
break;
|
||||||
|
#if '\r' != '\n'
|
||||||
|
case '\r':
|
||||||
|
*d++ = '\\'; *d++ = 'r';
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
case '\v':
|
||||||
|
*d++ = '\\'; *d++ = 'v';
|
||||||
|
break;
|
||||||
|
case '\"':
|
||||||
|
*d++ = '\\'; *d++ = '\"';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if(*s == 0x7f || (*s >= 0 && *s < 32)) {
|
||||||
|
sprintf(d, "\\%03o", *s);
|
||||||
|
d += strlen(d);
|
||||||
|
} else
|
||||||
|
*d++ = *s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*d++ = '"';
|
||||||
|
*d = 0;
|
||||||
|
|
||||||
|
return cfg_strdup("cfg_escape()", buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int cmp_comp(const void *v1, const void *v2) {
|
||||||
|
const Component_t *c1 = v1, *c2 = v2;
|
||||||
|
int ret = strcmp(c1->name, c2->name);
|
||||||
|
|
||||||
|
return ret? ret: c1->strct - c2->strct;
|
||||||
|
}
|
||||||
|
|
||||||
|
Component_t *cfg_comp_search(const char *name, int strct) {
|
||||||
|
static int init;
|
||||||
|
Component_t key;
|
||||||
|
|
||||||
|
if(!init++)
|
||||||
|
qsort(avr_comp, sizeof avr_comp/sizeof*avr_comp, sizeof(Component_t), cmp_comp);
|
||||||
|
|
||||||
|
|
||||||
|
key.name = name;
|
||||||
|
key.strct = strct;
|
||||||
|
return bsearch(&key, avr_comp, sizeof avr_comp/sizeof*avr_comp, sizeof(Component_t), cmp_comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *cfg_strct_name(int strct) {
|
||||||
|
switch(strct) {
|
||||||
|
case COMP_CONFIG_MAIN: return "avrdude.conf main";
|
||||||
|
case COMP_AVRPART: return "AVRPART";
|
||||||
|
case COMP_AVRMEM: return "AVRMEM";
|
||||||
|
case COMP_PROGRAMMER: return "PROGRAMMER";
|
||||||
|
}
|
||||||
|
return "unknown struct";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cfg_v_type(int type) {
|
||||||
|
switch(type) {
|
||||||
|
case V_NONE: return "void";
|
||||||
|
case V_NUM: return "number";
|
||||||
|
case V_NUM_REAL: return "real";
|
||||||
|
case V_STR: return "string";
|
||||||
|
case V_COMPONENT: return "component";
|
||||||
|
}
|
||||||
|
return "unknown v type";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *cfg_comp_type(int type) {
|
||||||
|
switch(type) {
|
||||||
|
case COMP_INT: return "number";
|
||||||
|
case COMP_SHORT: return "short";
|
||||||
|
case COMP_CHAR: return "char";
|
||||||
|
case COMP_STRING: return "string";
|
||||||
|
case COMP_CHAR_ARRAY: return "byte array";
|
||||||
|
case COMP_INT_LISTID: return "number list";
|
||||||
|
case COMP_STRING_LISTID: return "string list";
|
||||||
|
case COMP_OPCODE: return "opcode";
|
||||||
|
case COMP_PIN: return "pin";
|
||||||
|
case COMP_PIN_LIST: return "pin list";
|
||||||
|
}
|
||||||
|
return "unknown comp type";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Used by config_gram.y to assign a component in one of the relevant structures with a value
|
||||||
|
void cfg_assign(char *sp, int strct, Component_t *cp, VALUE *v) {
|
||||||
|
const char *str;
|
||||||
|
int num;
|
||||||
|
|
||||||
|
switch(cp->type) {
|
||||||
|
case COMP_CHAR:
|
||||||
|
case COMP_SHORT:
|
||||||
|
case COMP_INT:
|
||||||
|
if(v->type != V_NUM) {
|
||||||
|
yywarning("%s in %s expects a %s but is assigned a %s",
|
||||||
|
cp->name, cfg_strct_name(strct), cfg_comp_type(cp->type), cfg_v_type(v->type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: consider endianess (code currently assumes little endian)
|
||||||
|
num = v->number;
|
||||||
|
memcpy(sp+cp->offset, &num, cp->size);
|
||||||
|
break;
|
||||||
|
case COMP_STRING:
|
||||||
|
if(v->type != V_STR) {
|
||||||
|
yywarning("%s in %s expects a string but is assigned a %s",
|
||||||
|
cp->name, cfg_strct_name(strct), cfg_v_type(v->type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
str = cache_string(v->string);
|
||||||
|
memcpy(sp+cp->offset, &str, cp->size);
|
||||||
|
break;
|
||||||
|
// TODO: implement COMP_CHAR_ARRAY, COMP_INT_LISTID, COMP_STRING_LISTID, ...
|
||||||
|
default:
|
||||||
|
yywarning("%s in %s expects a %s but that is not implemented",
|
||||||
|
cp->name, cfg_strct_name(strct), cfg_comp_type(cp->type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically assign an mcuid if known from avrintel.c table
|
||||||
|
void cfg_update_mcuid(AVRPART *part) {
|
||||||
|
// Don't assign an mcuid for template parts that has a space in desc
|
||||||
|
if(!part->desc || *part->desc == 0 || strchr(part->desc, ' '))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Don't assign an mcuid for template parts where id starts with "."
|
||||||
|
if(!part->id || !*part->id || *part->id == '.')
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Don't assign an mcuid for 32-bit AVR parts
|
||||||
|
if(part->prog_modes & PM_aWire)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find an entry that shares the same name, overwrite mcuid with known, existing mcuid
|
||||||
|
for(size_t i=0; i < sizeof uP_table/sizeof *uP_table; i++) {
|
||||||
|
if(strcasecmp(part->desc, uP_table[i].name) == 0) {
|
||||||
|
if(part->mcuid != (int) uP_table[i].mcuid) {
|
||||||
|
if(part->mcuid >= 0 && verbose >= MSG_DEBUG)
|
||||||
|
yywarning("overwriting mcuid of part %s to be %d", part->desc, uP_table[i].mcuid);
|
||||||
|
part->mcuid = uP_table[i].mcuid;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// None have the same name: an entry with part->mcuid might be an error
|
||||||
|
for(size_t i=0; i < sizeof uP_table/sizeof *uP_table; i++)
|
||||||
|
if(part->mcuid == (int) uP_table[i].mcuid) {
|
||||||
|
// Complain unless it can be considered a variant, eg, ATmega32L and ATmega32
|
||||||
|
AVRMEM *flash = avr_locate_mem(part, "flash");
|
||||||
|
if(flash) {
|
||||||
|
size_t l1 = strlen(part->desc), l2 = strlen(uP_table[i].name);
|
||||||
|
if(strncasecmp(part->desc, uP_table[i].name, l1 < l2? l1: l2) ||
|
||||||
|
flash->size != uP_table[i].flashsize ||
|
||||||
|
flash->page_size != uP_table[i].pagesize ||
|
||||||
|
part->n_interrupts != (int8_t) uP_table[i].ninterrupts)
|
||||||
|
yywarning("mcuid %d is reserved for %s, use a free number >= %d",
|
||||||
|
part->mcuid, uP_table[i].name, sizeof uP_table/sizeof *uP_table);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Range check
|
||||||
|
if(part->mcuid < 0 || part->mcuid >= UB_N_MCU)
|
||||||
|
yywarning("mcuid %d for %s is out of range [0..%d], use a free number >= %d",
|
||||||
|
part->mcuid, part->desc, UB_N_MCU-1, sizeof uP_table/sizeof *uP_table);
|
||||||
|
}
|
||||||
|
|
106
src/config.h
106
src/config.h
|
@ -25,17 +25,61 @@
|
||||||
|
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
|
|
||||||
|
#if defined(WIN32) || defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
#define realpath(N,R) _fullpath((R), (N), PATH_MAX)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_STR_CONST 1024
|
|
||||||
|
|
||||||
enum { V_NONE, V_NUM, V_NUM_REAL, V_STR };
|
typedef struct {
|
||||||
|
char *kw; // Keyword near the comments
|
||||||
|
LISTID comms; // Chained list of comments
|
||||||
|
int rhs; // Comments to print rhs of keyword line
|
||||||
|
} COMMENT;
|
||||||
|
|
||||||
|
|
||||||
|
enum { // Which structures a component can occur in
|
||||||
|
COMP_CONFIG_MAIN,
|
||||||
|
COMP_PROGRAMMER,
|
||||||
|
COMP_AVRPART,
|
||||||
|
COMP_AVRMEM,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { // Component types in structure
|
||||||
|
COMP_INT,
|
||||||
|
COMP_SHORT,
|
||||||
|
COMP_CHAR,
|
||||||
|
COMP_STRING,
|
||||||
|
COMP_CHAR_ARRAY, // This and below are not yet implemented
|
||||||
|
COMP_INT_LISTID,
|
||||||
|
COMP_STRING_LISTID,
|
||||||
|
COMP_OPCODE,
|
||||||
|
COMP_PIN, // Pins may never be implemented
|
||||||
|
COMP_PIN_LIST
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct { // Description of a component in a structure
|
||||||
|
const char *name; // Component name
|
||||||
|
int strct; // Structure, eg, COMP_AVRPART
|
||||||
|
int offset, size, type; // Location, size and type within structure
|
||||||
|
} Component_t;
|
||||||
|
|
||||||
|
|
||||||
|
enum { // Value types for VALUE struct
|
||||||
|
V_NONE,
|
||||||
|
V_NUM,
|
||||||
|
V_NUM_REAL,
|
||||||
|
V_STR,
|
||||||
|
V_COMPONENT,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct value_t {
|
typedef struct value_t {
|
||||||
int type;
|
int type;
|
||||||
/*union { TODO: use an anonymous union here ? */
|
union {
|
||||||
int number;
|
int number;
|
||||||
double number_real;
|
double number_real;
|
||||||
char * string;
|
char * string;
|
||||||
/*};*/
|
Component_t *comp;
|
||||||
|
};
|
||||||
} VALUE;
|
} VALUE;
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,8 +94,9 @@ extern FILE * yyin;
|
||||||
extern PROGRAMMER * current_prog;
|
extern PROGRAMMER * current_prog;
|
||||||
extern AVRPART * current_part;
|
extern AVRPART * current_part;
|
||||||
extern AVRMEM * current_mem;
|
extern AVRMEM * current_mem;
|
||||||
extern int lineno;
|
extern int current_strct;
|
||||||
extern const char * infile;
|
extern int cfg_lineno;
|
||||||
|
extern char * cfg_infile;
|
||||||
extern LISTID string_list;
|
extern LISTID string_list;
|
||||||
extern LISTID number_list;
|
extern LISTID number_list;
|
||||||
extern bool is_alias; // current entry is alias
|
extern bool is_alias; // current entry is alias
|
||||||
|
@ -62,40 +107,61 @@ extern bool is_alias; // current entry is alias
|
||||||
#endif
|
#endif
|
||||||
extern YYSTYPE yylval;
|
extern YYSTYPE yylval;
|
||||||
|
|
||||||
extern char string_buf[MAX_STR_CONST];
|
|
||||||
extern char *string_buf_ptr;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int yyparse(void);
|
int yyparse(void);
|
||||||
|
|
||||||
int yyerror(char * errmsg, ...);
|
int yyerror(char *errmsg, ...);
|
||||||
|
|
||||||
int yywarning(char * errmsg, ...);
|
int yywarning(char *errmsg, ...);
|
||||||
|
|
||||||
TOKEN * new_token(int primary);
|
TOKEN *new_token(int primary);
|
||||||
|
|
||||||
void free_token(TOKEN * tkn);
|
void free_token(TOKEN *tkn);
|
||||||
|
|
||||||
void free_tokens(int n, ...);
|
void free_tokens(int n, ...);
|
||||||
|
|
||||||
TOKEN * number(char * text);
|
TOKEN *new_number(const char *text);
|
||||||
|
|
||||||
TOKEN * number_real(char * text);
|
TOKEN *new_number_real(const char *text);
|
||||||
|
|
||||||
TOKEN * hexnumber(char * text);
|
TOKEN *new_hexnumber(const char *text);
|
||||||
|
|
||||||
TOKEN * string(char * text);
|
TOKEN *new_constant(const char *text);
|
||||||
|
|
||||||
TOKEN * keyword(int primary);
|
TOKEN *new_string(const char *text);
|
||||||
|
|
||||||
void print_token(TOKEN * tkn);
|
TOKEN *new_keyword(int primary);
|
||||||
|
|
||||||
|
void print_token(TOKEN *tkn);
|
||||||
|
|
||||||
void pyytext(void);
|
void pyytext(void);
|
||||||
|
|
||||||
char * dup_string(const char * str);
|
COMMENT *locate_comment(const LISTID comments, const char *where, int rhs);
|
||||||
|
|
||||||
|
void cfg_capture_prologue(void);
|
||||||
|
|
||||||
|
LISTID cfg_get_prologue(void);
|
||||||
|
|
||||||
|
void capture_comment_str(const char *com, int lineno);
|
||||||
|
|
||||||
|
void capture_lvalue_kw(const char *kw, int lineno);
|
||||||
|
|
||||||
|
LISTID cfg_move_comments(void);
|
||||||
|
|
||||||
|
void cfg_pop_comms(void);
|
||||||
|
|
||||||
|
Component_t *cfg_comp_search(const char *name, int strct);
|
||||||
|
|
||||||
|
const char *cfg_v_type(int type);
|
||||||
|
|
||||||
|
const char *cfg_strct_name(int strct);
|
||||||
|
|
||||||
|
void cfg_assign(char *sp, int strct, Component_t *cp, VALUE *v);
|
||||||
|
|
||||||
|
void cfg_update_mcuid(AVRPART *part);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,7 +23,7 @@
|
||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ(2.60)
|
AC_PREREQ(2.60)
|
||||||
AC_INIT(avrdude, 7.0, avrdude-dev@nongnu.org)
|
AC_INIT(avrdude, 7.1-20230108, avrdude-dev@nongnu.org)
|
||||||
|
|
||||||
AC_CANONICAL_BUILD
|
AC_CANONICAL_BUILD
|
||||||
AC_CANONICAL_HOST
|
AC_CANONICAL_HOST
|
||||||
|
@ -577,6 +577,12 @@ else
|
||||||
echo "DON'T HAVE libhidapi"
|
echo "DON'T HAVE libhidapi"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test x$have_readline = xyes; then
|
||||||
|
echo "DO HAVE libreadline"
|
||||||
|
else
|
||||||
|
echo "DON'T HAVE libreadline"
|
||||||
|
fi
|
||||||
|
|
||||||
if test x$have_pthread = xyes; then
|
if test x$have_pthread = xyes; then
|
||||||
echo "DO HAVE pthread"
|
echo "DO HAVE pthread"
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
#
|
||||||
|
# configure.cmake - autoconf like multi-line configure
|
||||||
|
# Copyright (C) 2022 Marius Greuel
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Do a multi-line replace based on @<OPTION>_BEGIN@ and @<OPTION>_END@ tags.
|
||||||
|
macro(configure_option option)
|
||||||
|
if(${${option}})
|
||||||
|
string(REGEX REPLACE "(.*)@${option}_BEGIN@(.*)@${option}_END@(.*)" "\\1\\2\\3" CONTENTS "${CONTENTS}")
|
||||||
|
else()
|
||||||
|
string(REGEX REPLACE "(.*)@${option}_BEGIN@(.*)@${option}_END@(.*)" "\\1\\3" CONTENTS "${CONTENTS}")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Perform autoconf like multi-line configure
|
||||||
|
file(READ avrdude.conf.in CONTENTS)
|
||||||
|
configure_option(HAVE_PARPORT)
|
||||||
|
configure_option(HAVE_LINUXSPI)
|
||||||
|
configure_option(HAVE_LINUXGPIO)
|
||||||
|
file(WRITE avrdude.conf.in "${CONTENTS}")
|
||||||
|
|
||||||
|
configure_file(avrdude.conf.in avrdude.conf)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||||
|
* Copyright (C) 2022, Stefan Rueger <stefan.rueger@urclocks.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef developer_opts_h
|
||||||
|
#define developer_opts_h
|
||||||
|
|
||||||
|
void dev_output_pgm_part(int dev_opt_c, const char *programmer, int dev_opt_p, const char *partdesc);
|
||||||
|
void dev_output_part_defs(char *partdesc);
|
||||||
|
void dev_output_pgm_defs(char *programmer);
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||||
|
* Copyright (C) 2022, Stefan Rueger <stefan.rueger@urclocks.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef developer_opts_private_h
|
||||||
|
#define developer_opts_private_h
|
||||||
|
|
||||||
|
#define DEV_SPI_EN_CE_SIG 1
|
||||||
|
#define DEV_SPI_PROGMEM 2
|
||||||
|
#define DEV_SPI_PROGMEM_PAGED 4
|
||||||
|
#define DEV_SPI_LOAD_EXT_ADDR 8
|
||||||
|
#define DEV_SPI_EEPROM 16
|
||||||
|
#define DEV_SPI_EEPROM_PAGED 32
|
||||||
|
#define DEV_SPI_LOCK 64
|
||||||
|
#define DEV_SPI_CALIBRATION 128
|
||||||
|
#define DEV_SPI_LFUSE 256
|
||||||
|
#define DEV_SPI_HFUSE 512
|
||||||
|
#define DEV_SPI_EFUSE 1024
|
||||||
|
|
||||||
|
|
||||||
|
static int dev_message(int msglvl, const char *fmt, ...);
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DEV_INFO
|
||||||
|
#define DEV_INFO MSG_INFO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEV_NOTICE
|
||||||
|
#define DEV_NOTICE MSG_NOTICE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEV_NOTICE
|
||||||
|
#define DEV_NOTICE2 MSG_NOTICE2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define dev_info(...) dev_message(DEV_INFO, __VA_ARGS__)
|
||||||
|
#define dev_notice(...) dev_message(DEV_NOTICE, __VA_ARGS__)
|
||||||
|
#define dev_notice2(...) dev_message(DEV_NOTICE2, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define _pgmout(fmt, component) \
|
||||||
|
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component), pgm->comments)
|
||||||
|
|
||||||
|
#define _pgmout_fmt(name, fmt, what) \
|
||||||
|
dev_part_strct_entry(tsv, ".prog", id, NULL, name, dev_sprintf(fmt, what), pgm->comments)
|
||||||
|
|
||||||
|
#define _if_pgmout(cmp, fmt, component) do { \
|
||||||
|
if(!base || cmp(base->component, pgm->component)) \
|
||||||
|
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, dev_sprintf(fmt, pgm->component), pgm->comments); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc'd string
|
||||||
|
#define _if_pgmout_str(cmp, result, component) do { \
|
||||||
|
if(!base || cmp(base->component, pgm->component)) \
|
||||||
|
dev_part_strct_entry(tsv, ".prog", id, NULL, #component, result, pgm->comments); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
#define _partout(fmt, component) \
|
||||||
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, dev_sprintf(fmt, p->component), p->comments)
|
||||||
|
|
||||||
|
#define _if_partout(cmp, fmt, component) do { \
|
||||||
|
if(!base || cmp(base->component, p->component)) \
|
||||||
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, dev_sprintf(fmt, p->component), p->comments); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define _if_n_partout(cmp, n, fmt, component) do { \
|
||||||
|
if(!base || cmp(base->component, p->component, n)) \
|
||||||
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, dev_sprintf(fmt, p->component), p->comments); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc'd string
|
||||||
|
#define _partout_str(result, component) \
|
||||||
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result, p->comments)
|
||||||
|
|
||||||
|
// Result must be a malloc'd string
|
||||||
|
#define _if_partout_str(cmp, result, component) do { \
|
||||||
|
if(!base || cmp(base->component, p->component)) \
|
||||||
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result, p->comments); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc'd string
|
||||||
|
#define _if_n_partout_str(cmp, n, result, component) do { \
|
||||||
|
if(!base || cmp(base->component, p->component, n)) \
|
||||||
|
dev_part_strct_entry(tsv, ".pt", p->desc, NULL, #component, result, p->comments); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
#define _memout(fmt, component) \
|
||||||
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, dev_sprintf(fmt, m->component), m->comments)
|
||||||
|
|
||||||
|
#define _if_memout(cmp, fmt, component) do { \
|
||||||
|
if(!bm || cmp(bm->component, m->component)) \
|
||||||
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, dev_sprintf(fmt, m->component), m->comments); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc'd string
|
||||||
|
#define _memout_str(result, component) \
|
||||||
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, result, m->comments)
|
||||||
|
|
||||||
|
// Result must be a malloc'd string
|
||||||
|
#define _if_n_memout_str(cmp, n, result, component) do { \
|
||||||
|
if(!bm || cmp(bm->component, m->component, n)) \
|
||||||
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, result, m->comments); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define _memout_yn(component) \
|
||||||
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, cfg_strdup("_memout_yn()", m->component? "yes": "no"), m->comments)
|
||||||
|
|
||||||
|
#define _if_memout_yn(component) do { \
|
||||||
|
if(!bm || bm->component != m->component) \
|
||||||
|
dev_part_strct_entry(tsv, ".ptmm", p->desc, m->desc, #component, cfg_strdup("_if_memout_yn()", m->component? "yes": "no"), m->comments); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define _flagout(mask, name) \
|
||||||
|
_partout_str(cfg_strdup("_flagout()", p->flags & (mask)? "yes": "no"), name)
|
||||||
|
|
||||||
|
#define _if_flagout(mask, name) do { \
|
||||||
|
if(!base || (base->flags & (mask)) != (p->flags & (mask))) \
|
||||||
|
_partout_str(cfg_strdup("_if_flagout()", p->flags & (mask)? "yes": "no"), name); \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
// Result must be a malloc'd string
|
||||||
|
#define _cmderr(result, component) \
|
||||||
|
dev_part_strct_entry(tsv, ".cmderr", p->desc, m->desc, #component, result, NULL)
|
||||||
|
|
||||||
|
#endif
|
112
src/dfu.c
112
src/dfu.c
|
@ -38,9 +38,8 @@
|
||||||
|
|
||||||
#ifndef HAVE_LIBUSB
|
#ifndef HAVE_LIBUSB
|
||||||
|
|
||||||
struct dfu_dev *dfu_open(char *port_name) {
|
struct dfu_dev *dfu_open(const char *port_name) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: No USB support in this compile of avrdude\n",
|
pmsg_error("no USB support compiled for avrdude\n");
|
||||||
progname);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,8 +98,7 @@ static char * get_usb_string(usb_dev_handle * dev_handle, int index);
|
||||||
/* EXPORTED FUNCTION DEFINITIONS
|
/* EXPORTED FUNCTION DEFINITIONS
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct dfu_dev * dfu_open(char *port_spec)
|
struct dfu_dev *dfu_open(const char *port_spec) {
|
||||||
{
|
|
||||||
struct dfu_dev *dfu;
|
struct dfu_dev *dfu;
|
||||||
char *bus_name = NULL;
|
char *bus_name = NULL;
|
||||||
char *dev_name = NULL;
|
char *dev_name = NULL;
|
||||||
|
@ -112,16 +110,14 @@ struct dfu_dev * dfu_open(char *port_spec)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (strncmp(port_spec, "usb", 3) != 0) {
|
if (strncmp(port_spec, "usb", 3) != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: "
|
pmsg_error("invalid port specification %s for USB device\n", port_spec);
|
||||||
"Invalid port specification \"%s\" for USB device\n",
|
|
||||||
progname, port_spec);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(':' == port_spec[3]) {
|
if(':' == port_spec[3]) {
|
||||||
bus_name = strdup(port_spec + 3 + 1);
|
bus_name = strdup(port_spec + 3 + 1);
|
||||||
if (bus_name == NULL) {
|
if (bus_name == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: Out of memory in strdup\n", progname);
|
pmsg_error("out of memory in strdup\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +134,7 @@ struct dfu_dev * dfu_open(char *port_spec)
|
||||||
|
|
||||||
if (dfu == NULL)
|
if (dfu == NULL)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
|
pmsg_error("out of memory\n");
|
||||||
free(bus_name);
|
free(bus_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -172,9 +168,7 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (pid == 0 && dfu->dev_name == NULL) {
|
if (pid == 0 && dfu->dev_name == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: No DFU support for part; "
|
pmsg_error("no DFU support for part; specify PID in config or USB address (via -P) to override\n");
|
||||||
"specify PID in config or USB address (via -P) to override.\n",
|
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,20 +203,18 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid)
|
||||||
* why the match failed, and if we came across another DFU-capable part.
|
* why the match failed, and if we came across another DFU-capable part.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: Error: No matching USB device found\n", progname);
|
pmsg_error("no matching USB device found\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose)
|
pmsg_notice("found VID=0x%04x PID=0x%04x at %s:%s\n",
|
||||||
avrdude_message(MSG_INFO, "%s: Found VID=0x%04x PID=0x%04x at %s:%s\n",
|
found->descriptor.idVendor, found->descriptor.idProduct,
|
||||||
progname, found->descriptor.idVendor, found->descriptor.idProduct,
|
found->bus->dirname, found->filename);
|
||||||
found->bus->dirname, found->filename);
|
|
||||||
|
|
||||||
dfu->dev_handle = usb_open(found);
|
dfu->dev_handle = usb_open(found);
|
||||||
|
|
||||||
if (dfu->dev_handle == NULL) {
|
if (dfu->dev_handle == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: USB device at %s:%s: %s\n",
|
pmsg_error("USB device at %s:%s: %s\n", found->bus->dirname, found->filename, usb_strerror());
|
||||||
progname, found->bus->dirname, found->filename, usb_strerror());
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,37 +264,32 @@ int dfu_getstatus(struct dfu_dev *dfu, struct dfu_status *status)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
avrdude_message(MSG_TRACE, "%s: dfu_getstatus(): issuing control IN message\n",
|
pmsg_trace("dfu_getstatus(): issuing control IN message\n");
|
||||||
progname);
|
|
||||||
|
|
||||||
result = usb_control_msg(dfu->dev_handle,
|
result = usb_control_msg(dfu->dev_handle,
|
||||||
0x80 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_GETSTATUS, 0, 0,
|
0x80 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_GETSTATUS, 0, 0,
|
||||||
(char*) status, sizeof(struct dfu_status), dfu->timeout);
|
(char*) status, sizeof(struct dfu_status), dfu->timeout);
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to get DFU status: %s\n",
|
pmsg_error("unable to get DFU status: %s\n", usb_strerror());
|
||||||
progname, usb_strerror());
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result < sizeof(struct dfu_status)) {
|
if (result < sizeof(struct dfu_status)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to get DFU status: %s\n",
|
pmsg_error("unable to get DFU status: %s\n", "short read");
|
||||||
progname, "short read");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result > sizeof(struct dfu_status)) {
|
if (result > sizeof(struct dfu_status)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Oversize read (should not happen); "
|
pmsg_error("oversize read (should not happen); exiting\n");
|
||||||
"exiting\n", progname);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_TRACE, "%s: dfu_getstatus(): bStatus 0x%02x, bwPollTimeout %d, bState 0x%02x, iString %d\n",
|
pmsg_trace("dfu_getstatus(): bStatus 0x%02x, bwPollTimeout %d, bState 0x%02x, iString %d\n",
|
||||||
progname,
|
status->bStatus,
|
||||||
status->bStatus,
|
status->bwPollTimeout[0] | (status->bwPollTimeout[1] << 8) | (status->bwPollTimeout[2] << 16),
|
||||||
status->bwPollTimeout[0] | (status->bwPollTimeout[1] << 8) | (status->bwPollTimeout[2] << 16),
|
status->bState,
|
||||||
status->bState,
|
status->iString);
|
||||||
status->iString);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -311,16 +298,14 @@ int dfu_clrstatus(struct dfu_dev *dfu)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
avrdude_message(MSG_TRACE, "%s: dfu_clrstatus(): issuing control OUT message\n",
|
pmsg_trace("dfu_clrstatus(): issuing control OUT message\n");
|
||||||
progname);
|
|
||||||
|
|
||||||
result = usb_control_msg(dfu->dev_handle,
|
result = usb_control_msg(dfu->dev_handle,
|
||||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_CLRSTATUS, 0, 0,
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_CLRSTATUS, 0, 0,
|
||||||
NULL, 0, dfu->timeout);
|
NULL, 0, dfu->timeout);
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to clear DFU status: %s\n",
|
pmsg_error("unable to clear DFU status: %s\n", usb_strerror());
|
||||||
progname, usb_strerror());
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,16 +316,14 @@ int dfu_abort(struct dfu_dev *dfu)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
avrdude_message(MSG_TRACE, "%s: dfu_abort(): issuing control OUT message\n",
|
pmsg_trace("dfu_abort(): issuing control OUT message\n");
|
||||||
progname);
|
|
||||||
|
|
||||||
result = usb_control_msg(dfu->dev_handle,
|
result = usb_control_msg(dfu->dev_handle,
|
||||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_ABORT, 0, 0,
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_ABORT, 0, 0,
|
||||||
NULL, 0, dfu->timeout);
|
NULL, 0, dfu->timeout);
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to reset DFU state: %s\n",
|
pmsg_error("unable to reset DFU state: %s\n", usb_strerror());
|
||||||
progname, usb_strerror());
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,29 +335,26 @@ int dfu_dnload(struct dfu_dev *dfu, void *ptr, int size)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
avrdude_message(MSG_TRACE, "%s: dfu_dnload(): issuing control OUT message, wIndex = %d, ptr = %p, size = %d\n",
|
pmsg_trace("dfu_dnload(): issuing control OUT message, wIndex = %d, ptr = %p, size = %d\n",
|
||||||
progname, wIndex, ptr, size);
|
wIndex, ptr, size);
|
||||||
|
|
||||||
result = usb_control_msg(dfu->dev_handle,
|
result = usb_control_msg(dfu->dev_handle,
|
||||||
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_DNLOAD, wIndex++, 0,
|
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_DNLOAD, wIndex++, 0,
|
||||||
ptr, size, dfu->timeout);
|
ptr, size, dfu->timeout);
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: DFU_DNLOAD failed: %s\n",
|
pmsg_error("DFU_DNLOAD failed: %s\n", usb_strerror());
|
||||||
progname, usb_strerror());
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result < size) {
|
if (result < size) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: DFU_DNLOAD failed: %s\n",
|
pmsg_error("DFU_DNLOAD failed: short write\n");
|
||||||
progname, "short write");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result > size) {
|
if (result > size) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Oversize write (should not happen); " \
|
pmsg_error("DFU_DNLOAD failed: oversize write (should not happen)\n");
|
||||||
"exiting\n", progname);
|
return -1;
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -384,28 +364,25 @@ int dfu_upload(struct dfu_dev *dfu, void *ptr, int size)
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
avrdude_message(MSG_TRACE, "%s: dfu_upload(): issuing control IN message, wIndex = %d, ptr = %p, size = %d\n",
|
pmsg_trace("dfu_upload(): issuing control IN message, wIndex = %d, ptr = %p, size = %d\n",
|
||||||
progname, wIndex, ptr, size);
|
wIndex, ptr, size);
|
||||||
|
|
||||||
result = usb_control_msg(dfu->dev_handle,
|
result = usb_control_msg(dfu->dev_handle,
|
||||||
0x80 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_UPLOAD, wIndex++, 0,
|
0x80 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_UPLOAD, wIndex++, 0,
|
||||||
ptr, size, dfu->timeout);
|
ptr, size, dfu->timeout);
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: DFU_UPLOAD failed: %s\n",
|
pmsg_error("DFU_UPLOAD failed: %s\n", usb_strerror());
|
||||||
progname, usb_strerror());
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result < size) {
|
if (result < size) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: DFU_UPLOAD failed: %s\n",
|
pmsg_error("DFU_UPLOAD failed: %s\n", "short read");
|
||||||
progname, "short read");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result > size) {
|
if (result > size) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Oversize read (should not happen); "
|
pmsg_error("oversize read (should not happen); exiting\n");
|
||||||
"exiting\n", progname);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,26 +392,26 @@ int dfu_upload(struct dfu_dev *dfu, void *ptr, int size)
|
||||||
void dfu_show_info(struct dfu_dev *dfu)
|
void dfu_show_info(struct dfu_dev *dfu)
|
||||||
{
|
{
|
||||||
if (dfu->manf_str != NULL)
|
if (dfu->manf_str != NULL)
|
||||||
avrdude_message(MSG_INFO, " USB Vendor : %s (0x%04hX)\n",
|
msg_info(" USB Vendor : %s (0x%04hX)\n",
|
||||||
dfu->manf_str, (unsigned short) dfu->dev_desc.idVendor);
|
dfu->manf_str, (unsigned short) dfu->dev_desc.idVendor);
|
||||||
else
|
else
|
||||||
avrdude_message(MSG_INFO, " USB Vendor : 0x%04hX\n",
|
msg_info(" USB Vendor : 0x%04hX\n",
|
||||||
(unsigned short) dfu->dev_desc.idVendor);
|
(unsigned short) dfu->dev_desc.idVendor);
|
||||||
|
|
||||||
if (dfu->prod_str != NULL)
|
if (dfu->prod_str != NULL)
|
||||||
avrdude_message(MSG_INFO, " USB Product : %s (0x%04hX)\n",
|
msg_info(" USB Product : %s (0x%04hX)\n",
|
||||||
dfu->prod_str, (unsigned short) dfu->dev_desc.idProduct);
|
dfu->prod_str, (unsigned short) dfu->dev_desc.idProduct);
|
||||||
else
|
else
|
||||||
avrdude_message(MSG_INFO, " USB Product : 0x%04hX\n",
|
msg_info(" USB Product : 0x%04hX\n",
|
||||||
(unsigned short) dfu->dev_desc.idProduct);
|
(unsigned short) dfu->dev_desc.idProduct);
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, " USB Release : %hu.%hu.%hu\n",
|
msg_info(" USB Release : %hu.%hu.%hu\n",
|
||||||
((unsigned short) dfu->dev_desc.bcdDevice >> 8) & 0xFF,
|
((unsigned short) dfu->dev_desc.bcdDevice >> 8) & 0xFF,
|
||||||
((unsigned short) dfu->dev_desc.bcdDevice >> 4) & 0xF,
|
((unsigned short) dfu->dev_desc.bcdDevice >> 4) & 0xF,
|
||||||
((unsigned short) dfu->dev_desc.bcdDevice >> 0) & 0xF);
|
((unsigned short) dfu->dev_desc.bcdDevice >> 0) & 0xF);
|
||||||
|
|
||||||
if (dfu->serno_str != NULL)
|
if (dfu->serno_str != NULL)
|
||||||
avrdude_message(MSG_INFO, " USB Serial No : %s\n", dfu->serno_str);
|
msg_info(" USB Serial No : %s\n", dfu->serno_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* INTERNAL FUNCTION DEFINITIONS
|
/* INTERNAL FUNCTION DEFINITIONS
|
||||||
|
@ -451,15 +428,14 @@ char * get_usb_string(usb_dev_handle * dev_handle, int index) {
|
||||||
result = usb_get_string_simple(dev_handle, index, buffer, sizeof(buffer)-1);
|
result = usb_get_string_simple(dev_handle, index, buffer, sizeof(buffer)-1);
|
||||||
|
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: Failed to read USB device string %d: %s\n",
|
pmsg_error("unable to read USB device string %d: %s\n", index, usb_strerror());
|
||||||
progname, index, usb_strerror());
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = malloc(result+1);
|
str = malloc(result+1);
|
||||||
|
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: Out of memory allocating a string\n", progname);
|
pmsg_error("out of memory allocating a string\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,7 +114,7 @@ struct dfu_status {
|
||||||
|
|
||||||
// FUNCTIONS
|
// FUNCTIONS
|
||||||
|
|
||||||
extern struct dfu_dev * dfu_open(char *port_spec);
|
extern struct dfu_dev *dfu_open(const char *port_spec);
|
||||||
extern int dfu_init(struct dfu_dev *dfu,
|
extern int dfu_init(struct dfu_dev *dfu,
|
||||||
unsigned short vid, unsigned short pid);
|
unsigned short vid, unsigned short pid);
|
||||||
extern void dfu_close(struct dfu_dev *dfu);
|
extern void dfu_close(struct dfu_dev *dfu);
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
#
|
||||||
|
# CMakeLists.txt - CMake project for AVRDUDE documentation
|
||||||
|
# Copyright (C) 2022 Marius Greuel
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
set(AVRDUDE_CONF "${PROJECT_BINARY_DIR}/src/avrdude.conf")
|
||||||
|
|
||||||
|
set(TEXINFOS "${CMAKE_CURRENT_SOURCE_DIR}/avrdude.texi")
|
||||||
|
set(GENERATED_TEXINFOS
|
||||||
|
programmers.texi
|
||||||
|
programmer_types.texi
|
||||||
|
parts.texi
|
||||||
|
version.texi
|
||||||
|
)
|
||||||
|
|
||||||
|
string(TIMESTAMP TODAY "%d %B %Y")
|
||||||
|
set(DOCS_VERSION ${PROJECT_VERSION})
|
||||||
|
set(DOCS_UPDATED ${TODAY})
|
||||||
|
|
||||||
|
find_program(MAKEINFO_EXECUTABLE NAMES makeinfo)
|
||||||
|
find_program(TEXI2HTML_EXECUTABLE NAMES texi2html)
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# Custom rules for auto-generated texi
|
||||||
|
# =====================================
|
||||||
|
|
||||||
|
add_custom_target(avrdude_binaries DEPENDS avrdude conf)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT programmers.txt
|
||||||
|
DEPENDS avrdude_binaries
|
||||||
|
COMMAND $<TARGET_FILE:avrdude> -C ${AVRDUDE_CONF} -c ? 2>&1 | more > programmers.txt
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT programmer_types.txt
|
||||||
|
DEPENDS avrdude_binaries
|
||||||
|
COMMAND $<TARGET_FILE:avrdude> -C ${AVRDUDE_CONF} -c ?type 2>&1 | more > programmer_types.txt
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT parts.txt
|
||||||
|
DEPENDS avrdude_binaries
|
||||||
|
COMMAND $<TARGET_FILE:avrdude> -C ${AVRDUDE_CONF} -p ? 2>&1 | more > parts.txt
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT programmers.texi
|
||||||
|
DEPENDS programmers.txt
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-D TXT_FILE=programmers.txt
|
||||||
|
-D TEXI_FILE=programmers.texi
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/programmers.cmake"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT programmer_types.texi
|
||||||
|
DEPENDS programmer_types.txt
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-D TXT_FILE=programmer_types.txt
|
||||||
|
-D TEXI_FILE=programmer_types.texi
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/programmer_types.cmake"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT parts.texi
|
||||||
|
DEPENDS parts.txt
|
||||||
|
COMMAND ${CMAKE_COMMAND}
|
||||||
|
-D TXT_FILE=parts.txt
|
||||||
|
-D TEXI_FILE=parts.texi
|
||||||
|
-D COMMENTS_FILE=${CMAKE_CURRENT_SOURCE_DIR}/parts_comments.txt
|
||||||
|
-P "${CMAKE_CURRENT_SOURCE_DIR}/parts.cmake"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT version.texi
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "@set EDITION ${DOCS_VERSION}" > version.texi
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "@set VERSION ${DOCS_VERSION}" >> version.texi
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E echo "@set UPDATED ${DOCS_UPDATED}" >> version.texi
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# Custom rules for output files
|
||||||
|
# =====================================
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT avrdude.info
|
||||||
|
COMMAND ${MAKEINFO_EXECUTABLE} -o avrdude.info ${TEXINFOS}
|
||||||
|
DEPENDS ${TEXINFOS} ${GENERATED_TEXINFOS}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT avrdude.dvi
|
||||||
|
COMMAND ${MAKEINFO_EXECUTABLE}
|
||||||
|
--dvi
|
||||||
|
--Xopt=--quiet
|
||||||
|
--Xopt=--build-dir=dvi
|
||||||
|
-o avrdude.dvi
|
||||||
|
${TEXINFOS}
|
||||||
|
DEPENDS ${TEXINFOS} ${GENERATED_TEXINFOS}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT avrdude.pdf
|
||||||
|
COMMAND ${MAKEINFO_EXECUTABLE}
|
||||||
|
--pdf
|
||||||
|
--Xopt=--quiet
|
||||||
|
--Xopt=--build-dir=pdf
|
||||||
|
-o avrdude.pdf
|
||||||
|
${TEXINFOS}
|
||||||
|
DEPENDS ${TEXINFOS} ${GENERATED_TEXINFOS}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT avrdude.ps
|
||||||
|
COMMAND ${MAKEINFO_EXECUTABLE}
|
||||||
|
--ps
|
||||||
|
--Xopt=--quiet
|
||||||
|
--Xopt=--build-dir=ps
|
||||||
|
-o avrdude.ps
|
||||||
|
${TEXINFOS}
|
||||||
|
DEPENDS ${TEXINFOS} ${GENERATED_TEXINFOS}
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT avrdude-html/avrdude.html
|
||||||
|
COMMAND ${TEXI2HTML_EXECUTABLE}
|
||||||
|
--split=node
|
||||||
|
--css-include=avrdude.css
|
||||||
|
--output=avrdude-html
|
||||||
|
-I ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${TEXINFOS}
|
||||||
|
DEPENDS ${TEXINFOS} ${GENERATED_TEXINFOS} avrdude.css
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# Custom targets for output files
|
||||||
|
# =====================================
|
||||||
|
|
||||||
|
add_custom_target(info ALL DEPENDS avrdude.info)
|
||||||
|
add_custom_target(dvi ALL DEPENDS avrdude.dvi)
|
||||||
|
add_custom_target(pdf ALL DEPENDS avrdude.pdf)
|
||||||
|
add_custom_target(ps ALL DEPENDS avrdude.ps)
|
||||||
|
add_custom_target(html ALL DEPENDS avrdude-html/avrdude.html)
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# Install
|
||||||
|
# =====================================
|
||||||
|
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/avrdude.info" DESTINATION ${CMAKE_INSTALL_INFODIR})
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/avrdude.dvi" DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/avrdude.pdf" DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/avrdude.ps" DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/avrdude-html" DESTINATION ${CMAKE_INSTALL_DOCDIR})
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,37 @@
|
||||||
|
#
|
||||||
|
# programmers.cmake - create parts.texi from parts.txt
|
||||||
|
# Copyright (C) 2022 Marius Greuel
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
file(STRINGS ${COMMENTS_FILE} COMMENTS_CONTENTS)
|
||||||
|
|
||||||
|
file(STRINGS ${TXT_FILE} TXT_CONTENTS REGEX "=")
|
||||||
|
|
||||||
|
set(TEXI_CONTENTS "")
|
||||||
|
foreach(TXT_LINE IN LISTS TXT_CONTENTS)
|
||||||
|
string(REGEX REPLACE "^[ \t]*([^ \t]+)[ \t]*=[ \t]*(.*)$" "@item @code{\\1} @tab \\2" TEXI_LINE "${TXT_LINE}")
|
||||||
|
|
||||||
|
foreach(COMMENTS_LINE IN LISTS COMMENTS_CONTENTS)
|
||||||
|
string(REGEX MATCH "^([^ \t]*)(.*)$" DUMMY "${COMMENTS_LINE}")
|
||||||
|
set(PART_REGEX "${CMAKE_MATCH_1}")
|
||||||
|
set(COMMENT "${CMAKE_MATCH_2}")
|
||||||
|
string(REGEX REPLACE "(${PART_REGEX})" "\\1${COMMENT}" TEXI_LINE "${TEXI_LINE}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(TEXI_CONTENTS "${TEXI_CONTENTS}${TEXI_LINE}\n")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
file(WRITE ${TEXI_FILE} "${TEXI_CONTENTS}")
|
|
@ -0,0 +1,28 @@
|
||||||
|
#
|
||||||
|
# programmer_types.cmake - create programmer_types.texi from programmer_types.txt
|
||||||
|
# Copyright (C) 2022 Marius Greuel
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
file(STRINGS ${TXT_FILE} TXT_CONTENTS REGEX "=")
|
||||||
|
|
||||||
|
SET(TEXI_CONTENTS "")
|
||||||
|
foreach(TXT_LINE IN LISTS TXT_CONTENTS)
|
||||||
|
string(REGEX REPLACE "^[ \t]*([^ \t]+)[ \t]*=[ \t]*(.*)$" "@item @code{\\1} @tab \\2" TEXI_LINE "${TXT_LINE}")
|
||||||
|
string(REGEX REPLACE "<?(http[s]?://[^ \t,>]+)>?" "@url{\\1}" TEXI_LINE "${TEXI_LINE}")
|
||||||
|
set(TEXI_CONTENTS "${TEXI_CONTENTS}${TEXI_LINE}\n")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
file(WRITE ${TEXI_FILE} "${TEXI_CONTENTS}")
|
|
@ -0,0 +1,28 @@
|
||||||
|
#
|
||||||
|
# programmers.cmake - create programmers.texi from programmers.txt
|
||||||
|
# Copyright (C) 2022 Marius Greuel
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
file(STRINGS ${TXT_FILE} TXT_CONTENTS REGEX "=")
|
||||||
|
|
||||||
|
SET(TEXI_CONTENTS "")
|
||||||
|
foreach(TXT_LINE IN LISTS TXT_CONTENTS)
|
||||||
|
string(REGEX REPLACE "^[ \t]*([^ \t]+)[ \t]*=[ \t]*(.*)$" "@item @code{\\1} @tab \\2" TEXI_LINE "${TXT_LINE}")
|
||||||
|
string(REGEX REPLACE "[ \t>]*,?[ \t>]*<?(http[s]?://[^ \t>]+)>?" ",@*\n@url{\\1}" TEXI_LINE "${TEXI_LINE}")
|
||||||
|
set(TEXI_CONTENTS "${TEXI_CONTENTS}${TEXI_LINE}\n")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
file(WRITE ${TEXI_FILE} "${TEXI_CONTENTS}")
|
630
src/fileio.c
630
src/fileio.c
File diff suppressed because it is too large
Load Diff
251
src/flip1.c
251
src/flip1.c
|
@ -136,23 +136,23 @@ enum flip1_mem_unit {
|
||||||
|
|
||||||
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
|
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
|
||||||
|
|
||||||
static int flip1_open(PROGRAMMER *pgm, char *port_spec);
|
static int flip1_open(PROGRAMMER *pgm, const char *port_spec);
|
||||||
static int flip1_initialize(PROGRAMMER* pgm, AVRPART *part);
|
static int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part);
|
||||||
static void flip1_close(PROGRAMMER* pgm);
|
static void flip1_close(PROGRAMMER* pgm);
|
||||||
static void flip1_enable(PROGRAMMER* pgm);
|
static void flip1_enable(PROGRAMMER *pgm, const AVRPART *p);
|
||||||
static void flip1_disable(PROGRAMMER* pgm);
|
static void flip1_disable(const PROGRAMMER *pgm);
|
||||||
static void flip1_display(PROGRAMMER* pgm, const char *prefix);
|
static void flip1_display(const PROGRAMMER *pgm, const char *prefix);
|
||||||
static int flip1_program_enable(PROGRAMMER* pgm, AVRPART *part);
|
static int flip1_program_enable(const PROGRAMMER *pgm, const AVRPART *part);
|
||||||
static int flip1_chip_erase(PROGRAMMER* pgm, AVRPART *part);
|
static int flip1_chip_erase(const PROGRAMMER *pgm, const AVRPART *part);
|
||||||
static int flip1_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
static int flip1_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char *value);
|
unsigned long addr, unsigned char *value);
|
||||||
static int flip1_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
static int flip1_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char value);
|
unsigned long addr, unsigned char value);
|
||||||
static int flip1_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
static int flip1_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
|
||||||
static int flip1_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
static int flip1_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
|
||||||
static int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem);
|
static int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem);
|
||||||
static void flip1_setup(PROGRAMMER * pgm);
|
static void flip1_setup(PROGRAMMER * pgm);
|
||||||
static void flip1_teardown(PROGRAMMER * pgm);
|
static void flip1_teardown(PROGRAMMER * pgm);
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ static void flip1_teardown(PROGRAMMER * pgm);
|
||||||
|
|
||||||
static void flip1_show_info(struct flip1 *flip1);
|
static void flip1_show_info(struct flip1 *flip1);
|
||||||
|
|
||||||
static int flip1_read_memory(PROGRAMMER * pgm,
|
static int flip1_read_memory(const PROGRAMMER *pgm,
|
||||||
enum flip1_mem_unit mem_unit, uint32_t addr, void *ptr, int size);
|
enum flip1_mem_unit mem_unit, uint32_t addr, void *ptr, int size);
|
||||||
static int flip1_write_memory(struct dfu_dev *dfu,
|
static int flip1_write_memory(struct dfu_dev *dfu,
|
||||||
enum flip1_mem_unit mem_unit, uint32_t addr, const void *ptr, int size);
|
enum flip1_mem_unit mem_unit, uint32_t addr, const void *ptr, int size);
|
||||||
|
@ -176,8 +176,7 @@ static enum flip1_mem_unit flip1_mem_unit(const char *name);
|
||||||
|
|
||||||
/* THE INITPGM FUNCTION DEFINITIONS */
|
/* THE INITPGM FUNCTION DEFINITIONS */
|
||||||
|
|
||||||
void flip1_initpgm(PROGRAMMER *pgm)
|
void flip1_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "flip1");
|
strcpy(pgm->type, "flip1");
|
||||||
|
|
||||||
/* Mandatory Functions */
|
/* Mandatory Functions */
|
||||||
|
@ -201,14 +200,12 @@ void flip1_initpgm(PROGRAMMER *pgm)
|
||||||
#ifdef HAVE_LIBUSB
|
#ifdef HAVE_LIBUSB
|
||||||
/* EXPORTED PROGRAMMER FUNCTION DEFINITIONS */
|
/* EXPORTED PROGRAMMER FUNCTION DEFINITIONS */
|
||||||
|
|
||||||
int flip1_open(PROGRAMMER *pgm, char *port_spec)
|
int flip1_open(PROGRAMMER *pgm, const char *port_spec) {
|
||||||
{
|
|
||||||
FLIP1(pgm)->dfu = dfu_open(port_spec);
|
FLIP1(pgm)->dfu = dfu_open(port_spec);
|
||||||
return (FLIP1(pgm)->dfu != NULL) ? 0 : -1;
|
return (FLIP1(pgm)->dfu != NULL) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_initialize(PROGRAMMER* pgm, AVRPART *part)
|
int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||||
{
|
|
||||||
unsigned short vid, pid;
|
unsigned short vid, pid;
|
||||||
int result;
|
int result;
|
||||||
struct dfu_dev *dfu = FLIP1(pgm)->dfu;
|
struct dfu_dev *dfu = FLIP1(pgm)->dfu;
|
||||||
|
@ -237,16 +234,13 @@ int flip1_initialize(PROGRAMMER* pgm, AVRPART *part)
|
||||||
if (usbpid) {
|
if (usbpid) {
|
||||||
pid = *(int *)(ldata(usbpid));
|
pid = *(int *)(ldata(usbpid));
|
||||||
if (lnext(usbpid))
|
if (lnext(usbpid))
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: using PID 0x%04x, ignoring remaining PIDs in list\n",
|
pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid);
|
||||||
progname, pid);
|
|
||||||
} else {
|
} else {
|
||||||
pid = part->usbpid;
|
pid = part->usbpid;
|
||||||
}
|
}
|
||||||
if (!ovsigck && (part->flags & AVRPART_HAS_PDI)) {
|
if (!ovsigck && (part->prog_modes & PM_PDI)) {
|
||||||
avrdude_message(MSG_INFO, "%s: \"flip1\" (FLIP protocol version 1) is for AT90USB* and ATmega*U* devices.\n"
|
pmsg_error("flip1 (FLIP protocol version 1) is for AT90USB* and ATmega*U* devices\n");
|
||||||
"%s For Xmega devices, use \"flip2\".\n"
|
imsg_error("for Xmega devices, use flip2 (or use -F to bypass this check)\n");
|
||||||
"%s (Use -F to bypass this check.)\n",
|
|
||||||
progname, progbuf, progbuf);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,32 +252,25 @@ int flip1_initialize(PROGRAMMER* pgm, AVRPART *part)
|
||||||
/* Check if descriptor values are what we expect. */
|
/* Check if descriptor values are what we expect. */
|
||||||
|
|
||||||
if (dfu->dev_desc.idVendor != vid)
|
if (dfu->dev_desc.idVendor != vid)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB idVendor = 0x%04X (expected 0x%04X)\n",
|
pmsg_warning("USB idVendor = 0x%04X (expected 0x%04X)\n", dfu->dev_desc.idVendor, vid);
|
||||||
progname, dfu->dev_desc.idVendor, vid);
|
|
||||||
|
|
||||||
if (pid != 0 && dfu->dev_desc.idProduct != pid)
|
if (pid != 0 && dfu->dev_desc.idProduct != pid)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB idProduct = 0x%04X (expected 0x%04X)\n",
|
pmsg_warning("USB idProduct = 0x%04X (expected 0x%04X)\n", dfu->dev_desc.idProduct, pid);
|
||||||
progname, dfu->dev_desc.idProduct, pid);
|
|
||||||
|
|
||||||
if (dfu->dev_desc.bNumConfigurations != 1)
|
if (dfu->dev_desc.bNumConfigurations != 1)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bNumConfigurations = %d (expected 1)\n",
|
pmsg_warning("USB bNumConfigurations = %d (expected 1)\n", (int) dfu->dev_desc.bNumConfigurations);
|
||||||
progname, (int) dfu->dev_desc.bNumConfigurations);
|
|
||||||
|
|
||||||
if (dfu->conf_desc.bNumInterfaces != 1)
|
if (dfu->conf_desc.bNumInterfaces != 1)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bNumInterfaces = %d (expected 1)\n",
|
pmsg_warning("USB bNumInterfaces = %d (expected 1)\n", (int) dfu->conf_desc.bNumInterfaces);
|
||||||
progname, (int) dfu->conf_desc.bNumInterfaces);
|
|
||||||
|
|
||||||
if (dfu->dev_desc.bDeviceClass != 254)
|
if (dfu->dev_desc.bDeviceClass != 254)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceClass = %d (expected 254)\n",
|
pmsg_warning("USB bDeviceClass = %d (expected 254)\n", (int) dfu->dev_desc.bDeviceClass);
|
||||||
progname, (int) dfu->dev_desc.bDeviceClass);
|
|
||||||
|
|
||||||
if (dfu->dev_desc.bDeviceSubClass != 1)
|
if (dfu->dev_desc.bDeviceSubClass != 1)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceSubClass = %d (expected 1)\n",
|
pmsg_warning("USB bDeviceSubClass = %d (expected 1)\n", (int) dfu->dev_desc.bDeviceSubClass);
|
||||||
progname, (int) dfu->dev_desc.bDeviceSubClass);
|
|
||||||
|
|
||||||
if (dfu->dev_desc.bDeviceProtocol != 0)
|
if (dfu->dev_desc.bDeviceProtocol != 0)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceProtocol = %d (expected 0)\n",
|
pmsg_warning("USB bDeviceProtocol = %d (expected 0)\n", (int) dfu->dev_desc.bDeviceProtocol);
|
||||||
progname, (int) dfu->dev_desc.bDeviceProtocol);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* doc7618 claims an interface class of FEh and a subclas 01h.
|
* doc7618 claims an interface class of FEh and a subclas 01h.
|
||||||
|
@ -293,21 +280,17 @@ int flip1_initialize(PROGRAMMER* pgm, AVRPART *part)
|
||||||
*/
|
*/
|
||||||
if (0) {
|
if (0) {
|
||||||
if (dfu->intf_desc.bInterfaceClass != 254)
|
if (dfu->intf_desc.bInterfaceClass != 254)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceClass = %d (expected 254)\n",
|
pmsg_warning("USB bInterfaceClass = %d (expected 254)\n", (int) dfu->intf_desc.bInterfaceClass);
|
||||||
progname, (int) dfu->intf_desc.bInterfaceClass);
|
|
||||||
|
|
||||||
if (dfu->intf_desc.bInterfaceSubClass != 1)
|
if (dfu->intf_desc.bInterfaceSubClass != 1)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceSubClass = %d (expected 1)\n",
|
pmsg_warning("USB bInterfaceSubClass = %d (expected 1)\n", (int) dfu->intf_desc.bInterfaceSubClass);
|
||||||
progname, (int) dfu->intf_desc.bInterfaceSubClass);
|
|
||||||
|
|
||||||
if (dfu->intf_desc.bInterfaceProtocol != 0)
|
if (dfu->intf_desc.bInterfaceProtocol != 0)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceSubClass = %d (expected 0)\n",
|
pmsg_warning("USB bInterfaceSubClass = %d (expected 0)\n", (int) dfu->intf_desc.bInterfaceProtocol);
|
||||||
progname, (int) dfu->intf_desc.bInterfaceProtocol);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dfu->dev_desc.bMaxPacketSize0 != 32)
|
if (dfu->dev_desc.bMaxPacketSize0 != 32)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: bMaxPacketSize0 (%d) != 32, things might go wrong\n",
|
pmsg_warning("bMaxPacketSize0 (%d) != 32, things might go wrong\n", dfu->dev_desc.bMaxPacketSize0);
|
||||||
progname, dfu->dev_desc.bMaxPacketSize0);
|
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
flip1_show_info(FLIP1(pgm));
|
flip1_show_info(FLIP1(pgm));
|
||||||
|
@ -322,31 +305,26 @@ flip1_initialize_fail:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip1_close(PROGRAMMER* pgm)
|
void flip1_close(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
if (FLIP1(pgm)->dfu != NULL) {
|
if (FLIP1(pgm)->dfu != NULL) {
|
||||||
dfu_close(FLIP1(pgm)->dfu);
|
dfu_close(FLIP1(pgm)->dfu);
|
||||||
FLIP1(pgm)->dfu = NULL;
|
FLIP1(pgm)->dfu = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip1_enable(PROGRAMMER* pgm)
|
void flip1_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip1_disable(PROGRAMMER* pgm)
|
void flip1_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip1_display(PROGRAMMER* pgm, const char *prefix)
|
void flip1_display(const PROGRAMMER *pgm, const char *prefix) {
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_program_enable(PROGRAMMER* pgm, AVRPART *part)
|
int flip1_program_enable(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||||
{
|
|
||||||
/* I couldn't find anything that uses this function, although it is marked
|
/* I couldn't find anything that uses this function, although it is marked
|
||||||
* as "mandatory" in pgm.c. In case anyone does use it, we'll report an
|
* as "mandatory" in pgm.c. In case anyone does use it, we'll report an
|
||||||
* error if we failed to initialize.
|
* error if we failed to initialize.
|
||||||
|
@ -355,14 +333,13 @@ int flip1_program_enable(PROGRAMMER* pgm, AVRPART *part)
|
||||||
return (FLIP1(pgm)->dfu != NULL) ? 0 : -1;
|
return (FLIP1(pgm)->dfu != NULL) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_chip_erase(PROGRAMMER* pgm, AVRPART *part)
|
int flip1_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||||
{
|
|
||||||
struct dfu_status status;
|
struct dfu_status status;
|
||||||
int cmd_result = 0;
|
int cmd_result = 0;
|
||||||
int aux_result;
|
int aux_result;
|
||||||
unsigned int default_timeout = FLIP1(pgm)->dfu->timeout;
|
unsigned int default_timeout = FLIP1(pgm)->dfu->timeout;
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: flip_chip_erase()\n", progname);
|
pmsg_notice2("flip_chip_erase()\n");
|
||||||
|
|
||||||
struct flip1_cmd cmd = {
|
struct flip1_cmd cmd = {
|
||||||
FLIP1_CMD_WRITE_COMMAND, { 0, 0xff }
|
FLIP1_CMD_WRITE_COMMAND, { 0, 0xff }
|
||||||
|
@ -377,8 +354,7 @@ int flip1_chip_erase(PROGRAMMER* pgm, AVRPART *part)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (status.bStatus != DFU_STATUS_OK) {
|
if (status.bStatus != DFU_STATUS_OK) {
|
||||||
avrdude_message(MSG_INFO, "%s: failed to send chip erase command: %s\n",
|
pmsg_error("unable to send chip erase command: %s\n", flip1_status_str(&status));
|
||||||
progname, flip1_status_str(&status));
|
|
||||||
if (status.bState == STATE_dfuERROR)
|
if (status.bState == STATE_dfuERROR)
|
||||||
dfu_clrstatus(FLIP1(pgm)->dfu);
|
dfu_clrstatus(FLIP1(pgm)->dfu);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -387,7 +363,7 @@ int flip1_chip_erase(PROGRAMMER* pgm, AVRPART *part)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip1_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char *value)
|
unsigned long addr, unsigned char *value)
|
||||||
{
|
{
|
||||||
enum flip1_mem_unit mem_unit;
|
enum flip1_mem_unit mem_unit;
|
||||||
|
@ -395,12 +371,11 @@ int flip1_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
if (FLIP1(pgm)->dfu == NULL)
|
if (FLIP1(pgm)->dfu == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (strcasecmp(mem->desc, "signature") == 0) {
|
if (strcmp(mem->desc, "signature") == 0) {
|
||||||
if (flip1_read_sig_bytes(pgm, part, mem) < 0)
|
if (flip1_read_sig_bytes(pgm, part, mem) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (addr > mem->size) {
|
if (addr >= mem->size) {
|
||||||
avrdude_message(MSG_INFO, "%s: flip1_read_byte(signature): address %lu out of range\n",
|
pmsg_error("signature address %lu out of range [0, %d]\n", addr, mem->size-1);
|
||||||
progname, addr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*value = mem->buf[addr];
|
*value = mem->buf[addr];
|
||||||
|
@ -410,10 +385,7 @@ int flip1_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
mem_unit = flip1_mem_unit(mem->desc);
|
mem_unit = flip1_mem_unit(mem->desc);
|
||||||
|
|
||||||
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
|
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: "
|
pmsg_error("%s memory not accessible using FLIP\n", mem->desc);
|
||||||
"\"%s\" memory not accessible using FLIP",
|
|
||||||
progname, mem->desc);
|
|
||||||
avrdude_message(MSG_INFO, "\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -424,7 +396,7 @@ int flip1_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
return flip1_read_memory(pgm, mem_unit, addr, value, 1);
|
return flip1_read_memory(pgm, mem_unit, addr, value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip1_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char value)
|
unsigned long addr, unsigned char value)
|
||||||
{
|
{
|
||||||
enum flip1_mem_unit mem_unit;
|
enum flip1_mem_unit mem_unit;
|
||||||
|
@ -435,17 +407,14 @@ int flip1_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
mem_unit = flip1_mem_unit(mem->desc);
|
mem_unit = flip1_mem_unit(mem->desc);
|
||||||
|
|
||||||
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
|
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: "
|
pmsg_error("%s memory not accessible using FLIP\n", mem->desc);
|
||||||
"\"%s\" memory not accessible using FLIP",
|
|
||||||
progname, mem->desc);
|
|
||||||
avrdude_message(MSG_INFO, "\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flip1_write_memory(FLIP1(pgm)->dfu, mem_unit, addr, &value, 1);
|
return flip1_write_memory(FLIP1(pgm)->dfu, mem_unit, addr, &value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip1_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
enum flip1_mem_unit mem_unit;
|
enum flip1_mem_unit mem_unit;
|
||||||
|
@ -456,10 +425,7 @@ int flip1_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
mem_unit = flip1_mem_unit(mem->desc);
|
mem_unit = flip1_mem_unit(mem->desc);
|
||||||
|
|
||||||
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
|
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: "
|
pmsg_error("%s memory not accessible using FLIP\n", mem->desc);
|
||||||
"\"%s\" memory not accessible using FLIP",
|
|
||||||
progname, mem->desc);
|
|
||||||
avrdude_message(MSG_INFO, "\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +436,7 @@ int flip1_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
return flip1_read_memory(pgm, mem_unit, addr, mem->buf + addr, n_bytes);
|
return flip1_read_memory(pgm, mem_unit, addr, mem->buf + addr, n_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip1_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
enum flip1_mem_unit mem_unit;
|
enum flip1_mem_unit mem_unit;
|
||||||
|
@ -482,17 +448,13 @@ int flip1_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
mem_unit = flip1_mem_unit(mem->desc);
|
mem_unit = flip1_mem_unit(mem->desc);
|
||||||
|
|
||||||
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
|
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: "
|
pmsg_error("%s memory not accessible using FLIP\n", mem->desc);
|
||||||
"\"%s\" memory not accessible using FLIP",
|
|
||||||
progname, mem->desc);
|
|
||||||
avrdude_message(MSG_INFO, "\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_bytes > INT_MAX) {
|
if (n_bytes > INT_MAX) {
|
||||||
/* This should never happen, unless the int type is only 16 bits. */
|
/* This should never happen, unless the int type is only 16 bits. */
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Attempting to read more than %d bytes\n",
|
pmsg_error("attempting to read more than %d bytes\n", INT_MAX);
|
||||||
progname, INT_MAX);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,16 +464,14 @@ int flip1_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
return (result == 0) ? n_bytes : -1;
|
return (result == 0) ? n_bytes : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
|
int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem) {
|
||||||
{
|
pmsg_notice2("flip1_read_sig_bytes(): ");
|
||||||
avrdude_message(MSG_NOTICE2, "%s: flip1_read_sig_bytes(): ", progname);
|
|
||||||
|
|
||||||
if (FLIP1(pgm)->dfu == NULL)
|
if (FLIP1(pgm)->dfu == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (mem->size < sizeof(FLIP1(pgm)->part_sig)) {
|
if (mem->size < sizeof(FLIP1(pgm)->part_sig)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Signature read must be at least %u bytes\n",
|
pmsg_error("signature read must be at least %u bytes\n", (unsigned int) sizeof(FLIP1(pgm)->part_sig));
|
||||||
progname, (unsigned int) sizeof(FLIP1(pgm)->part_sig));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,7 +488,7 @@ int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
|
||||||
FLIP1_CMD_READ_COMMAND, FLIP1_READ_FAMILY_CODE
|
FLIP1_CMD_READ_COMMAND, FLIP1_READ_FAMILY_CODE
|
||||||
};
|
};
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "from device\n");
|
msg_notice2("from device\n");
|
||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
|
@ -545,8 +505,7 @@ int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
|
||||||
|
|
||||||
if (status.bStatus != DFU_STATUS_OK)
|
if (status.bStatus != DFU_STATUS_OK)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: failed to send cmd for signature byte %d: %s\n",
|
pmsg_error("unable to send cmd for signature byte %d: %s\n", i, flip1_status_str(&status));
|
||||||
progname, i, flip1_status_str(&status));
|
|
||||||
if (status.bState == STATE_dfuERROR)
|
if (status.bState == STATE_dfuERROR)
|
||||||
dfu_clrstatus(FLIP1(pgm)->dfu);
|
dfu_clrstatus(FLIP1(pgm)->dfu);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -560,8 +519,7 @@ int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
|
||||||
|
|
||||||
if (status.bStatus != DFU_STATUS_OK)
|
if (status.bStatus != DFU_STATUS_OK)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: failed to read signature byte %d: %s\n",
|
pmsg_error("unable to read signature byte %d: %s\n", i, flip1_status_str(&status));
|
||||||
progname, i, flip1_status_str(&status));
|
|
||||||
if (status.bState == STATE_dfuERROR)
|
if (status.bState == STATE_dfuERROR)
|
||||||
dfu_clrstatus(FLIP1(pgm)->dfu);
|
dfu_clrstatus(FLIP1(pgm)->dfu);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -570,7 +528,7 @@ int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE2, "cached\n");
|
msg_notice2("cached\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(mem->buf, FLIP1(pgm)->part_sig, sizeof(FLIP1(pgm)->part_sig));
|
memcpy(mem->buf, FLIP1(pgm)->part_sig, sizeof(FLIP1(pgm)->part_sig));
|
||||||
|
@ -583,8 +541,7 @@ void flip1_setup(PROGRAMMER * pgm)
|
||||||
pgm->cookie = calloc(1, sizeof(struct flip1));
|
pgm->cookie = calloc(1, sizeof(struct flip1));
|
||||||
|
|
||||||
if (pgm->cookie == NULL) {
|
if (pgm->cookie == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: Out of memory allocating private data structure\n",
|
pmsg_error("out of memory allocating private data structure\n");
|
||||||
progname);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -601,11 +558,10 @@ void flip1_teardown(PROGRAMMER * pgm)
|
||||||
void flip1_show_info(struct flip1 *flip1)
|
void flip1_show_info(struct flip1 *flip1)
|
||||||
{
|
{
|
||||||
dfu_show_info(flip1->dfu);
|
dfu_show_info(flip1->dfu);
|
||||||
avrdude_message(MSG_INFO, " USB max packet size : %hu\n",
|
msg_info(" USB max packet size : %hu\n", (unsigned short) flip1->dfu->dev_desc.bMaxPacketSize0);
|
||||||
(unsigned short) flip1->dfu->dev_desc.bMaxPacketSize0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_read_memory(PROGRAMMER * pgm,
|
int flip1_read_memory(const PROGRAMMER *pgm,
|
||||||
enum flip1_mem_unit mem_unit, uint32_t addr, void *ptr, int size)
|
enum flip1_mem_unit mem_unit, uint32_t addr, void *ptr, int size)
|
||||||
{
|
{
|
||||||
struct dfu_dev *dfu = FLIP1(pgm)->dfu;
|
struct dfu_dev *dfu = FLIP1(pgm)->dfu;
|
||||||
|
@ -619,8 +575,7 @@ int flip1_read_memory(PROGRAMMER * pgm,
|
||||||
unsigned int default_timeout = dfu->timeout;
|
unsigned int default_timeout = dfu->timeout;
|
||||||
|
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: flip_read_memory(%s, 0x%04x, %d)\n",
|
pmsg_notice2("flip_read_memory(%s, 0x%04x, %d)\n", flip1_mem_unit_str(mem_unit), addr, size);
|
||||||
progname, flip1_mem_unit_str(mem_unit), addr, size);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* As this function is called once per page, no need to handle 64
|
* As this function is called once per page, no need to handle 64
|
||||||
|
@ -650,9 +605,8 @@ int flip1_read_memory(PROGRAMMER * pgm,
|
||||||
|
|
||||||
if (status.bStatus != DFU_STATUS_OK)
|
if (status.bStatus != DFU_STATUS_OK)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: failed to read %u bytes of %s memory @%u: %s\n",
|
pmsg_error("unable to read %u bytes of %s memory @%u: %s\n", size,
|
||||||
progname, size, flip1_mem_unit_str(mem_unit), addr,
|
flip1_mem_unit_str(mem_unit), addr, flip1_status_str(&status));
|
||||||
flip1_status_str(&status));
|
|
||||||
if (status.bState == STATE_dfuERROR)
|
if (status.bState == STATE_dfuERROR)
|
||||||
dfu_clrstatus(dfu);
|
dfu_clrstatus(dfu);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -663,13 +617,14 @@ int flip1_read_memory(PROGRAMMER * pgm,
|
||||||
|
|
||||||
if (cmd_result < 0 && aux_result == 0 &&
|
if (cmd_result < 0 && aux_result == 0 &&
|
||||||
status.bStatus == DFU_STATUS_ERR_WRITE) {
|
status.bStatus == DFU_STATUS_ERR_WRITE) {
|
||||||
if (FLIP1(pgm)->security_mode_flag == 0)
|
if (FLIP1(pgm)->security_mode_flag == 0) {
|
||||||
avrdude_message(MSG_INFO, "\n%s:\n"
|
msg_error("\n");
|
||||||
"%s***********************************************************************\n"
|
pmsg_error("\n");
|
||||||
"%sMaybe the device is in ``security mode´´, and needs a chip erase first?\n"
|
imsg_error("***********************************************************************\n");
|
||||||
"%s***********************************************************************\n"
|
imsg_error("Maybe the device is in ``security mode´´, and needs a chip erase first?\n");
|
||||||
"\n",
|
imsg_error("***********************************************************************\n");
|
||||||
progname, progbuf, progbuf, progbuf);
|
msg_error("\n");
|
||||||
|
}
|
||||||
FLIP1(pgm)->security_mode_flag = 1;
|
FLIP1(pgm)->security_mode_flag = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -678,9 +633,8 @@ int flip1_read_memory(PROGRAMMER * pgm,
|
||||||
|
|
||||||
if (status.bStatus != DFU_STATUS_OK)
|
if (status.bStatus != DFU_STATUS_OK)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: failed to read %u bytes of %s memory @%u: %s\n",
|
pmsg_error("unable to read %u bytes of %s memory @%u: %s\n", size,
|
||||||
progname, size, flip1_mem_unit_str(mem_unit), addr,
|
flip1_mem_unit_str(mem_unit), addr, flip1_status_str(&status));
|
||||||
flip1_status_str(&status));
|
|
||||||
if (status.bState == STATE_dfuERROR)
|
if (status.bState == STATE_dfuERROR)
|
||||||
dfu_clrstatus(dfu);
|
dfu_clrstatus(dfu);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -712,14 +666,14 @@ int flip1_write_memory(struct dfu_dev *dfu,
|
||||||
unsigned int default_timeout = dfu->timeout;
|
unsigned int default_timeout = dfu->timeout;
|
||||||
unsigned char *buf;
|
unsigned char *buf;
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: flip_write_memory(%s, 0x%04x, %d)\n",
|
pmsg_notice2("flip_write_memory(%s, 0x%04x, %d)\n",
|
||||||
progname, flip1_mem_unit_str(mem_unit), addr, size);
|
flip1_mem_unit_str(mem_unit), addr, size);
|
||||||
|
|
||||||
if (size < 32) {
|
if (size < 32) {
|
||||||
/* presumably single-byte updates; must be padded to USB endpoint size */
|
/* presumably single-byte updates; must be padded to USB endpoint size */
|
||||||
if ((addr + size - 1) / 32 != addr / 32) {
|
if ((addr + size - 1) / 32 != addr / 32) {
|
||||||
avrdude_message(MSG_INFO, "%s: flip_write_memory(): begin (0x%x) and end (0x%x) not within same 32-byte block\n",
|
pmsg_error("begin 0x%x and end 0x%x not within same 32-byte block\n",
|
||||||
progname, addr, addr + size - 1);
|
addr, addr + size - 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
write_size = 32;
|
write_size = 32;
|
||||||
|
@ -730,7 +684,7 @@ int flip1_write_memory(struct dfu_dev *dfu,
|
||||||
if ((buf = malloc(sizeof(struct flip1_cmd_header) +
|
if ((buf = malloc(sizeof(struct flip1_cmd_header) +
|
||||||
write_size +
|
write_size +
|
||||||
sizeof(struct flip1_prog_footer))) == 0) {
|
sizeof(struct flip1_prog_footer))) == 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Out of memory\n", progname);
|
pmsg_error("out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,9 +733,8 @@ int flip1_write_memory(struct dfu_dev *dfu,
|
||||||
|
|
||||||
if (status.bStatus != DFU_STATUS_OK)
|
if (status.bStatus != DFU_STATUS_OK)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: failed to write %u bytes of %s memory @%u: %s\n",
|
pmsg_error("unable to write %u bytes of %s memory @%u: %s\n", size,
|
||||||
progname, size, flip1_mem_unit_str(mem_unit), addr,
|
flip1_mem_unit_str(mem_unit), addr, flip1_status_str(&status));
|
||||||
flip1_status_str(&status));
|
|
||||||
if (status.bState == STATE_dfuERROR)
|
if (status.bState == STATE_dfuERROR)
|
||||||
dfu_clrstatus(dfu);
|
dfu_clrstatus(dfu);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -810,8 +763,7 @@ int flip1_set_mem_page(struct dfu_dev *dfu,
|
||||||
|
|
||||||
if (status.bStatus != DFU_STATUS_OK)
|
if (status.bStatus != DFU_STATUS_OK)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: failed to set memory page: %s\n",
|
pmsg_error("unable to set memory page: %s\n", flip1_status_str(&status));
|
||||||
progname, flip1_status_str(&status));
|
|
||||||
if (status.bState == STATE_dfuERROR)
|
if (status.bState == STATE_dfuERROR)
|
||||||
dfu_clrstatus(dfu);
|
dfu_clrstatus(dfu);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -856,23 +808,20 @@ const char * flip1_mem_unit_str(enum flip1_mem_unit mem_unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum flip1_mem_unit flip1_mem_unit(const char *name) {
|
enum flip1_mem_unit flip1_mem_unit(const char *name) {
|
||||||
if (strcasecmp(name, "flash") == 0)
|
if (strcmp(name, "flash") == 0)
|
||||||
return FLIP1_MEM_UNIT_FLASH;
|
return FLIP1_MEM_UNIT_FLASH;
|
||||||
if (strcasecmp(name, "eeprom") == 0)
|
if (strcmp(name, "eeprom") == 0)
|
||||||
return FLIP1_MEM_UNIT_EEPROM;
|
return FLIP1_MEM_UNIT_EEPROM;
|
||||||
return FLIP1_MEM_UNIT_UNKNOWN;
|
return FLIP1_MEM_UNIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
#else /* HAVE_LIBUSB */
|
#else /* HAVE_LIBUSB */
|
||||||
// Dummy functions
|
// Dummy functions
|
||||||
int flip1_open(PROGRAMMER *pgm, char *port_spec)
|
int flip1_open(PROGRAMMER *pgm, const char *port_spec) {
|
||||||
{
|
pmsg_error("no USB support compiled for avrdude\n");
|
||||||
fprintf(stderr, "%s: Error: No USB support in this compile of avrdude\n",
|
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_initialize(PROGRAMMER* pgm, AVRPART *part)
|
int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -880,54 +829,48 @@ void flip1_close(PROGRAMMER* pgm)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip1_enable(PROGRAMMER* pgm)
|
void flip1_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip1_disable(PROGRAMMER* pgm)
|
void flip1_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip1_display(PROGRAMMER* pgm, const char *prefix)
|
void flip1_display(const PROGRAMMER *pgm, const char *prefix) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_program_enable(PROGRAMMER* pgm, AVRPART *part)
|
int flip1_program_enable(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_chip_erase(PROGRAMMER* pgm, AVRPART *part)
|
int flip1_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip1_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char *value)
|
unsigned long addr, unsigned char *value)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip1_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char value)
|
unsigned long addr, unsigned char value)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip1_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip1_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
|
int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem) {
|
||||||
{
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char flip1_desc[];
|
extern const char flip1_desc[];
|
||||||
extern void flip1_initpgm(PROGRAMMER * pgm);
|
extern void flip1_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
378
src/flip2.c
378
src/flip2.c
|
@ -121,31 +121,33 @@ enum flip2_mem_unit {
|
||||||
FLIP2_MEM_UNIT_EXT_MEM_DF = 0x10
|
FLIP2_MEM_UNIT_EXT_MEM_DF = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBUSB
|
||||||
|
|
||||||
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
|
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
|
||||||
|
|
||||||
static int flip2_open(PROGRAMMER *pgm, char *port_spec);
|
static int flip2_open(PROGRAMMER *pgm, const char *port_spec);
|
||||||
static int flip2_initialize(PROGRAMMER* pgm, AVRPART *part);
|
static int flip2_initialize(const PROGRAMMER *pgm, const AVRPART *part);
|
||||||
static void flip2_close(PROGRAMMER* pgm);
|
static void flip2_close(PROGRAMMER* pgm);
|
||||||
static void flip2_enable(PROGRAMMER* pgm);
|
static void flip2_enable(PROGRAMMER *pgm, const AVRPART *p);
|
||||||
static void flip2_disable(PROGRAMMER* pgm);
|
static void flip2_disable(const PROGRAMMER *pgm);
|
||||||
static void flip2_display(PROGRAMMER* pgm, const char *prefix);
|
static void flip2_display(const PROGRAMMER *pgm, const char *prefix);
|
||||||
static int flip2_program_enable(PROGRAMMER* pgm, AVRPART *part);
|
static int flip2_program_enable(const PROGRAMMER *pgm, const AVRPART *part);
|
||||||
static int flip2_chip_erase(PROGRAMMER* pgm, AVRPART *part);
|
static int flip2_chip_erase(const PROGRAMMER *pgm, const AVRPART *part);
|
||||||
static int flip2_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
static int flip2_start_app(const PROGRAMMER *pgm);
|
||||||
|
static int flip2_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char *value);
|
unsigned long addr, unsigned char *value);
|
||||||
static int flip2_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
static int flip2_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char value);
|
unsigned long addr, unsigned char value);
|
||||||
static int flip2_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
static int flip2_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
|
||||||
static int flip2_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
static int flip2_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
|
||||||
static int flip2_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem);
|
static int flip2_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem);
|
||||||
|
static int flip2_parseexitspecs(PROGRAMMER* pgm, const char *s);
|
||||||
static void flip2_setup(PROGRAMMER * pgm);
|
static void flip2_setup(PROGRAMMER * pgm);
|
||||||
static void flip2_teardown(PROGRAMMER * pgm);
|
static void flip2_teardown(PROGRAMMER * pgm);
|
||||||
|
|
||||||
/* INTERNAL PROGRAMMER FUNCTION PROTOTYPES */
|
/* INTERNAL PROGRAMMER FUNCTION PROTOTYPES */
|
||||||
#ifdef HAVE_LIBUSB
|
|
||||||
// The internal ones are made conditional, as they're not defined further down #ifndef HAVE_LIBUSB
|
|
||||||
|
|
||||||
static void flip2_show_info(struct flip2 *flip2);
|
static void flip2_show_info(struct flip2 *flip2);
|
||||||
|
|
||||||
|
@ -166,12 +168,7 @@ static const char * flip2_status_str(const struct dfu_status *status);
|
||||||
static const char * flip2_mem_unit_str(enum flip2_mem_unit mem_unit);
|
static const char * flip2_mem_unit_str(enum flip2_mem_unit mem_unit);
|
||||||
static enum flip2_mem_unit flip2_mem_unit(const char *name);
|
static enum flip2_mem_unit flip2_mem_unit(const char *name);
|
||||||
|
|
||||||
#endif /* HAVE_LIBUSB */
|
void flip2_initpgm(PROGRAMMER *pgm) {
|
||||||
|
|
||||||
/* THE INITPGM FUNCTION DEFINITIONS */
|
|
||||||
|
|
||||||
void flip2_initpgm(PROGRAMMER *pgm)
|
|
||||||
{
|
|
||||||
strcpy(pgm->type, "flip2");
|
strcpy(pgm->type, "flip2");
|
||||||
|
|
||||||
/* Mandatory Functions */
|
/* Mandatory Functions */
|
||||||
|
@ -188,21 +185,19 @@ void flip2_initpgm(PROGRAMMER *pgm)
|
||||||
pgm->read_byte = flip2_read_byte;
|
pgm->read_byte = flip2_read_byte;
|
||||||
pgm->write_byte = flip2_write_byte;
|
pgm->write_byte = flip2_write_byte;
|
||||||
pgm->read_sig_bytes = flip2_read_sig_bytes;
|
pgm->read_sig_bytes = flip2_read_sig_bytes;
|
||||||
|
pgm->parseexitspecs = flip2_parseexitspecs;
|
||||||
pgm->setup = flip2_setup;
|
pgm->setup = flip2_setup;
|
||||||
pgm->teardown = flip2_teardown;
|
pgm->teardown = flip2_teardown;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LIBUSB
|
|
||||||
/* EXPORTED PROGRAMMER FUNCTION DEFINITIONS */
|
/* EXPORTED PROGRAMMER FUNCTION DEFINITIONS */
|
||||||
|
|
||||||
int flip2_open(PROGRAMMER *pgm, char *port_spec)
|
int flip2_open(PROGRAMMER *pgm, const char *port_spec) {
|
||||||
{
|
|
||||||
FLIP2(pgm)->dfu = dfu_open(port_spec);
|
FLIP2(pgm)->dfu = dfu_open(port_spec);
|
||||||
return (FLIP2(pgm)->dfu != NULL) ? 0 : -1;
|
return (FLIP2(pgm)->dfu != NULL) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip2_initialize(PROGRAMMER* pgm, AVRPART *part)
|
int flip2_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||||
{
|
|
||||||
unsigned short vid, pid;
|
unsigned short vid, pid;
|
||||||
int result;
|
int result;
|
||||||
struct dfu_dev *dfu = FLIP2(pgm)->dfu;
|
struct dfu_dev *dfu = FLIP2(pgm)->dfu;
|
||||||
|
@ -231,17 +226,15 @@ int flip2_initialize(PROGRAMMER* pgm, AVRPART *part)
|
||||||
if (usbpid) {
|
if (usbpid) {
|
||||||
pid = *(int *)(ldata(usbpid));
|
pid = *(int *)(ldata(usbpid));
|
||||||
if (lnext(usbpid))
|
if (lnext(usbpid))
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: using PID 0x%04x, ignoring remaining PIDs in list\n",
|
pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid);
|
||||||
progname, pid);
|
|
||||||
} else {
|
} else {
|
||||||
pid = part->usbpid;
|
pid = part->usbpid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ovsigck && !(part->flags & AVRPART_HAS_PDI)) {
|
if (!ovsigck && !(part->prog_modes & PM_PDI)) {
|
||||||
avrdude_message(MSG_INFO, "%s: \"flip2\" (FLIP protocol version 2) is for Xmega devices.\n"
|
pmsg_error("flip2 (FLIP protocol version 2) is for Xmega devices\n");
|
||||||
"%s For AT90USB* or ATmega*U* devices, use \"flip1\".\n"
|
imsg_error("for AT90USB* or ATmega*U* devices, use flip1\n");
|
||||||
"%s (Use -F to bypass this check.)\n",
|
imsg_error("(or use -F to bypass this check)\n");
|
||||||
progname, progbuf, progbuf);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,44 +246,44 @@ int flip2_initialize(PROGRAMMER* pgm, AVRPART *part)
|
||||||
/* Check if descriptor values are what we expect. */
|
/* Check if descriptor values are what we expect. */
|
||||||
|
|
||||||
if (dfu->dev_desc.idVendor != vid)
|
if (dfu->dev_desc.idVendor != vid)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB idVendor = 0x%04X (expected 0x%04X)\n",
|
pmsg_warning("USB idVendor = 0x%04X (expected 0x%04X)\n",
|
||||||
progname, dfu->dev_desc.idVendor, vid);
|
dfu->dev_desc.idVendor, vid);
|
||||||
|
|
||||||
if (pid != 0 && dfu->dev_desc.idProduct != pid)
|
if (pid != 0 && dfu->dev_desc.idProduct != pid)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB idProduct = 0x%04X (expected 0x%04X)\n",
|
pmsg_warning("USB idProduct = 0x%04X (expected 0x%04X)\n",
|
||||||
progname, dfu->dev_desc.idProduct, pid);
|
dfu->dev_desc.idProduct, pid);
|
||||||
|
|
||||||
if (dfu->dev_desc.bNumConfigurations != 1)
|
if (dfu->dev_desc.bNumConfigurations != 1)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bNumConfigurations = %d (expected 1)\n",
|
pmsg_error("USB bNumConfigurations = %d (expected 1)\n",
|
||||||
progname, (int) dfu->dev_desc.bNumConfigurations);
|
(int) dfu->dev_desc.bNumConfigurations);
|
||||||
|
|
||||||
if (dfu->conf_desc.bNumInterfaces != 1)
|
if (dfu->conf_desc.bNumInterfaces != 1)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bNumInterfaces = %d (expected 1)\n",
|
pmsg_error("USB bNumInterfaces = %d (expected 1)\n",
|
||||||
progname, (int) dfu->conf_desc.bNumInterfaces);
|
(int) dfu->conf_desc.bNumInterfaces);
|
||||||
|
|
||||||
if (dfu->dev_desc.bDeviceClass != 0)
|
if (dfu->dev_desc.bDeviceClass != 0)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceClass = %d (expected 0)\n",
|
pmsg_error("USB bDeviceClass = %d (expected 0)\n",
|
||||||
progname, (int) dfu->dev_desc.bDeviceClass);
|
(int) dfu->dev_desc.bDeviceClass);
|
||||||
|
|
||||||
if (dfu->dev_desc.bDeviceSubClass != 0)
|
if (dfu->dev_desc.bDeviceSubClass != 0)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceSubClass = %d (expected 0)\n",
|
pmsg_error("USB bDeviceSubClass = %d (expected 0)\n",
|
||||||
progname, (int) dfu->dev_desc.bDeviceSubClass);
|
(int) dfu->dev_desc.bDeviceSubClass);
|
||||||
|
|
||||||
if (dfu->dev_desc.bDeviceProtocol != 0)
|
if (dfu->dev_desc.bDeviceProtocol != 0)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceProtocol = %d (expected 0)\n",
|
pmsg_error("USB bDeviceProtocol = %d (expected 0)\n",
|
||||||
progname, (int) dfu->dev_desc.bDeviceProtocol);
|
(int) dfu->dev_desc.bDeviceProtocol);
|
||||||
|
|
||||||
if (dfu->intf_desc.bInterfaceClass != 0xFF)
|
if (dfu->intf_desc.bInterfaceClass != 0xFF)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceClass = %d (expected 255)\n",
|
pmsg_error("USB bInterfaceClass = %d (expected 255)\n",
|
||||||
progname, (int) dfu->intf_desc.bInterfaceClass);
|
(int) dfu->intf_desc.bInterfaceClass);
|
||||||
|
|
||||||
if (dfu->intf_desc.bInterfaceSubClass != 0)
|
if (dfu->intf_desc.bInterfaceSubClass != 0)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceSubClass = %d (expected 0)\n",
|
pmsg_error("USB bInterfaceSubClass = %d (expected 0)\n",
|
||||||
progname, (int) dfu->intf_desc.bInterfaceSubClass);
|
(int) dfu->intf_desc.bInterfaceSubClass);
|
||||||
|
|
||||||
if (dfu->intf_desc.bInterfaceProtocol != 0)
|
if (dfu->intf_desc.bInterfaceProtocol != 0)
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceSubClass = %d (expected 0)\n",
|
pmsg_error("USB bInterfaceSubClass = %d (expected 0)\n",
|
||||||
progname, (int) dfu->intf_desc.bInterfaceProtocol);
|
(int) dfu->intf_desc.bInterfaceProtocol);
|
||||||
|
|
||||||
result = flip2_read_memory(FLIP2(pgm)->dfu,
|
result = flip2_read_memory(FLIP2(pgm)->dfu,
|
||||||
FLIP2_MEM_UNIT_SIGNATURE, 0, FLIP2(pgm)->part_sig, 4);
|
FLIP2_MEM_UNIT_SIGNATURE, 0, FLIP2(pgm)->part_sig, 4);
|
||||||
|
@ -318,28 +311,27 @@ flip2_initialize_fail:
|
||||||
void flip2_close(PROGRAMMER* pgm)
|
void flip2_close(PROGRAMMER* pgm)
|
||||||
{
|
{
|
||||||
if (FLIP2(pgm)->dfu != NULL) {
|
if (FLIP2(pgm)->dfu != NULL) {
|
||||||
|
if (pgm->exit_reset == EXIT_RESET_ENABLED)
|
||||||
|
flip2_start_app(pgm);
|
||||||
|
|
||||||
dfu_close(FLIP2(pgm)->dfu);
|
dfu_close(FLIP2(pgm)->dfu);
|
||||||
FLIP2(pgm)->dfu = NULL;
|
FLIP2(pgm)->dfu = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip2_enable(PROGRAMMER* pgm)
|
void flip2_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip2_disable(PROGRAMMER* pgm)
|
void flip2_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip2_display(PROGRAMMER* pgm, const char *prefix)
|
void flip2_display(const PROGRAMMER *pgm, const char *prefix) {
|
||||||
{
|
|
||||||
/* Nothing to do. */
|
/* Nothing to do. */
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip2_program_enable(PROGRAMMER* pgm, AVRPART *part)
|
int flip2_program_enable(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||||
{
|
|
||||||
/* I couldn't find anything that uses this function, although it is marked
|
/* I couldn't find anything that uses this function, although it is marked
|
||||||
* as "mandatory" in pgm.c. In case anyone does use it, we'll report an
|
* as "mandatory" in pgm.c. In case anyone does use it, we'll report an
|
||||||
* error if we failed to initialize.
|
* error if we failed to initialize.
|
||||||
|
@ -348,13 +340,12 @@ int flip2_program_enable(PROGRAMMER* pgm, AVRPART *part)
|
||||||
return (FLIP2(pgm)->dfu != NULL) ? 0 : -1;
|
return (FLIP2(pgm)->dfu != NULL) ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip2_chip_erase(PROGRAMMER* pgm, AVRPART *part)
|
int flip2_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
|
||||||
{
|
|
||||||
struct dfu_status status;
|
struct dfu_status status;
|
||||||
int cmd_result = 0;
|
int cmd_result = 0;
|
||||||
int aux_result;
|
int aux_result;
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: flip_chip_erase()\n", progname);
|
pmsg_notice2("flip_chip_erase()\n");
|
||||||
|
|
||||||
struct flip2_cmd cmd = {
|
struct flip2_cmd cmd = {
|
||||||
FLIP2_CMD_GROUP_EXEC, FLIP2_CMD_CHIP_ERASE, { 0xFF, 0, 0, 0 }
|
FLIP2_CMD_GROUP_EXEC, FLIP2_CMD_CHIP_ERASE, { 0xFF, 0, 0, 0 }
|
||||||
|
@ -372,9 +363,8 @@ int flip2_chip_erase(PROGRAMMER* pgm, AVRPART *part)
|
||||||
status.bState == ((FLIP2_STATUS_ERASE_ONGOING >> 0) & 0xFF))
|
status.bState == ((FLIP2_STATUS_ERASE_ONGOING >> 0) & 0xFF))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
} else
|
}
|
||||||
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
|
pmsg_error("DFU status %s\n", flip2_status_str(&status));
|
||||||
flip2_status_str(&status));
|
|
||||||
dfu_clrstatus(FLIP2(pgm)->dfu);
|
dfu_clrstatus(FLIP2(pgm)->dfu);
|
||||||
} else
|
} else
|
||||||
break;
|
break;
|
||||||
|
@ -383,7 +373,23 @@ int flip2_chip_erase(PROGRAMMER* pgm, AVRPART *part)
|
||||||
return cmd_result;
|
return cmd_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip2_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip2_start_app(const PROGRAMMER *pgm) {
|
||||||
|
pmsg_info("starting application\n");
|
||||||
|
|
||||||
|
struct flip2_cmd cmd = {
|
||||||
|
FLIP2_CMD_GROUP_EXEC, FLIP2_CMD_START_APP, { 0x00, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// queue command
|
||||||
|
int cmd_result = dfu_dnload(FLIP2(pgm)->dfu, &cmd, sizeof(cmd));
|
||||||
|
|
||||||
|
// repeat dnload to actually execute
|
||||||
|
dfu_dnload(FLIP2(pgm)->dfu, &cmd, sizeof(cmd));
|
||||||
|
|
||||||
|
return cmd_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flip2_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char *value)
|
unsigned long addr, unsigned char *value)
|
||||||
{
|
{
|
||||||
enum flip2_mem_unit mem_unit;
|
enum flip2_mem_unit mem_unit;
|
||||||
|
@ -394,19 +400,17 @@ int flip2_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
mem_unit = flip2_mem_unit(mem->desc);
|
mem_unit = flip2_mem_unit(mem->desc);
|
||||||
|
|
||||||
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
|
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: "
|
pmsg_error("%s memory not accessible using FLIP", mem->desc);
|
||||||
"\"%s\" memory not accessible using FLIP",
|
|
||||||
progname, mem->desc);
|
|
||||||
if (strcmp(mem->desc, "flash") == 0)
|
if (strcmp(mem->desc, "flash") == 0)
|
||||||
avrdude_message(MSG_INFO, " (did you mean \"application\"?)");
|
msg_error(" (did you mean \"application\"?)");
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_error("\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flip2_read_memory(FLIP2(pgm)->dfu, mem_unit, addr, value, 1);
|
return flip2_read_memory(FLIP2(pgm)->dfu, mem_unit, addr, value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip2_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip2_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char value)
|
unsigned long addr, unsigned char value)
|
||||||
{
|
{
|
||||||
enum flip2_mem_unit mem_unit;
|
enum flip2_mem_unit mem_unit;
|
||||||
|
@ -417,19 +421,17 @@ int flip2_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
mem_unit = flip2_mem_unit(mem->desc);
|
mem_unit = flip2_mem_unit(mem->desc);
|
||||||
|
|
||||||
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
|
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: "
|
pmsg_error("%s memory not accessible using FLIP", mem->desc);
|
||||||
"\"%s\" memory not accessible using FLIP",
|
|
||||||
progname, mem->desc);
|
|
||||||
if (strcmp(mem->desc, "flash") == 0)
|
if (strcmp(mem->desc, "flash") == 0)
|
||||||
avrdude_message(MSG_INFO, " (did you mean \"application\"?)");
|
msg_error(" (did you mean \"application\"?)");
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_error("\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flip2_write_memory(FLIP2(pgm)->dfu, mem_unit, addr, &value, 1);
|
return flip2_write_memory(FLIP2(pgm)->dfu, mem_unit, addr, &value, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip2_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip2_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
enum flip2_mem_unit mem_unit;
|
enum flip2_mem_unit mem_unit;
|
||||||
|
@ -441,19 +443,16 @@ int flip2_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
mem_unit = flip2_mem_unit(mem->desc);
|
mem_unit = flip2_mem_unit(mem->desc);
|
||||||
|
|
||||||
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
|
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: "
|
pmsg_error("%s memory not accessible using FLIP", mem->desc);
|
||||||
"\"%s\" memory not accessible using FLIP",
|
|
||||||
progname, mem->desc);
|
|
||||||
if (strcmp(mem->desc, "flash") == 0)
|
if (strcmp(mem->desc, "flash") == 0)
|
||||||
avrdude_message(MSG_INFO, " (did you mean \"application\"?)");
|
msg_error(" (did you mean \"application\"?)");
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_error("\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_bytes > INT_MAX) {
|
if (n_bytes > INT_MAX) {
|
||||||
/* This should never happen, unless the int type is only 16 bits. */
|
/* This should never happen, unless the int type is only 16 bits. */
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Attempting to read more than %d bytes\n",
|
pmsg_error("attempting to read more than %d bytes\n", INT_MAX);
|
||||||
progname, INT_MAX);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,7 +462,7 @@ int flip2_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
return (result == 0) ? n_bytes : -1;
|
return (result == 0) ? n_bytes : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip2_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
int flip2_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
enum flip2_mem_unit mem_unit;
|
enum flip2_mem_unit mem_unit;
|
||||||
|
@ -475,19 +474,16 @@ int flip2_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
mem_unit = flip2_mem_unit(mem->desc);
|
mem_unit = flip2_mem_unit(mem->desc);
|
||||||
|
|
||||||
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
|
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: "
|
pmsg_error("%s memory not accessible using FLIP", mem->desc);
|
||||||
"\"%s\" memory not accessible using FLIP",
|
|
||||||
progname, mem->desc);
|
|
||||||
if (strcmp(mem->desc, "flash") == 0)
|
if (strcmp(mem->desc, "flash") == 0)
|
||||||
avrdude_message(MSG_INFO, " (did you mean \"application\"?)");
|
msg_error(" (did you mean \"application\"?)");
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_error("\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n_bytes > INT_MAX) {
|
if (n_bytes > INT_MAX) {
|
||||||
/* This should never happen, unless the int type is only 16 bits. */
|
/* This should never happen, unless the int type is only 16 bits. */
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Attempting to read more than %d bytes\n",
|
pmsg_error("attempting to read more than %d bytes\n", INT_MAX);
|
||||||
progname, INT_MAX);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,14 +493,35 @@ int flip2_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
||||||
return (result == 0) ? n_bytes : -1;
|
return (result == 0) ? n_bytes : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip2_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
|
// Parse the -E option flag
|
||||||
{
|
int flip2_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
|
||||||
|
char *cp, *s, *str = cfg_strdup("flip2_parseextitspecs()", sp);
|
||||||
|
|
||||||
|
s = str;
|
||||||
|
while ((cp = strtok(s, ","))) {
|
||||||
|
s = NULL;
|
||||||
|
if (!strcmp(cp, "reset")) {
|
||||||
|
pgm->exit_reset = EXIT_RESET_ENABLED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!strcmp(cp, "noreset")) {
|
||||||
|
pgm->exit_reset = EXIT_RESET_DISABLED;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
free(str);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(str);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flip2_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem) {
|
||||||
if (FLIP2(pgm)->dfu == NULL)
|
if (FLIP2(pgm)->dfu == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (mem->size < sizeof(FLIP2(pgm)->part_sig)) {
|
if (mem->size < sizeof(FLIP2(pgm)->part_sig)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Signature read must be at least %u bytes\n",
|
pmsg_error("signature read must be at least %u bytes\n", (unsigned int) sizeof(FLIP2(pgm)->part_sig));
|
||||||
progname, (unsigned int) sizeof(FLIP2(pgm)->part_sig));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,8 +534,7 @@ void flip2_setup(PROGRAMMER * pgm)
|
||||||
pgm->cookie = calloc(1, sizeof(struct flip2));
|
pgm->cookie = calloc(1, sizeof(struct flip2));
|
||||||
|
|
||||||
if (pgm->cookie == NULL) {
|
if (pgm->cookie == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: Out of memory allocating private data structure\n",
|
pmsg_error("out of memory allocating private data structure\n");
|
||||||
progname);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -536,24 +552,24 @@ void flip2_show_info(struct flip2 *flip2)
|
||||||
{
|
{
|
||||||
dfu_show_info(flip2->dfu);
|
dfu_show_info(flip2->dfu);
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, " Part signature : 0x%02X%02X%02X\n",
|
msg_info(" Part signature : 0x%02X%02X%02X\n",
|
||||||
(int) flip2->part_sig[0],
|
(int) flip2->part_sig[0],
|
||||||
(int) flip2->part_sig[1],
|
(int) flip2->part_sig[1],
|
||||||
(int) flip2->part_sig[2]);
|
(int) flip2->part_sig[2]);
|
||||||
|
|
||||||
if (flip2->part_rev < 26)
|
if (flip2->part_rev < 26)
|
||||||
avrdude_message(MSG_INFO, " Part revision : %c\n",
|
msg_info(" Part revision : %c\n",
|
||||||
(char) (flip2->part_rev + 'A'));
|
(char) (flip2->part_rev + 'A'));
|
||||||
else
|
else
|
||||||
avrdude_message(MSG_INFO, " Part revision : %c%c\n",
|
msg_info(" Part revision : %c%c\n",
|
||||||
(char) (flip2->part_rev / 26 - 1 + 'A'),
|
(char) (flip2->part_rev / 26 - 1 + 'A'),
|
||||||
(char) (flip2->part_rev % 26 + 'A'));
|
(char) (flip2->part_rev % 26 + 'A'));
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, " Bootloader version : 2.%hu.%hu\n",
|
msg_info(" Bootloader version : 2.%hu.%hu\n",
|
||||||
((unsigned short) flip2->boot_ver >> 4) & 0xF,
|
((unsigned short) flip2->boot_ver >> 4) & 0xF,
|
||||||
((unsigned short) flip2->boot_ver >> 0) & 0xF);
|
((unsigned short) flip2->boot_ver >> 0) & 0xF);
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, " USB max packet size : %hu\n",
|
msg_info(" USB max packet size : %hu\n",
|
||||||
(unsigned short) flip2->dfu->dev_desc.bMaxPacketSize0);
|
(unsigned short) flip2->dfu->dev_desc.bMaxPacketSize0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,18 +582,15 @@ int flip2_read_memory(struct dfu_dev *dfu,
|
||||||
int read_size;
|
int read_size;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: flip_read_memory(%s, 0x%04x, %d)\n",
|
pmsg_notice2("flip_read_memory(%s, 0x%04x, %d)\n", flip2_mem_unit_str(mem_unit), addr, size);
|
||||||
progname, flip2_mem_unit_str(mem_unit), addr, size);
|
|
||||||
|
|
||||||
result = flip2_set_mem_unit(dfu, mem_unit);
|
result = flip2_set_mem_unit(dfu, mem_unit);
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
if ((mem_name = flip2_mem_unit_str(mem_unit)) != NULL)
|
if ((mem_name = flip2_mem_unit_str(mem_unit)) != NULL)
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory unit 0x%02X (%s)\n",
|
pmsg_error("unable to set memory unit 0x%02X (%s)\n", (int) mem_unit, mem_name);
|
||||||
progname, (int) mem_unit, mem_name);
|
|
||||||
else
|
else
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory unit 0x%02X\n",
|
pmsg_error("unable to set memory unit 0x%02X\n", (int) mem_unit);
|
||||||
progname, (int) mem_unit);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,8 +598,7 @@ int flip2_read_memory(struct dfu_dev *dfu,
|
||||||
result = flip2_set_mem_page(dfu, page_addr);
|
result = flip2_set_mem_page(dfu, page_addr);
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory page 0x%04hX\n",
|
pmsg_error("unable to set memory page 0x%04hX\n", page_addr);
|
||||||
progname, page_addr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -597,8 +609,7 @@ int flip2_read_memory(struct dfu_dev *dfu,
|
||||||
if (page_addr != prev_page_addr) {
|
if (page_addr != prev_page_addr) {
|
||||||
result = flip2_set_mem_page(dfu, page_addr);
|
result = flip2_set_mem_page(dfu, page_addr);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory page 0x%04hX\n",
|
pmsg_error("unable to set memory page 0x%04hX\n", page_addr);
|
||||||
progname, page_addr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -607,8 +618,7 @@ int flip2_read_memory(struct dfu_dev *dfu,
|
||||||
result = flip2_read_max1k(dfu, addr & 0xFFFF, ptr, read_size);
|
result = flip2_read_max1k(dfu, addr & 0xFFFF, ptr, read_size);
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to read 0x%04X bytes at 0x%04lX\n",
|
pmsg_error("unable to read 0x%04X bytes at 0x%04lX\n", read_size, (unsigned long) addr);
|
||||||
progname, read_size, (unsigned long) addr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,18 +639,15 @@ int flip2_write_memory(struct dfu_dev *dfu,
|
||||||
int write_size;
|
int write_size;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: flip_write_memory(%s, 0x%04x, %d)\n",
|
pmsg_notice2("flip_write_memory(%s, 0x%04x, %d)\n", flip2_mem_unit_str(mem_unit), addr, size);
|
||||||
progname, flip2_mem_unit_str(mem_unit), addr, size);
|
|
||||||
|
|
||||||
result = flip2_set_mem_unit(dfu, mem_unit);
|
result = flip2_set_mem_unit(dfu, mem_unit);
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
if ((mem_name = flip2_mem_unit_str(mem_unit)) != NULL)
|
if ((mem_name = flip2_mem_unit_str(mem_unit)) != NULL)
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory unit 0x%02X (%s)\n",
|
pmsg_error("unable to set memory unit 0x%02X (%s)\n", (int) mem_unit, mem_name);
|
||||||
progname, (int) mem_unit, mem_name);
|
|
||||||
else
|
else
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory unit 0x%02X\n",
|
pmsg_error("unable to set memory unit 0x%02X\n", (int) mem_unit);
|
||||||
progname, (int) mem_unit);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,8 +655,7 @@ int flip2_write_memory(struct dfu_dev *dfu,
|
||||||
result = flip2_set_mem_page(dfu, page_addr);
|
result = flip2_set_mem_page(dfu, page_addr);
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory page 0x%04hX\n",
|
pmsg_error("unable to set memory page 0x%04hX\n", page_addr);
|
||||||
progname, page_addr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,8 +666,7 @@ int flip2_write_memory(struct dfu_dev *dfu,
|
||||||
if (page_addr != prev_page_addr) {
|
if (page_addr != prev_page_addr) {
|
||||||
result = flip2_set_mem_page(dfu, page_addr);
|
result = flip2_set_mem_page(dfu, page_addr);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory page 0x%04hX\n",
|
pmsg_error("unable to set memory page 0x%04hX\n", page_addr);
|
||||||
progname, page_addr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -670,8 +675,7 @@ int flip2_write_memory(struct dfu_dev *dfu,
|
||||||
result = flip2_write_max1k(dfu, addr & 0xFFFF, ptr, write_size);
|
result = flip2_write_max1k(dfu, addr & 0xFFFF, ptr, write_size);
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Failed to write 0x%04X bytes at 0x%04lX\n",
|
pmsg_error("unable to write 0x%04X bytes at 0x%04lX\n", write_size, (unsigned long) addr);
|
||||||
progname, write_size, (unsigned long) addr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,11 +711,9 @@ int flip2_set_mem_unit(struct dfu_dev *dfu, enum flip2_mem_unit mem_unit)
|
||||||
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
||||||
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Unknown memory unit (0x%02x)\n",
|
pmsg_error("unknown memory unit (0x%02x)\n", (unsigned int) mem_unit);
|
||||||
progname, (unsigned int) mem_unit);
|
|
||||||
} else
|
} else
|
||||||
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
|
pmsg_error("DFU status %s\n", flip2_status_str(&status));
|
||||||
flip2_status_str(&status));
|
|
||||||
dfu_clrstatus(dfu);
|
dfu_clrstatus(dfu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -744,11 +746,9 @@ int flip2_set_mem_page(struct dfu_dev *dfu,
|
||||||
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
||||||
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Page address out of range (0x%04hx)\n",
|
pmsg_error("page address out of range (0x%04hx)\n", page_addr);
|
||||||
progname, page_addr);
|
|
||||||
} else
|
} else
|
||||||
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
|
pmsg_error("DFU status %s\n", flip2_status_str(&status));
|
||||||
flip2_status_str(&status));
|
|
||||||
dfu_clrstatus(dfu);
|
dfu_clrstatus(dfu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,11 +789,9 @@ flip2_read_max1k_status:
|
||||||
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
||||||
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Address out of range [0x%04hX,0x%04hX]\n",
|
pmsg_error("address out of range [0x%04hX,0x%04hX]\n", offset, offset+size-1);
|
||||||
progname, offset, offset+size-1);
|
|
||||||
} else
|
} else
|
||||||
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
|
pmsg_error("DFU status %s\n", flip2_status_str(&status));
|
||||||
flip2_status_str(&status));
|
|
||||||
dfu_clrstatus(dfu);
|
dfu_clrstatus(dfu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,8 +817,7 @@ int flip2_write_max1k(struct dfu_dev *dfu,
|
||||||
cmd.args[3] = ((offset+size-1) >> 0) & 0xFF;
|
cmd.args[3] = ((offset+size-1) >> 0) & 0xFF;
|
||||||
|
|
||||||
if (size > 0x400) {
|
if (size > 0x400) {
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Write block too large (%hu > 1024)\n",
|
pmsg_error("erite block too large (%hu > 1024)\n", size);
|
||||||
progname, size);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -850,11 +847,9 @@ int flip2_write_max1k(struct dfu_dev *dfu,
|
||||||
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
|
||||||
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Error: Address out of range [0x%04hX,0x%04hX]\n",
|
pmsg_error("address out of range [0x%04hX,0x%04hX]\n", offset, offset+size-1);
|
||||||
progname, offset, offset+size-1);
|
|
||||||
} else
|
} else
|
||||||
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
|
pmsg_error("DFU status %s\n", flip2_status_str(&status));
|
||||||
flip2_status_str(&status));
|
|
||||||
dfu_clrstatus(dfu);
|
dfu_clrstatus(dfu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -905,93 +900,26 @@ const char * flip2_mem_unit_str(enum flip2_mem_unit mem_unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum flip2_mem_unit flip2_mem_unit(const char *name) {
|
enum flip2_mem_unit flip2_mem_unit(const char *name) {
|
||||||
if (strcasecmp(name, "application") == 0)
|
if (strcmp(name, "application") == 0)
|
||||||
return FLIP2_MEM_UNIT_FLASH;
|
return FLIP2_MEM_UNIT_FLASH;
|
||||||
if (strcasecmp(name, "eeprom") == 0)
|
if (strcmp(name, "eeprom") == 0)
|
||||||
return FLIP2_MEM_UNIT_EEPROM;
|
return FLIP2_MEM_UNIT_EEPROM;
|
||||||
if (strcasecmp(name, "signature") == 0)
|
if (strcmp(name, "signature") == 0)
|
||||||
return FLIP2_MEM_UNIT_SIGNATURE;
|
return FLIP2_MEM_UNIT_SIGNATURE;
|
||||||
return FLIP2_MEM_UNIT_UNKNOWN;
|
return FLIP2_MEM_UNIT_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* HAVE_LIBUSB */
|
#else /* !HAVE_LIBUSB */
|
||||||
|
|
||||||
/* EXPORTED PROGRAMMER FUNCTION DEFINITIONS */
|
// Give a proper error if we were not compiled with libusb
|
||||||
|
static int flip2_nousb_open(PROGRAMMER* pgm, const char* name) {
|
||||||
int flip2_open(PROGRAMMER *pgm, char *port_spec)
|
pmsg_error("no USB support; please compile with libusb installed\n");
|
||||||
{
|
return -1;
|
||||||
fprintf(stderr, "%s: Error: No USB support in this compile of avrdude\n",
|
|
||||||
progname);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int flip2_initialize(PROGRAMMER* pgm, AVRPART *part)
|
void flip2_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
strcpy(pgm->type, "flip2");
|
||||||
return -1;
|
pgm->open = flip2_nousb_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
void flip2_close(PROGRAMMER* pgm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void flip2_enable(PROGRAMMER* pgm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void flip2_disable(PROGRAMMER* pgm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void flip2_display(PROGRAMMER* pgm, const char *prefix)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int flip2_program_enable(PROGRAMMER* pgm, AVRPART *part)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int flip2_chip_erase(PROGRAMMER* pgm, AVRPART *part)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int flip2_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
|
||||||
unsigned long addr, unsigned char *value)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int flip2_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
|
||||||
unsigned long addr, unsigned char value)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int flip2_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int flip2_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
|
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int flip2_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void flip2_setup(PROGRAMMER * pgm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void flip2_teardown(PROGRAMMER * pgm)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* HAVE_LIBUSB */
|
#endif /* HAVE_LIBUSB */
|
||||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char flip2_desc[];
|
extern const char flip2_desc[];
|
||||||
extern void flip2_initpgm(PROGRAMMER * pgm);
|
extern void flip2_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
643
src/ft245r.c
643
src/ft245r.c
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@
|
||||||
#define ft245r_h
|
#define ft245r_h
|
||||||
|
|
||||||
extern const char ft245r_desc[];
|
extern const char ft245r_desc[];
|
||||||
void ft245r_initpgm (PROGRAMMER * pgm);
|
void ft245r_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
|
|
||||||
#endif /* ft245r_h */
|
#endif /* ft245r_h */
|
||||||
|
|
1998
src/jtag3.c
1998
src/jtag3.c
File diff suppressed because it is too large
Load Diff
37
src/jtag3.h
37
src/jtag3.h
|
@ -25,27 +25,32 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int jtag3_open_common(PROGRAMMER * pgm, char * port);
|
int jtag3_open_common(PROGRAMMER *pgm, const char *port);
|
||||||
int jtag3_send(PROGRAMMER * pgm, unsigned char * data, size_t len);
|
int jtag3_send(const PROGRAMMER *pgm, unsigned char *data, size_t len);
|
||||||
int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg);
|
int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg);
|
||||||
void jtag3_close(PROGRAMMER * pgm);
|
void jtag3_close(PROGRAMMER * pgm);
|
||||||
int jtag3_getsync(PROGRAMMER * pgm, int mode);
|
int jtag3_getsync(const PROGRAMMER *pgm, int mode);
|
||||||
int jtag3_getparm(PROGRAMMER * pgm, unsigned char scope,
|
int jtag3_getparm(const PROGRAMMER *pgm, unsigned char scope,
|
||||||
unsigned char section, unsigned char parm,
|
unsigned char section, unsigned char parm,
|
||||||
unsigned char *value, unsigned char length);
|
unsigned char *value, unsigned char length);
|
||||||
int jtag3_setparm(PROGRAMMER * pgm, unsigned char scope,
|
int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope,
|
||||||
unsigned char section, unsigned char parm,
|
unsigned char section, unsigned char parm,
|
||||||
unsigned char *value, unsigned char length);
|
unsigned char *value, unsigned char length);
|
||||||
int jtag3_command(PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
|
int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
|
||||||
unsigned char **resp, const char *descr);
|
unsigned char **resp, const char *descr);
|
||||||
|
void jtag3_display(const PROGRAMMER *pgm, const char *p);
|
||||||
|
void jtag3_print_parms1(const PROGRAMMER *pgm, const char *p, FILE *fp);
|
||||||
|
int jtag3_set_vtarget(const PROGRAMMER *pgm, double voltage);
|
||||||
extern const char jtag3_desc[];
|
extern const char jtag3_desc[];
|
||||||
extern const char jtag3_dw_desc[];
|
extern const char jtag3_dw_desc[];
|
||||||
extern const char jtag3_pdi_desc[];
|
extern const char jtag3_pdi_desc[];
|
||||||
extern const char jtag3_updi_desc[];
|
extern const char jtag3_updi_desc[];
|
||||||
void jtag3_initpgm (PROGRAMMER * pgm);
|
extern const char jtag3_tpi_desc[];
|
||||||
void jtag3_dw_initpgm (PROGRAMMER * pgm);
|
void jtag3_initpgm(PROGRAMMER *pgm);
|
||||||
void jtag3_pdi_initpgm (PROGRAMMER * pgm);
|
void jtag3_dw_initpgm(PROGRAMMER *pgm);
|
||||||
void jtag3_updi_initpgm (PROGRAMMER * pgm);
|
void jtag3_pdi_initpgm(PROGRAMMER *pgm);
|
||||||
|
void jtag3_updi_initpgm(PROGRAMMER *pgm);
|
||||||
|
void jtag3_tpi_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions are referenced from stk500v2.c for JTAGICE3 in
|
* These functions are referenced from stk500v2.c for JTAGICE3 in
|
||||||
|
|
|
@ -96,6 +96,7 @@
|
||||||
#define SCOPE_GENERAL 0x01
|
#define SCOPE_GENERAL 0x01
|
||||||
#define SCOPE_AVR_ISP 0x11
|
#define SCOPE_AVR_ISP 0x11
|
||||||
#define SCOPE_AVR 0x12
|
#define SCOPE_AVR 0x12
|
||||||
|
#define SCOPE_AVR_TPI 0x14
|
||||||
|
|
||||||
/* Info scope */
|
/* Info scope */
|
||||||
#define CMD3_GET_INFO 0x00
|
#define CMD3_GET_INFO 0x00
|
||||||
|
@ -144,6 +145,7 @@
|
||||||
# define RSP3_FAIL_WRONG_MODE 0x32 /* progmode vs. non-prog */
|
# define RSP3_FAIL_WRONG_MODE 0x32 /* progmode vs. non-prog */
|
||||||
# define RSP3_FAIL_UNSUPP_MEMORY 0x34 /* unsupported memory type */
|
# define RSP3_FAIL_UNSUPP_MEMORY 0x34 /* unsupported memory type */
|
||||||
# define RSP3_FAIL_WRONG_LENGTH 0x35 /* wrong lenth for mem access */
|
# 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_OCD_LOCKED 0x44 /* device is locked */
|
||||||
# define RSP3_FAIL_NOT_UNDERSTOOD 0x91
|
# define RSP3_FAIL_NOT_UNDERSTOOD 0x91
|
||||||
|
|
||||||
|
@ -183,16 +185,24 @@
|
||||||
* precedes each parameter address. There are distinct parameter
|
* precedes each parameter address. There are distinct parameter
|
||||||
* sets for generic and AVR scope.
|
* sets for generic and AVR scope.
|
||||||
*/
|
*/
|
||||||
#define PARM3_HW_VER 0x00 /* section 0, generic scope, 1 byte */
|
#define PARM3_HW_VER 0x00 /* section 0, generic scope, 1 byte */
|
||||||
#define PARM3_FW_MAJOR 0x01 /* section 0, generic scope, 1 byte */
|
#define PARM3_FW_MAJOR 0x01 /* section 0, generic scope, 1 byte */
|
||||||
#define PARM3_FW_MINOR 0x02 /* section 0, generic scope, 1 byte */
|
#define PARM3_FW_MINOR 0x02 /* section 0, generic scope, 1 byte */
|
||||||
#define PARM3_FW_RELEASE 0x03 /* section 0, generic scope, 1 byte;
|
#define PARM3_FW_RELEASE 0x03 /* section 0, generic scope, 1 byte;
|
||||||
* always asked for by Atmel Studio,
|
* always asked for by Atmel Studio,
|
||||||
* but never displayed there */
|
* but never displayed there */
|
||||||
#define PARM3_VTARGET 0x00 /* section 1, generic scope, 2 bytes, in millivolts */
|
|
||||||
#define PARM3_VBUF 0x01 /* section 1, generic scope, 2 bytes, bufferred target voltage reference */
|
#define PARM3_VTARGET 0x00 /* section 1, generic scope, 2 bytes, in millivolts */
|
||||||
#define PARM3_VUSB 0x02 /* section 1, generic scope, 2 bytes, USB voltage */
|
#define PARM3_VBUF 0x01 /* section 1, generic scope, 2 bytes, bufferred target voltage reference */
|
||||||
#define PARM3_VADJUST 0x20 /* section 1, generic scope, 2 bytes, set voltage */
|
#define PARM3_VUSB 0x02 /* section 1, generic scope, 2 bytes, USB voltage */
|
||||||
|
#define PARM3_ANALOG_A_CURRENT 0x10 /* section 1, generic scope, 2 bytes, Ch A current in milliamps, Powerdebugger only */
|
||||||
|
#define PARM3_ANALOG_A_VOLTAGE 0x11 /* section 1, generic scope, 2 bytes, Ch A voltage in millivolts, Powerdebugger only */
|
||||||
|
#define PARM3_ANALOG_B_CURRENT 0x12 /* section 1, generic scope, 2 bytes, Ch B current in milliamps, Powerdebugger only */
|
||||||
|
#define PARM3_ANALOG_B_VOLTAGE 0x13 /* section 1, generic scope, 2 bytes, Ch V voltage in millivolts, Powerdebugger only */
|
||||||
|
#define PARM3_TSUP_VOLTAGE_MEAS 0x14 /* section 1, generic scope, 2 bytes, target voltage measurement in millivolts */
|
||||||
|
#define PARM3_USB_VOLTAGE_MEAS 0x15 /* section 1, generic scope, 2 bytes, USB voltage measurement in millivolts */
|
||||||
|
#define PARM3_VADJUST 0x20 /* section 1, generic scope, 2 bytes, set voltage in millivolts */
|
||||||
|
#define PARM3_ANALOG_STATUS 0x30 /* section 1, generic scope, 2 bytes, analog status */
|
||||||
|
|
||||||
#define PARM3_DEVICEDESC 0x00 /* section 2, memory etc. configuration,
|
#define PARM3_DEVICEDESC 0x00 /* section 2, memory etc. configuration,
|
||||||
* 31 bytes for tiny/mega AVR, 47 bytes
|
* 31 bytes for tiny/mega AVR, 47 bytes
|
||||||
|
@ -236,6 +246,14 @@
|
||||||
#define PARM3_OPT_12V_UPDI_ENABLE 0x06
|
#define PARM3_OPT_12V_UPDI_ENABLE 0x06
|
||||||
#define PARM3_OPT_CHIP_ERASE_TO_ENTER 0x07
|
#define PARM3_OPT_CHIP_ERASE_TO_ENTER 0x07
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UPDI high-voltage enable modes
|
||||||
|
*/
|
||||||
|
#define PARM3_UPDI_HV_NONE 0x00 /* Do not use high-voltage */
|
||||||
|
#define PARM3_UPDI_HV_SIMPLE_PULSE 0x01 /* Issue a single high-voltage pulse immediately*/
|
||||||
|
#define PARM3_UPDI_HV_AUTO_POWER_TOGGLE 0x02 /* Toggle power automatically and then apply a high-voltage pulse */
|
||||||
|
#define PARM3_UPDI_HV_USER_POWER_TOGGLE 0x03 /* The user toggles power, and the tool applies a high-voltage pulse on power-up */
|
||||||
|
|
||||||
/* Xmega erase memory types, for CMND_XMEGA_ERASE */
|
/* Xmega erase memory types, for CMND_XMEGA_ERASE */
|
||||||
#define XMEGA_ERASE_CHIP 0x00
|
#define XMEGA_ERASE_CHIP 0x00
|
||||||
#define XMEGA_ERASE_APP 0x01
|
#define XMEGA_ERASE_APP 0x01
|
||||||
|
@ -297,6 +315,60 @@
|
||||||
#define UPDI_ADDRESS_MODE_24BIT 1
|
#define UPDI_ADDRESS_MODE_24BIT 1
|
||||||
#define FUSES_SYSCFG0_OFFSET 5
|
#define FUSES_SYSCFG0_OFFSET 5
|
||||||
|
|
||||||
|
// TPI Protocol commands
|
||||||
|
#define XPRG_CMD_ENTER_PROGMODE 0x01
|
||||||
|
#define XPRG_CMD_LEAVE_PROGMODE 0x02
|
||||||
|
#define XPRG_CMD_ERASE 0x03
|
||||||
|
#define XPRG_CMD_WRITE_MEM 0x04
|
||||||
|
#define XPRG_CMD_READ_MEM 0x05
|
||||||
|
#define XPRG_CMD_CRC 0x06
|
||||||
|
#define XPRG_CMD_SET_PARAM 0x07
|
||||||
|
|
||||||
|
// TPI Protocol responses
|
||||||
|
// Success
|
||||||
|
#define XPRG_ERR_OK 0x00
|
||||||
|
// Errors
|
||||||
|
#define XPRG_ERR_FAILED 0x01
|
||||||
|
#define XPRG_ERR_COLLISION 0x02
|
||||||
|
#define XPRG_ERR_TIMEOUT 0x03
|
||||||
|
#define XPRG_ERR_ILLEGAL_PARAM 0x04
|
||||||
|
#define XPRG_ERR_UNKNOWN_COMMAND 0x10
|
||||||
|
|
||||||
|
// TPI Memory types
|
||||||
|
#define XPRG_MEM_TYPE_APPL 0x01
|
||||||
|
#define XPRG_MEM_TYPE_BOOT 0x02
|
||||||
|
#define XPRG_MEM_TYPE_EEPROM 0x03
|
||||||
|
#define XPRG_MEM_TYPE_FUSE 0x04
|
||||||
|
#define XPRG_MEM_TYPE_LOCKBITS 0x05
|
||||||
|
#define XPRG_MEM_TYPE_USERSIG 0x06
|
||||||
|
#define XPRG_MEM_TYPE_FACTORY_CALIBRATION 0x07
|
||||||
|
|
||||||
|
// TPI Erase modes
|
||||||
|
#define XPRG_ERASE_CHIP 0x01
|
||||||
|
#define XPRG_ERASE_APP 0x02
|
||||||
|
#define XPRG_ERASE_BOOT 0x03
|
||||||
|
#define XPRG_ERASE_EEPROM 0x04
|
||||||
|
#define XPRG_ERASE_APP_PAGE 0x05
|
||||||
|
#define XPRG_ERASE_BOOT_PAGE 0x06
|
||||||
|
#define XPRG_ERASE_EEPROM_PAGE 0x07
|
||||||
|
#define XPRG_ERASE_USERSIG 0x08
|
||||||
|
// Erase types for Tiny XPROG
|
||||||
|
#define XPRG_ERASE_CONFIG 0x09
|
||||||
|
|
||||||
|
// TPI Parameters
|
||||||
|
// XPROG parameters of different sizes
|
||||||
|
// 4-byte address
|
||||||
|
#define XPRG_PARAM_NVMBASE 0x01
|
||||||
|
// 2-byte page size
|
||||||
|
#define XPRG_PARAM_EEPPAGESIZE 0x02
|
||||||
|
// tiny TPI, 1-byte address
|
||||||
|
#define XPRG_PARAM_NVMCMD_ADDR 0x03
|
||||||
|
#define XPRG_PARAM_NVMCSR_ADDR 0x04
|
||||||
|
|
||||||
|
#define TPI_NVMCMD_ADDRESS 0x33
|
||||||
|
#define TPI_NVMCSR_ADDRESS 0x32
|
||||||
|
|
||||||
|
|
||||||
#if !defined(JTAG3_PRIVATE_EXPORTED)
|
#if !defined(JTAG3_PRIVATE_EXPORTED)
|
||||||
|
|
||||||
struct mega_device_desc {
|
struct mega_device_desc {
|
||||||
|
@ -392,5 +464,7 @@ struct updi_device_desc {
|
||||||
unsigned char flash_page_size_msb; // Extends flash_page_size, used in 24-bit mode
|
unsigned char flash_page_size_msb; // Extends flash_page_size, used in 24-bit mode
|
||||||
|
|
||||||
unsigned char address_mode; // 0x00 = 16-bit mode, 0x01 = 24-bit mode
|
unsigned char address_mode; // 0x00 = 16-bit mode, 0x01 = 24-bit mode
|
||||||
|
|
||||||
|
unsigned char hvupdi_variant; // Indicates the target UPDI HV implementation
|
||||||
};
|
};
|
||||||
#endif /* JTAG3_PRIVATE_EXPORTED */
|
#endif /* JTAG3_PRIVATE_EXPORTED */
|
||||||
|
|
479
src/jtagmkI.c
479
src/jtagmkI.c
File diff suppressed because it is too large
Load Diff
|
@ -26,7 +26,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char jtagmkI_desc[];
|
extern const char jtagmkI_desc[];
|
||||||
void jtagmkI_initpgm (PROGRAMMER * pgm);
|
void jtagmkI_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
1382
src/jtagmkII.c
1382
src/jtagmkII.c
File diff suppressed because it is too large
Load Diff
|
@ -25,27 +25,29 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len);
|
int jtagmkII_send(const PROGRAMMER *pgm, unsigned char *data, size_t len);
|
||||||
int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg);
|
int jtagmkII_recv(const PROGRAMMER *pgm, unsigned char **msg);
|
||||||
void jtagmkII_close(PROGRAMMER * pgm);
|
void jtagmkII_close(PROGRAMMER * pgm);
|
||||||
int jtagmkII_getsync(PROGRAMMER * pgm, int mode);
|
int jtagmkII_getsync(const PROGRAMMER *pgm, int mode);
|
||||||
int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm,
|
int jtagmkII_getparm(const PROGRAMMER *pgm, unsigned char parm,
|
||||||
unsigned char * value);
|
unsigned char * value);
|
||||||
|
|
||||||
extern const char jtagmkII_desc[];
|
extern const char jtagmkII_desc[];
|
||||||
extern const char jtagmkII_avr32_desc[];
|
extern const char jtagmkII_avr32_desc[];
|
||||||
extern const char jtagmkII_dw_desc[];
|
extern const char jtagmkII_dw_desc[];
|
||||||
extern const char jtagmkII_pdi_desc[];
|
extern const char jtagmkII_pdi_desc[];
|
||||||
|
extern const char jtagmkII_updi_desc[];
|
||||||
extern const char jtagmkII_dragon_desc[];
|
extern const char jtagmkII_dragon_desc[];
|
||||||
extern const char jtagmkII_dragon_dw_desc[];
|
extern const char jtagmkII_dragon_dw_desc[];
|
||||||
extern const char jtagmkII_dragon_pdi_desc[];
|
extern const char jtagmkII_dragon_pdi_desc[];
|
||||||
void jtagmkII_initpgm (PROGRAMMER * pgm);
|
void jtagmkII_initpgm(PROGRAMMER *pgm);
|
||||||
void jtagmkII_avr32_initpgm (PROGRAMMER * pgm);
|
void jtagmkII_avr32_initpgm(PROGRAMMER *pgm);
|
||||||
void jtagmkII_dw_initpgm (PROGRAMMER * pgm);
|
void jtagmkII_dw_initpgm(PROGRAMMER *pgm);
|
||||||
void jtagmkII_pdi_initpgm (PROGRAMMER * pgm);
|
void jtagmkII_pdi_initpgm(PROGRAMMER *pgm);
|
||||||
void jtagmkII_dragon_initpgm (PROGRAMMER * pgm);
|
void jtagmkII_updi_initpgm(PROGRAMMER *pgm);
|
||||||
void jtagmkII_dragon_dw_initpgm (PROGRAMMER * pgm);
|
void jtagmkII_dragon_initpgm(PROGRAMMER *pgm);
|
||||||
void jtagmkII_dragon_pdi_initpgm (PROGRAMMER * pgm);
|
void jtagmkII_dragon_dw_initpgm(PROGRAMMER *pgm);
|
||||||
|
void jtagmkII_dragon_pdi_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These functions are referenced from stk500v2.c for JTAG ICE mkII
|
* These functions are referenced from stk500v2.c for JTAG ICE mkII
|
||||||
|
|
323
src/lexer.l
323
src/lexer.l
|
@ -39,15 +39,21 @@
|
||||||
#define YYERRCODE 256
|
#define YYERRCODE 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* capture lvalue keywords to associate comments with that assignment */
|
||||||
|
#define ccap() capture_lvalue_kw(yytext, cfg_lineno)
|
||||||
|
|
||||||
|
static void adjust_cfg_lineno(const char *p) {
|
||||||
|
while(*p)
|
||||||
|
if(*p++ == '\n')
|
||||||
|
cfg_lineno++;
|
||||||
|
}
|
||||||
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
DIGIT [0-9]
|
DIGIT [0-9]
|
||||||
HEXDIGIT [0-9a-fA-F]
|
HEXDIGIT [0-9a-fA-F]
|
||||||
SIGN [+-]
|
SIGN [+-]
|
||||||
|
|
||||||
%x strng
|
|
||||||
%x incl
|
|
||||||
%x comment
|
|
||||||
%option nounput
|
%option nounput
|
||||||
|
|
||||||
/* Bump resources for classic lex. */
|
/* Bump resources for classic lex. */
|
||||||
|
@ -57,35 +63,47 @@ SIGN [+-]
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
#{SIGN}*{DIGIT}+ { yylval = number(yytext); return TKN_NUMBER; }
|
{DIGIT}+ { yylval = new_number(yytext); return TKN_NUMBER; /* sign is treated in grammar */ }
|
||||||
#{SIGN}*{DIGIT}+"."{DIGIT}* { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
{SIGN}?{DIGIT}+"."{DIGIT}* { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; }
|
||||||
#{SIGN}*"."{DIGIT}* { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
{SIGN}?"."{DIGIT}+ { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; }
|
||||||
{DIGIT}+ { yylval = number(yytext); return TKN_NUMBER; }
|
|
||||||
{DIGIT}+"."{DIGIT}* { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
|
||||||
"."{DIGIT}+ { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
|
|
||||||
|
|
||||||
"\"" { string_buf_ptr = string_buf; BEGIN(strng); }
|
["]([^"\\\n]|\\.|\\\n)*["] {
|
||||||
|
char *str= cfg_strdup("lexer.l", yytext);
|
||||||
|
cfg_unescape(str, str+1);
|
||||||
|
size_t len = strlen(str);
|
||||||
|
if(len)
|
||||||
|
str[len-1] = 0;
|
||||||
|
yylval = new_string(str);
|
||||||
|
free(str);
|
||||||
|
return TKN_STRING;
|
||||||
|
}
|
||||||
|
|
||||||
0x{HEXDIGIT}+ { yylval = hexnumber(yytext); return TKN_NUMBER; }
|
0x{HEXDIGIT}+ { yylval = new_hexnumber(yytext); return TKN_NUMBER; }
|
||||||
|
|
||||||
|
#\n#\ PROGRAMMER\ DEFINITIONS\n#\n+ { /* Record comments so far as prologue and skip */
|
||||||
|
cfg_capture_prologue();
|
||||||
|
adjust_cfg_lineno(yytext);
|
||||||
|
}
|
||||||
|
|
||||||
|
#\n#\ PART\ DEFINITIONS\n#\n+ { /* Ignore part definions header */
|
||||||
|
adjust_cfg_lineno(yytext);
|
||||||
|
}
|
||||||
|
|
||||||
# { /* The following eats '#' style comments to end of line */
|
[ \t]*#[^\n]*\n+ { /* Record and skip # comments including preceding white space */
|
||||||
BEGIN(comment); }
|
capture_comment_str(yytext, cfg_lineno);
|
||||||
<comment>[^\n] { /* eat comments */ }
|
adjust_cfg_lineno(yytext);
|
||||||
<comment>\n { lineno++; BEGIN(INITIAL); }
|
}
|
||||||
|
|
||||||
|
"/*" { /* The following eats multiline C style comments, they are not captured */
|
||||||
"/*" { /* The following eats multiline C style comments */
|
|
||||||
int c;
|
int c;
|
||||||
int comment_start;
|
int comment_start;
|
||||||
|
|
||||||
comment_start = lineno;
|
comment_start = cfg_lineno;
|
||||||
while (1) {
|
while (1) {
|
||||||
while (((c = input()) != '*') && (c != EOF)) {
|
while (((c = input()) != '*') && (c != EOF)) {
|
||||||
/* eat up text of comment, but keep counting lines */
|
/* eat up text of comment, but keep counting lines */
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
lineno++;
|
cfg_lineno++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == '*') {
|
if (c == '*') {
|
||||||
|
@ -103,156 +121,175 @@ SIGN [+-]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
<strng>\" { *string_buf_ptr = 0; string_buf_ptr = string_buf;
|
(?x: prog_modes | mcuid | n_interrupts | n_page_erase | n_word_writes | n_boot_sections |
|
||||||
yylval = string(string_buf_ptr); BEGIN(INITIAL); return TKN_STRING; }
|
boot_section_size | autobaud_sync | idr | rampz | spmcr | eecr | eind ) { /* struct components */
|
||||||
<strng>\\n *string_buf_ptr++ = '\n';
|
|
||||||
<strng>\\t *string_buf_ptr++ = '\t';
|
|
||||||
<strng>\\r *string_buf_ptr++ = '\r';
|
|
||||||
<strng>\\b *string_buf_ptr++ = '\b';
|
|
||||||
<strng>\\f *string_buf_ptr++ = '\f';
|
|
||||||
<strng>\\(.|\n) *(string_buf_ptr++) = yytext[1];
|
|
||||||
<strng>[^\\\n\"]+ { char *yptr = yytext; while (*yptr)
|
|
||||||
*(string_buf_ptr++) = *(yptr++); }
|
|
||||||
|
|
||||||
<strng>\n { yyerror("unterminated character constant");
|
Component_t *cp = cfg_comp_search(yytext, current_strct);
|
||||||
return YYERRCODE; }
|
if(!cp) {
|
||||||
|
yyerror("unknown component %s in %s", yytext, cfg_strct_name(current_strct));
|
||||||
|
return YYERRCODE;
|
||||||
|
}
|
||||||
|
yylval = new_token(TKN_COMPONENT);
|
||||||
|
yylval->value.comp = cp;
|
||||||
|
ccap();
|
||||||
|
return TKN_COMPONENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
PM_(SPM|TPI|ISP|PDI|UPDI|HVSP|HVPP|debugWIRE|JTAG|JTAGmkI|XMEGAJTAG|AVR32JTAG|aWire) { /* Constants */
|
||||||
|
yylval = new_constant(yytext);
|
||||||
|
return TKN_NUMBER;
|
||||||
|
}
|
||||||
|
|
||||||
alias { yylval=NULL; return K_ALIAS; }
|
alias { yylval=NULL; return K_ALIAS; }
|
||||||
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
|
allowfullpagebitstream { yylval=NULL; ccap(); return K_ALLOWFULLPAGEBITSTREAM; }
|
||||||
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
|
avr910_devcode { yylval=NULL; ccap(); return K_AVR910_DEVCODE; }
|
||||||
bank_size { yylval=NULL; return K_PAGE_SIZE; }
|
bank_size { yylval=NULL; return K_PAGE_SIZE; }
|
||||||
banked { yylval=NULL; return K_PAGED; }
|
banked { yylval=NULL; return K_PAGED; }
|
||||||
baudrate { yylval=NULL; return K_BAUDRATE; }
|
baudrate { yylval=NULL; ccap(); return K_BAUDRATE; }
|
||||||
blocksize { yylval=NULL; return K_BLOCKSIZE; }
|
blocksize { yylval=NULL; ccap(); return K_BLOCKSIZE; }
|
||||||
bs2 { yylval=NULL; return K_BS2; }
|
bs2 { yylval=NULL; ccap(); return K_BS2; }
|
||||||
buff { yylval=NULL; return K_BUFF; }
|
buff { yylval=NULL; ccap(); return K_BUFF; }
|
||||||
bytedelay { yylval=NULL; return K_BYTEDELAY; }
|
bytedelay { yylval=NULL; ccap(); return K_BYTEDELAY; }
|
||||||
chip_erase { yylval=new_token(K_CHIP_ERASE); return K_CHIP_ERASE; }
|
chip_erase { yylval=new_token(K_CHIP_ERASE); ccap(); return K_CHIP_ERASE; }
|
||||||
chip_erase_delay { yylval=NULL; return K_CHIP_ERASE_DELAY; }
|
chip_erase_delay { yylval=NULL; ccap(); return K_CHIP_ERASE_DELAY; }
|
||||||
chiperasepolltimeout { yylval=NULL; return K_CHIPERASEPOLLTIMEOUT; }
|
chiperasepolltimeout { yylval=NULL; ccap(); return K_CHIPERASEPOLLTIMEOUT; }
|
||||||
chiperasepulsewidth { yylval=NULL; return K_CHIPERASEPULSEWIDTH; }
|
chiperasepulsewidth { yylval=NULL; ccap(); return K_CHIPERASEPULSEWIDTH; }
|
||||||
chiperasetime { yylval=NULL; return K_CHIPERASETIME; }
|
chiperasetime { yylval=NULL; ccap(); return K_CHIPERASETIME; }
|
||||||
cmdexedelay { yylval=NULL; return K_CMDEXEDELAY; }
|
cmdexedelay { yylval=NULL; ccap(); return K_CMDEXEDELAY; }
|
||||||
connection_type { yylval=NULL; return K_CONNTYPE; }
|
connection_type { yylval=NULL; ccap(); return K_CONNTYPE; }
|
||||||
dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
|
dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
|
||||||
default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; }
|
default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; }
|
||||||
default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
|
default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
|
||||||
default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
|
default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
|
||||||
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
|
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
|
||||||
delay { yylval=NULL; return K_DELAY; }
|
default_spi { yylval=NULL; return K_DEFAULT_SPI; }
|
||||||
desc { yylval=NULL; return K_DESC; }
|
delay { yylval=NULL; ccap(); return K_DELAY; }
|
||||||
family_id { yylval=NULL; return K_FAMILY_ID; }
|
desc { yylval=NULL; ccap(); return K_DESC; }
|
||||||
devicecode { yylval=NULL; return K_DEVICECODE; }
|
devicecode { yylval=NULL; ccap(); return K_DEVICECODE; }
|
||||||
eecr { yylval=NULL; return K_EECR; }
|
|
||||||
eeprom { yylval=NULL; return K_EEPROM; }
|
eeprom { yylval=NULL; return K_EEPROM; }
|
||||||
eeprom_instr { yylval=NULL; return K_EEPROM_INSTR; }
|
eeprom_instr { yylval=NULL; ccap(); return K_EEPROM_INSTR; }
|
||||||
enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; }
|
enablepageprogramming { yylval=NULL; ccap(); return K_ENABLEPAGEPROGRAMMING; }
|
||||||
errled { yylval=NULL; return K_ERRLED; }
|
errled { yylval=NULL; ccap(); return K_ERRLED; }
|
||||||
|
family_id { yylval=NULL; ccap(); return K_FAMILY_ID; }
|
||||||
flash { yylval=NULL; return K_FLASH; }
|
flash { yylval=NULL; return K_FLASH; }
|
||||||
flash_instr { yylval=NULL; return K_FLASH_INSTR; }
|
flash_instr { yylval=NULL; ccap(); return K_FLASH_INSTR; }
|
||||||
has_debugwire { yylval=NULL; return K_HAS_DW; }
|
has_debugwire { yylval=NULL; ccap(); return K_HAS_DW; }
|
||||||
has_jtag { yylval=NULL; return K_HAS_JTAG; }
|
has_jtag { yylval=NULL; ccap(); return K_HAS_JTAG; }
|
||||||
has_pdi { yylval=NULL; return K_HAS_PDI; }
|
has_pdi { yylval=NULL; ccap(); return K_HAS_PDI; }
|
||||||
has_tpi { yylval=NULL; return K_HAS_TPI; }
|
has_tpi { yylval=NULL; ccap(); return K_HAS_TPI; }
|
||||||
has_updi { yylval=NULL; return K_HAS_UPDI; }
|
has_updi { yylval=NULL; ccap(); return K_HAS_UPDI; }
|
||||||
hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; }
|
hventerstabdelay { yylval=NULL; ccap(); return K_HVENTERSTABDELAY; }
|
||||||
hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; }
|
hvleavestabdelay { yylval=NULL; ccap(); return K_HVLEAVESTABDELAY; }
|
||||||
hvsp_controlstack { yylval=NULL; return K_HVSP_CONTROLSTACK; }
|
hvsp_controlstack { yylval=NULL; ccap(); return K_HVSP_CONTROLSTACK; }
|
||||||
hvspcmdexedelay { yylval=NULL; return K_HVSPCMDEXEDELAY; }
|
hvspcmdexedelay { yylval=NULL; ccap(); return K_HVSPCMDEXEDELAY; }
|
||||||
id { yylval=NULL; return K_ID; }
|
hvupdi_support { yylval=NULL; ccap(); return K_HVUPDI_SUPPORT; }
|
||||||
idr { yylval=NULL; return K_IDR; }
|
hvupdi_variant { yylval=NULL; ccap(); return K_HVUPDI_VARIANT; }
|
||||||
|
id { yylval=NULL; ccap(); return K_ID; }
|
||||||
io { yylval=new_token(K_IO); return K_IO; }
|
io { yylval=new_token(K_IO); return K_IO; }
|
||||||
is_at90s1200 { yylval=NULL; return K_IS_AT90S1200; }
|
is_at90s1200 { yylval=NULL; ccap(); return K_IS_AT90S1200; }
|
||||||
is_avr32 { yylval=NULL; return K_IS_AVR32; }
|
is_avr32 { yylval=NULL; ccap(); return K_IS_AVR32; }
|
||||||
latchcycles { yylval=NULL; return K_LATCHCYCLES; }
|
latchcycles { yylval=NULL; ccap(); return K_LATCHCYCLES; }
|
||||||
load_ext_addr { yylval=new_token(K_LOAD_EXT_ADDR); return K_LOAD_EXT_ADDR; }
|
load_ext_addr { yylval=new_token(K_LOAD_EXT_ADDR); ccap(); return K_LOAD_EXT_ADDR; }
|
||||||
loadpage_hi { yylval=new_token(K_LOADPAGE_HI); return K_LOADPAGE_HI; }
|
loadpage_hi { yylval=new_token(K_LOADPAGE_HI); ccap(); return K_LOADPAGE_HI; }
|
||||||
loadpage_lo { yylval=new_token(K_LOADPAGE_LO); return K_LOADPAGE_LO; }
|
loadpage_lo { yylval=new_token(K_LOADPAGE_LO); ccap(); return K_LOADPAGE_LO; }
|
||||||
max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; }
|
max_write_delay { yylval=NULL; ccap(); return K_MAX_WRITE_DELAY; }
|
||||||
mcu_base { yylval=NULL; return K_MCU_BASE; }
|
mcu_base { yylval=NULL; ccap(); return K_MCU_BASE; }
|
||||||
memory { yylval=NULL; return K_MEMORY; }
|
memory { yylval=NULL; ccap(); current_strct = COMP_AVRMEM; return K_MEMORY; }
|
||||||
min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; }
|
min_write_delay { yylval=NULL; ccap(); return K_MIN_WRITE_DELAY; }
|
||||||
miso { yylval=NULL; return K_MISO; }
|
miso { yylval=NULL; ccap(); return K_SDI; } // Deprecated
|
||||||
mode { yylval=NULL; return K_MODE; }
|
mode { yylval=NULL; ccap(); return K_MODE; }
|
||||||
mosi { yylval=NULL; return K_MOSI; }
|
mosi { yylval=NULL; ccap(); return K_SDO; } // Deprecated
|
||||||
no { yylval=new_token(K_NO); return K_NO; }
|
no { yylval=new_token(K_NO); return K_NO; }
|
||||||
|
NULL { yylval=NULL; return K_NULL; }
|
||||||
num_banks { yylval=NULL; return K_NUM_PAGES; }
|
num_banks { yylval=NULL; return K_NUM_PAGES; }
|
||||||
num_pages { yylval=NULL; return K_NUM_PAGES; }
|
num_pages { yylval=NULL; ccap(); return K_NUM_PAGES; }
|
||||||
nvm_base { yylval=NULL; return K_NVM_BASE; }
|
nvm_base { yylval=NULL; ccap(); return K_NVM_BASE; }
|
||||||
ocd_base { yylval=NULL; return K_OCD_BASE; }
|
ocd_base { yylval=NULL; ccap(); return K_OCD_BASE; }
|
||||||
ocdrev { yylval=NULL; return K_OCDREV; }
|
ocdrev { yylval=NULL; ccap(); return K_OCDREV; }
|
||||||
offset { yylval=NULL; return K_OFFSET; }
|
offset { yylval=NULL; ccap(); return K_OFFSET; }
|
||||||
page_size { yylval=NULL; return K_PAGE_SIZE; }
|
paged { yylval=NULL; ccap(); return K_PAGED; }
|
||||||
paged { yylval=NULL; return K_PAGED; }
|
pagel { yylval=NULL; ccap(); return K_PAGEL; }
|
||||||
pagel { yylval=NULL; return K_PAGEL; }
|
page_size { yylval=NULL; ccap(); return K_PAGE_SIZE; }
|
||||||
parallel { yylval=NULL; return K_PARALLEL; }
|
parallel { yylval=NULL; ccap(); return K_PARALLEL; }
|
||||||
parent { yylval=NULL; return K_PARENT; }
|
parent { yylval=NULL; return K_PARENT; }
|
||||||
part { yylval=NULL; return K_PART; }
|
part { yylval=NULL; ccap(); current_strct = COMP_AVRPART; return K_PART; }
|
||||||
pgm_enable { yylval=new_token(K_PGM_ENABLE); return K_PGM_ENABLE; }
|
pgm_enable { yylval=new_token(K_PGM_ENABLE); ccap(); return K_PGM_ENABLE; }
|
||||||
pgmled { yylval=NULL; return K_PGMLED; }
|
pgmled { yylval=NULL; ccap(); return K_PGMLED; }
|
||||||
pollindex { yylval=NULL; return K_POLLINDEX; }
|
pollindex { yylval=NULL; ccap(); return K_POLLINDEX; }
|
||||||
pollmethod { yylval=NULL; return K_POLLMETHOD; }
|
pollmethod { yylval=NULL; ccap(); return K_POLLMETHOD; }
|
||||||
pollvalue { yylval=NULL; return K_POLLVALUE; }
|
pollvalue { yylval=NULL; ccap(); return K_POLLVALUE; }
|
||||||
postdelay { yylval=NULL; return K_POSTDELAY; }
|
postdelay { yylval=NULL; ccap(); return K_POSTDELAY; }
|
||||||
poweroffdelay { yylval=NULL; return K_POWEROFFDELAY; }
|
poweroffdelay { yylval=NULL; ccap(); return K_POWEROFFDELAY; }
|
||||||
pp_controlstack { yylval=NULL; return K_PP_CONTROLSTACK; }
|
pp_controlstack { yylval=NULL; ccap(); return K_PP_CONTROLSTACK; }
|
||||||
predelay { yylval=NULL; return K_PREDELAY; }
|
predelay { yylval=NULL; ccap(); return K_PREDELAY; }
|
||||||
progmodedelay { yylval=NULL; return K_PROGMODEDELAY; }
|
progmodedelay { yylval=NULL; ccap(); return K_PROGMODEDELAY; }
|
||||||
programfusepolltimeout { yylval=NULL; return K_PROGRAMFUSEPOLLTIMEOUT; }
|
programfusepolltimeout { yylval=NULL; ccap(); return K_PROGRAMFUSEPOLLTIMEOUT; }
|
||||||
programfusepulsewidth { yylval=NULL; return K_PROGRAMFUSEPULSEWIDTH; }
|
programfusepulsewidth { yylval=NULL; ccap(); return K_PROGRAMFUSEPULSEWIDTH; }
|
||||||
programlockpolltimeout { yylval=NULL; return K_PROGRAMLOCKPOLLTIMEOUT; }
|
programlockpolltimeout { yylval=NULL; ccap(); return K_PROGRAMLOCKPOLLTIMEOUT; }
|
||||||
programlockpulsewidth { yylval=NULL; return K_PROGRAMLOCKPULSEWIDTH; }
|
programlockpulsewidth { yylval=NULL; ccap(); return K_PROGRAMLOCKPULSEWIDTH; }
|
||||||
programmer { yylval=NULL; return K_PROGRAMMER; }
|
programmer { yylval=NULL; ccap(); current_strct = COMP_PROGRAMMER; return K_PROGRAMMER; }
|
||||||
pseudo { yylval=new_token(K_PSEUDO); return K_PSEUDO; }
|
pseudo { yylval=new_token(K_PSEUDO); return K_PSEUDO; }
|
||||||
pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; }
|
pwroff_after_write { yylval=NULL; ccap(); return K_PWROFF_AFTER_WRITE; }
|
||||||
rampz { yylval=NULL; return K_RAMPZ; }
|
rdyled { yylval=NULL; ccap(); return K_RDYLED; }
|
||||||
rdyled { yylval=NULL; return K_RDYLED; }
|
read { yylval=new_token(K_READ); ccap(); return K_READ; }
|
||||||
read { yylval=new_token(K_READ); return K_READ; }
|
read_hi { yylval=new_token(K_READ_HI); ccap(); return K_READ_HI; }
|
||||||
read_hi { yylval=new_token(K_READ_HI); return K_READ_HI; }
|
read_lo { yylval=new_token(K_READ_LO); ccap(); return K_READ_LO; }
|
||||||
read_lo { yylval=new_token(K_READ_LO); return K_READ_LO; }
|
readback { yylval=NULL; ccap(); return K_READBACK; }
|
||||||
readback_p1 { yylval=NULL; return K_READBACK_P1; }
|
readback_p1 { yylval=NULL; ccap(); return K_READBACK_P1; }
|
||||||
readback_p2 { yylval=NULL; return K_READBACK_P2; }
|
readback_p2 { yylval=NULL; ccap(); return K_READBACK_P2; }
|
||||||
readsize { yylval=NULL; return K_READSIZE; }
|
readsize { yylval=NULL; ccap(); return K_READSIZE; }
|
||||||
reset { yylval=new_token(K_RESET); return K_RESET; }
|
reset { yylval=new_token(K_RESET); ccap(); return K_RESET; }
|
||||||
resetdelay { yylval=NULL; return K_RESETDELAY; }
|
resetdelay { yylval=NULL; ccap(); return K_RESETDELAY; }
|
||||||
resetdelayms { yylval=NULL; return K_RESETDELAYMS; }
|
resetdelayms { yylval=NULL; ccap(); return K_RESETDELAYMS; }
|
||||||
resetdelayus { yylval=NULL; return K_RESETDELAYUS; }
|
resetdelayus { yylval=NULL; ccap(); return K_RESETDELAYUS; }
|
||||||
retry_pulse { yylval=NULL; return K_RETRY_PULSE; }
|
retry_pulse { yylval=NULL; ccap(); return K_RETRY_PULSE; }
|
||||||
sck { yylval=new_token(K_SCK); return K_SCK; }
|
sck { yylval=new_token(K_SCK); ccap(); return K_SCK; }
|
||||||
serial { yylval=NULL; return K_SERIAL; }
|
sdi { yylval=NULL; ccap(); return K_SDI; }
|
||||||
signature { yylval=NULL; return K_SIGNATURE; }
|
sdo { yylval=NULL; ccap(); return K_SDO; }
|
||||||
size { yylval=NULL; return K_SIZE; }
|
serial { yylval=NULL; ccap(); return K_SERIAL; }
|
||||||
spmcr { yylval=NULL; return K_SPMCR; }
|
signature { yylval=NULL; ccap(); return K_SIGNATURE; }
|
||||||
stabdelay { yylval=NULL; return K_STABDELAY; }
|
size { yylval=NULL; ccap(); return K_SIZE; }
|
||||||
stk500_devcode { yylval=NULL; return K_STK500_DEVCODE; }
|
spi { yylval=NULL; return K_SPI; }
|
||||||
synchcycles { yylval=NULL; return K_SYNCHCYCLES; }
|
stabdelay { yylval=NULL; ccap(); return K_STABDELAY; }
|
||||||
synchloops { yylval=NULL; return K_SYNCHLOOPS; }
|
stk500_devcode { yylval=NULL; ccap(); return K_STK500_DEVCODE; }
|
||||||
timeout { yylval=NULL; return K_TIMEOUT; }
|
synchcycles { yylval=NULL; ccap(); return K_SYNCHCYCLES; }
|
||||||
togglevtg { yylval=NULL; return K_TOGGLEVTG; }
|
synchloops { yylval=NULL; ccap(); return K_SYNCHLOOPS; }
|
||||||
type { yylval=NULL; return K_TYPE; }
|
timeout { yylval=NULL; ccap(); return K_TIMEOUT; }
|
||||||
|
togglevtg { yylval=NULL; ccap(); return K_TOGGLEVTG; }
|
||||||
|
type { yylval=NULL; ccap(); return K_TYPE; }
|
||||||
usb { yylval=NULL; return K_USB; }
|
usb { yylval=NULL; return K_USB; }
|
||||||
usbdev { yylval=NULL; return K_USBDEV; }
|
usbdev { yylval=NULL; ccap(); return K_USBDEV; }
|
||||||
usbpid { yylval=NULL; return K_USBPID; }
|
usbpid { yylval=NULL; ccap(); return K_USBPID; }
|
||||||
usbproduct { yylval=NULL; return K_USBPRODUCT; }
|
usbproduct { yylval=NULL; ccap(); return K_USBPRODUCT; }
|
||||||
usbsn { yylval=NULL; return K_USBSN; }
|
usbsn { yylval=NULL; ccap(); return K_USBSN; }
|
||||||
usbvendor { yylval=NULL; return K_USBVENDOR; }
|
usbvendor { yylval=NULL; ccap(); return K_USBVENDOR; }
|
||||||
usbvid { yylval=NULL; return K_USBVID; }
|
usbvid { yylval=NULL; ccap(); return K_USBVID; }
|
||||||
vcc { yylval=NULL; return K_VCC; }
|
vcc { yylval=NULL; ccap(); return K_VCC; }
|
||||||
vfyled { yylval=NULL; return K_VFYLED; }
|
vfyled { yylval=NULL; ccap(); return K_VFYLED; }
|
||||||
write { yylval=new_token(K_WRITE); return K_WRITE; }
|
write { yylval=new_token(K_WRITE); ccap(); return K_WRITE; }
|
||||||
write_hi { yylval=new_token(K_WRITE_HI); return K_WRITE_HI; }
|
write_hi { yylval=new_token(K_WRITE_HI); ccap(); return K_WRITE_HI; }
|
||||||
write_lo { yylval=new_token(K_WRITE_LO); return K_WRITE_LO; }
|
write_lo { yylval=new_token(K_WRITE_LO); ccap(); return K_WRITE_LO; }
|
||||||
writepage { yylval=new_token(K_WRITEPAGE); return K_WRITEPAGE; }
|
writepage { yylval=new_token(K_WRITEPAGE); ccap(); return K_WRITEPAGE; }
|
||||||
yes { yylval=new_token(K_YES); return K_YES; }
|
yes { yylval=new_token(K_YES); return K_YES; }
|
||||||
|
|
||||||
"," { yylval = NULL; pyytext(); return TKN_COMMA; }
|
"," { yylval = NULL; pyytext(); return TKN_COMMA; }
|
||||||
"=" { yylval = NULL; pyytext(); return TKN_EQUAL; }
|
"=" { yylval = NULL; pyytext(); return TKN_EQUAL; }
|
||||||
";" { yylval = NULL; pyytext(); return TKN_SEMI; }
|
";" { yylval = NULL; pyytext(); return TKN_SEMI; }
|
||||||
"~" { yylval = NULL; pyytext(); return TKN_TILDE; }
|
|
||||||
|
"|" { yylval = NULL; pyytext(); return OP_OR; }
|
||||||
|
"^" { yylval = NULL; pyytext(); return OP_XOR; }
|
||||||
|
"&" { yylval = NULL; pyytext(); return OP_AND; }
|
||||||
|
"+" { yylval = NULL; pyytext(); return OP_PLUS; }
|
||||||
|
"-" { yylval = NULL; pyytext(); return OP_MINUS; }
|
||||||
|
"*" { yylval = NULL; pyytext(); return OP_TIMES; }
|
||||||
|
"/" { yylval = NULL; pyytext(); return OP_DIVIDE; }
|
||||||
|
"%" { yylval = NULL; pyytext(); return OP_MODULO; }
|
||||||
|
"~" { yylval = NULL; pyytext(); return OP_TILDE; }
|
||||||
|
|
||||||
"(" { yylval = NULL; pyytext(); return TKN_LEFT_PAREN; }
|
"(" { yylval = NULL; pyytext(); return TKN_LEFT_PAREN; }
|
||||||
")" { yylval = NULL; pyytext(); return TKN_RIGHT_PAREN; }
|
")" { yylval = NULL; pyytext(); return TKN_RIGHT_PAREN; }
|
||||||
|
|
||||||
"\n" { lineno++; }
|
"\n" { cfg_lineno++; }
|
||||||
[ \r\t]+ { /* ignore whitespace */ }
|
[ \r\t]+ { /* ignore whitespace */ }
|
||||||
|
|
||||||
c: { yyerror("possible old-style config file entry\n"
|
c: { yyerror("possible old-style config file entry\n"
|
||||||
|
|
597
src/libavrdude.h
597
src/libavrdude.h
|
@ -27,6 +27,16 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
typedef uint32_t pinmask_t;
|
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, eg, by avr_signature() if caller
|
||||||
|
// might proceed with chip erase
|
||||||
|
|
||||||
/* formerly lists.h */
|
/* formerly lists.h */
|
||||||
|
|
||||||
|
@ -159,6 +169,7 @@ enum ctl_stack_t {
|
||||||
CTL_STACK_HVSP /* high voltage serial programming control stack */
|
CTL_STACK_HVSP /* high voltage serial programming control stack */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* serial programming instruction bit specifications
|
* serial programming instruction bit specifications
|
||||||
*/
|
*/
|
||||||
|
@ -173,23 +184,33 @@ typedef struct opcode {
|
||||||
} OPCODE;
|
} OPCODE;
|
||||||
|
|
||||||
|
|
||||||
#define AVRPART_SERIALOK 0x0001 /* part supports serial programming */
|
// Any changes here, please also reflect in dev_part_strct() of developer_opts.c
|
||||||
#define AVRPART_PARALLELOK 0x0002 /* part supports parallel programming */
|
#define AVRPART_SERIALOK 1 // Part supports serial programming
|
||||||
#define AVRPART_PSEUDOPARALLEL 0x0004 /* part has pseudo parallel support */
|
#define AVRPART_PARALLELOK 2 // Part supports parallel programming
|
||||||
#define AVRPART_HAS_JTAG 0x0008 /* part has a JTAG i/f */
|
#define AVRPART_PSEUDOPARALLEL 4 // Part has pseudo parallel support
|
||||||
#define AVRPART_ALLOWFULLPAGEBITSTREAM 0x0010 /* JTAG ICE mkII param. */
|
#define AVRPART_ALLOWFULLPAGEBITSTREAM 8 // JTAG ICE mkII param
|
||||||
#define AVRPART_ENABLEPAGEPROGRAMMING 0x0020 /* JTAG ICE mkII param. */
|
#define AVRPART_ENABLEPAGEPROGRAMMING 16 // JTAG ICE mkII param
|
||||||
#define AVRPART_HAS_DW 0x0040 /* part has a debugWire i/f */
|
#define AVRPART_IS_AT90S1200 32 // Part is an AT90S1200, needs special treatment
|
||||||
#define AVRPART_HAS_PDI 0x0080 /* part has PDI i/f rather than ISP (ATxmega) */
|
|
||||||
#define AVRPART_AVR32 0x0100 /* part is in AVR32 family */
|
// Programming modes for parts and programmers: reflect changes in lexer.l, developer_opts.c and config.c
|
||||||
#define AVRPART_INIT_SMC 0x0200 /* part will undergo chip erase */
|
#define PM_SPM 1 // Bootloaders, self-programming with SPM opcodes or NVM Controllers
|
||||||
#define AVRPART_WRITE 0x0400 /* at least one write operation specified */
|
#define PM_TPI 2 // Tiny Programming Interface (t4, t5, t9, t10, t20, t40, t102, t104)
|
||||||
#define AVRPART_HAS_TPI 0x0800 /* part has TPI i/f rather than ISP (ATtiny4/5/9/10) */
|
#define PM_ISP 4 // SPI programming for In-System Programming (almost all classic parts)
|
||||||
#define AVRPART_IS_AT90S1200 0x1000 /* part is an AT90S1200 (needs special treatment) */
|
#define PM_PDI 8 // Program and Debug Interface (xmega parts)
|
||||||
#define AVRPART_HAS_UPDI 0x2000 /* part has UPDI i/f (AVR8X) */
|
#define PM_UPDI 16 // Unified Program and Debug Interface
|
||||||
|
#define PM_HVSP 32 // High Voltage Serial Programming (some classic parts)
|
||||||
|
#define PM_HVPP 64 // High Voltage Parallel Programming (most non-HVSP classic parts)
|
||||||
|
#define PM_debugWIRE 128 // Simpler alternative to JTAG (a subset of HVPP/HVSP parts)
|
||||||
|
#define PM_JTAG 256 // Joint Test Action Group standard (some classic parts)
|
||||||
|
#define PM_JTAGmkI 512 // Subset of PM_JTAG, older parts, Atmel ICE mkI
|
||||||
|
#define PM_XMEGAJTAG 1024 // JTAG, some XMEGA parts
|
||||||
|
#define PM_AVR32JTAG 2048 // JTAG for 32-bit AVRs
|
||||||
|
#define PM_aWire 4096 // For 32-bit AVRs
|
||||||
|
|
||||||
|
#define HV_UPDI_VARIANT_0 0 /* Shared UPDI/GPIO/RESET pin, HV on UPDI pin (tinyAVR0/1/2)*/
|
||||||
|
#define HV_UPDI_VARIANT_1 1 /* Dedicated UPDI pin, no HV (megaAVR0/AVR-Dx) */
|
||||||
|
#define HV_UPDI_VARIANT_2 2 /* Shared UPDI pin, HV on _RESET (AVR-DD/AVR-Ex) */
|
||||||
|
|
||||||
#define AVR_DESCLEN 64
|
|
||||||
#define AVR_IDLEN 32
|
|
||||||
#define AVR_FAMILYIDLEN 7
|
#define AVR_FAMILYIDLEN 7
|
||||||
#define AVR_SIBLEN 16
|
#define AVR_SIBLEN 16
|
||||||
#define CTL_STACK_SIZE 32
|
#define CTL_STACK_SIZE 32
|
||||||
|
@ -198,10 +219,27 @@ typedef struct opcode {
|
||||||
|
|
||||||
#define TAG_ALLOCATED 1 /* memory byte is allocated */
|
#define TAG_ALLOCATED 1 /* memory byte is allocated */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Any changes in AVRPART or AVRMEM, please also ensure changes are made in
|
||||||
|
* - lexer.l
|
||||||
|
* - Either Component_t avr_comp[] of config.c or in config_gram.y
|
||||||
|
* - dev_part_strct() in developer_opts.c
|
||||||
|
* - avr_new_part() and/or avr_new_memtype() in avrpart.c for
|
||||||
|
* initialisation; note that all const char * must be initialised with ""
|
||||||
|
*/
|
||||||
typedef struct avrpart {
|
typedef struct avrpart {
|
||||||
char desc[AVR_DESCLEN]; /* long part name */
|
const char * desc; /* long part name */
|
||||||
char id[AVR_IDLEN]; /* short part name */
|
const char * id; /* short part name */
|
||||||
char family_id[AVR_FAMILYIDLEN+1]; /* family id in the SIB (avr8x) */
|
LISTID comments; // Used by developer options -p*/[ASsr...]
|
||||||
|
const char * parent_id; /* Used by developer options */
|
||||||
|
const char * family_id; /* family id in the SIB (avr8x) */
|
||||||
|
int prog_modes; /* Programming interfaces, see #define PM_... */
|
||||||
|
int mcuid; /* Unique id in 0..2039 for urclock programmer */
|
||||||
|
int n_interrupts; /* Number of interrupts, used for vector bootloaders */
|
||||||
|
int n_page_erase; /* If set, number of pages erased during NVM erase */
|
||||||
|
int n_boot_sections; /* Number of boot sections */
|
||||||
|
int boot_section_size; /* Size of (smallest) boot section, if any */
|
||||||
|
int hvupdi_variant; /* HV pulse on UPDI pin, no pin or RESET pin */
|
||||||
int stk500_devcode; /* stk500 device code */
|
int stk500_devcode; /* stk500 device code */
|
||||||
int avr910_devcode; /* avr910 device code */
|
int avr910_devcode; /* avr910 device code */
|
||||||
int chip_erase_delay; /* microseconds */
|
int chip_erase_delay; /* microseconds */
|
||||||
|
@ -214,65 +252,74 @@ typedef struct avrpart {
|
||||||
this pin (PIN_AVR_*) */
|
this pin (PIN_AVR_*) */
|
||||||
unsigned flags; /* see AVRPART_ masks */
|
unsigned flags; /* see AVRPART_ masks */
|
||||||
|
|
||||||
int timeout; /* stk500 v2 xml file parameter */
|
/* STK500 v2 parameters from ATDF files */
|
||||||
int stabdelay; /* stk500 v2 xml file parameter */
|
int timeout;
|
||||||
int cmdexedelay; /* stk500 v2 xml file parameter */
|
int stabdelay;
|
||||||
int synchloops; /* stk500 v2 xml file parameter */
|
int cmdexedelay;
|
||||||
int bytedelay; /* stk500 v2 xml file parameter */
|
int synchloops;
|
||||||
int pollindex; /* stk500 v2 xml file parameter */
|
int bytedelay;
|
||||||
unsigned char pollvalue; /* stk500 v2 xml file parameter */
|
int pollindex;
|
||||||
int predelay; /* stk500 v2 xml file parameter */
|
unsigned char pollvalue;
|
||||||
int postdelay; /* stk500 v2 xml file parameter */
|
int predelay;
|
||||||
int pollmethod; /* stk500 v2 xml file parameter */
|
int postdelay;
|
||||||
|
int pollmethod;
|
||||||
|
|
||||||
enum ctl_stack_t ctl_stack_type; /* what to use the ctl stack for */
|
enum ctl_stack_t ctl_stack_type; /* what to use the ctl stack for */
|
||||||
unsigned char controlstack[CTL_STACK_SIZE]; /* stk500v2 PP/HVSP ctl stack */
|
unsigned char controlstack[CTL_STACK_SIZE]; /* stk500v2 PP/HVSP ctl stack */
|
||||||
unsigned char flash_instr[FLASH_INSTR_SIZE]; /* flash instructions (debugWire, JTAG) */
|
unsigned char flash_instr[FLASH_INSTR_SIZE]; /* flash instructions (debugWire, JTAG) */
|
||||||
unsigned char eeprom_instr[EEPROM_INSTR_SIZE]; /* EEPROM instructions (debugWire, JTAG) */
|
unsigned char eeprom_instr[EEPROM_INSTR_SIZE]; /* EEPROM instructions (debugWire, JTAG) */
|
||||||
|
|
||||||
int hventerstabdelay; /* stk500 v2 hv mode parameter */
|
/* STK500 v2 hv mode parameters */
|
||||||
int progmodedelay; /* stk500 v2 hv mode parameter */
|
int hventerstabdelay;
|
||||||
int latchcycles; /* stk500 v2 hv mode parameter */
|
int progmodedelay;
|
||||||
int togglevtg; /* stk500 v2 hv mode parameter */
|
int latchcycles;
|
||||||
int poweroffdelay; /* stk500 v2 hv mode parameter */
|
int togglevtg;
|
||||||
int resetdelayms; /* stk500 v2 hv mode parameter */
|
int poweroffdelay;
|
||||||
int resetdelayus; /* stk500 v2 hv mode parameter */
|
int resetdelayms;
|
||||||
int hvleavestabdelay; /* stk500 v2 hv mode parameter */
|
int resetdelayus;
|
||||||
int resetdelay; /* stk500 v2 hv mode parameter */
|
int hvleavestabdelay;
|
||||||
int chiperasepulsewidth; /* stk500 v2 hv mode parameter */
|
int resetdelay;
|
||||||
int chiperasepolltimeout; /* stk500 v2 hv mode parameter */
|
int chiperasepulsewidth;
|
||||||
int chiperasetime; /* stk500 v2 hv mode parameter */
|
int chiperasepolltimeout;
|
||||||
int programfusepulsewidth; /* stk500 v2 hv mode parameter */
|
int chiperasetime;
|
||||||
int programfusepolltimeout; /* stk500 v2 hv mode parameter */
|
int programfusepulsewidth;
|
||||||
int programlockpulsewidth; /* stk500 v2 hv mode parameter */
|
int programfusepolltimeout;
|
||||||
int programlockpolltimeout; /* stk500 v2 hv mode parameter */
|
int programlockpulsewidth;
|
||||||
int synchcycles; /* stk500 v2 hv mode parameter */
|
int programlockpolltimeout;
|
||||||
int hvspcmdexedelay; /* stk500 v2 xml file parameter */
|
int synchcycles;
|
||||||
|
int hvspcmdexedelay;
|
||||||
|
|
||||||
unsigned char idr; /* JTAG ICE mkII XML file parameter */
|
|
||||||
unsigned char rampz; /* JTAG ICE mkII XML file parameter */
|
|
||||||
unsigned char spmcr; /* JTAG ICE mkII XML file parameter */
|
|
||||||
unsigned short eecr; /* JTAC ICE mkII XML file parameter */
|
|
||||||
unsigned int mcu_base; /* Base address of MCU control block in ATxmega devices */
|
|
||||||
unsigned int nvm_base; /* Base address of NVM controller in ATxmega devices */
|
|
||||||
unsigned int ocd_base; /* Base address of OCD module in AVR8X/UPDI devices */
|
|
||||||
int ocdrev; /* OCD revision (JTAGICE3 parameter, from AS6 XML files) */
|
|
||||||
|
|
||||||
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
/* debugWIRE and/or JTAG ICE mkII XML file parameters */
|
||||||
|
unsigned char idr; /* I/O address of IDR (OCD) reg */
|
||||||
|
unsigned char rampz; /* I/O address of RAMPZ reg */
|
||||||
|
unsigned char spmcr; /* memory address of SPMCR reg */
|
||||||
|
unsigned char eecr; /* memory address of EECR reg */
|
||||||
|
unsigned char eind; /* memory address of EIND reg */
|
||||||
|
unsigned int mcu_base; /* Base address of MCU control block in ATxmega devices */
|
||||||
|
unsigned int nvm_base; /* Base address of NVM controller in ATxmega devices */
|
||||||
|
unsigned int ocd_base; /* Base address of OCD module in AVR8X/UPDI devices */
|
||||||
|
int ocdrev; /* OCD revision (JTAGICE3 parameter, from AS6 XML files) */
|
||||||
|
|
||||||
LISTID mem; /* avr memory definitions */
|
/* Bootloader paramater */
|
||||||
LISTID mem_alias; /* memory alias definitions */
|
unsigned char autobaud_sync; /* Sync byte for bootloader autobaud, must be <= 0x30 */
|
||||||
char config_file[PATH_MAX]; /* config file where defined */
|
|
||||||
int lineno; /* config file line number */
|
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
||||||
|
|
||||||
|
LISTID mem; /* avr memory definitions */
|
||||||
|
LISTID mem_alias; /* memory alias definitions */
|
||||||
|
const char * config_file; /* config file where defined */
|
||||||
|
int lineno; /* config file line number */
|
||||||
} AVRPART;
|
} AVRPART;
|
||||||
|
|
||||||
#define AVR_MEMDESCLEN 64
|
|
||||||
typedef struct avrmem {
|
typedef struct avrmem {
|
||||||
char desc[AVR_MEMDESCLEN]; /* memory description ("flash", "eeprom", etc) */
|
const char *desc; /* memory description ("flash", "eeprom", etc) */
|
||||||
|
LISTID comments; // Used by developer options -p*/[ASsr...]
|
||||||
int paged; /* page addressed (e.g. ATmega flash) */
|
int paged; /* page addressed (e.g. ATmega flash) */
|
||||||
int size; /* total memory size in bytes */
|
int size; /* total memory size in bytes */
|
||||||
int page_size; /* size of memory page (if page addressed) */
|
int page_size; /* size of memory page (if page addressed) */
|
||||||
int num_pages; /* number of pages (if page addressed) */
|
int num_pages; /* number of pages (if page addressed) */
|
||||||
|
int n_word_writes; /* TPI only: number words to write at a time */
|
||||||
unsigned int offset; /* offset in IO memory (ATxmega) */
|
unsigned int offset; /* offset in IO memory (ATxmega) */
|
||||||
int min_write_delay; /* microseconds */
|
int min_write_delay; /* microseconds */
|
||||||
int max_write_delay; /* microseconds */
|
int max_write_delay; /* microseconds */
|
||||||
|
@ -294,7 +341,7 @@ typedef struct avrmem {
|
||||||
} AVRMEM;
|
} AVRMEM;
|
||||||
|
|
||||||
typedef struct avrmem_alias {
|
typedef struct avrmem_alias {
|
||||||
char desc[AVR_MEMDESCLEN]; /* alias name ("syscfg0" etc.) */
|
const char *desc; /* alias name ("syscfg0" etc.) */
|
||||||
AVRMEM *aliased_mem;
|
AVRMEM *aliased_mem;
|
||||||
} AVRMEM_ALIAS;
|
} AVRMEM_ALIAS;
|
||||||
|
|
||||||
|
@ -302,38 +349,46 @@ typedef struct avrmem_alias {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int intlog2(unsigned int n);
|
||||||
|
|
||||||
/* Functions for OPCODE structures */
|
/* Functions for OPCODE structures */
|
||||||
OPCODE * avr_new_opcode(void);
|
OPCODE * avr_new_opcode(void);
|
||||||
void avr_free_opcode(OPCODE * op);
|
void avr_free_opcode(OPCODE * op);
|
||||||
int avr_set_bits(OPCODE * op, unsigned char * cmd);
|
int avr_set_bits(const OPCODE *op, unsigned char *cmd);
|
||||||
int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr);
|
int avr_set_addr(const OPCODE *op, unsigned char *cmd, unsigned long addr);
|
||||||
int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data);
|
int avr_set_addr_mem(const AVRMEM *mem, int opnum, unsigned char *cmd, unsigned long addr);
|
||||||
int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data);
|
int avr_set_input(const OPCODE *op, unsigned char *cmd, unsigned char data);
|
||||||
int avr_get_output_index(OPCODE * op);
|
int avr_get_output(const OPCODE *op, const unsigned char *res, unsigned char *data);
|
||||||
|
int avr_get_output_index(const OPCODE *op);
|
||||||
|
char cmdbitchar(CMDBIT cb);
|
||||||
|
char *cmdbitstr(CMDBIT cb);
|
||||||
|
const char *opcodename(int opnum);
|
||||||
|
char *opcode2str(const OPCODE *op, int opnum, int detailed);
|
||||||
|
|
||||||
/* Functions for AVRMEM structures */
|
/* Functions for AVRMEM structures */
|
||||||
AVRMEM * avr_new_memtype(void);
|
AVRMEM * avr_new_memtype(void);
|
||||||
AVRMEM_ALIAS * avr_new_memalias(void);
|
AVRMEM_ALIAS * avr_new_memalias(void);
|
||||||
int avr_initmem(AVRPART * p);
|
int avr_initmem(const AVRPART *p);
|
||||||
AVRMEM * avr_dup_mem(AVRMEM * m);
|
AVRMEM * avr_dup_mem(const AVRMEM *m);
|
||||||
void avr_free_mem(AVRMEM * m);
|
void avr_free_mem(AVRMEM * m);
|
||||||
void avr_free_memalias(AVRMEM_ALIAS * m);
|
void avr_free_memalias(AVRMEM_ALIAS * m);
|
||||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc);
|
AVRMEM * avr_locate_mem(const AVRPART *p, const char *desc);
|
||||||
AVRMEM * avr_locate_mem_noalias(AVRPART * p, char * desc);
|
AVRMEM * avr_locate_mem_noalias(const AVRPART *p, const char *desc);
|
||||||
AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, char * desc);
|
AVRMEM_ALIAS * avr_locate_memalias(const AVRPART *p, const char *desc);
|
||||||
AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig);
|
AVRMEM_ALIAS * avr_find_memalias(const AVRPART *p, const AVRMEM *m_orig);
|
||||||
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m,
|
||||||
int type, int verbose);
|
const AVRPART *p, int verbose);
|
||||||
|
|
||||||
/* Functions for AVRPART structures */
|
/* Functions for AVRPART structures */
|
||||||
AVRPART * avr_new_part(void);
|
AVRPART * avr_new_part(void);
|
||||||
AVRPART * avr_dup_part(AVRPART * d);
|
AVRPART * avr_dup_part(const AVRPART *d);
|
||||||
void avr_free_part(AVRPART * d);
|
void avr_free_part(AVRPART * d);
|
||||||
AVRPART * locate_part(LISTID parts, char * partdesc);
|
AVRPART * locate_part(const LISTID parts, const char *partdesc);
|
||||||
AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode);
|
AVRPART * locate_part_by_avr910_devcode(const LISTID parts, int devcode);
|
||||||
AVRPART * locate_part_by_signature(LISTID parts, unsigned char * sig,
|
AVRPART * locate_part_by_signature(const LISTID parts, unsigned char *sig,
|
||||||
int sigsize);
|
int sigsize);
|
||||||
void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose);
|
void avr_display(FILE *f, const AVRPART *p, const char *prefix, int verbose);
|
||||||
|
|
||||||
typedef void (*walk_avrparts_cb)(const char *name, const char *desc,
|
typedef void (*walk_avrparts_cb)(const char *name, const char *desc,
|
||||||
const char *cfgname, int cfglineno,
|
const char *cfgname, int cfglineno,
|
||||||
|
@ -341,6 +396,8 @@ typedef void (*walk_avrparts_cb)(const char *name, const char *desc,
|
||||||
void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie);
|
void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie);
|
||||||
void sort_avrparts(LISTID avrparts);
|
void sort_avrparts(LISTID avrparts);
|
||||||
|
|
||||||
|
int part_match(const char *pattern, const char *string);
|
||||||
|
|
||||||
int compare_memory_masked(AVRMEM * m, uint8_t buf1, uint8_t buf2);
|
int compare_memory_masked(AVRMEM * m, uint8_t buf1, uint8_t buf2);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -354,8 +411,8 @@ enum {
|
||||||
PPI_AVR_BUFF,
|
PPI_AVR_BUFF,
|
||||||
PIN_AVR_RESET,
|
PIN_AVR_RESET,
|
||||||
PIN_AVR_SCK,
|
PIN_AVR_SCK,
|
||||||
PIN_AVR_MOSI,
|
PIN_AVR_SDO,
|
||||||
PIN_AVR_MISO,
|
PIN_AVR_SDI,
|
||||||
PIN_LED_ERR,
|
PIN_LED_ERR,
|
||||||
PIN_LED_RDY,
|
PIN_LED_RDY,
|
||||||
PIN_LED_PGM,
|
PIN_LED_PGM,
|
||||||
|
@ -377,7 +434,7 @@ enum {
|
||||||
/** Number of pins in each element of the bitfield */
|
/** Number of pins in each element of the bitfield */
|
||||||
#define PIN_FIELD_ELEMENT_SIZE (sizeof(pinmask_t) * 8)
|
#define PIN_FIELD_ELEMENT_SIZE (sizeof(pinmask_t) * 8)
|
||||||
/** Numer of elements to store the complete bitfield of all pins */
|
/** Numer of elements to store the complete bitfield of all pins */
|
||||||
#define PIN_FIELD_SIZE ((PIN_MAX + PIN_FIELD_ELEMENT_SIZE)/PIN_FIELD_ELEMENT_SIZE)
|
#define PIN_FIELD_SIZE ((PIN_MAX+1 + PIN_FIELD_ELEMENT_SIZE-1)/PIN_FIELD_ELEMENT_SIZE)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This sets the corresponding bits to 1 or 0, the inverse mask is used to invert the value in necessary.
|
* This sets the corresponding bits to 1 or 0, the inverse mask is used to invert the value in necessary.
|
||||||
|
@ -488,7 +545,15 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist
|
||||||
const char * avr_pin_name(int pinname);
|
const char * avr_pin_name(int pinname);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function returns a string representation of defined pins eg. ~1,2,~4,~5,7
|
* Returns the name of the pin as lowercase string.
|
||||||
|
*
|
||||||
|
* @param pinname the pinname which we want as string.
|
||||||
|
* @returns a lowercase string with the pinname, or <unknown> if pinname is invalid.
|
||||||
|
*/
|
||||||
|
const char * avr_pin_lcname(int pinname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns a string of defined pins, eg, ~1,2,~4,~5,7 or " (not used)"
|
||||||
* Another execution of this function will overwrite the previous result in the static buffer.
|
* Another execution of this function will overwrite the previous result in the static buffer.
|
||||||
*
|
*
|
||||||
* @param[in] pindef the pin definition for which we want the string representation
|
* @param[in] pindef the pin definition for which we want the string representation
|
||||||
|
@ -497,9 +562,17 @@ const char * avr_pin_name(int pinname);
|
||||||
const char * pins_to_str(const struct pindef_t * const pindef);
|
const char * pins_to_str(const struct pindef_t * const pindef);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function returns a string representation of pins in the mask eg. 1,3,5-7,9,12
|
* This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or ""
|
||||||
|
*
|
||||||
|
* @param[in] pindef the pin definition for which we want the string representation
|
||||||
|
* @returns a pointer to a string, which was created by strdup
|
||||||
|
*/
|
||||||
|
char *pins_to_strdup(const struct pindef_t * const pindef);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns a string representation of pins in the mask, eg, 1,3,5-7,9,12
|
||||||
* Another execution of this function will overwrite the previous result in the static buffer.
|
* Another execution of this function will overwrite the previous result in the static buffer.
|
||||||
* Consecutive pin number are representated as start-end.
|
* Consecutive pin number are represented as start-end.
|
||||||
*
|
*
|
||||||
* @param[in] pinmask the pin mask for which we want the string representation
|
* @param[in] pinmask the pin mask for which we want the string representation
|
||||||
* @returns pointer to a static string.
|
* @returns pointer to a static string.
|
||||||
|
@ -516,7 +589,9 @@ const char * pinmask_to_str(const pinmask_t * const pinmask);
|
||||||
|
|
||||||
The target file will be selected at configure time. */
|
The target file will be selected at configure time. */
|
||||||
|
|
||||||
extern long serial_recv_timeout;
|
extern long serial_recv_timeout; /* ms */
|
||||||
|
extern long serial_drain_timeout; /* ms */
|
||||||
|
|
||||||
union filedescriptor
|
union filedescriptor
|
||||||
{
|
{
|
||||||
int ifd;
|
int ifd;
|
||||||
|
@ -571,19 +646,19 @@ union pinfo
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct serial_device
|
struct serial_device {
|
||||||
{
|
|
||||||
// open should return -1 on error, other values on success
|
// open should return -1 on error, other values on success
|
||||||
int (*open)(char * port, union pinfo pinfo, union filedescriptor *fd);
|
int (*open)(const char *port, union pinfo pinfo, union filedescriptor *fd);
|
||||||
int (*setparams)(union filedescriptor *fd, long baud, unsigned long cflags);
|
int (*setparams)(const union filedescriptor *fd, long baud, unsigned long cflags);
|
||||||
void (*close)(union filedescriptor *fd);
|
void (*close)(union filedescriptor *fd);
|
||||||
|
|
||||||
int (*send)(union filedescriptor *fd, const unsigned char * buf, size_t buflen);
|
int (*send)(const union filedescriptor *fd, const unsigned char * buf, size_t buflen);
|
||||||
int (*recv)(union filedescriptor *fd, unsigned char * buf, size_t buflen);
|
int (*recv)(const union filedescriptor *fd, unsigned char * buf, size_t buflen);
|
||||||
int (*drain)(union filedescriptor *fd, int display);
|
int (*drain)(const union filedescriptor *fd, int display);
|
||||||
|
|
||||||
int (*set_dtr_rts)(union filedescriptor *fd, int is_on);
|
int (*set_dtr_rts)(const union filedescriptor *fd, int is_on);
|
||||||
|
|
||||||
|
const char *usbsn;
|
||||||
int flags;
|
int flags;
|
||||||
#define SERDEV_FL_NONE 0x0000 /* no flags */
|
#define SERDEV_FL_NONE 0x0000 /* no flags */
|
||||||
#define SERDEV_FL_CANSETSPEED 0x0001 /* device can change speed */
|
#define SERDEV_FL_CANSETSPEED 0x0001 /* device can change speed */
|
||||||
|
@ -604,15 +679,21 @@ extern struct serial_device usbhid_serdev;
|
||||||
#define serial_drain (serdev->drain)
|
#define serial_drain (serdev->drain)
|
||||||
#define serial_set_dtr_rts (serdev->set_dtr_rts)
|
#define serial_set_dtr_rts (serdev->set_dtr_rts)
|
||||||
|
|
||||||
|
// See avrcache.c
|
||||||
|
typedef struct { // Memory cache for a subset of cached pages
|
||||||
|
int size, page_size; // Size of cache (flash or eeprom size) and page size
|
||||||
|
unsigned int offset; // Offset of flash/eeprom memory
|
||||||
|
unsigned char *cont, *copy; // current memory contens and device copy of it
|
||||||
|
unsigned char *iscached; // iscached[i] set when page i has been loaded
|
||||||
|
} AVR_Cache;
|
||||||
|
|
||||||
/* formerly pgm.h */
|
/* formerly pgm.h */
|
||||||
|
|
||||||
#define ON 1
|
#define ON 1
|
||||||
#define OFF 0
|
#define OFF 0
|
||||||
|
|
||||||
#define PGM_DESCLEN 80
|
|
||||||
#define PGM_PORTLEN PATH_MAX
|
#define PGM_PORTLEN PATH_MAX
|
||||||
#define PGM_TYPELEN 32
|
#define PGM_TYPELEN 32
|
||||||
#define PGM_USBSTRINGLEN 256
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EXIT_VCC_UNSPEC,
|
EXIT_VCC_UNSPEC,
|
||||||
|
@ -635,106 +716,142 @@ typedef enum {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CONNTYPE_PARALLEL,
|
CONNTYPE_PARALLEL,
|
||||||
CONNTYPE_SERIAL,
|
CONNTYPE_SERIAL,
|
||||||
CONNTYPE_USB
|
CONNTYPE_USB,
|
||||||
|
CONNTYPE_SPI
|
||||||
} conntype_t;
|
} conntype_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Any changes in PROGRAMMER, please also ensure changes are made in
|
||||||
|
* - lexer.l
|
||||||
|
* - Either Component_t avr_comp[] of config.c or config_gram.y
|
||||||
|
* - dev_pgm_strct() in developer_opts.c
|
||||||
|
* - pgm_new() in pgm.c for initialisation; note that all const char * must
|
||||||
|
* be initialised with ""
|
||||||
|
*/
|
||||||
typedef struct programmer_t {
|
typedef struct programmer_t {
|
||||||
LISTID id;
|
LISTID id;
|
||||||
char desc[PGM_DESCLEN];
|
const char *desc;
|
||||||
char type[PGM_TYPELEN];
|
void (*initpgm)(struct programmer_t *pgm); // Sets up the AVRDUDE programmer
|
||||||
char port[PGM_PORTLEN];
|
LISTID comments; // Used by developer options -c*/[ASsr...]
|
||||||
void (*initpgm)(struct programmer_t * pgm);
|
const char *parent_id; // Used by developer options
|
||||||
unsigned int pinno[N_PINS];
|
int prog_modes; // Programming interfaces, see #define PM_...
|
||||||
struct pindef_t pin[N_PINS];
|
struct pindef_t pin[N_PINS];
|
||||||
exit_vcc_t exit_vcc;
|
|
||||||
exit_reset_t exit_reset;
|
|
||||||
exit_datahigh_t exit_datahigh;
|
|
||||||
conntype_t conntype;
|
conntype_t conntype;
|
||||||
int ppidata;
|
|
||||||
int ppictrl;
|
|
||||||
int baudrate;
|
int baudrate;
|
||||||
int usbvid;
|
int usbvid;
|
||||||
LISTID usbpid;
|
LISTID usbpid;
|
||||||
char usbdev[PGM_USBSTRINGLEN], usbsn[PGM_USBSTRINGLEN];
|
const char *usbdev;
|
||||||
char usbvendor[PGM_USBSTRINGLEN], usbproduct[PGM_USBSTRINGLEN];
|
const char *usbsn;
|
||||||
double bitclock; /* JTAG ICE clock period in microseconds */
|
const char *usbvendor;
|
||||||
int ispdelay; /* ISP clock delay */
|
const char *usbproduct;
|
||||||
|
LISTID hvupdi_support; // List of UPDI HV variants the tool supports, see HV_UPDI_VARIANT_x
|
||||||
|
|
||||||
|
// Values below are not set by config_gram.y; ensure fd is first for dev_pgm_raw()
|
||||||
union filedescriptor fd;
|
union filedescriptor fd;
|
||||||
int page_size; /* page size if the programmer supports paged write/load */
|
char type[PGM_TYPELEN];
|
||||||
int (*rdy_led) (struct programmer_t * pgm, int value);
|
char port[PGM_PORTLEN];
|
||||||
int (*err_led) (struct programmer_t * pgm, int value);
|
unsigned int pinno[N_PINS]; // TODO to be removed if old pin data no longer needed
|
||||||
int (*pgm_led) (struct programmer_t * pgm, int value);
|
exit_vcc_t exit_vcc; // Should these be set in avrdude.conf?
|
||||||
int (*vfy_led) (struct programmer_t * pgm, int value);
|
exit_reset_t exit_reset;
|
||||||
int (*initialize) (struct programmer_t * pgm, AVRPART * p);
|
exit_datahigh_t exit_datahigh;
|
||||||
void (*display) (struct programmer_t * pgm, const char * p);
|
int ppidata;
|
||||||
void (*enable) (struct programmer_t * pgm);
|
int ppictrl;
|
||||||
void (*disable) (struct programmer_t * pgm);
|
int ispdelay; // ISP clock delay
|
||||||
void (*powerup) (struct programmer_t * pgm);
|
int page_size; // Page size if the programmer supports paged write/load
|
||||||
void (*powerdown) (struct programmer_t * pgm);
|
double bitclock; // JTAG ICE clock period in microseconds
|
||||||
int (*program_enable) (struct programmer_t * pgm, AVRPART * p);
|
|
||||||
int (*chip_erase) (struct programmer_t * pgm, AVRPART * p);
|
int (*rdy_led) (const struct programmer_t *pgm, int value);
|
||||||
int (*unlock) (struct programmer_t * pgm, AVRPART * p);
|
int (*err_led) (const struct programmer_t *pgm, int value);
|
||||||
int (*cmd) (struct programmer_t * pgm, const unsigned char *cmd,
|
int (*pgm_led) (const struct programmer_t *pgm, int value);
|
||||||
|
int (*vfy_led) (const struct programmer_t *pgm, int value);
|
||||||
|
int (*initialize) (const struct programmer_t *pgm, const AVRPART *p); // Sets up the physical programmer
|
||||||
|
void (*display) (const struct programmer_t *pgm, const char *p);
|
||||||
|
void (*enable) (struct programmer_t *pgm, const AVRPART *p);
|
||||||
|
void (*disable) (const struct programmer_t *pgm);
|
||||||
|
void (*powerup) (const struct programmer_t *pgm);
|
||||||
|
void (*powerdown) (const struct programmer_t *pgm);
|
||||||
|
int (*program_enable) (const struct programmer_t *pgm, const AVRPART *p);
|
||||||
|
int (*chip_erase) (const struct programmer_t *pgm, const AVRPART *p);
|
||||||
|
int (*unlock) (const struct programmer_t *pgm, const AVRPART *p);
|
||||||
|
int (*cmd) (const struct programmer_t *pgm, const unsigned char *cmd,
|
||||||
unsigned char *res);
|
unsigned char *res);
|
||||||
int (*cmd_tpi) (struct programmer_t * pgm, const unsigned char *cmd,
|
int (*cmd_tpi) (const struct programmer_t *pgm, const unsigned char *cmd,
|
||||||
int cmd_len, unsigned char res[], int res_len);
|
int cmd_len, unsigned char res[], int res_len);
|
||||||
int (*spi) (struct programmer_t * pgm, const unsigned char *cmd,
|
int (*spi) (const struct programmer_t *pgm, const unsigned char *cmd,
|
||||||
unsigned char *res, int count);
|
unsigned char *res, int count);
|
||||||
int (*open) (struct programmer_t * pgm, char * port);
|
int (*open) (struct programmer_t *pgm, const char *port);
|
||||||
void (*close) (struct programmer_t * pgm);
|
void (*close) (struct programmer_t *pgm);
|
||||||
int (*paged_write) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
|
int (*paged_write) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size, unsigned int baseaddr,
|
unsigned int page_size, unsigned int baseaddr,
|
||||||
unsigned int n_bytes);
|
unsigned int n_bytes);
|
||||||
int (*paged_load) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
|
int (*paged_load) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size, unsigned int baseaddr,
|
unsigned int page_size, unsigned int baseaddr,
|
||||||
unsigned int n_bytes);
|
unsigned int n_bytes);
|
||||||
int (*page_erase) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
|
int (*page_erase) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int baseaddr);
|
unsigned int baseaddr);
|
||||||
void (*write_setup) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m);
|
void (*write_setup) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m);
|
||||||
int (*write_byte) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
|
int (*write_byte) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned long addr, unsigned char value);
|
unsigned long addr, unsigned char value);
|
||||||
int (*read_byte) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
|
int (*read_byte) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned long addr, unsigned char * value);
|
unsigned long addr, unsigned char *value);
|
||||||
int (*read_sig_bytes) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m);
|
int (*read_sig_bytes) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m);
|
||||||
int (*read_sib) (struct programmer_t * pgm, AVRPART * p, char *sib);
|
int (*read_sib) (const struct programmer_t *pgm, const AVRPART *p, char *sib);
|
||||||
void (*print_parms) (struct programmer_t * pgm);
|
int (*term_keep_alive)(const struct programmer_t *pgm, const AVRPART *p);
|
||||||
int (*set_vtarget) (struct programmer_t * pgm, double v);
|
void (*print_parms) (const struct programmer_t *pgm, FILE *fp);
|
||||||
int (*set_varef) (struct programmer_t * pgm, unsigned int chan, double v);
|
int (*set_vtarget) (const struct programmer_t *pgm, double v);
|
||||||
int (*set_fosc) (struct programmer_t * pgm, double v);
|
int (*set_varef) (const struct programmer_t *pgm, unsigned int chan, double v);
|
||||||
int (*set_sck_period) (struct programmer_t * pgm, double v);
|
int (*set_fosc) (const struct programmer_t *pgm, double v);
|
||||||
int (*setpin) (struct programmer_t * pgm, int pinfunc, int value);
|
int (*set_sck_period) (const struct programmer_t *pgm, double v);
|
||||||
int (*getpin) (struct programmer_t * pgm, int pinfunc);
|
int (*setpin) (const struct programmer_t *pgm, int pinfunc, int value);
|
||||||
int (*highpulsepin) (struct programmer_t * pgm, int pinfunc);
|
int (*getpin) (const struct programmer_t *pgm, int pinfunc);
|
||||||
int (*parseexitspecs) (struct programmer_t * pgm, char *s);
|
int (*highpulsepin) (const struct programmer_t *pgm, int pinfunc);
|
||||||
int (*perform_osccal) (struct programmer_t * pgm);
|
int (*parseexitspecs) (struct programmer_t *pgm, const char *s);
|
||||||
int (*parseextparams) (struct programmer_t * pgm, LISTID xparams);
|
int (*perform_osccal) (const struct programmer_t *pgm);
|
||||||
void (*setup) (struct programmer_t * pgm);
|
int (*parseextparams) (const struct programmer_t *pgm, const LISTID xparams);
|
||||||
void (*teardown) (struct programmer_t * pgm);
|
void (*setup) (struct programmer_t *pgm);
|
||||||
char config_file[PATH_MAX]; /* config file where defined */
|
void (*teardown) (struct programmer_t *pgm);
|
||||||
int lineno; /* config file line number */
|
int (*flash_readhook) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *flm, const char *fname, int size);
|
||||||
void *cookie; /* for private use by the programmer */
|
// Cached r/w API for terminal reads/writes
|
||||||
char flag; /* for private use of the programmer */
|
int (*write_byte_cached)(const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
|
unsigned long addr, unsigned char value);
|
||||||
|
int (*read_byte_cached)(const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
|
unsigned long addr, unsigned char *value);
|
||||||
|
int (*chip_erase_cached)(const struct programmer_t *pgm, const AVRPART *p);
|
||||||
|
int (*page_erase_cached)(const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
|
unsigned int baseaddr);
|
||||||
|
int (*readonly) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
|
unsigned int addr);
|
||||||
|
int (*flush_cache) (const struct programmer_t *pgm, const AVRPART *p);
|
||||||
|
int (*reset_cache) (const struct programmer_t *pgm, const AVRPART *p);
|
||||||
|
AVR_Cache *cp_flash, *cp_eeprom;
|
||||||
|
|
||||||
|
const char *config_file; // Config file where defined
|
||||||
|
int lineno; // Config file line number
|
||||||
|
void *cookie; // For private use by the programmer
|
||||||
|
char flag; // For use by pgm->initpgm()
|
||||||
} PROGRAMMER;
|
} PROGRAMMER;
|
||||||
|
|
||||||
|
#define NO_PIN (PIN_MAX + 1U) // Magic pinno[] value for unused pins
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PROGRAMMER * pgm_new(void);
|
PROGRAMMER * pgm_new(void);
|
||||||
PROGRAMMER * pgm_dup(const PROGRAMMER * const src);
|
PROGRAMMER * pgm_dup(const PROGRAMMER *src);
|
||||||
void pgm_free(PROGRAMMER * const p);
|
void pgm_free(PROGRAMMER *p);
|
||||||
|
|
||||||
void programmer_display(PROGRAMMER * pgm, const char * p);
|
void programmer_display(PROGRAMMER * pgm, const char * p);
|
||||||
|
|
||||||
/* show is a mask like this (1<<PIN_AVR_SCK)|(1<<PIN_AVR_MOSI)| ... */
|
/* show is a mask like this (1<<PIN_AVR_SCK)|(1<<PIN_AVR_SDO)| ... */
|
||||||
#define SHOW_ALL_PINS (~0u)
|
#define SHOW_ALL_PINS (~0u)
|
||||||
#define SHOW_PPI_PINS ((1<<PPI_AVR_VCC)|(1<<PPI_AVR_BUFF))
|
#define SHOW_PPI_PINS ((1<<PPI_AVR_VCC)|(1<<PPI_AVR_BUFF))
|
||||||
#define SHOW_AVR_PINS ((1<<PIN_AVR_RESET)|(1<<PIN_AVR_SCK)|(1<<PIN_AVR_MOSI)|(1<<PIN_AVR_MISO))
|
#define SHOW_AVR_PINS ((1<<PIN_AVR_RESET)|(1<<PIN_AVR_SCK)|(1<<PIN_AVR_SDO)|(1<<PIN_AVR_SDI))
|
||||||
#define SHOW_LED_PINS ((1<<PIN_LED_ERR)|(1<<PIN_LED_RDY)|(1<<PIN_LED_PGM)|(1<<PIN_LED_VFY))
|
#define SHOW_LED_PINS ((1<<PIN_LED_ERR)|(1<<PIN_LED_RDY)|(1<<PIN_LED_PGM)|(1<<PIN_LED_VFY))
|
||||||
void pgm_display_generic_mask(PROGRAMMER * pgm, const char * p, unsigned int show);
|
void pgm_display_generic_mask(const PROGRAMMER *pgm, const char *p, unsigned int show);
|
||||||
void pgm_display_generic(PROGRAMMER * pgm, const char * p);
|
void pgm_display_generic(const PROGRAMMER *pgm, const char *p);
|
||||||
|
|
||||||
PROGRAMMER * locate_programmer(LISTID programmers, const char * configid);
|
PROGRAMMER *locate_programmer(const LISTID programmers, const char *configid);
|
||||||
|
|
||||||
typedef void (*walk_programmers_cb)(const char *name, const char *desc,
|
typedef void (*walk_programmers_cb)(const char *name, const char *desc,
|
||||||
const char *cfgname, int cfglineno,
|
const char *cfgname, int cfglineno,
|
||||||
|
@ -749,9 +866,10 @@ void sort_programmers(LISTID programmers);
|
||||||
|
|
||||||
/* formerly avr.h */
|
/* formerly avr.h */
|
||||||
|
|
||||||
typedef void (*FP_UpdateProgress)(int percent, double etime, char *hdr);
|
typedef void (*FP_UpdateProgress)(int percent, double etime, const char *hdr, int finish);
|
||||||
|
|
||||||
extern struct avrpart parts[];
|
extern struct avrpart parts[];
|
||||||
|
extern const char *avr_mem_order[100];
|
||||||
|
|
||||||
extern FP_UpdateProgress update_progress;
|
extern FP_UpdateProgress update_progress;
|
||||||
|
|
||||||
|
@ -759,41 +877,81 @@ extern FP_UpdateProgress update_progress;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int avr_tpi_poll_nvmbsy(PROGRAMMER *pgm);
|
int avr_tpi_poll_nvmbsy(const PROGRAMMER *pgm);
|
||||||
int avr_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p);
|
int avr_tpi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
int avr_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p, unsigned char guard_time);
|
int avr_tpi_program_enable(const PROGRAMMER *pgm, const AVRPART *p, unsigned char guard_time);
|
||||||
int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
int avr_read_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char * value);
|
unsigned long addr, unsigned char * value);
|
||||||
|
|
||||||
int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, AVRPART * v);
|
int avr_read_mem(const PROGRAMMER * pgm, const AVRPART *p, const AVRMEM *mem, const AVRPART *v);
|
||||||
|
|
||||||
int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
int avr_read(const PROGRAMMER * pgm, const AVRPART *p, const char *memtype, const AVRPART *v);
|
||||||
|
|
||||||
|
int avr_write_page(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr);
|
unsigned long addr);
|
||||||
|
|
||||||
int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
unsigned long avr_ustimestamp();
|
||||||
|
|
||||||
|
unsigned long avr_mstimestamp();
|
||||||
|
|
||||||
|
double avr_timestamp();
|
||||||
|
|
||||||
|
int avr_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char data);
|
unsigned long addr, unsigned char data);
|
||||||
|
|
||||||
int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char data);
|
unsigned long addr, unsigned char data);
|
||||||
|
|
||||||
int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int size, int auto_erase);
|
||||||
int auto_erase);
|
|
||||||
|
|
||||||
int avr_signature(PROGRAMMER * pgm, AVRPART * p);
|
int avr_write(const PROGRAMMER *pgm, const AVRPART *p, const char *memtype, int size, int auto_erase);
|
||||||
|
|
||||||
int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size);
|
int avr_signature(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
|
||||||
int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles);
|
int avr_verify(const PROGRAMMER *pgm, const AVRPART *p, const AVRPART *v, const char *m, int size);
|
||||||
|
|
||||||
int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles);
|
int avr_get_cycle_count(const PROGRAMMER *pgm, const AVRPART *p, int *cycles);
|
||||||
|
|
||||||
int avr_mem_hiaddr(AVRMEM * mem);
|
int avr_put_cycle_count(const PROGRAMMER *pgm, const AVRPART *p, int cycles);
|
||||||
|
|
||||||
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p);
|
void avr_add_mem_order(const char *str);
|
||||||
|
|
||||||
int avr_unlock(PROGRAMMER * pgm, AVRPART * p);
|
int avr_memtype_is_flash_type(const char *mem);
|
||||||
|
|
||||||
void report_progress (int completed, int total, char *hdr);
|
int avr_mem_is_flash_type(const AVRMEM *mem);
|
||||||
|
|
||||||
|
int avr_memtype_is_eeprom_type(const char *mem);
|
||||||
|
|
||||||
|
int avr_mem_is_eeprom_type(const AVRMEM *mem);
|
||||||
|
|
||||||
|
int avr_mem_is_known(const char *str);
|
||||||
|
|
||||||
|
int avr_mem_might_be_known(const char *str);
|
||||||
|
|
||||||
|
#define disable_trailing_ff_removal() avr_mem_hiaddr(NULL)
|
||||||
|
int avr_mem_hiaddr(const AVRMEM * mem);
|
||||||
|
|
||||||
|
int avr_chip_erase(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
|
||||||
|
int avr_unlock(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
|
||||||
|
void report_progress(int completed, int total, const char *hdr);
|
||||||
|
|
||||||
|
int avr_has_paged_access(const PROGRAMMER *pgm, const AVRMEM *m);
|
||||||
|
|
||||||
|
int avr_read_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, unsigned char *buf);
|
||||||
|
|
||||||
|
int avr_write_page_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int addr, unsigned char *data);
|
||||||
|
|
||||||
|
int avr_is_and(const unsigned char *s1, const unsigned char *s2, const unsigned char *s3, size_t n);
|
||||||
|
|
||||||
|
// Bytewise cached read/write API
|
||||||
|
int avr_read_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char *value);
|
||||||
|
int avr_write_byte_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned long addr, unsigned char data);
|
||||||
|
int avr_chip_erase_cached(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
int avr_page_erase_cached(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, unsigned int baseaddr);
|
||||||
|
int avr_flush_cache(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
int avr_reset_cache(const PROGRAMMER *pgm, const AVRPART *p);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -811,7 +969,8 @@ typedef enum {
|
||||||
FMT_DEC,
|
FMT_DEC,
|
||||||
FMT_OCT,
|
FMT_OCT,
|
||||||
FMT_BIN,
|
FMT_BIN,
|
||||||
FMT_ELF
|
FMT_ELF,
|
||||||
|
FMT_IHXC,
|
||||||
} FILEFMT;
|
} FILEFMT;
|
||||||
|
|
||||||
struct fioparms {
|
struct fioparms {
|
||||||
|
@ -825,17 +984,20 @@ struct fioparms {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
FIO_READ,
|
FIO_READ,
|
||||||
FIO_WRITE
|
FIO_WRITE,
|
||||||
|
FIO_READ_FOR_VERIFY,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char * fmtstr(FILEFMT format);
|
char * fileio_fmtstr(FILEFMT format);
|
||||||
|
|
||||||
int fileio(int op, char * filename, FILEFMT format,
|
int fileio_fmt_autodetect(const char * fname);
|
||||||
struct avrpart * p, char * memtype, int size);
|
|
||||||
|
int fileio(int oprwv, const char *filename, FILEFMT format,
|
||||||
|
const AVRPART *p, const char *memtype, int size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -854,6 +1016,7 @@ enum updateflags {
|
||||||
UF_NONE = 0,
|
UF_NONE = 0,
|
||||||
UF_NOWRITE = 1,
|
UF_NOWRITE = 1,
|
||||||
UF_AUTO_ERASE = 2,
|
UF_AUTO_ERASE = 2,
|
||||||
|
UF_VERIFY = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -864,6 +1027,17 @@ typedef struct update_t {
|
||||||
int format;
|
int format;
|
||||||
} UPDATE;
|
} UPDATE;
|
||||||
|
|
||||||
|
typedef struct { // File reads for flash can exclude trailing 0xff, which are cut off
|
||||||
|
int nbytes, // Number of bytes set including 0xff but excluding cut off, trailing 0xff
|
||||||
|
nsections, // Number of consecutive sections in source excluding cut off, trailing 0xff
|
||||||
|
npages, // Number of memory pages needed excluding pages solely with trailing 0xff
|
||||||
|
nfill, // Number of fill bytes to make up full pages that are needed
|
||||||
|
ntrailing, // Number of trailing 0xff in source
|
||||||
|
firstaddr, // First address set in [0, mem->size-1]
|
||||||
|
lastaddr; // Highest address set by input file
|
||||||
|
} Filestats;
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -873,8 +1047,24 @@ extern UPDATE * dup_update(UPDATE * upd);
|
||||||
extern UPDATE * new_update(int op, char * memtype, int filefmt,
|
extern UPDATE * new_update(int op, char * memtype, int filefmt,
|
||||||
char * filename);
|
char * filename);
|
||||||
extern void free_update(UPDATE * upd);
|
extern void free_update(UPDATE * upd);
|
||||||
extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
|
extern int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd,
|
||||||
enum updateflags flags);
|
enum updateflags flags);
|
||||||
|
|
||||||
|
extern int memstats(const AVRPART *p, const char *memtype, int size, Filestats *fsp);
|
||||||
|
|
||||||
|
// Convenience functions for printing
|
||||||
|
const char *update_plural(int x);
|
||||||
|
const char *update_inname(const char *fn);
|
||||||
|
const char *update_outname(const char *fn);
|
||||||
|
const char *update_interval(int a, int b);
|
||||||
|
|
||||||
|
// Helper functions for dry run to determine file access
|
||||||
|
int update_is_okfile(const char *fn);
|
||||||
|
int update_is_writeable(const char *fn);
|
||||||
|
int update_is_readable(const char *fn);
|
||||||
|
|
||||||
|
int update_dryrun(const AVRPART *p, UPDATE *upd);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -887,7 +1077,7 @@ extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
|
||||||
|
|
||||||
typedef struct programmer_type_t {
|
typedef struct programmer_type_t {
|
||||||
const char * const id;
|
const char * const id;
|
||||||
void (*initpgm)(struct programmer_t * pgm);
|
void (*initpgm)(struct programmer_t *pgm);
|
||||||
const char * const desc;
|
const char * const desc;
|
||||||
} PROGRAMMER_TYPE;
|
} PROGRAMMER_TYPE;
|
||||||
|
|
||||||
|
@ -895,7 +1085,9 @@ typedef struct programmer_type_t {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const PROGRAMMER_TYPE * locate_programmer_type(/*LISTID programmer_types, */const char * id);
|
const PROGRAMMER_TYPE *locate_programmer_type(const char *id);
|
||||||
|
|
||||||
|
const char *locate_programmer_type_id(void (*initpgm)(struct programmer_t *pgm));
|
||||||
|
|
||||||
typedef void (*walk_programmer_types_cb)(const char *id, const char *desc,
|
typedef void (*walk_programmer_types_cb)(const char *id, const char *desc,
|
||||||
void *cookie);
|
void *cookie);
|
||||||
|
@ -909,9 +1101,10 @@ void walk_programmer_types(/*LISTID programmer_types,*/ walk_programmer_types_cb
|
||||||
|
|
||||||
extern LISTID part_list;
|
extern LISTID part_list;
|
||||||
extern LISTID programmers;
|
extern LISTID programmers;
|
||||||
extern char default_programmer[];
|
extern const char *default_programmer;
|
||||||
extern char default_parallel[];
|
extern const char *default_parallel;
|
||||||
extern char default_serial[];
|
extern const char *default_serial;
|
||||||
|
extern const char *default_spi;
|
||||||
extern double default_bitclock;
|
extern double default_bitclock;
|
||||||
|
|
||||||
/* This name is fixed, it's only here for symmetry with
|
/* This name is fixed, it's only here for symmetry with
|
||||||
|
@ -922,12 +1115,24 @@ extern double default_bitclock;
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void *cfg_malloc(const char *funcname, size_t n);
|
||||||
|
|
||||||
|
char *cfg_strdup(const char *funcname, const char *s);
|
||||||
|
|
||||||
int init_config(void);
|
int init_config(void);
|
||||||
|
|
||||||
void cleanup_config(void);
|
void cleanup_config(void);
|
||||||
|
|
||||||
int read_config(const char * file);
|
int read_config(const char * file);
|
||||||
|
|
||||||
|
const char *cache_string(const char *file);
|
||||||
|
|
||||||
|
unsigned char *cfg_unescapeu(unsigned char *d, const unsigned char *s);
|
||||||
|
|
||||||
|
char *cfg_unescape(char *d, const char *s);
|
||||||
|
|
||||||
|
char *cfg_escape(const char *s);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,18 +31,18 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define ppi_claim(fd) \
|
#define ppi_claim(fd) \
|
||||||
if (ioctl(fd, PPCLAIM)) { \
|
if (ioctl(fd, PPCLAIM)) { \
|
||||||
avrdude_message(MSG_INFO, "%s: can't claim device \"%s\": %s\n\n", \
|
pmsg_ext_error("cannot claim port %s: %s\n\n", \
|
||||||
progname, port, strerror(errno)); \
|
port, strerror(errno)); \
|
||||||
close(fd); \
|
close(fd); \
|
||||||
return; \
|
return; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ppi_release(fd) \
|
#define ppi_release(fd) \
|
||||||
if (ioctl(fd, PPRELEASE)) { \
|
if (ioctl(fd, PPRELEASE)) { \
|
||||||
avrdude_message(MSG_INFO, "%s: can't release device: %s\n\n", \
|
pmsg_ext_error("cannot release device: %s\n\n", \
|
||||||
progname, strerror(errno)); \
|
strerror(errno)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DO_PPI_READ(fd, reg, valp) \
|
#define DO_PPI_READ(fd, reg, valp) \
|
||||||
|
|
193
src/linuxgpio.c
193
src/linuxgpio.c
|
@ -27,6 +27,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "avrdude.h"
|
#include "avrdude.h"
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
|
@ -48,8 +49,6 @@
|
||||||
* GPIO user space helpers
|
* GPIO user space helpers
|
||||||
* The following functions are acting on an "unsigned gpio" argument, which corresponds to the
|
* The following functions are acting on an "unsigned gpio" argument, which corresponds to the
|
||||||
* gpio numbering scheme in the kernel (starting from 0).
|
* gpio numbering scheme in the kernel (starting from 0).
|
||||||
* The higher level functions use "int pin" to specify the pins with an offset of 1:
|
|
||||||
* gpio = pin - 1;
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define GPIO_DIR_IN 0
|
#define GPIO_DIR_IN 0
|
||||||
|
@ -62,7 +61,7 @@ static int linuxgpio_export(unsigned int gpio)
|
||||||
|
|
||||||
fd = open("/sys/class/gpio/export", O_WRONLY);
|
fd = open("/sys/class/gpio/export", O_WRONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("Can't open /sys/class/gpio/export");
|
pmsg_ext_error("cannot open /sys/class/gpio/export: %s\n", strerror(errno));
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +79,7 @@ static int linuxgpio_unexport(unsigned int gpio)
|
||||||
|
|
||||||
fd = open("/sys/class/gpio/unexport", O_WRONLY);
|
fd = open("/sys/class/gpio/unexport", O_WRONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("Can't open /sys/class/gpio/unexport");
|
pmsg_ext_error("cannot open /sys/class/gpio/unexport: %s\n", strerror(errno));
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,7 +107,7 @@ static int linuxgpio_dir(unsigned int gpio, unsigned int dir)
|
||||||
|
|
||||||
fd = open(buf, O_WRONLY);
|
fd = open(buf, O_WRONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("Can't open gpioX/direction");
|
pmsg_ext_error("cannot open %s: %s\n", buf, strerror(errno));
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,32 +137,31 @@ static int linuxgpio_dir_in(unsigned int gpio)
|
||||||
|
|
||||||
#define N_GPIO (PIN_MAX + 1)
|
#define N_GPIO (PIN_MAX + 1)
|
||||||
|
|
||||||
|
/* Delay between checks for successful GPIO export (100ms) */
|
||||||
|
#define GPIO_SYSFS_OPEN_DELAY 100000
|
||||||
|
/* Number of retries to check for successful GPIO exports */
|
||||||
|
#define GPIO_SYSFS_OPEN_RETRIES 10
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* an array which holds open FDs to /sys/class/gpio/gpioXX/value for all needed pins
|
* an array which holds open FDs to /sys/class/gpio/gpioXX/value for all needed pins
|
||||||
*/
|
*/
|
||||||
static int linuxgpio_fds[N_GPIO] ;
|
static int linuxgpio_fds[N_GPIO] ;
|
||||||
|
|
||||||
|
|
||||||
static int linuxgpio_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
static int linuxgpio_setpin(const PROGRAMMER *pgm, int pinfunc, int value) {
|
||||||
{
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
int r;
|
|
||||||
int pin = pgm->pinno[pinfunc]; // TODO
|
|
||||||
|
|
||||||
if (pin & PIN_INVERSE)
|
|
||||||
{
|
|
||||||
value = !value;
|
|
||||||
pin &= PIN_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( linuxgpio_fds[pin] < 0 )
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (value)
|
unsigned pin = pgm->pinno[pinfunc];
|
||||||
r = write(linuxgpio_fds[pin], "1", 1);
|
if (pin & PIN_INVERSE)
|
||||||
else
|
value = !value;
|
||||||
r = write(linuxgpio_fds[pin], "0", 1);
|
pin &= PIN_MASK;
|
||||||
|
|
||||||
if (r!=1) return -1;
|
if (pin > PIN_MAX || linuxgpio_fds[pin] < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (write(linuxgpio_fds[pin], value? "1": "0", 1) != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (pgm->ispdelay > 1)
|
if (pgm->ispdelay > 1)
|
||||||
bitbang_delay(pgm->ispdelay);
|
bitbang_delay(pgm->ispdelay);
|
||||||
|
@ -171,41 +169,34 @@ static int linuxgpio_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxgpio_getpin(PROGRAMMER * pgm, int pinfunc)
|
static int linuxgpio_getpin(const PROGRAMMER *pgm, int pinfunc) {
|
||||||
{
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
unsigned char invert=0;
|
return -1;
|
||||||
|
|
||||||
|
unsigned int pin = pgm->pinno[pinfunc];
|
||||||
|
int invert = !!(pin & PIN_INVERSE);
|
||||||
|
pin &= PIN_MASK;
|
||||||
|
|
||||||
|
if(pin > PIN_MAX || linuxgpio_fds[pin] < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if(lseek(linuxgpio_fds[pin], 0, SEEK_SET) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
char c;
|
char c;
|
||||||
int pin = pgm->pinno[pinfunc]; // TODO
|
if(read(linuxgpio_fds[pin], &c, 1) != 1)
|
||||||
|
|
||||||
if (pin & PIN_INVERSE)
|
|
||||||
{
|
|
||||||
invert = 1;
|
|
||||||
pin &= PIN_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( linuxgpio_fds[pin] < 0 )
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (lseek(linuxgpio_fds[pin], 0, SEEK_SET)<0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (read(linuxgpio_fds[pin], &c, 1)!=1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (c=='0')
|
|
||||||
return 0+invert;
|
|
||||||
else if (c=='1')
|
|
||||||
return 1-invert;
|
|
||||||
else
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
return c=='0'? 0+invert: c=='1'? 1-invert: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxgpio_highpulsepin(PROGRAMMER * pgm, int pinfunc)
|
static int linuxgpio_highpulsepin(const PROGRAMMER *pgm, int pinfunc) {
|
||||||
{
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
int pin = pgm->pinno[pinfunc]; // TODO
|
return -1;
|
||||||
|
|
||||||
if ( linuxgpio_fds[pin & PIN_MASK] < 0 )
|
unsigned int pin = pgm->pinno[pinfunc] & PIN_MASK;
|
||||||
|
|
||||||
|
if (pin > PIN_MAX || linuxgpio_fds[pin] < 0 )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
linuxgpio_setpin(pgm, pinfunc, 1);
|
linuxgpio_setpin(pgm, pinfunc, 1);
|
||||||
|
@ -216,35 +207,31 @@ static int linuxgpio_highpulsepin(PROGRAMMER * pgm, int pinfunc)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void linuxgpio_display(PROGRAMMER *pgm, const char *p)
|
static void linuxgpio_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
msg_info("%sPin assignment : /sys/class/gpio/gpio{n}\n",p);
|
||||||
avrdude_message(MSG_INFO, "%sPin assignment : /sys/class/gpio/gpio{n}\n",p);
|
|
||||||
pgm_display_generic_mask(pgm, p, SHOW_AVR_PINS);
|
pgm_display_generic_mask(pgm, p, SHOW_AVR_PINS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxgpio_enable(PROGRAMMER *pgm)
|
static void linuxgpio_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxgpio_disable(PROGRAMMER *pgm)
|
static void linuxgpio_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxgpio_powerup(PROGRAMMER *pgm)
|
static void linuxgpio_powerup(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxgpio_powerdown(PROGRAMMER *pgm)
|
static void linuxgpio_powerdown(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxgpio_open(PROGRAMMER *pgm, char *port)
|
static int linuxgpio_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
int r, i, pin;
|
int r, i, pin;
|
||||||
|
char gpio_path[60];
|
||||||
|
struct stat stat_buf;
|
||||||
|
|
||||||
if (bitbang_check_prerequisites(pgm) < 0)
|
if (bitbang_check_prerequisites(pgm) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -252,33 +239,58 @@ static int linuxgpio_open(PROGRAMMER *pgm, char *port)
|
||||||
|
|
||||||
for (i=0; i<N_GPIO; i++)
|
for (i=0; i<N_GPIO; i++)
|
||||||
linuxgpio_fds[i] = -1;
|
linuxgpio_fds[i] = -1;
|
||||||
//Avrdude assumes that if a pin number is 0 it means not used/available
|
// Avrdude assumes that if a pin number is invalid it means not used/available
|
||||||
//this causes a problem because 0 is a valid GPIO number in Linux sysfs.
|
for (i = 1; i < N_PINS; i++) { // The pin enumeration in libavrdude.h starts with PPI_AVR_VCC = 1
|
||||||
//To avoid annoying off by one pin numbering we assume SCK, MOSI, MISO
|
if ((pgm->pinno[i] & PIN_MASK) <= PIN_MAX) {
|
||||||
//and RESET pins are always defined in avrdude.conf, even as 0. If they're
|
|
||||||
//not programming will not work anyway. The drawbacks of this approach are
|
|
||||||
//that unwanted toggling of GPIO0 can occur and that other optional pins
|
|
||||||
//mostry LED status, can't be set to GPIO0. It can be fixed when a better
|
|
||||||
//solution exists.
|
|
||||||
for (i=0; i<N_PINS; i++) {
|
|
||||||
if ( (pgm->pinno[i] & PIN_MASK) != 0 ||
|
|
||||||
i == PIN_AVR_RESET ||
|
|
||||||
i == PIN_AVR_SCK ||
|
|
||||||
i == PIN_AVR_MOSI ||
|
|
||||||
i == PIN_AVR_MISO ) {
|
|
||||||
pin = pgm->pinno[i] & PIN_MASK;
|
pin = pgm->pinno[i] & PIN_MASK;
|
||||||
if ((r=linuxgpio_export(pin)) < 0) {
|
if ((r=linuxgpio_export(pin)) < 0) {
|
||||||
avrdude_message(MSG_INFO, "Can't export GPIO %d, already exported/busy?: %s",
|
pmsg_ext_error("cannot export GPIO %d, already exported/busy?: %s",
|
||||||
pin, strerror(errno));
|
pin, strerror(errno));
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if (i == PIN_AVR_MISO)
|
|
||||||
r=linuxgpio_dir_in(pin);
|
|
||||||
else
|
|
||||||
r=linuxgpio_dir_out(pin);
|
|
||||||
|
|
||||||
if (r < 0)
|
/* Wait until GPIO directory appears */
|
||||||
|
snprintf(gpio_path, sizeof(gpio_path), "/sys/class/gpio/gpio%u", pin);
|
||||||
|
unsigned int retry_count;
|
||||||
|
for (retry_count = 0; retry_count < GPIO_SYSFS_OPEN_RETRIES; retry_count++) {
|
||||||
|
int ret = stat(gpio_path, &stat_buf);
|
||||||
|
if (ret == 0) {
|
||||||
|
break;
|
||||||
|
} else if (ret < 0 && errno != ENOENT) {
|
||||||
|
linuxgpio_unexport(pin);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep(GPIO_SYSFS_OPEN_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write direction, looping in case of EACCES errors due to delayed
|
||||||
|
* udev permission rule application after export */
|
||||||
|
for (retry_count = 0; retry_count < GPIO_SYSFS_OPEN_RETRIES; retry_count++) {
|
||||||
|
usleep(GPIO_SYSFS_OPEN_DELAY);
|
||||||
|
if (i == PIN_AVR_SDI)
|
||||||
|
r=linuxgpio_dir_in(pin);
|
||||||
|
else
|
||||||
|
r=linuxgpio_dir_out(pin);
|
||||||
|
|
||||||
|
if (r >= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (errno != EACCES) {
|
||||||
|
linuxgpio_unexport(pin);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retry_count)
|
||||||
|
pmsg_notice2("needed %d retr%s for linuxgpio_dir_%s(%s)\n",
|
||||||
|
retry_count, retry_count > 1? "ies": "y",
|
||||||
|
i == PIN_AVR_SDI? "in": "out", avr_pin_name(pin));
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
linuxgpio_unexport(pin);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if ((linuxgpio_fds[pin]=linuxgpio_openfd(pin)) < 0)
|
if ((linuxgpio_fds[pin]=linuxgpio_openfd(pin)) < 0)
|
||||||
return linuxgpio_fds[pin];
|
return linuxgpio_fds[pin];
|
||||||
|
@ -299,20 +311,21 @@ static void linuxgpio_close(PROGRAMMER *pgm)
|
||||||
for (i=0; i<N_GPIO; i++) {
|
for (i=0; i<N_GPIO; i++) {
|
||||||
if (linuxgpio_fds[i] >= 0 && i != reset_pin) {
|
if (linuxgpio_fds[i] >= 0 && i != reset_pin) {
|
||||||
close(linuxgpio_fds[i]);
|
close(linuxgpio_fds[i]);
|
||||||
|
linuxgpio_fds[i] = -1;
|
||||||
linuxgpio_dir_in(i);
|
linuxgpio_dir_in(i);
|
||||||
linuxgpio_unexport(i);
|
linuxgpio_unexport(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//configure RESET as input, if there's external pull up it will go high
|
//configure RESET as input, if there's external pull up it will go high
|
||||||
if (linuxgpio_fds[reset_pin] >= 0) {
|
if(reset_pin <= PIN_MAX && linuxgpio_fds[reset_pin] >= 0) {
|
||||||
close(linuxgpio_fds[reset_pin]);
|
close(linuxgpio_fds[reset_pin]);
|
||||||
|
linuxgpio_fds[reset_pin] = -1;
|
||||||
linuxgpio_dir_in(reset_pin);
|
linuxgpio_dir_in(reset_pin);
|
||||||
linuxgpio_unexport(reset_pin);
|
linuxgpio_unexport(reset_pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void linuxgpio_initpgm(PROGRAMMER *pgm)
|
void linuxgpio_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "linuxgpio");
|
strcpy(pgm->type, "linuxgpio");
|
||||||
|
|
||||||
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
||||||
|
@ -344,10 +357,8 @@ const char linuxgpio_desc[] = "GPIO bitbanging using the Linux sysfs interface";
|
||||||
|
|
||||||
#else /* !HAVE_LINUXGPIO */
|
#else /* !HAVE_LINUXGPIO */
|
||||||
|
|
||||||
void linuxgpio_initpgm(PROGRAMMER * pgm)
|
void linuxgpio_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
pmsg_error("Linux sysfs GPIO support not available in this configuration\n");
|
||||||
avrdude_message(MSG_INFO, "%s: Linux sysfs GPIO support not available in this configuration\n",
|
|
||||||
progname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char linuxgpio_desc[] = "GPIO bitbanging using the Linux sysfs interface (not available)";
|
const char linuxgpio_desc[] = "GPIO bitbanging using the Linux sysfs interface (not available)";
|
||||||
|
|
|
@ -27,7 +27,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char linuxgpio_desc[];
|
extern const char linuxgpio_desc[];
|
||||||
void linuxgpio_initpgm (PROGRAMMER * pgm);
|
void linuxgpio_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
164
src/linuxspi.c
164
src/linuxspi.c
|
@ -62,14 +62,22 @@
|
||||||
|
|
||||||
#define LINUXSPI "linuxspi"
|
#define LINUXSPI "linuxspi"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private data for this programmer.
|
||||||
|
*/
|
||||||
|
struct pdata {
|
||||||
|
int disable_no_cs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
|
||||||
|
|
||||||
static int fd_spidev, fd_gpiochip, fd_linehandle;
|
static int fd_spidev, fd_gpiochip, fd_linehandle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sends/receives a message in full duplex mode
|
* @brief Sends/receives a message in full duplex mode
|
||||||
* @return -1 on failure, otherwise number of bytes sent/received
|
* @return -1 on failure, otherwise number of bytes sent/received
|
||||||
*/
|
*/
|
||||||
static int linuxspi_spi_duplex(PROGRAMMER *pgm, const unsigned char *tx, unsigned char *rx, int len)
|
static int linuxspi_spi_duplex(const PROGRAMMER *pgm, const unsigned char *tx, unsigned char *rx, int len) {
|
||||||
{
|
|
||||||
struct spi_ioc_transfer tr;
|
struct spi_ioc_transfer tr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -78,27 +86,33 @@ static int linuxspi_spi_duplex(PROGRAMMER *pgm, const unsigned char *tx, unsigne
|
||||||
.rx_buf = (unsigned long)rx,
|
.rx_buf = (unsigned long)rx,
|
||||||
.len = len,
|
.len = len,
|
||||||
.delay_usecs = 1,
|
.delay_usecs = 1,
|
||||||
.speed_hz = 1.0 / pgm->bitclock, // seconds to Hz
|
.speed_hz = 1.0 / pgm->bitclock,
|
||||||
.bits_per_word = 8,
|
.bits_per_word = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
ret = ioctl(fd_spidev, SPI_IOC_MESSAGE(1), &tr);
|
ret = ioctl(fd_spidev, SPI_IOC_MESSAGE(1), &tr);
|
||||||
if (ret != len)
|
if (ret != len) {
|
||||||
avrdude_message(MSG_INFO, "\n%s: error: Unable to send SPI message\n", progname);
|
int ioctl_errno = errno;
|
||||||
|
msg_error("\n");
|
||||||
|
pmsg_error("unable to send SPI message");
|
||||||
|
if (ioctl_errno)
|
||||||
|
msg_error("%s", strerror(ioctl_errno));
|
||||||
|
msg_error("\n");
|
||||||
|
}
|
||||||
|
|
||||||
return (ret == -1) ? -1 : 0;
|
return ret == -1? -1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxspi_setup(PROGRAMMER *pgm)
|
static void linuxspi_setup(PROGRAMMER *pgm) {
|
||||||
{
|
pgm->cookie = cfg_malloc("linuxspi_setup()", sizeof(struct pdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxspi_teardown(PROGRAMMER* pgm)
|
static void linuxspi_teardown(PROGRAMMER* pgm) {
|
||||||
{
|
free(pgm->cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxspi_reset_mcu(PROGRAMMER *pgm, bool active)
|
static int linuxspi_reset_mcu(const PROGRAMMER *pgm, bool active) {
|
||||||
{
|
|
||||||
struct gpiohandle_data data;
|
struct gpiohandle_data data;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -120,21 +134,20 @@ static int linuxspi_reset_mcu(PROGRAMMER *pgm, bool active)
|
||||||
#endif
|
#endif
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
avrdude_message(MSG_INFO, "%s error: Unable to set GPIO line %d value\n",
|
pmsg_ext_error("unable to set GPIO line %d value: %s\n", pgm->pinno[PIN_AVR_RESET] & PIN_MASK, strerror(errno));
|
||||||
progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxspi_open(PROGRAMMER *pgm, char *port)
|
static int linuxspi_open(PROGRAMMER *pgm, const char *pt) {
|
||||||
{
|
|
||||||
const char *port_error =
|
const char *port_error =
|
||||||
"%s: error: Unknown port specification. "
|
"unknown port specification, "
|
||||||
"Please use the format /dev/spidev:/dev/gpiochip[:resetno]\n";
|
"please use the format /dev/spidev:/dev/gpiochip[:resetno]\n";
|
||||||
char port_default[] = "/dev/spidev0.0:/dev/gpiochip0";
|
char port_default[] = "/dev/spidev0.0:/dev/gpiochip0";
|
||||||
char *spidev, *gpiochip, *reset_pin;
|
char *spidev, *gpiochip, *reset_pin;
|
||||||
|
char *port = cfg_strdup("linuxspi_open()", pt);
|
||||||
struct gpiohandle_request req;
|
struct gpiohandle_request req;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -144,13 +157,13 @@ static int linuxspi_open(PROGRAMMER *pgm, char *port)
|
||||||
|
|
||||||
spidev = strtok(port, ":");
|
spidev = strtok(port, ":");
|
||||||
if (!spidev) {
|
if (!spidev) {
|
||||||
avrdude_message(MSG_INFO, port_error, progname);
|
pmsg_error("%s", port_error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gpiochip = strtok(NULL, ":");
|
gpiochip = strtok(NULL, ":");
|
||||||
if (!gpiochip) {
|
if (!gpiochip) {
|
||||||
avrdude_message(MSG_INFO, port_error, progname);
|
pmsg_error("%s", port_error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,27 +175,32 @@ static int linuxspi_open(PROGRAMMER *pgm, char *port)
|
||||||
strcpy(pgm->port, port);
|
strcpy(pgm->port, port);
|
||||||
fd_spidev = open(pgm->port, O_RDWR);
|
fd_spidev = open(pgm->port, O_RDWR);
|
||||||
if (fd_spidev < 0) {
|
if (fd_spidev < 0) {
|
||||||
avrdude_message(MSG_INFO, "\n%s: error: Unable to open the spidev device %s", progname, pgm->port);
|
pmsg_ext_error("unable to open the spidev device %s: %s\n", pgm->port, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t mode = SPI_MODE_0 | SPI_NO_CS;
|
uint32_t mode = SPI_MODE_0;
|
||||||
|
if (!PDATA(pgm)->disable_no_cs)
|
||||||
|
mode |= SPI_NO_CS;
|
||||||
|
|
||||||
ret = ioctl(fd_spidev, SPI_IOC_WR_MODE32, &mode);
|
ret = ioctl(fd_spidev, SPI_IOC_WR_MODE32, &mode);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
avrdude_message(MSG_INFO, "%s: error: Unable to set SPI mode %0X on %s\n",
|
int ioctl_errno = errno;
|
||||||
progname, mode, spidev);
|
pmsg_ext_error("unable to set SPI mode %02X on %s: %s\n", mode, spidev, strerror(errno));
|
||||||
|
if(ioctl_errno == EINVAL && !PDATA(pgm)->disable_no_cs)
|
||||||
|
pmsg_error("try -x disable_no_cs\n");
|
||||||
goto close_spidev;
|
goto close_spidev;
|
||||||
}
|
}
|
||||||
fd_gpiochip = open(gpiochip, 0);
|
fd_gpiochip = open(gpiochip, 0);
|
||||||
if (fd_gpiochip < 0) {
|
if (fd_gpiochip < 0) {
|
||||||
avrdude_message(MSG_INFO, "\n%s error: Unable to open the gpiochip %s", progname, gpiochip);
|
pmsg_ext_error("unable to open the gpiochip %s: %s\n", gpiochip, strerror(errno));
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto close_spidev;
|
goto close_spidev;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(req.consumer_label, progname);
|
strcpy(req.consumer_label, progname);
|
||||||
req.lines = 1;
|
req.lines = 1;
|
||||||
req.lineoffsets[0] = pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE;
|
req.lineoffsets[0] = pgm->pinno[PIN_AVR_RESET] & PIN_MASK;
|
||||||
req.default_values[0] = !!(pgm->pinno[PIN_AVR_RESET] & PIN_INVERSE);
|
req.default_values[0] = !!(pgm->pinno[PIN_AVR_RESET] & PIN_INVERSE);
|
||||||
req.flags = GPIOHANDLE_REQUEST_OUTPUT;
|
req.flags = GPIOHANDLE_REQUEST_OUTPUT;
|
||||||
|
|
||||||
|
@ -194,7 +212,7 @@ static int linuxspi_open(PROGRAMMER *pgm, char *port)
|
||||||
struct gpio_v2_line_request reqv2;
|
struct gpio_v2_line_request reqv2;
|
||||||
|
|
||||||
memset(&reqv2, 0, sizeof(reqv2));
|
memset(&reqv2, 0, sizeof(reqv2));
|
||||||
reqv2.offsets[0] = pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE;
|
reqv2.offsets[0] = pgm->pinno[PIN_AVR_RESET] & PIN_MASK;
|
||||||
strncpy(reqv2.consumer, progname, sizeof(reqv2.consumer) - 1);
|
strncpy(reqv2.consumer, progname, sizeof(reqv2.consumer) - 1);
|
||||||
reqv2.config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
|
reqv2.config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
|
||||||
reqv2.config.num_attrs = 1;
|
reqv2.config.num_attrs = 1;
|
||||||
|
@ -210,8 +228,7 @@ static int linuxspi_open(PROGRAMMER *pgm, char *port)
|
||||||
#endif
|
#endif
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
avrdude_message(MSG_INFO, "%s error: Unable to get GPIO line %d\n",
|
pmsg_ext_error("unable to get GPIO line %d. %s\n", pgm->pinno[PIN_AVR_RESET] & PIN_MASK, strerror(errno));
|
||||||
progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE);
|
|
||||||
goto close_gpiochip;
|
goto close_gpiochip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,16 +237,12 @@ static int linuxspi_open(PROGRAMMER *pgm, char *port)
|
||||||
goto close_out;
|
goto close_out;
|
||||||
|
|
||||||
if (pgm->baudrate != 0) {
|
if (pgm->baudrate != 0) {
|
||||||
avrdude_message(MSG_INFO,
|
pmsg_warning("obsolete use of -b <clock> option for bit clock; use -B <clock>\n");
|
||||||
"%s: obsolete use of -b <clock> option for bit clock; use -B <clock>\n",
|
pgm->bitclock = 1.0 / pgm->baudrate;
|
||||||
progname);
|
|
||||||
pgm->bitclock = 1.0 / pgm->baudrate;
|
|
||||||
}
|
}
|
||||||
if (pgm->bitclock == 0) {
|
if (pgm->bitclock == 0) {
|
||||||
avrdude_message(MSG_NOTICE,
|
pmsg_notice("defaulting bit clock to 200 kHz\n");
|
||||||
"%s: defaulting bit clock to 200 kHz\n",
|
pgm->bitclock = 5E-6; // 200 kHz - 5 µs
|
||||||
progname);
|
|
||||||
pgm->bitclock = 5E-6; // 200 kHz - 5 µs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -243,8 +256,7 @@ close_spidev:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxspi_close(PROGRAMMER *pgm)
|
static void linuxspi_close(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
switch (pgm->exit_reset) {
|
switch (pgm->exit_reset) {
|
||||||
case EXIT_RESET_ENABLED:
|
case EXIT_RESET_ENABLED:
|
||||||
linuxspi_reset_mcu(pgm, true);
|
linuxspi_reset_mcu(pgm, true);
|
||||||
|
@ -263,25 +275,21 @@ static void linuxspi_close(PROGRAMMER *pgm)
|
||||||
close(fd_gpiochip);
|
close(fd_gpiochip);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxspi_disable(PROGRAMMER* pgm)
|
static void linuxspi_disable(const PROGRAMMER* pgm) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxspi_enable(PROGRAMMER* pgm)
|
static void linuxspi_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linuxspi_display(PROGRAMMER* pgm, const char* p)
|
static void linuxspi_display(const PROGRAMMER* pgm, const char* p) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxspi_initialize(PROGRAMMER *pgm, AVRPART *p)
|
static int linuxspi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
int tries, ret;
|
int tries, ret;
|
||||||
|
|
||||||
if (p->flags & AVRPART_HAS_TPI) {
|
if (p->prog_modes & PM_TPI) {
|
||||||
/* We do not support tpi. This is a dedicated SPI thing */
|
/* We do not support TPI. This is a dedicated SPI thing */
|
||||||
avrdude_message(MSG_INFO, "%s: error: Programmer " LINUXSPI " does not support TPI\n", progname);
|
pmsg_error("programmer " LINUXSPI " does not support TPI\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,22 +303,21 @@ static int linuxspi_initialize(PROGRAMMER *pgm, AVRPART *p)
|
||||||
} while(tries++ < 65);
|
} while(tries++ < 65);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
avrdude_message(MSG_INFO, "%s: error: AVR device not responding\n", progname);
|
pmsg_error("AVR device not responding\n");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxspi_cmd(PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res)
|
static int linuxspi_cmd(const PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res)
|
||||||
{
|
{
|
||||||
return linuxspi_spi_duplex(pgm, cmd, res, 4);
|
return linuxspi_spi_duplex(pgm, cmd, res, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxspi_program_enable(PROGRAMMER *pgm, AVRPART *p)
|
static int linuxspi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
unsigned char cmd[4], res[4];
|
unsigned char cmd[4], res[4];
|
||||||
|
|
||||||
if (!p->op[AVR_OP_PGM_ENABLE]) {
|
if (!p->op[AVR_OP_PGM_ENABLE]) {
|
||||||
avrdude_message(MSG_INFO, "%s: error: program enable instruction not defined for part \"%s\"\n", progname, p->desc);
|
pmsg_error("program enable instruction not defined for part %s\n", p->desc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,7 +335,7 @@ static int linuxspi_program_enable(PROGRAMMER *pgm, AVRPART *p)
|
||||||
* plus two CPU clock cycles. See Table 25-5 on page 240 for definition of
|
* plus two CPU clock cycles. See Table 25-5 on page 240 for definition of
|
||||||
* minimum pulse width on RESET pin, t RST
|
* minimum pulse width on RESET pin, t RST
|
||||||
* 2. Wait for at least 20 ms and then enable serial programming by sending
|
* 2. Wait for at least 20 ms and then enable serial programming by sending
|
||||||
* the Programming Enable serial instruction to the MOSI pin
|
* the Programming Enable serial instruction to the SDO pin
|
||||||
* 3. The serial programming instructions will not work if the communication
|
* 3. The serial programming instructions will not work if the communication
|
||||||
* is out of synchronization. When in sync, the second byte (0x53) will echo
|
* is out of synchronization. When in sync, the second byte (0x53) will echo
|
||||||
* back when issuing the third byte of the Programming Enable instruction
|
* back when issuing the third byte of the Programming Enable instruction
|
||||||
|
@ -349,12 +356,11 @@ static int linuxspi_program_enable(PROGRAMMER *pgm, AVRPART *p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxspi_chip_erase(PROGRAMMER *pgm, AVRPART *p)
|
static int linuxspi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
unsigned char cmd[4], res[4];
|
unsigned char cmd[4], res[4];
|
||||||
|
|
||||||
if (!p->op[AVR_OP_CHIP_ERASE]) {
|
if (!p->op[AVR_OP_CHIP_ERASE]) {
|
||||||
avrdude_message(MSG_INFO, "%s: error: chip erase instruction not defined for part \"%s\"\n", progname, p->desc);
|
pmsg_error("chip erase instruction not defined for part %s\n", p->desc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,12 +373,12 @@ static int linuxspi_chip_erase(PROGRAMMER *pgm, AVRPART *p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int linuxspi_parseexitspecs(PROGRAMMER *pgm, char *s)
|
static int linuxspi_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
|
||||||
{
|
char *cp, *s, *str = cfg_strdup("linuxspi_parseextitspecs()", sp);
|
||||||
char *cp;
|
|
||||||
|
|
||||||
|
s = str;
|
||||||
while ((cp = strtok(s, ","))) {
|
while ((cp = strtok(s, ","))) {
|
||||||
s = 0;
|
s = NULL;
|
||||||
if (!strcmp(cp, "reset")) {
|
if (!strcmp(cp, "reset")) {
|
||||||
pgm->exit_reset = EXIT_RESET_ENABLED;
|
pgm->exit_reset = EXIT_RESET_ENABLED;
|
||||||
continue;
|
continue;
|
||||||
|
@ -381,14 +387,35 @@ static int linuxspi_parseexitspecs(PROGRAMMER *pgm, char *s)
|
||||||
pgm->exit_reset = EXIT_RESET_DISABLED;
|
pgm->exit_reset = EXIT_RESET_DISABLED;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
free(str);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(str);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void linuxspi_initpgm(PROGRAMMER *pgm)
|
static int linuxspi_parseextparams(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||||
{
|
LNODEID ln;
|
||||||
|
const char *extended_param;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
for (ln = lfirst(extparms); ln; ln = lnext(ln)) {
|
||||||
|
extended_param = ldata(ln);
|
||||||
|
|
||||||
|
if (strcmp(extended_param, "disable_no_cs") == 0) {
|
||||||
|
PDATA(pgm)->disable_no_cs = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmsg_error("invalid extended parameter '%s'\n", extended_param);
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linuxspi_initpgm(PROGRAMMER *pgm) {
|
||||||
strcpy(pgm->type, LINUXSPI);
|
strcpy(pgm->type, LINUXSPI);
|
||||||
|
|
||||||
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
||||||
|
@ -410,16 +437,15 @@ void linuxspi_initpgm(PROGRAMMER *pgm)
|
||||||
pgm->setup = linuxspi_setup;
|
pgm->setup = linuxspi_setup;
|
||||||
pgm->teardown = linuxspi_teardown;
|
pgm->teardown = linuxspi_teardown;
|
||||||
pgm->parseexitspecs = linuxspi_parseexitspecs;
|
pgm->parseexitspecs = linuxspi_parseexitspecs;
|
||||||
|
pgm->parseextparams = linuxspi_parseextparams;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char linuxspi_desc[] = "SPI using Linux spidev driver";
|
const char linuxspi_desc[] = "SPI using Linux spidev driver";
|
||||||
|
|
||||||
#else /* !HAVE_LINUXSPI */
|
#else /* !HAVE_LINUXSPI */
|
||||||
|
|
||||||
void linuxspi_initpgm(PROGRAMMER * pgm)
|
void linuxspi_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
pmsg_error("Linux SPI driver not available in this configuration\n");
|
||||||
avrdude_message(MSG_INFO, "%s: Linux SPI driver not available in this configuration\n",
|
|
||||||
progname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char linuxspi_desc[] = "SPI using Linux spidev driver (not available)";
|
const char linuxspi_desc[] = "SPI using Linux spidev driver (not available)";
|
||||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char linuxspi_desc[];
|
extern const char linuxspi_desc[];
|
||||||
void linuxspi_initpgm (PROGRAMMER * pgm);
|
void linuxspi_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
1055
src/main.c
1055
src/main.c
File diff suppressed because it is too large
Load Diff
|
@ -139,6 +139,22 @@ static int micronucleus_check_connection(pdata_t* pdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool micronucleus_is_device_responsive(pdata_t* pdata, struct usb_device* device)
|
||||||
|
{
|
||||||
|
pdata->usb_handle = usb_open(device);
|
||||||
|
if (pdata->usb_handle == NULL)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = micronucleus_check_connection(pdata);
|
||||||
|
|
||||||
|
usb_close(pdata->usb_handle);
|
||||||
|
pdata->usb_handle = NULL;
|
||||||
|
|
||||||
|
return result >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int micronucleus_reconnect(pdata_t* pdata)
|
static int micronucleus_reconnect(pdata_t* pdata)
|
||||||
{
|
{
|
||||||
struct usb_device* device = usb_device(pdata->usb_handle);
|
struct usb_device* device = usb_device(pdata->usb_handle);
|
||||||
|
@ -148,7 +164,7 @@ static int micronucleus_reconnect(pdata_t* pdata)
|
||||||
|
|
||||||
for (int i = 0; i < 25; i++)
|
for (int i = 0; i < 25; i++)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE, "%s: Trying to reconnect...\n", progname);
|
pmsg_notice("trying to reconnect ...\n");
|
||||||
|
|
||||||
pdata->usb_handle = usb_open(device);
|
pdata->usb_handle = usb_open(device);
|
||||||
if (pdata->usb_handle != NULL)
|
if (pdata->usb_handle != NULL)
|
||||||
|
@ -172,14 +188,12 @@ static int micronucleus_get_bootloader_info_v1(pdata_t* pdata)
|
||||||
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: WARNING: Failed to get bootloader info block: %s\n",
|
pmsg_warning("unable to get bootloader info block: %s\n", usb_strerror());
|
||||||
progname, usb_strerror());
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else if (result < sizeof(buffer))
|
else if (result < sizeof(buffer))
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: WARNING: Received invalid bootloader info block size: %d\n",
|
pmsg_warning("received invalid bootloader info block size: %d\n", result);
|
||||||
progname, result);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -241,14 +255,12 @@ static int micronucleus_get_bootloader_info_v2(pdata_t* pdata)
|
||||||
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: WARNING: Failed to get bootloader info block: %s\n",
|
pmsg_warning("unable to get bootloader info block: %s\n", usb_strerror());
|
||||||
progname, usb_strerror());
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else if (result < sizeof(buffer))
|
else if (result < sizeof(buffer))
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: WARNING: Received invalid bootloader info block size: %d\n",
|
pmsg_warning("received invalid bootloader info block size: %d\n", result);
|
||||||
progname, result);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,19 +298,19 @@ static int micronucleus_get_bootloader_info(pdata_t* pdata)
|
||||||
|
|
||||||
static void micronucleus_dump_device_info(pdata_t* pdata)
|
static void micronucleus_dump_device_info(pdata_t* pdata)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE, "%s: Bootloader version: %d.%d\n", progname, pdata->major_version, pdata->minor_version);
|
pmsg_notice("Bootloader version: %d.%d\n", pdata->major_version, pdata->minor_version);
|
||||||
avrdude_message(MSG_NOTICE, "%s: Available flash size: %u\n", progname, pdata->flash_size);
|
imsg_notice("Available flash size: %u\n", pdata->flash_size);
|
||||||
avrdude_message(MSG_NOTICE, "%s: Page size: %u\n", progname, pdata->page_size);
|
imsg_notice("Page size: %u\n", pdata->page_size);
|
||||||
avrdude_message(MSG_NOTICE, "%s: Bootloader start: 0x%04X\n", progname, pdata->bootloader_start);
|
imsg_notice("Bootloader start: 0x%04X\n", pdata->bootloader_start);
|
||||||
avrdude_message(MSG_NOTICE, "%s: Write sleep: %ums\n", progname, pdata->write_sleep);
|
imsg_notice("Write sleep: %ums\n", pdata->write_sleep);
|
||||||
avrdude_message(MSG_NOTICE, "%s: Erase sleep: %ums\n", progname, pdata->erase_sleep);
|
imsg_notice("Erase sleep: %ums\n", pdata->erase_sleep);
|
||||||
avrdude_message(MSG_NOTICE, "%s: Signature1: 0x%02X\n", progname, pdata->signature1);
|
imsg_notice("Signature1: 0x%02X\n", pdata->signature1);
|
||||||
avrdude_message(MSG_NOTICE, "%s: Signature2: 0x%02X\n", progname, pdata->signature2);
|
imsg_notice("Signature2: 0x%02X\n", pdata->signature2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_erase_device(pdata_t* pdata)
|
static int micronucleus_erase_device(pdata_t* pdata)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_erase_device()\n", progname);
|
pmsg_debug("micronucleus_erase_device()\n");
|
||||||
|
|
||||||
int result = usb_control_msg(
|
int result = usb_control_msg(
|
||||||
pdata->usb_handle,
|
pdata->usb_handle,
|
||||||
|
@ -313,10 +325,10 @@ static int micronucleus_erase_device(pdata_t* pdata)
|
||||||
{
|
{
|
||||||
case -EIO:
|
case -EIO:
|
||||||
case -EPIPE:
|
case -EPIPE:
|
||||||
avrdude_message(MSG_NOTICE, "%s: Ignoring last error of erase command: %s\n", progname, usb_strerror());
|
pmsg_notice("ignoring last error of erase command: %s\n", usb_strerror());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
avrdude_message(MSG_INFO, "%s: WARNING: Failed is issue erase command, code %d: %s\n", progname, result, usb_strerror());
|
pmsg_warning("erase command failed, code %d: %s\n", result, usb_strerror());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,12 +338,12 @@ static int micronucleus_erase_device(pdata_t* pdata)
|
||||||
result = micronucleus_check_connection(pdata);
|
result = micronucleus_check_connection(pdata);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE, "%s: Connection dropped, trying to reconnect...\n", progname);
|
pmsg_notice("connection dropped, trying to reconnect ...\n");
|
||||||
|
|
||||||
result = micronucleus_reconnect(pdata);
|
result = micronucleus_reconnect(pdata);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: WARNING: Failed to reconnect USB device: %s\n", progname, usb_strerror());
|
pmsg_warning("unable to reconnect USB device: %s\n", usb_strerror());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,7 +369,7 @@ static int micronucleus_patch_reset_vector(pdata_t* pdata, uint8_t* buffer)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: The reset vector of the user program does not contain a branch instruction.\n", progname);
|
pmsg_error("the reset vector of the user program does not contain a branch instruction\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -415,7 +427,7 @@ static int micronucleus_write_page_v1(pdata_t* pdata, uint32_t address, uint8_t*
|
||||||
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Failed to transfer page: %s\n", progname, usb_strerror());
|
pmsg_error("unable to transfer page: %s\n", usb_strerror());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,7 +445,7 @@ static int micronucleus_write_page_v2(pdata_t* pdata, uint32_t address, uint8_t*
|
||||||
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Failed to transfer page: %s\n", progname, usb_strerror());
|
pmsg_error("unable to transfer page: %s\n", usb_strerror());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,7 +462,7 @@ static int micronucleus_write_page_v2(pdata_t* pdata, uint32_t address, uint8_t*
|
||||||
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Failed to transfer page: %s\n", progname, usb_strerror());
|
pmsg_error("unable to transfer page: %s\n", usb_strerror());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -460,7 +472,7 @@ static int micronucleus_write_page_v2(pdata_t* pdata, uint32_t address, uint8_t*
|
||||||
|
|
||||||
static int micronucleus_write_page(pdata_t* pdata, uint32_t address, uint8_t* buffer, uint32_t size)
|
static int micronucleus_write_page(pdata_t* pdata, uint32_t address, uint8_t* buffer, uint32_t size)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_write_page(address=0x%04X, size=%d)\n", progname, address, size);
|
pmsg_debug("micronucleus_write_page(address=0x%04X, size=%d)\n", address, size);
|
||||||
|
|
||||||
if (address == 0)
|
if (address == 0)
|
||||||
{
|
{
|
||||||
|
@ -512,7 +524,7 @@ static int micronucleus_write_page(pdata_t* pdata, uint32_t address, uint8_t* bu
|
||||||
|
|
||||||
static int micronucleus_start(pdata_t* pdata)
|
static int micronucleus_start(pdata_t* pdata)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_start()\n", progname);
|
pmsg_debug("micronucleus_start()\n");
|
||||||
|
|
||||||
int result = usb_control_msg(
|
int result = usb_control_msg(
|
||||||
pdata->usb_handle,
|
pdata->usb_handle,
|
||||||
|
@ -523,7 +535,7 @@ static int micronucleus_start(pdata_t* pdata)
|
||||||
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
MICRONUCLEUS_DEFAULT_TIMEOUT);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: WARNING: Failed is issue start command: %s\n", progname, usb_strerror());
|
pmsg_warning("start command failed: %s\n", usb_strerror());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,11 +546,11 @@ static int micronucleus_start(pdata_t* pdata)
|
||||||
|
|
||||||
static void micronucleus_setup(PROGRAMMER* pgm)
|
static void micronucleus_setup(PROGRAMMER* pgm)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_setup()\n", progname);
|
pmsg_debug("micronucleus_setup()\n");
|
||||||
|
|
||||||
if ((pgm->cookie = malloc(sizeof(pdata_t))) == 0)
|
if ((pgm->cookie = malloc(sizeof(pdata_t))) == 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: micronucleus_setup(): Out of memory allocating private data\n", progname);
|
pmsg_error("out of memory allocating private data\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,13 +559,12 @@ static void micronucleus_setup(PROGRAMMER* pgm)
|
||||||
|
|
||||||
static void micronucleus_teardown(PROGRAMMER* pgm)
|
static void micronucleus_teardown(PROGRAMMER* pgm)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_teardown()\n", progname);
|
pmsg_debug("micronucleus_teardown()\n");
|
||||||
free(pgm->cookie);
|
free(pgm->cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_initialize(PROGRAMMER* pgm, AVRPART* p)
|
static int micronucleus_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
pmsg_debug("micronucleus_initialize()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_initialize()\n", progname);
|
|
||||||
|
|
||||||
pdata_t* pdata = PDATA(pgm);
|
pdata_t* pdata = PDATA(pgm);
|
||||||
|
|
||||||
|
@ -566,19 +577,16 @@ static int micronucleus_initialize(PROGRAMMER* pgm, AVRPART* p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void micronucleus_display(PROGRAMMER* pgm, const char* prefix)
|
static void micronucleus_display(const PROGRAMMER *pgm, const char *prefix) {
|
||||||
{
|
pmsg_debug("micronucleus_display()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_display()\n", progname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void micronucleus_powerup(PROGRAMMER* pgm)
|
static void micronucleus_powerup(const PROGRAMMER *pgm) {
|
||||||
{
|
pmsg_debug("micronucleus_powerup()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_powerup()\n", progname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void micronucleus_powerdown(PROGRAMMER* pgm)
|
static void micronucleus_powerdown(const PROGRAMMER *pgm) {
|
||||||
{
|
pmsg_debug("micronucleus_powerdown()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_powerdown()\n", progname);
|
|
||||||
|
|
||||||
pdata_t* pdata = PDATA(pgm);
|
pdata_t* pdata = PDATA(pgm);
|
||||||
if (pdata->write_last_page)
|
if (pdata->write_last_page)
|
||||||
|
@ -602,29 +610,25 @@ static void micronucleus_powerdown(PROGRAMMER* pgm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void micronucleus_enable(PROGRAMMER* pgm)
|
static void micronucleus_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
pmsg_debug("micronucleus_enable()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_enable()\n", progname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void micronucleus_disable(PROGRAMMER* pgm)
|
static void micronucleus_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
pmsg_debug("micronucleus_disable()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_disable()\n", progname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_program_enable(PROGRAMMER* pgm, AVRPART* p)
|
static int micronucleus_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
pmsg_debug("micronucleus_program_enable()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_program_enable()\n", progname);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_read_sig_bytes(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem)
|
static int micronucleus_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem) {
|
||||||
{
|
pmsg_debug("micronucleus_read_sig_bytes()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_read_sig_bytes()\n", progname);
|
|
||||||
|
|
||||||
if (mem->size < 3)
|
if (mem->size < 3)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: memory size too small for read_sig_bytes", progname);
|
pmsg_error("memory size %d < 3 too small for read_sig_bytes", mem->size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,20 +639,18 @@ static int micronucleus_read_sig_bytes(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_chip_erase(PROGRAMMER* pgm, AVRPART* p)
|
static int micronucleus_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
pmsg_debug("micronucleus_chip_erase()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_chip_erase()\n", progname);
|
|
||||||
|
|
||||||
pdata_t* pdata = PDATA(pgm);
|
pdata_t* pdata = PDATA(pgm);
|
||||||
return micronucleus_erase_device(pdata);
|
return micronucleus_erase_device(pdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_open(PROGRAMMER* pgm, char* port)
|
static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
|
||||||
{
|
pmsg_debug("micronucleus_open(\"%s\")\n", port);
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_open(\"%s\")\n", progname, port);
|
|
||||||
|
|
||||||
pdata_t* pdata = PDATA(pgm);
|
pdata_t* pdata = PDATA(pgm);
|
||||||
char* bus_name = NULL;
|
const char *bus_name = NULL;
|
||||||
char* dev_name = NULL;
|
char* dev_name = NULL;
|
||||||
|
|
||||||
// if no -P was given or '-P usb' was given
|
// if no -P was given or '-P usb' was given
|
||||||
|
@ -673,8 +675,8 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
|
||||||
|
|
||||||
if (port != NULL && dev_name == NULL)
|
if (port != NULL && dev_name == NULL)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: ERROR: Invalid -P value: '%s'\n", progname, port);
|
pmsg_error("invalid -P value %s\n", port);
|
||||||
avrdude_message(MSG_INFO, "%sUse -P usb:bus:device\n", progbuf);
|
imsg_error("use -P usb:bus:device\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,14 +690,14 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
|
||||||
pid = *(int*)(ldata(usbpid));
|
pid = *(int*)(ldata(usbpid));
|
||||||
if (lnext(usbpid))
|
if (lnext(usbpid))
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: WARNING: using PID 0x%04x, ignoring remaining PIDs in list\n",
|
pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid);
|
||||||
progname, pid);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usb_init();
|
usb_init();
|
||||||
|
|
||||||
bool show_retry_message = true;
|
bool show_retry_message = true;
|
||||||
|
bool show_unresponsive_device_message = true;
|
||||||
|
|
||||||
time_t start_time = time(NULL);
|
time_t start_time = time(NULL);
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -717,8 +719,19 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
|
||||||
pdata->major_version = (uint8_t)(device->descriptor.bcdDevice >> 8);
|
pdata->major_version = (uint8_t)(device->descriptor.bcdDevice >> 8);
|
||||||
pdata->minor_version = (uint8_t)(device->descriptor.bcdDevice >> 0);
|
pdata->minor_version = (uint8_t)(device->descriptor.bcdDevice >> 0);
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE, "%s: Found device with Micronucleus V%d.%d, bus:device: %s:%s\n",
|
if (!micronucleus_is_device_responsive(pdata, device))
|
||||||
progname,
|
{
|
||||||
|
if (show_unresponsive_device_message)
|
||||||
|
{
|
||||||
|
pmsg_warning("unresponsive Micronucleus device detected, please reconnect ...\n");
|
||||||
|
|
||||||
|
show_unresponsive_device_message = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
pmsg_notice("found device with Micronucleus V%d.%d, bus:device: %s:%s\n",
|
||||||
pdata->major_version, pdata->minor_version,
|
pdata->major_version, pdata->minor_version,
|
||||||
bus->dirname, device->filename);
|
bus->dirname, device->filename);
|
||||||
|
|
||||||
|
@ -733,8 +746,7 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
|
||||||
|
|
||||||
if (pdata->major_version > MICRONUCLEUS_MAX_MAJOR_VERSION)
|
if (pdata->major_version > MICRONUCLEUS_MAX_MAJOR_VERSION)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: WARNING: device with unsupported version (V%d.%d) of Micronucleus detected.\n",
|
pmsg_warning("device with unsupported Micronucleus version V%d.%d\n",
|
||||||
progname,
|
|
||||||
pdata->major_version, pdata->minor_version);
|
pdata->major_version, pdata->minor_version);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -742,7 +754,7 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
|
||||||
pdata->usb_handle = usb_open(device);
|
pdata->usb_handle = usb_open(device);
|
||||||
if (pdata->usb_handle == NULL)
|
if (pdata->usb_handle == NULL)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: ERROR: Failed to open USB device: %s\n", progname, usb_strerror());
|
pmsg_error("unable to open USB device: %s\n", usb_strerror());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -754,16 +766,15 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
|
||||||
{
|
{
|
||||||
if (pdata->wait_timout < 0)
|
if (pdata->wait_timout < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: No device found, waiting for device to be plugged in...\n", progname);
|
pmsg_error("no device found, waiting for device to be plugged in ...\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: No device found, waiting %d seconds for device to be plugged in...\n",
|
pmsg_error("no device found, waiting %d seconds for device to be plugged in ...\n",
|
||||||
progname,
|
|
||||||
pdata->wait_timout);
|
pdata->wait_timout);
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: Press CTRL-C to terminate.\n", progname);
|
pmsg_error("press CTRL-C to terminate\n");
|
||||||
show_retry_message = false;
|
show_retry_message = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -779,8 +790,7 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
|
||||||
|
|
||||||
if (!pdata->usb_handle)
|
if (!pdata->usb_handle)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: ERROR: Could not find device with Micronucleus bootloader (%04X:%04X)\n",
|
pmsg_error("cannot find device with Micronucleus bootloader (%04X:%04X)\n", vid, pid);
|
||||||
progname, vid, pid);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,7 +799,7 @@ static int micronucleus_open(PROGRAMMER* pgm, char* port)
|
||||||
|
|
||||||
static void micronucleus_close(PROGRAMMER* pgm)
|
static void micronucleus_close(PROGRAMMER* pgm)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_close()\n", progname);
|
pmsg_debug("micronucleus_close()\n");
|
||||||
|
|
||||||
pdata_t* pdata = PDATA(pgm);
|
pdata_t* pdata = PDATA(pgm);
|
||||||
if (pdata->usb_handle != NULL)
|
if (pdata->usb_handle != NULL)
|
||||||
|
@ -799,11 +809,10 @@ static void micronucleus_close(PROGRAMMER* pgm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_read_byte(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
|
static int micronucleus_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char* value)
|
unsigned long addr, unsigned char* value)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_read_byte(desc=%s, addr=0x%0X)\n",
|
pmsg_debug("micronucleus_read_byte(desc=%s, addr=0x%04lX)\n", mem->desc, addr);
|
||||||
progname, mem->desc, addr);
|
|
||||||
|
|
||||||
if (strcmp(mem->desc, "lfuse") == 0 ||
|
if (strcmp(mem->desc, "lfuse") == 0 ||
|
||||||
strcmp(mem->desc, "hfuse") == 0 ||
|
strcmp(mem->desc, "hfuse") == 0 ||
|
||||||
|
@ -815,34 +824,31 @@ static int micronucleus_read_byte(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Unsupported memory type: %s\n", progname, mem->desc);
|
pmsg_notice("reading not supported for %s memory\n", mem->desc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_write_byte(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
|
static int micronucleus_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char value)
|
unsigned long addr, unsigned char value)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_write_byte(desc=%s, addr=0x%0X)\n",
|
pmsg_debug("micronucleus_write_byte(desc=%s, addr=0x%04lX)\n", mem->desc, addr);
|
||||||
progname, mem->desc, addr);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_paged_load(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
|
static int micronucleus_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_paged_load(page_size=0x%X, addr=0x%X, n_bytes=0x%X)\n",
|
pmsg_debug("micronucleus_paged_load(page_size=0x%X, addr=0x%X, n_bytes=0x%X)\n", page_size, addr, n_bytes);
|
||||||
progname, page_size, addr, n_bytes);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_paged_write(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
|
static int micronucleus_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_paged_write(page_size=0x%X, addr=0x%X, n_bytes=0x%X)\n",
|
pmsg_debug("micronucleus_paged_write(page_size=0x%X, addr=0x%X, n_bytes=0x%X)\n", page_size, addr, n_bytes);
|
||||||
progname, page_size, addr, n_bytes);
|
|
||||||
|
|
||||||
if (strcmp(mem->desc, "flash") == 0)
|
if (strcmp(mem->desc, "flash") == 0)
|
||||||
{
|
{
|
||||||
|
@ -850,20 +856,20 @@ static int micronucleus_paged_write(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
|
||||||
|
|
||||||
if (n_bytes > page_size)
|
if (n_bytes > page_size)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Buffer size (%u) exceeds page size (%u)\n", progname, n_bytes, page_size);
|
pmsg_error("buffer size %u exceeds page size %u\n", n_bytes, page_size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr + n_bytes > pdata->flash_size)
|
if (addr + n_bytes > pdata->flash_size)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Program size (%u) exceeds flash size (%u)\n", progname, addr + n_bytes, pdata->flash_size);
|
pmsg_error("program size %u exceeds flash size %u\n", addr + n_bytes, pdata->flash_size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* page_buffer = (uint8_t*)malloc(pdata->page_size);
|
uint8_t* page_buffer = (uint8_t*)malloc(pdata->page_size);
|
||||||
if (page_buffer == NULL)
|
if (page_buffer == NULL)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Failed to allocate memory\n", progname);
|
pmsg_error("unable to allocate memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -891,14 +897,13 @@ static int micronucleus_paged_write(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Unsupported memory type: %s\n", progname, mem->desc);
|
pmsg_error("unsupported memory type: %s\n", mem->desc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int micronucleus_parseextparams(PROGRAMMER* pgm, LISTID xparams)
|
static int micronucleus_parseextparams(const PROGRAMMER *pgm, const LISTID xparams) {
|
||||||
{
|
pmsg_debug("micronucleus_parseextparams()\n");
|
||||||
avrdude_message(MSG_DEBUG, "%s: micronucleus_parseextparams()\n", progname);
|
|
||||||
|
|
||||||
pdata_t* pdata = PDATA(pgm);
|
pdata_t* pdata = PDATA(pgm);
|
||||||
for (LNODEID node = lfirst(xparams); node != NULL; node = lnext(node))
|
for (LNODEID node = lfirst(xparams); node != NULL; node = lnext(node))
|
||||||
|
@ -917,7 +922,7 @@ static int micronucleus_parseextparams(PROGRAMMER* pgm, LISTID xparams)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Invalid extended parameter '%s'\n", progname, param);
|
pmsg_error("invalid extended parameter '%s'\n", param);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -925,8 +930,7 @@ static int micronucleus_parseextparams(PROGRAMMER* pgm, LISTID xparams)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void micronucleus_initpgm(PROGRAMMER* pgm)
|
void micronucleus_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "Micronucleus V2.0");
|
strcpy(pgm->type, "Micronucleus V2.0");
|
||||||
|
|
||||||
pgm->setup = micronucleus_setup;
|
pgm->setup = micronucleus_setup;
|
||||||
|
@ -953,14 +957,12 @@ void micronucleus_initpgm(PROGRAMMER* pgm)
|
||||||
#else /* !HAVE_LIBUSB */
|
#else /* !HAVE_LIBUSB */
|
||||||
|
|
||||||
// Give a proper error if we were not compiled with libusb
|
// Give a proper error if we were not compiled with libusb
|
||||||
static int micronucleus_nousb_open(struct programmer_t* pgm, char* name)
|
static int micronucleus_nousb_open(PROGRAMMER* pgm, const char* name) {
|
||||||
{
|
pmsg_error("no usb support; please compile again with libusb installed\n");
|
||||||
avrdude_message(MSG_INFO, "%s: error: No usb support. Please compile again with libusb installed.\n", progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void micronucleus_initpgm(PROGRAMMER* pgm)
|
void micronucleus_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "micronucleus");
|
strcpy(pgm->type, "micronucleus");
|
||||||
pgm->open = micronucleus_nousb_open;
|
pgm->open = micronucleus_nousb_open;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char micronucleus_desc[];
|
extern const char micronucleus_desc[];
|
||||||
void micronucleus_initpgm(PROGRAMMER* pgm);
|
void micronucleus_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
#pragma comment(lib, "ws2_32.lib")
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
#pragma comment(lib, "setupapi.lib")
|
#pragma comment(lib, "setupapi.lib")
|
||||||
|
|
||||||
|
#define strerror_r(errno,buf,len) strerror_s(buf,len,errno)
|
||||||
|
|
||||||
|
#define R_OK 4
|
||||||
|
#define W_OK 2
|
||||||
|
#define X_OK 1
|
||||||
#define F_OK 0
|
#define F_OK 0
|
||||||
|
|
||||||
#define PATH_MAX _MAX_PATH
|
#define PATH_MAX _MAX_PATH
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
//
|
||||||
|
// readline.cpp
|
||||||
|
// Copyright (C) 2022 Marius Greuel
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include "readline/readline.h"
|
||||||
|
#include "readline/history.h"
|
||||||
|
|
||||||
|
int rl_readline_version = 0x0502;
|
||||||
|
|
||||||
|
static rl_vcpfunc_t* rl_handler;
|
||||||
|
static std::unique_ptr<std::thread> rl_thread;
|
||||||
|
static std::mutex rl_mutex;
|
||||||
|
static std::string rl_line;
|
||||||
|
static bool rl_has_line = false;
|
||||||
|
|
||||||
|
static void get_line_thread()
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
std::getline(std::cin, line);
|
||||||
|
|
||||||
|
const std::lock_guard<std::mutex> lock(rl_mutex);
|
||||||
|
rl_line = line;
|
||||||
|
rl_has_line = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void call_handler(const char* string)
|
||||||
|
{
|
||||||
|
if (rl_thread)
|
||||||
|
{
|
||||||
|
rl_thread->join();
|
||||||
|
rl_thread = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rl_handler != nullptr)
|
||||||
|
{
|
||||||
|
if (string == nullptr)
|
||||||
|
{
|
||||||
|
rl_handler(nullptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rl_handler(_strdup(string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int rl_input_available(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rl_callback_read_char(void)
|
||||||
|
{
|
||||||
|
if (std::cin.eof())
|
||||||
|
{
|
||||||
|
call_handler(nullptr);
|
||||||
|
}
|
||||||
|
else if (!rl_thread)
|
||||||
|
{
|
||||||
|
rl_thread = std::make_unique<std::thread>(get_line_thread);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const std::lock_guard<std::mutex> lock(rl_mutex);
|
||||||
|
if (rl_has_line)
|
||||||
|
{
|
||||||
|
rl_has_line = false;
|
||||||
|
call_handler(rl_line.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rl_callback_handler_install(char* prompt, rl_vcpfunc_t* handler)
|
||||||
|
{
|
||||||
|
rl_handler = handler;
|
||||||
|
|
||||||
|
std::cout << prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rl_callback_handler_remove(void)
|
||||||
|
{
|
||||||
|
rl_handler = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_history(const char*)
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
//
|
||||||
|
// history.h
|
||||||
|
// Copyright (C) 2022 Marius Greuel
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void add_history(const char* string);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,24 @@
|
||||||
|
//
|
||||||
|
// readline.h
|
||||||
|
// Copyright (C) 2022 Marius Greuel
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (rl_vcpfunc_t)(char* line);
|
||||||
|
|
||||||
|
extern int rl_readline_version;
|
||||||
|
|
||||||
|
int rl_input_available(void);
|
||||||
|
void rl_callback_read_char(void);
|
||||||
|
void rl_callback_handler_install(char* prompt, rl_vcpfunc_t* handler);
|
||||||
|
void rl_callback_handler_remove(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
113
src/par.c
113
src/par.c
|
@ -73,8 +73,7 @@ static struct ppipins_t ppipins[] = {
|
||||||
|
|
||||||
#define NPINS (sizeof(ppipins)/sizeof(struct ppipins_t))
|
#define NPINS (sizeof(ppipins)/sizeof(struct ppipins_t))
|
||||||
|
|
||||||
static int par_setpin_internal(PROGRAMMER * pgm, int pin, int value)
|
static int par_setpin_internal(const PROGRAMMER *pgm, int pin, int value) {
|
||||||
{
|
|
||||||
int inverted;
|
int inverted;
|
||||||
|
|
||||||
inverted = pin & PIN_INVERSE;
|
inverted = pin & PIN_INVERSE;
|
||||||
|
@ -102,15 +101,20 @@ static int par_setpin_internal(PROGRAMMER * pgm, int pin, int value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int par_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
static int par_setpin(const PROGRAMMER * pgm, int pinfunc, int value) {
|
||||||
{
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
return par_setpin_internal(pgm, pgm->pinno[pinfunc], value);
|
return par_setpin_internal(pgm, pgm->pinno[pinfunc], value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void par_setmany(PROGRAMMER * pgm, int pinfunc, int value)
|
static void par_setmany(const PROGRAMMER *pgm, int pinfunc, int value) {
|
||||||
{
|
int pin, mask, pinset;
|
||||||
int pin, mask;
|
|
||||||
int pinset = pgm->pinno[pinfunc];
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pinset = pgm->pinno[pinfunc];
|
||||||
|
|
||||||
/* mask is anything non-pin - needs to be applied to each par_setpin to preserve inversion */
|
/* mask is anything non-pin - needs to be applied to each par_setpin to preserve inversion */
|
||||||
mask = pinset & (~PIN_MASK);
|
mask = pinset & (~PIN_MASK);
|
||||||
|
@ -121,11 +125,13 @@ static void par_setmany(PROGRAMMER * pgm, int pinfunc, int value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int par_getpin(PROGRAMMER * pgm, int pinfunc)
|
static int par_getpin(const PROGRAMMER * pgm, int pinfunc) {
|
||||||
{
|
int value, inverted, pin;
|
||||||
int value;
|
|
||||||
int inverted;
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
int pin = pgm->pinno[pinfunc];
|
return -1;
|
||||||
|
|
||||||
|
pin = pgm->pinno[pinfunc];
|
||||||
|
|
||||||
inverted = pin & PIN_INVERSE;
|
inverted = pin & PIN_INVERSE;
|
||||||
pin &= PIN_MASK;
|
pin &= PIN_MASK;
|
||||||
|
@ -150,10 +156,13 @@ static int par_getpin(PROGRAMMER * pgm, int pinfunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int par_highpulsepin(PROGRAMMER * pgm, int pinfunc)
|
static int par_highpulsepin(const PROGRAMMER *pgm, int pinfunc) {
|
||||||
{
|
int inverted, pin;
|
||||||
int inverted;
|
|
||||||
int pin = pgm->pinno[pinfunc];
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
pin = pgm->pinno[pinfunc];
|
||||||
|
|
||||||
inverted = pin & PIN_INVERSE;
|
inverted = pin & PIN_INVERSE;
|
||||||
pin &= PIN_MASK;
|
pin &= PIN_MASK;
|
||||||
|
@ -190,8 +199,7 @@ static int par_highpulsepin(PROGRAMMER * pgm, int pinfunc)
|
||||||
/*
|
/*
|
||||||
* apply power to the AVR processor
|
* apply power to the AVR processor
|
||||||
*/
|
*/
|
||||||
static void par_powerup(PROGRAMMER * pgm)
|
static void par_powerup(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
par_setmany(pgm, PPI_AVR_VCC, 1); /* power up */
|
par_setmany(pgm, PPI_AVR_VCC, 1); /* power up */
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
}
|
}
|
||||||
|
@ -200,18 +208,15 @@ static void par_powerup(PROGRAMMER * pgm)
|
||||||
/*
|
/*
|
||||||
* remove power from the AVR processor
|
* remove power from the AVR processor
|
||||||
*/
|
*/
|
||||||
static void par_powerdown(PROGRAMMER * pgm)
|
static void par_powerdown(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
par_setmany(pgm, PPI_AVR_VCC, 0); /* power down */
|
par_setmany(pgm, PPI_AVR_VCC, 0); /* power down */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void par_disable(PROGRAMMER * pgm)
|
static void par_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
par_setmany(pgm, PPI_AVR_BUFF, 1); /* turn off */
|
par_setmany(pgm, PPI_AVR_BUFF, 1); /* turn off */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void par_enable(PROGRAMMER * pgm)
|
static void par_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* Prepare to start talking to the connected device - pull reset low
|
* Prepare to start talking to the connected device - pull reset low
|
||||||
* first, delay a few milliseconds, then enable the buffer. This
|
* first, delay a few milliseconds, then enable the buffer. This
|
||||||
|
@ -232,8 +237,7 @@ static void par_enable(PROGRAMMER * pgm)
|
||||||
par_setmany(pgm, PPI_AVR_BUFF, 0);
|
par_setmany(pgm, PPI_AVR_BUFF, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int par_open(PROGRAMMER * pgm, char * port)
|
static int par_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (bitbang_check_prerequisites(pgm) < 0)
|
if (bitbang_check_prerequisites(pgm) < 0)
|
||||||
|
@ -241,8 +245,7 @@ static int par_open(PROGRAMMER * pgm, char * port)
|
||||||
|
|
||||||
ppi_open(port, &pgm->fd);
|
ppi_open(port, &pgm->fd);
|
||||||
if (pgm->fd.ifd < 0) {
|
if (pgm->fd.ifd < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: failed to open parallel port \"%s\"\n\n",
|
pmsg_error("unable to open parallel port %s\n\n", port);
|
||||||
progname, port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,14 +254,14 @@ static int par_open(PROGRAMMER * pgm, char * port)
|
||||||
*/
|
*/
|
||||||
rc = ppi_getall(&pgm->fd, PPIDATA);
|
rc = ppi_getall(&pgm->fd, PPIDATA);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: error reading status of ppi data port\n", progname);
|
pmsg_error("unable to read status of ppi data port\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pgm->ppidata = rc;
|
pgm->ppidata = rc;
|
||||||
|
|
||||||
rc = ppi_getall(&pgm->fd, PPICTRL);
|
rc = ppi_getall(&pgm->fd, PPICTRL);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: error reading status of ppi ctrl port\n", progname);
|
pmsg_error("unable to read status of ppi ctrl port\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pgm->ppictrl = rc;
|
pgm->ppictrl = rc;
|
||||||
|
@ -267,8 +270,7 @@ static int par_open(PROGRAMMER * pgm, char * port)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void par_close(PROGRAMMER * pgm)
|
static void par_close(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore pin values before closing,
|
* Restore pin values before closing,
|
||||||
|
@ -331,40 +333,41 @@ static void par_close(PROGRAMMER * pgm)
|
||||||
/*
|
/*
|
||||||
* parse the -E string
|
* parse the -E string
|
||||||
*/
|
*/
|
||||||
static int par_parseexitspecs(PROGRAMMER * pgm, char *s)
|
static int par_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
|
||||||
{
|
char *cp, *s, *str = cfg_strdup("par_parseexitspecs()", sp);
|
||||||
char *cp;
|
|
||||||
|
|
||||||
while ((cp = strtok(s, ","))) {
|
s = str;
|
||||||
if (strcmp(cp, "reset") == 0) {
|
while((cp = strtok(s, ","))) {
|
||||||
|
if(strcmp(cp, "reset") == 0)
|
||||||
pgm->exit_reset = EXIT_RESET_ENABLED;
|
pgm->exit_reset = EXIT_RESET_ENABLED;
|
||||||
}
|
|
||||||
else if (strcmp(cp, "noreset") == 0) {
|
else if(strcmp(cp, "noreset") == 0)
|
||||||
pgm->exit_reset = EXIT_RESET_DISABLED;
|
pgm->exit_reset = EXIT_RESET_DISABLED;
|
||||||
}
|
|
||||||
else if (strcmp(cp, "vcc") == 0) {
|
else if(strcmp(cp, "vcc") == 0)
|
||||||
pgm->exit_vcc = EXIT_VCC_ENABLED;
|
pgm->exit_vcc = EXIT_VCC_ENABLED;
|
||||||
}
|
|
||||||
else if (strcmp(cp, "novcc") == 0) {
|
else if(strcmp(cp, "novcc") == 0)
|
||||||
pgm->exit_vcc = EXIT_VCC_DISABLED;
|
pgm->exit_vcc = EXIT_VCC_DISABLED;
|
||||||
}
|
|
||||||
else if (strcmp(cp, "d_high") == 0) {
|
else if(strcmp(cp, "d_high") == 0)
|
||||||
pgm->exit_datahigh = EXIT_DATAHIGH_ENABLED;
|
pgm->exit_datahigh = EXIT_DATAHIGH_ENABLED;
|
||||||
}
|
|
||||||
else if (strcmp(cp, "d_low") == 0) {
|
else if(strcmp(cp, "d_low") == 0)
|
||||||
pgm->exit_datahigh = EXIT_DATAHIGH_DISABLED;
|
pgm->exit_datahigh = EXIT_DATAHIGH_DISABLED;
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
|
free(str);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
s = 0; /* strtok() should be called with the actual string only once */
|
s = NULL; // Only call strtok() once with the actual string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(str);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void par_initpgm(PROGRAMMER * pgm)
|
void par_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "PPI");
|
strcpy(pgm->type, "PPI");
|
||||||
|
|
||||||
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
||||||
|
@ -400,10 +403,8 @@ void par_initpgm(PROGRAMMER * pgm)
|
||||||
|
|
||||||
#else /* !HAVE_PARPORT */
|
#else /* !HAVE_PARPORT */
|
||||||
|
|
||||||
void par_initpgm(PROGRAMMER * pgm)
|
void par_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
pmsg_error("parallel port access not available in this configuration\n");
|
||||||
avrdude_message(MSG_INFO, "%s: parallel port access not available in this configuration\n",
|
|
||||||
progname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_PARPORT */
|
#endif /* HAVE_PARPORT */
|
||||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char par_desc[];
|
extern const char par_desc[];
|
||||||
void par_initpgm (PROGRAMMER * pgm);
|
void par_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
298
src/pgm.c
298
src/pgm.c
|
@ -28,64 +28,68 @@
|
||||||
#include "avrdude.h"
|
#include "avrdude.h"
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
|
|
||||||
static int pgm_default_2 (struct programmer_t *, AVRPART *);
|
static void pgm_default(void);
|
||||||
static int pgm_default_3 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem,
|
static int pgm_default_2(const PROGRAMMER *, const AVRPART *);
|
||||||
unsigned long addr, unsigned char * value);
|
static int pgm_default_3(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
static void pgm_default_4 (struct programmer_t *);
|
unsigned long addr, unsigned char * value);
|
||||||
static int pgm_default_5 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem,
|
static void pgm_default_4(const PROGRAMMER *);
|
||||||
unsigned long addr, unsigned char data);
|
static int pgm_default_5(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
static void pgm_default_6 (struct programmer_t *, const char *);
|
unsigned long addr, unsigned char data);
|
||||||
|
static void pgm_default_6(const PROGRAMMER *, const char *);
|
||||||
|
|
||||||
|
|
||||||
static int pgm_default_open (struct programmer_t *pgm, char * name)
|
static int pgm_default_open(PROGRAMMER *pgm, const char *name) {
|
||||||
{
|
pmsg_error("programmer does not support open()");
|
||||||
avrdude_message(MSG_INFO, "\n%s: Fatal error: Programmer does not support open()",
|
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pgm_default_led (struct programmer_t * pgm, int value)
|
static void pgm_default_close(PROGRAMMER *pgm) {
|
||||||
{
|
pgm_default();
|
||||||
/*
|
}
|
||||||
* If programmer has no LEDs, just do nothing.
|
|
||||||
*/
|
static void pgm_default_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
|
pgm_default();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pgm_default_led(const PROGRAMMER *pgm, int value) {
|
||||||
|
// If programmer has no LEDs, just do nothing
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void pgm_default_powerup_powerdown (struct programmer_t * pgm)
|
static void pgm_default_powerup_powerdown(const PROGRAMMER *pgm) {
|
||||||
{
|
// If programmer does not support powerup/down, just do nothing
|
||||||
/*
|
|
||||||
* If programmer does not support powerup/down, just do nothing.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PROGRAMMER * pgm_new(void)
|
PROGRAMMER *pgm_new(void) {
|
||||||
{
|
PROGRAMMER *pgm = (PROGRAMMER *) cfg_malloc("pgm_new()", sizeof(*pgm));
|
||||||
int i;
|
const char *nulp = cache_string("");
|
||||||
PROGRAMMER * pgm;
|
|
||||||
|
|
||||||
pgm = (PROGRAMMER *)malloc(sizeof(*pgm));
|
|
||||||
if (pgm == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory allocating programmer structure\n",
|
|
||||||
progname);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(pgm, 0, sizeof(*pgm));
|
|
||||||
|
|
||||||
|
// Initialise const char * and LISTID entities
|
||||||
pgm->id = lcreat(NULL, 0);
|
pgm->id = lcreat(NULL, 0);
|
||||||
pgm->usbpid = lcreat(NULL, 0);
|
pgm->usbpid = lcreat(NULL, 0);
|
||||||
pgm->desc[0] = 0;
|
pgm->hvupdi_support = lcreat(NULL, 0);
|
||||||
pgm->type[0] = 0;
|
pgm->desc = nulp;
|
||||||
pgm->config_file[0] = 0;
|
pgm->parent_id = nulp;
|
||||||
|
pgm->usbdev = nulp;
|
||||||
|
pgm->usbsn = nulp;
|
||||||
|
pgm->usbvendor = nulp;
|
||||||
|
pgm->usbproduct = nulp;
|
||||||
|
pgm->config_file = nulp;
|
||||||
|
|
||||||
|
// Allocate cache structures for flash and EEPROM, *do not* free in pgm_free()
|
||||||
|
pgm->cp_flash = cfg_malloc("pgm_new()", sizeof(AVR_Cache));
|
||||||
|
pgm->cp_eeprom = cfg_malloc("pgm_new()", sizeof(AVR_Cache));
|
||||||
|
|
||||||
|
// Default values
|
||||||
|
pgm->initpgm = NULL;
|
||||||
pgm->lineno = 0;
|
pgm->lineno = 0;
|
||||||
pgm->baudrate = 0;
|
pgm->baudrate = 0;
|
||||||
pgm->initpgm = NULL;
|
|
||||||
|
|
||||||
for (i=0; i<N_PINS; i++) {
|
// Clear pin array
|
||||||
pgm->pinno[i] = 0;
|
for(int i=0; i<N_PINS; i++) {
|
||||||
|
pgm->pinno[i] = NO_PIN;
|
||||||
pin_clear_all(&(pgm->pin[i]));
|
pin_clear_all(&(pgm->pin[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,14 +99,14 @@ PROGRAMMER * pgm_new(void)
|
||||||
*/
|
*/
|
||||||
pgm->initialize = pgm_default_2;
|
pgm->initialize = pgm_default_2;
|
||||||
pgm->display = pgm_default_6;
|
pgm->display = pgm_default_6;
|
||||||
pgm->enable = pgm_default_4;
|
pgm->enable = pgm_default_enable;
|
||||||
pgm->disable = pgm_default_4;
|
pgm->disable = pgm_default_4;
|
||||||
pgm->powerup = pgm_default_powerup_powerdown;
|
pgm->powerup = pgm_default_powerup_powerdown;
|
||||||
pgm->powerdown = pgm_default_powerup_powerdown;
|
pgm->powerdown = pgm_default_powerup_powerdown;
|
||||||
pgm->program_enable = pgm_default_2;
|
pgm->program_enable = pgm_default_2;
|
||||||
pgm->chip_erase = pgm_default_2;
|
pgm->chip_erase = pgm_default_2;
|
||||||
pgm->open = pgm_default_open;
|
pgm->open = pgm_default_open;
|
||||||
pgm->close = pgm_default_4;
|
pgm->close = pgm_default_close;
|
||||||
pgm->read_byte = pgm_default_3;
|
pgm->read_byte = pgm_default_3;
|
||||||
pgm->write_byte = pgm_default_5;
|
pgm->write_byte = pgm_default_5;
|
||||||
|
|
||||||
|
@ -115,172 +119,187 @@ PROGRAMMER * pgm_new(void)
|
||||||
pgm->err_led = pgm_default_led;
|
pgm->err_led = pgm_default_led;
|
||||||
pgm->pgm_led = pgm_default_led;
|
pgm->pgm_led = pgm_default_led;
|
||||||
pgm->vfy_led = pgm_default_led;
|
pgm->vfy_led = pgm_default_led;
|
||||||
|
pgm->read_byte_cached = avr_read_byte_cached;
|
||||||
|
pgm->write_byte_cached = avr_write_byte_cached;
|
||||||
|
pgm->chip_erase_cached = avr_chip_erase_cached;
|
||||||
|
pgm->page_erase_cached = avr_page_erase_cached;
|
||||||
|
pgm->flush_cache = avr_flush_cache;
|
||||||
|
pgm->reset_cache = avr_reset_cache;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* optional functions - these are checked to make sure they are
|
* optional functions - these are checked to make sure they are
|
||||||
* assigned before they are called
|
* assigned before they are called
|
||||||
*/
|
*/
|
||||||
|
pgm->unlock = NULL;
|
||||||
pgm->cmd = NULL;
|
pgm->cmd = NULL;
|
||||||
pgm->cmd_tpi = NULL;
|
pgm->cmd_tpi = NULL;
|
||||||
pgm->spi = NULL;
|
pgm->spi = NULL;
|
||||||
pgm->paged_write = NULL;
|
pgm->paged_write = NULL;
|
||||||
pgm->paged_load = NULL;
|
pgm->paged_load = NULL;
|
||||||
|
pgm->page_erase = NULL;
|
||||||
pgm->write_setup = NULL;
|
pgm->write_setup = NULL;
|
||||||
pgm->read_sig_bytes = NULL;
|
pgm->read_sig_bytes = NULL;
|
||||||
|
pgm->read_sib = NULL;
|
||||||
|
pgm->term_keep_alive= NULL;
|
||||||
|
pgm->print_parms = NULL;
|
||||||
pgm->set_vtarget = NULL;
|
pgm->set_vtarget = NULL;
|
||||||
pgm->set_varef = NULL;
|
pgm->set_varef = NULL;
|
||||||
pgm->set_fosc = NULL;
|
pgm->set_fosc = NULL;
|
||||||
|
pgm->set_sck_period = NULL;
|
||||||
|
pgm->setpin = NULL;
|
||||||
|
pgm->getpin = NULL;
|
||||||
|
pgm->highpulsepin = NULL;
|
||||||
|
pgm->parseexitspecs = NULL;
|
||||||
pgm->perform_osccal = NULL;
|
pgm->perform_osccal = NULL;
|
||||||
pgm->parseextparams = NULL;
|
pgm->parseextparams = NULL;
|
||||||
pgm->setup = NULL;
|
pgm->setup = NULL;
|
||||||
pgm->teardown = NULL;
|
pgm->teardown = NULL;
|
||||||
|
pgm->readonly = NULL;
|
||||||
|
pgm->flash_readhook = NULL;
|
||||||
|
|
||||||
|
// For allocating "global" memory by the programmer
|
||||||
|
pgm->cookie = NULL;
|
||||||
|
|
||||||
return pgm;
|
return pgm;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pgm_free(PROGRAMMER * const p)
|
void pgm_free(PROGRAMMER *p) {
|
||||||
{
|
if(p) {
|
||||||
ldestroy_cb(p->id, free);
|
if(p->id) {
|
||||||
ldestroy_cb(p->usbpid, free);
|
ldestroy_cb(p->id, free);
|
||||||
p->id = NULL;
|
p->id = NULL;
|
||||||
p->usbpid = NULL;
|
|
||||||
/* this is done by pgm_teardown, but usually cookie is not set to NULL */
|
|
||||||
/* if (p->cookie !=NULL) {
|
|
||||||
free(p->cookie);
|
|
||||||
p->cookie = NULL;
|
|
||||||
}*/
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
PROGRAMMER * pgm_dup(const PROGRAMMER * const src)
|
|
||||||
{
|
|
||||||
PROGRAMMER * pgm;
|
|
||||||
LNODEID ln;
|
|
||||||
|
|
||||||
pgm = (PROGRAMMER *)malloc(sizeof(*pgm));
|
|
||||||
if (pgm == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory allocating programmer structure\n",
|
|
||||||
progname);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(pgm, src, sizeof(*pgm));
|
|
||||||
|
|
||||||
pgm->id = lcreat(NULL, 0);
|
|
||||||
pgm->usbpid = lcreat(NULL, 0);
|
|
||||||
|
|
||||||
for (ln = lfirst(src->usbpid); ln; ln = lnext(ln)) {
|
|
||||||
int *ip = malloc(sizeof(int));
|
|
||||||
if (ip == NULL) {
|
|
||||||
avrdude_message(MSG_INFO, "%s: out of memory allocating programmer structure\n",
|
|
||||||
progname);
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
*ip = *(int *) ldata(ln);
|
if(p->usbpid) {
|
||||||
ladd(pgm->usbpid, ip);
|
ldestroy_cb(p->usbpid, free);
|
||||||
|
p->usbpid = NULL;
|
||||||
|
}
|
||||||
|
if(p->hvupdi_support) {
|
||||||
|
ldestroy_cb(p->hvupdi_support, free);
|
||||||
|
p->hvupdi_support = NULL;
|
||||||
|
}
|
||||||
|
// Never free const char *, eg, p->desc, which are set by cache_string()
|
||||||
|
// p->cookie is freed by pgm_teardown
|
||||||
|
// Never free cp_eeprom or cp_flash cache structures
|
||||||
|
free(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PROGRAMMER *pgm_dup(const PROGRAMMER *src) {
|
||||||
|
PROGRAMMER *pgm = pgm_new();
|
||||||
|
|
||||||
|
if(src) {
|
||||||
|
ldestroy_cb(pgm->id, free);
|
||||||
|
ldestroy_cb(pgm->usbpid, free);
|
||||||
|
ldestroy_cb(pgm->hvupdi_support, free);
|
||||||
|
// There must be only one cache, even though the part is duplicated
|
||||||
|
if(pgm->cp_flash)
|
||||||
|
free(pgm->cp_flash);
|
||||||
|
if(pgm->cp_eeprom)
|
||||||
|
free(pgm->cp_eeprom);
|
||||||
|
|
||||||
|
memcpy(pgm, src, sizeof(*pgm));
|
||||||
|
|
||||||
|
pgm->id = lcreat(NULL, 0);
|
||||||
|
pgm->usbpid = lcreat(NULL, 0);
|
||||||
|
pgm->hvupdi_support = lcreat(NULL, 0);
|
||||||
|
|
||||||
|
// Leave id list empty but copy usbpid and hvupdi_support over
|
||||||
|
if(src->hvupdi_support)
|
||||||
|
for(LNODEID ln = lfirst(src->hvupdi_support); ln; ln = lnext(ln)) {
|
||||||
|
int *ip = cfg_malloc("pgm_dup()", sizeof(int));
|
||||||
|
*ip = *(int *) ldata(ln);
|
||||||
|
ladd(pgm->hvupdi_support, ip);
|
||||||
|
}
|
||||||
|
if(src->usbpid)
|
||||||
|
for(LNODEID ln = lfirst(src->usbpid); ln; ln = lnext(ln)) {
|
||||||
|
int *ip = cfg_malloc("pgm_dup()", sizeof(int));
|
||||||
|
*ip = *(int *) ldata(ln);
|
||||||
|
ladd(pgm->usbpid, ip);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pgm;
|
return pgm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void pgm_default(void)
|
static void pgm_default(void) {
|
||||||
{
|
pmsg_error("programmer operation not supported\n");
|
||||||
avrdude_message(MSG_INFO, "%s: programmer operation not supported\n", progname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int pgm_default_2 (struct programmer_t * pgm, AVRPART * p)
|
static int pgm_default_2 (const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
pgm_default();
|
pgm_default();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pgm_default_3 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem,
|
static int pgm_default_3 (const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char * value)
|
unsigned long addr, unsigned char * value) {
|
||||||
{
|
|
||||||
pgm_default();
|
pgm_default();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pgm_default_4 (struct programmer_t * pgm)
|
static void pgm_default_4 (const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
pgm_default();
|
pgm_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pgm_default_5 (struct programmer_t * pgm, AVRPART * p, AVRMEM * mem,
|
static int pgm_default_5 (const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char data)
|
unsigned long addr, unsigned char data) {
|
||||||
{
|
|
||||||
pgm_default();
|
pgm_default();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pgm_default_6 (struct programmer_t * pgm, const char * p)
|
static void pgm_default_6 (const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
|
||||||
pgm_default();
|
pgm_default();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void programmer_display(PROGRAMMER * pgm, const char * p)
|
void programmer_display(PROGRAMMER *pgm, const char * p) {
|
||||||
{
|
msg_info("%sProgrammer Type : %s\n", p, pgm->type);
|
||||||
avrdude_message(MSG_INFO, "%sProgrammer Type : %s\n", p, pgm->type);
|
msg_info("%sDescription : %s\n", p, pgm->desc);
|
||||||
avrdude_message(MSG_INFO, "%sDescription : %s\n", p, pgm->desc);
|
|
||||||
|
|
||||||
pgm->display(pgm, p);
|
pgm->display(pgm, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pgm_display_generic_mask(PROGRAMMER * pgm, const char * p, unsigned int show)
|
void pgm_display_generic_mask(const PROGRAMMER *pgm, const char *p, unsigned int show) {
|
||||||
{
|
|
||||||
if(show & (1<<PPI_AVR_VCC))
|
if(show & (1<<PPI_AVR_VCC))
|
||||||
avrdude_message(MSG_INFO, "%s VCC = %s\n", p, pins_to_str(&pgm->pin[PPI_AVR_VCC]));
|
msg_info("%s VCC = %s\n", p, pins_to_str(&pgm->pin[PPI_AVR_VCC]));
|
||||||
if(show & (1<<PPI_AVR_BUFF))
|
if(show & (1<<PPI_AVR_BUFF))
|
||||||
avrdude_message(MSG_INFO, "%s BUFF = %s\n", p, pins_to_str(&pgm->pin[PPI_AVR_BUFF]));
|
msg_info("%s BUFF = %s\n", p, pins_to_str(&pgm->pin[PPI_AVR_BUFF]));
|
||||||
if(show & (1<<PIN_AVR_RESET))
|
if(show & (1<<PIN_AVR_RESET))
|
||||||
avrdude_message(MSG_INFO, "%s RESET = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_RESET]));
|
msg_info("%s RESET = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_RESET]));
|
||||||
if(show & (1<<PIN_AVR_SCK))
|
if(show & (1<<PIN_AVR_SCK))
|
||||||
avrdude_message(MSG_INFO, "%s SCK = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SCK]));
|
msg_info("%s SCK = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SCK]));
|
||||||
if(show & (1<<PIN_AVR_MOSI))
|
if(show & (1<<PIN_AVR_SDO))
|
||||||
avrdude_message(MSG_INFO, "%s MOSI = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_MOSI]));
|
msg_info("%s SDO = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SDO]));
|
||||||
if(show & (1<<PIN_AVR_MISO))
|
if(show & (1<<PIN_AVR_SDI))
|
||||||
avrdude_message(MSG_INFO, "%s MISO = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_MISO]));
|
msg_info("%s SDI = %s\n", p, pins_to_str(&pgm->pin[PIN_AVR_SDI]));
|
||||||
if(show & (1<<PIN_LED_ERR))
|
if(show & (1<<PIN_LED_ERR))
|
||||||
avrdude_message(MSG_INFO, "%s ERR LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_ERR]));
|
msg_info("%s ERR LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_ERR]));
|
||||||
if(show & (1<<PIN_LED_RDY))
|
if(show & (1<<PIN_LED_RDY))
|
||||||
avrdude_message(MSG_INFO, "%s RDY LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_RDY]));
|
msg_info("%s RDY LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_RDY]));
|
||||||
if(show & (1<<PIN_LED_PGM))
|
if(show & (1<<PIN_LED_PGM))
|
||||||
avrdude_message(MSG_INFO, "%s PGM LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_PGM]));
|
msg_info("%s PGM LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_PGM]));
|
||||||
if(show & (1<<PIN_LED_VFY))
|
if(show & (1<<PIN_LED_VFY))
|
||||||
avrdude_message(MSG_INFO, "%s VFY LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_VFY]));
|
msg_info("%s VFY LED = %s\n", p, pins_to_str(&pgm->pin[PIN_LED_VFY]));
|
||||||
}
|
}
|
||||||
|
|
||||||
void pgm_display_generic(PROGRAMMER * pgm, const char * p)
|
void pgm_display_generic(const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
|
||||||
pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS);
|
pgm_display_generic_mask(pgm, p, SHOW_ALL_PINS);
|
||||||
}
|
}
|
||||||
|
|
||||||
PROGRAMMER * locate_programmer(LISTID programmers, const char * configid)
|
PROGRAMMER *locate_programmer(const LISTID programmers, const char *configid) {
|
||||||
{
|
PROGRAMMER *p = NULL;
|
||||||
LNODEID ln1, ln2;
|
int found = 0;
|
||||||
PROGRAMMER * p = NULL;
|
|
||||||
const char * id;
|
|
||||||
int found;
|
|
||||||
|
|
||||||
found = 0;
|
for(LNODEID ln1=lfirst(programmers); ln1 && !found; ln1=lnext(ln1)) {
|
||||||
|
|
||||||
for (ln1=lfirst(programmers); ln1 && !found; ln1=lnext(ln1)) {
|
|
||||||
p = ldata(ln1);
|
p = ldata(ln1);
|
||||||
for (ln2=lfirst(p->id); ln2 && !found; ln2=lnext(ln2)) {
|
for(LNODEID ln2=lfirst(p->id); ln2 && !found; ln2=lnext(ln2))
|
||||||
id = ldata(ln2);
|
if(strcasecmp(configid, (const char *) ldata(ln2)) == 0)
|
||||||
if (strcasecmp(configid, id) == 0)
|
|
||||||
found = 1;
|
found = 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found)
|
return found? p: NULL;
|
||||||
return p;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -310,16 +329,11 @@ void walk_programmers(LISTID programmers, walk_programmers_cb cb, void *cookie)
|
||||||
/*
|
/*
|
||||||
* Compare function to sort the list of programmers
|
* Compare function to sort the list of programmers
|
||||||
*/
|
*/
|
||||||
static int sort_programmer_compare(PROGRAMMER * p1,PROGRAMMER * p2)
|
static int sort_programmer_compare(const PROGRAMMER *p1, const PROGRAMMER *p2) {
|
||||||
{
|
if(p1 == NULL || p1->id == NULL || p2 == NULL || p2->id == NULL)
|
||||||
char* id1;
|
|
||||||
char* id2;
|
|
||||||
if(p1 == NULL || p2 == NULL) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
id1 = ldata(lfirst(p1->id));
|
return strcasecmp(ldata(lfirst(p1->id)), ldata(lfirst(p2->id)));
|
||||||
id2 = ldata(lfirst(p2->id));
|
|
||||||
return strncasecmp(id1,id2,AVR_IDLEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
112
src/pgm_type.c
112
src/pgm_type.c
|
@ -51,60 +51,64 @@
|
||||||
#include "stk500generic.h"
|
#include "stk500generic.h"
|
||||||
#include "stk500v2.h"
|
#include "stk500v2.h"
|
||||||
#include "teensy.h"
|
#include "teensy.h"
|
||||||
|
#include "urclock.h"
|
||||||
#include "usbasp.h"
|
#include "usbasp.h"
|
||||||
#include "usbtiny.h"
|
#include "usbtiny.h"
|
||||||
#include "wiring.h"
|
#include "wiring.h"
|
||||||
#include "xbee.h"
|
#include "xbee.h"
|
||||||
|
|
||||||
|
|
||||||
const PROGRAMMER_TYPE programmers_types[] = {
|
const PROGRAMMER_TYPE programmers_types[] = { // Name(s) the programmers call themselves
|
||||||
{"arduino", arduino_initpgm, arduino_desc},
|
{"arduino", arduino_initpgm, arduino_desc}, // "Arduino"
|
||||||
{"avr910", avr910_initpgm, avr910_desc},
|
{"avr910", avr910_initpgm, avr910_desc}, // "avr910"
|
||||||
{"avrftdi", avrftdi_initpgm, avrftdi_desc},
|
{"avrftdi", avrftdi_initpgm, avrftdi_desc}, // "avrftdi"
|
||||||
{"buspirate", buspirate_initpgm, buspirate_desc},
|
{"buspirate", buspirate_initpgm, buspirate_desc}, // "BusPirate"
|
||||||
{"buspirate_bb", buspirate_bb_initpgm, buspirate_bb_desc},
|
{"buspirate_bb", buspirate_bb_initpgm, buspirate_bb_desc}, // "BusPirate_BB"
|
||||||
{"butterfly", butterfly_initpgm, butterfly_desc},
|
{"butterfly", butterfly_initpgm, butterfly_desc}, // "butterfly"
|
||||||
{"butterfly_mk", butterfly_mk_initpgm, butterfly_mk_desc},
|
{"butterfly_mk", butterfly_mk_initpgm, butterfly_mk_desc}, // "butterfly_mk"
|
||||||
{"dragon_dw", jtagmkII_dragon_dw_initpgm, jtagmkII_dragon_dw_desc},
|
{"dragon_dw", jtagmkII_dragon_dw_initpgm, jtagmkII_dragon_dw_desc}, // "DRAGON_DW"
|
||||||
{"dragon_hvsp", stk500v2_dragon_hvsp_initpgm, stk500v2_dragon_hvsp_desc},
|
{"dragon_hvsp", stk500v2_dragon_hvsp_initpgm, stk500v2_dragon_hvsp_desc}, // "DRAGON_HVSP"
|
||||||
{"dragon_isp", stk500v2_dragon_isp_initpgm, stk500v2_dragon_isp_desc},
|
{"dragon_isp", stk500v2_dragon_isp_initpgm, stk500v2_dragon_isp_desc}, // "DRAGON_ISP"
|
||||||
{"dragon_jtag", jtagmkII_dragon_initpgm, jtagmkII_dragon_desc},
|
{"dragon_jtag", jtagmkII_dragon_initpgm, jtagmkII_dragon_desc}, // "DRAGON_JTAG"
|
||||||
{"dragon_pdi", jtagmkII_dragon_pdi_initpgm, jtagmkII_dragon_pdi_desc},
|
{"dragon_pdi", jtagmkII_dragon_pdi_initpgm, jtagmkII_dragon_pdi_desc}, // "DRAGON_PDI"
|
||||||
{"dragon_pp", stk500v2_dragon_pp_initpgm, stk500v2_dragon_pp_desc},
|
{"dragon_pp", stk500v2_dragon_pp_initpgm, stk500v2_dragon_pp_desc}, // "DRAGON_PP"
|
||||||
{"flip1", flip1_initpgm, flip1_desc},
|
{"flip1", flip1_initpgm, flip1_desc}, // "flip1"
|
||||||
{"flip2", flip2_initpgm, flip2_desc},
|
{"flip2", flip2_initpgm, flip2_desc}, // "flip2"
|
||||||
{"ftdi_syncbb", ft245r_initpgm, ft245r_desc},
|
{"ftdi_syncbb", ft245r_initpgm, ft245r_desc}, // "ftdi_syncbb"
|
||||||
{"jtagmki", jtagmkI_initpgm, jtagmkI_desc},
|
{"jtagmki", jtagmkI_initpgm, jtagmkI_desc}, // "JTAGMKI"
|
||||||
{"jtagmkii", jtagmkII_initpgm, jtagmkII_desc},
|
{"jtagmkii", jtagmkII_initpgm, jtagmkII_desc}, // "JTAGMKII"
|
||||||
{"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc},
|
{"jtagmkii_avr32", jtagmkII_avr32_initpgm, jtagmkII_avr32_desc}, // "JTAGMKII_AVR32"
|
||||||
{"jtagmkii_dw", jtagmkII_dw_initpgm, jtagmkII_dw_desc},
|
{"jtagmkii_dw", jtagmkII_dw_initpgm, jtagmkII_dw_desc}, // "JTAGMKII_DW"
|
||||||
{"jtagmkii_isp", stk500v2_jtagmkII_initpgm, stk500v2_jtagmkII_desc},
|
{"jtagmkii_isp", stk500v2_jtagmkII_initpgm, stk500v2_jtagmkII_desc}, // "JTAGMKII_ISP"
|
||||||
{"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc},
|
{"jtagmkii_pdi", jtagmkII_pdi_initpgm, jtagmkII_pdi_desc}, // "JTAGMKII_PDI"
|
||||||
{"jtagice3", jtag3_initpgm, jtag3_desc},
|
{"jtagmkii_updi", jtagmkII_updi_initpgm, jtagmkII_updi_desc}, // "JTAGMKII_UPDI"
|
||||||
{"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc},
|
{"jtagice3", jtag3_initpgm, jtag3_desc}, // "JTAGICE3"
|
||||||
{"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc},
|
{"jtagice3_pdi", jtag3_pdi_initpgm, jtag3_pdi_desc}, // "JTAGICE3_PDI"
|
||||||
{"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc},
|
{"jtagice3_updi", jtag3_updi_initpgm, jtag3_updi_desc}, // "JTAGICE3_UPDI"
|
||||||
{"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc},
|
{"jtagice3_dw", jtag3_dw_initpgm, jtag3_dw_desc}, // "JTAGICE3_DW"
|
||||||
{"linuxgpio", linuxgpio_initpgm, linuxgpio_desc},
|
{"jtagice3_isp", stk500v2_jtag3_initpgm, stk500v2_jtag3_desc}, // "JTAG3_ISP"
|
||||||
{"linuxspi", linuxspi_initpgm, linuxspi_desc},
|
{"jtagice3_tpi", jtag3_tpi_initpgm, jtag3_tpi_desc}, // "JTAGICE3_TPI"
|
||||||
{"micronucleus", micronucleus_initpgm, micronucleus_desc},
|
{"linuxgpio", linuxgpio_initpgm, linuxgpio_desc}, // "linuxgpio"
|
||||||
{"par", par_initpgm, par_desc},
|
{"linuxspi", linuxspi_initpgm, linuxspi_desc}, // LINUXSPI
|
||||||
{"pickit2", pickit2_initpgm, pickit2_desc},
|
{"micronucleus", micronucleus_initpgm, micronucleus_desc}, // "micronucleus" or "Micronucleus V2.0"
|
||||||
{"serbb", serbb_initpgm, serbb_desc},
|
{"par", par_initpgm, par_desc}, // "PPI"
|
||||||
{"serialupdi", serialupdi_initpgm, serialupdi_desc},
|
{"pickit2", pickit2_initpgm, pickit2_desc}, // "pickit2"
|
||||||
{"stk500", stk500_initpgm, stk500_desc},
|
{"serbb", serbb_initpgm, serbb_desc}, // "SERBB"
|
||||||
{"stk500generic", stk500generic_initpgm, stk500generic_desc},
|
{"serialupdi", serialupdi_initpgm, serialupdi_desc}, // "serialupdi"
|
||||||
{"stk500v2", stk500v2_initpgm, stk500v2_desc},
|
{"stk500", stk500_initpgm, stk500_desc}, // "STK500"
|
||||||
{"stk500hvsp", stk500hvsp_initpgm, stk500hvsp_desc},
|
{"stk500generic", stk500generic_initpgm, stk500generic_desc}, // "STK500GENERIC"
|
||||||
{"stk500pp", stk500pp_initpgm, stk500pp_desc},
|
{"stk500v2", stk500v2_initpgm, stk500v2_desc}, // "STK500V2"
|
||||||
{"stk600", stk600_initpgm, stk600_desc},
|
{"stk500hvsp", stk500hvsp_initpgm, stk500hvsp_desc}, // "STK500HVSP"
|
||||||
{"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc},
|
{"stk500pp", stk500pp_initpgm, stk500pp_desc}, // "STK500PP"
|
||||||
{"stk600pp", stk600pp_initpgm, stk600pp_desc},
|
{"stk600", stk600_initpgm, stk600_desc}, // "STK600"
|
||||||
{"teensy", teensy_initpgm, teensy_desc},
|
{"stk600hvsp", stk600hvsp_initpgm, stk600hvsp_desc}, // "STK600HVSP"
|
||||||
{"usbasp", usbasp_initpgm, usbasp_desc},
|
{"stk600pp", stk600pp_initpgm, stk600pp_desc}, // "STK600PP"
|
||||||
{"usbtiny", usbtiny_initpgm, usbtiny_desc},
|
{"teensy", teensy_initpgm, teensy_desc}, // "teensy"
|
||||||
{"wiring", wiring_initpgm, wiring_desc},
|
{"urclock", urclock_initpgm, urclock_desc}, // "Urclock"
|
||||||
{"xbee", xbee_initpgm, xbee_desc},
|
{"usbasp", usbasp_initpgm, usbasp_desc}, // "usbasp"
|
||||||
|
{"usbtiny", usbtiny_initpgm, usbtiny_desc}, // "USBtiny" or "usbtiny"
|
||||||
|
{"wiring", wiring_initpgm, wiring_desc}, // "Wiring"
|
||||||
|
{"xbee", xbee_initpgm, xbee_desc}, // "XBee"
|
||||||
};
|
};
|
||||||
|
|
||||||
const PROGRAMMER_TYPE * locate_programmer_type(const char * id)
|
const PROGRAMMER_TYPE * locate_programmer_type(const char * id)
|
||||||
|
@ -127,6 +131,16 @@ const PROGRAMMER_TYPE * locate_programmer_type(const char * id)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return type id given the init function or "" if not found
|
||||||
|
const char *locate_programmer_type_id(void (*initpgm)(PROGRAMMER *pgm)) {
|
||||||
|
for (int i=0; i < sizeof programmers_types/sizeof*programmers_types; i++)
|
||||||
|
if(programmers_types[i].initpgm == initpgm)
|
||||||
|
return programmers_types[i].id;
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over the list of programmers given as "programmers", and
|
* Iterate over the list of programmers given as "programmers", and
|
||||||
* call the callback function cb for each entry found. cb is being
|
* call the callback function cb for each entry found. cb is being
|
||||||
|
@ -160,5 +174,3 @@ void walk_programmer_types(walk_programmer_types_cb cb, void *cookie)
|
||||||
cb(p->id, p->desc, cookie);
|
cb(p->id, p->desc, cookie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
216
src/pickit2.c
216
src/pickit2.c
|
@ -38,9 +38,9 @@
|
||||||
* RST - VPP/MCLR (1)
|
* RST - VPP/MCLR (1)
|
||||||
* VDD - VDD Target (2) -- possibly optional if AVR self powered
|
* VDD - VDD Target (2) -- possibly optional if AVR self powered
|
||||||
* GND - GND (3)
|
* GND - GND (3)
|
||||||
* MISO - PGD (4)
|
* SDI - PGD (4)
|
||||||
* SCLK - PDC (5)
|
* SCLK - PDC (5)
|
||||||
* MOSI - AUX (6)
|
* SDO - AUX (6)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ac_cfg.h"
|
#include "ac_cfg.h"
|
||||||
|
@ -72,13 +72,13 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define DEBUG(...) do { avrdude_message(MSG_DEBUG, __VA_ARGS__); } while(0)
|
#define DEBUG(...) do { msg_debug(__VA_ARGS__); } while(0)
|
||||||
#else
|
#else
|
||||||
#define DEBUG(...) ((void)0)
|
#define DEBUG(...) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define DEBUGRECV(...) do { avrdude_message(MSG_DEBUG, __VA_ARGS__); } while(0)
|
#define DEBUGRECV(...) do { msg_debug(__VA_ARGS__); } while(0)
|
||||||
#else
|
#else
|
||||||
#define DEBUGRECV(...) ((void)0)
|
#define DEBUGRECV(...) ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
@ -104,8 +104,8 @@ static int usb_open_device(struct usb_dev_handle **dev, int vid, int pid);
|
||||||
#define USB_ERROR_IO 5
|
#define USB_ERROR_IO 5
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
static int pickit2_write_report(PROGRAMMER *pgm, const unsigned char report[65]);
|
static int pickit2_write_report(const PROGRAMMER *pgm, const unsigned char report[65]);
|
||||||
static int pickit2_read_report(PROGRAMMER *pgm, unsigned char report[65]);
|
static int pickit2_read_report(const PROGRAMMER *pgm, unsigned char report[65]);
|
||||||
|
|
||||||
#ifndef MIN
|
#ifndef MIN
|
||||||
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
|
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
|
||||||
|
@ -164,8 +164,7 @@ static void pickit2_setup(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0)
|
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: pickit2_setup(): Out of memory allocating private data\n",
|
pmsg_error("out of memory allocating private data\n");
|
||||||
progname);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
memset(pgm->cookie, 0, sizeof(struct pdata));
|
memset(pgm->cookie, 0, sizeof(struct pdata));
|
||||||
|
@ -179,37 +178,36 @@ static void pickit2_teardown(PROGRAMMER * pgm)
|
||||||
free(pgm->cookie);
|
free(pgm->cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_open(PROGRAMMER * pgm, char * port)
|
static int pickit2_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
#if (defined(WIN32) && defined(HAVE_LIBHID))
|
#if (defined(WIN32) && defined(HAVE_LIBHID))
|
||||||
PDATA(pgm)->usb_handle = open_hid(PICKIT2_VID, PICKIT2_PID);
|
PDATA(pgm)->usb_handle = open_hid(PICKIT2_VID, PICKIT2_PID);
|
||||||
|
|
||||||
if (PDATA(pgm)->usb_handle == INVALID_HANDLE_VALUE)
|
if (PDATA(pgm)->usb_handle == INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
/* no PICkit2 found */
|
/* no PICkit2 found */
|
||||||
avrdude_message(MSG_INFO, "%s: error: could not find PICkit2 with vid=0x%x pid=0x%x\n",
|
pmsg_error("cannot find PICkit2 with vid=0x%x pid=0x%x\n", PICKIT2_VID, PICKIT2_PID);
|
||||||
progname, PICKIT2_VID, PICKIT2_PID);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// get the device description while we're at it
|
// Get the device description while we're at it and overlay it on pgm->desc
|
||||||
short buff[PGM_DESCLEN-1], i;
|
short wbuf[80-1];
|
||||||
HidD_GetProductString(PDATA(pgm)->usb_handle, buff, PGM_DESCLEN-1);
|
char *cbuf = cfg_malloc("pickit2_open()", sizeof wbuf/sizeof*wbuf + (pgm->desc? strlen(pgm->desc): 0) + 2);
|
||||||
|
HidD_GetProductString(PDATA(pgm)->usb_handle, wbuf, sizeof wbuf/sizeof*wbuf);
|
||||||
|
|
||||||
// convert from wide chars, but do not overwrite trailing '\0'
|
if(pgm->desc && *pgm->desc)
|
||||||
memset(&(pgm->desc), 0, PGM_DESCLEN);
|
strcpy(cbuf, pgm->desc);
|
||||||
for (i = 0; i < (PGM_DESCLEN-1) && buff[i]; i++)
|
|
||||||
{
|
// Convert from wide chars and overlay over initial part of desc
|
||||||
pgm->desc[i] = (char)buff[i]; // TODO what about little/big endian???
|
for (int i = 0; i < sizeof wbuf/sizeof*wbuf && wbuf[i]; i++)
|
||||||
}
|
cbuf[i] = (char) wbuf[i]; // TODO what about little/big endian???
|
||||||
|
pgm->desc = cache_string(cbuf);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (usb_open_device(&(PDATA(pgm)->usb_handle), PICKIT2_VID, PICKIT2_PID) < 0)
|
if (usb_open_device(&(PDATA(pgm)->usb_handle), PICKIT2_VID, PICKIT2_PID) < 0)
|
||||||
{
|
{
|
||||||
/* no PICkit2 found */
|
/* no PICkit2 found */
|
||||||
avrdude_message(MSG_INFO, "%s: error: could not find PICkit2 with vid=0x%x pid=0x%x\n",
|
pmsg_error("cannot find PICkit2 with vid=0x%x pid=0x%x\n", PICKIT2_VID, PICKIT2_PID);
|
||||||
progname, PICKIT2_VID, PICKIT2_PID);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -239,8 +237,7 @@ static void pickit2_close(PROGRAMMER * pgm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int pickit2_initialize(PROGRAMMER * pgm, AVRPART * p)
|
static int pickit2_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
unsigned char temp[4];
|
unsigned char temp[4];
|
||||||
memset(temp, 0, sizeof(temp));
|
memset(temp, 0, sizeof(temp));
|
||||||
|
|
||||||
|
@ -258,7 +255,7 @@ static int pickit2_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
//memset(report, 0, sizeof(report));
|
//memset(report, 0, sizeof(report));
|
||||||
if ((errorCode = pickit2_read_report(pgm, report)) >= 4)
|
if ((errorCode = pickit2_read_report(pgm, report)) >= 4)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE, "%s: %s firmware version %d.%d.%d\n", progname, pgm->desc, (int)report[1], (int)report[2], (int)report[3]);
|
pmsg_notice("%s firmware version %d.%d.%d\n", pgm->desc, (int)report[1], (int)report[2], (int)report[3]);
|
||||||
|
|
||||||
// set the pins, apply reset,
|
// set the pins, apply reset,
|
||||||
// TO DO: apply vtarget (if requested though -x option)
|
// TO DO: apply vtarget (if requested though -x option)
|
||||||
|
@ -293,19 +290,19 @@ static int pickit2_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
|
|
||||||
if (pickit2_write_report(pgm, report) < 0)
|
if (pickit2_write_report(pgm, report) < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "pickit2_read_report failed (ec %d). %s\n", errorCode, usb_strerror());
|
pmsg_error("pickit2_read_report failed (ec %d). %s\n", errorCode, usb_strerror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "pickit2_read_report failed (ec %d). %s\n", errorCode, usb_strerror());
|
pmsg_error("pickit2_read_report failed (ec %d). %s\n", errorCode, usb_strerror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "pickit2_write_report failed (ec %d). %s\n", errorCode, usb_strerror());
|
pmsg_error("pickit2_write_report failed (ec %d). %s\n", errorCode, usb_strerror());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,8 +312,7 @@ static int pickit2_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pickit2_disable(PROGRAMMER * pgm)
|
static void pickit2_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* make sure all pins are floating & all voltages are off */
|
/* make sure all pins are floating & all voltages are off */
|
||||||
static const unsigned char report[65] =
|
static const unsigned char report[65] =
|
||||||
{
|
{
|
||||||
|
@ -337,16 +333,12 @@ static void pickit2_disable(PROGRAMMER * pgm)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pickit2_enable(PROGRAMMER * pgm)
|
static void pickit2_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pickit2_display(PROGRAMMER * pgm, const char * p)
|
static void pickit2_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
DEBUG("%s: found %s version %d.%d.%d\n", progname, p, 1, 1, 1);
|
||||||
DEBUG( "%s: Found \"%s\" version %d.%d.%d\n", progname, p, 1, 1, 1);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,14 +346,12 @@ static void pickit2_display(PROGRAMMER * pgm, const char * p)
|
||||||
#define readReport(x) 0
|
#define readReport(x) 0
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static int pickit2_rdy_led (struct programmer_t * pgm, int value)
|
static int pickit2_rdy_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
// no rdy led
|
// no rdy led
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_err_led(struct programmer_t * pgm, int value)
|
static int pickit2_err_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
// there is no error led, so just flash the busy led a few times
|
// there is no error led, so just flash the busy led a few times
|
||||||
uint8_t report[65] =
|
uint8_t report[65] =
|
||||||
{
|
{
|
||||||
|
@ -384,8 +374,7 @@ static int pickit2_err_led(struct programmer_t * pgm, int value)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int pickit2_pgm_led (struct programmer_t * pgm, int value)
|
static int pickit2_pgm_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
// script to set busy led appropriately
|
// script to set busy led appropriately
|
||||||
uint8_t report[65] = {0, CMD_EXEC_SCRIPT_2(1),
|
uint8_t report[65] = {0, CMD_EXEC_SCRIPT_2(1),
|
||||||
value ? SCR_BUSY_LED_ON : SCR_BUSY_LED_OFF,
|
value ? SCR_BUSY_LED_ON : SCR_BUSY_LED_OFF,
|
||||||
|
@ -395,33 +384,28 @@ static int pickit2_pgm_led (struct programmer_t * pgm, int value)
|
||||||
return pickit2_write_report(pgm, report) != -1;
|
return pickit2_write_report(pgm, report) != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_vfy_led (struct programmer_t * pgm, int value)
|
static int pickit2_vfy_led(const PROGRAMMER *pgm, int value) {
|
||||||
{
|
|
||||||
// no such thing - maybe just call pgm_led
|
// no such thing - maybe just call pgm_led
|
||||||
|
|
||||||
return pgm->pgm_led(pgm, value);
|
return pgm->pgm_led(pgm, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pickit2_powerup(struct programmer_t * pgm)
|
static void pickit2_powerup(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
// turn vdd on?
|
// turn vdd on?
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pickit2_powerdown(struct programmer_t * pgm)
|
static void pickit2_powerdown(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
// do what?
|
// do what?
|
||||||
pgm->disable(pgm);
|
pgm->disable(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_program_enable(struct programmer_t * pgm, AVRPART * p)
|
static int pickit2_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
unsigned char cmd[4];
|
unsigned char cmd[4];
|
||||||
unsigned char res[4];
|
unsigned char res[4];
|
||||||
|
|
||||||
if (p->op[AVR_OP_PGM_ENABLE] == NULL)
|
if (p->op[AVR_OP_PGM_ENABLE] == NULL)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "program enable instruction not defined for part \"%s\"\n",
|
pmsg_error("program enable instruction not defined for part %s\n", p->desc);
|
||||||
p->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,13 +415,13 @@ static int pickit2_program_enable(struct programmer_t * pgm, AVRPART * p)
|
||||||
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
avrdude_message(MSG_DEBUG, "program_enable(): sending command. Resp = ");
|
msg_debug("program_enable(): sending command. Resp = ");
|
||||||
|
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_DEBUG, "%x ", (int)res[i]);
|
msg_debug("%x ", (int)res[i]);
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_DEBUG, "\n");
|
msg_debug("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for sync character
|
// check for sync character
|
||||||
|
@ -447,15 +431,13 @@ static int pickit2_program_enable(struct programmer_t * pgm, AVRPART * p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_chip_erase(struct programmer_t * pgm, AVRPART * p)
|
static int pickit2_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
unsigned char cmd[4];
|
unsigned char cmd[4];
|
||||||
unsigned char res[4];
|
unsigned char res[4];
|
||||||
|
|
||||||
if (p->op[AVR_OP_CHIP_ERASE] == NULL)
|
if (p->op[AVR_OP_CHIP_ERASE] == NULL)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "chip erase instruction not defined for part \"%s\"\n",
|
pmsg_error("chip erase instruction not defined for part %s\n", p->desc);
|
||||||
p->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,9 +455,9 @@ static int pickit2_chip_erase(struct programmer_t * pgm, AVRPART * p)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
static int pickit2_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes) {
|
||||||
{
|
|
||||||
// only supporting flash & eeprom page reads
|
// only supporting flash & eeprom page reads
|
||||||
if ((!mem->paged || page_size <= 1) || (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0))
|
if ((!mem->paged || page_size <= 1) || (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0))
|
||||||
{
|
{
|
||||||
|
@ -491,18 +473,15 @@ static int pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
|
|
||||||
pgm->pgm_led(pgm, ON);
|
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; )
|
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
|
// 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
|
// the data into packets -- but we need to keep transfers frequent so that we can update the
|
||||||
// status indicator bar
|
// status indicator bar
|
||||||
|
@ -531,7 +510,7 @@ static int pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "no read command specified\n");
|
pmsg_error("no read command specified\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +522,7 @@ static int pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
|
|
||||||
if (bytes_read < 0)
|
if (bytes_read < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "Failed @ pgm->spi()\n");
|
pmsg_error("failed @ pgm->spi()\n");
|
||||||
pgm->err_led(pgm, ON);
|
pgm->err_led(pgm, ON);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -569,7 +548,7 @@ static int pickit2_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int pickit2_commit_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
static int pickit2_commit_page(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr)
|
unsigned long addr)
|
||||||
{
|
{
|
||||||
OPCODE * wp, * lext;
|
OPCODE * wp, * lext;
|
||||||
|
@ -577,8 +556,7 @@ static int pickit2_commit_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
wp = mem->op[AVR_OP_WRITEPAGE];
|
wp = mem->op[AVR_OP_WRITEPAGE];
|
||||||
if (wp == NULL)
|
if (wp == NULL)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "pickit2_commit_page(): memory \"%s\" not configured for page writes\n",
|
pmsg_error("memory %s not configured for page writes\n", mem->desc);
|
||||||
mem->desc);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -619,13 +597,13 @@ static int pickit2_commit_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
}
|
}
|
||||||
|
|
||||||
// not actually a paged write, but a bulk/batch write
|
// not actually a paged write, but a bulk/batch write
|
||||||
static int pickit2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
static int pickit2_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
// only paged write for flash implemented
|
// only paged write for flash implemented
|
||||||
if (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0)
|
if (strcmp(mem->desc, "flash") != 0 && strcmp(mem->desc, "eeprom") != 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "Part does not support %d paged write of %s\n", page_size, mem->desc);
|
pmsg_error("part does not support %d paged write of %s\n", page_size, mem->desc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +660,7 @@ static int pickit2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
writeop = mem->op[AVR_OP_WRITE_LO];
|
writeop = mem->op[AVR_OP_WRITE_LO];
|
||||||
caddr = addr; // maybe this should divide by 2 & use the write_high opcode also
|
caddr = addr; // maybe this should divide by 2 & use the write_high opcode also
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "Error AVR_OP_WRITE_LO defined only (where's the HIGH command?)\n");
|
pmsg_error("%s AVR_OP_WRITE_LO defined only (where is the HIGH command?)\n", mem->desc);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -707,7 +685,7 @@ static int pickit2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
|
|
||||||
if (bytes_read < 0)
|
if (bytes_read < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "Failed @ pgm->spi()\n");
|
pmsg_error("failed @ pgm->spi()\n");
|
||||||
pgm->err_led(pgm, ON);
|
pgm->err_led(pgm, ON);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -732,14 +710,14 @@ static int pickit2_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int pickit2_cmd(struct programmer_t * pgm, const unsigned char *cmd,
|
static int pickit2_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
unsigned char *res)
|
unsigned char *res)
|
||||||
{
|
{
|
||||||
return pgm->spi(pgm, cmd, res, 4);
|
return pgm->spi(pgm, cmd, res, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// breaks up the cmd[] data into packets & sends to the pickit2. Data shifted in is stored in res[].
|
// breaks up the cmd[] data into packets & sends to the pickit2. Data shifted in is stored in res[].
|
||||||
static int pickit2_spi(struct programmer_t * pgm, const unsigned char *cmd,
|
static int pickit2_spi(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
unsigned char *res, int n_bytes)
|
unsigned char *res, int n_bytes)
|
||||||
{
|
{
|
||||||
int retval = 0, temp1 = 0, temp2 = 0, count = n_bytes;
|
int retval = 0, temp1 = 0, temp2 = 0, count = n_bytes;
|
||||||
|
@ -1059,8 +1037,7 @@ static HANDLE open_hid(unsigned short vid, unsigned short pid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// simple read with timeout
|
// simple read with timeout
|
||||||
static int usb_read_interrupt(PROGRAMMER *pgm, void *buff, int size, int timeout)
|
static int usb_read_interrupt(const PROGRAMMER *pgm, void *buff, int size, int timeout) {
|
||||||
{
|
|
||||||
OVERLAPPED ovr;
|
OVERLAPPED ovr;
|
||||||
DWORD bytesRead = 0;
|
DWORD bytesRead = 0;
|
||||||
|
|
||||||
|
@ -1085,8 +1062,7 @@ static int usb_read_interrupt(PROGRAMMER *pgm, void *buff, int size, int timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
// simple write with timeout
|
// simple write with timeout
|
||||||
static int usb_write_interrupt(PROGRAMMER *pgm, const void *buff, int size, int timeout)
|
static int usb_write_interrupt(const PROGRAMMER *pgm, const void *buff, int size, int timeout) {
|
||||||
{
|
|
||||||
OVERLAPPED ovr;
|
OVERLAPPED ovr;
|
||||||
DWORD bytesWritten = 0;
|
DWORD bytesWritten = 0;
|
||||||
|
|
||||||
|
@ -1110,13 +1086,11 @@ static int usb_write_interrupt(PROGRAMMER *pgm, const void *buff, int size, int
|
||||||
return bytesWritten > 0 ? bytesWritten : -1;
|
return bytesWritten > 0 ? bytesWritten : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_write_report(PROGRAMMER * pgm, const unsigned char report[65])
|
static int pickit2_write_report(const PROGRAMMER *pgm, const unsigned char report[65]) {
|
||||||
{
|
|
||||||
return usb_write_interrupt(pgm, report, 65, PDATA(pgm)->transaction_timeout); // XXX
|
return usb_write_interrupt(pgm, report, 65, PDATA(pgm)->transaction_timeout); // XXX
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_read_report(PROGRAMMER * pgm, unsigned char report[65])
|
static int pickit2_read_report(const PROGRAMMER *pgm, unsigned char report[65]) {
|
||||||
{
|
|
||||||
return usb_read_interrupt(pgm, report, 65, PDATA(pgm)->transaction_timeout);
|
return usb_read_interrupt(pgm, report, 65, PDATA(pgm)->transaction_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1149,25 +1123,27 @@ static int usb_open_device(struct usb_dev_handle **device, int vendor, int produ
|
||||||
if (handle == NULL)
|
if (handle == NULL)
|
||||||
{
|
{
|
||||||
errorCode = USB_ERROR_ACCESS;
|
errorCode = USB_ERROR_ACCESS;
|
||||||
avrdude_message(MSG_INFO, "%s: Warning: cannot open USB device: %s\n", progname, usb_strerror());
|
pmsg_warning("cannot open USB device: %s\n", usb_strerror());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return with opened device handle
|
// return with opened device handle
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_NOTICE, "Device %p seemed to open OK.\n", handle);
|
msg_notice("device %p seemed to open OK\n", handle);
|
||||||
|
|
||||||
if ((errorCode = usb_set_configuration(handle, 1)) < 0)
|
if ((errorCode = usb_set_configuration(handle, 1)) < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "Could not set configuration. Error code %d, %s.\n"
|
pmsg_ext_error("cannot set configuration, error code %d, %s\n"
|
||||||
"You may need to run avrdude as root or set up correct usb port permissions.", errorCode, usb_strerror());
|
"you may need to run avrdude as root or set up correct usb port permissions",
|
||||||
|
errorCode, usb_strerror());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((errorCode = usb_claim_interface(handle, 0)) < 0)
|
if ((errorCode = usb_claim_interface(handle, 0)) < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "Could not claim interface. Error code %d, %s\n"
|
pmsg_ext_error("cannot claim interface, error code %d, %s\n"
|
||||||
"You may need to run avrdude as root or set up correct usb port permissions.", errorCode, usb_strerror());
|
"You may need to run avrdude as root or set up correct usb port permissions.",
|
||||||
|
errorCode, usb_strerror());
|
||||||
}
|
}
|
||||||
|
|
||||||
errorCode = 0;
|
errorCode = 0;
|
||||||
|
@ -1181,21 +1157,18 @@ static int usb_open_device(struct usb_dev_handle **device, int vendor, int produ
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_write_report(PROGRAMMER * pgm, const unsigned char report[65])
|
static int pickit2_write_report(const PROGRAMMER *pgm, const unsigned char report[65]) {
|
||||||
{
|
|
||||||
// endpoint 1 OUT??
|
// endpoint 1 OUT??
|
||||||
return usb_interrupt_write(PDATA(pgm)->usb_handle, USB_ENDPOINT_OUT | 1, (char*)(report+1), 64, PDATA(pgm)->transaction_timeout);
|
return usb_interrupt_write(PDATA(pgm)->usb_handle, USB_ENDPOINT_OUT | 1, (char*)(report+1), 64, PDATA(pgm)->transaction_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pickit2_read_report(PROGRAMMER * pgm, unsigned char report[65])
|
static int pickit2_read_report(const PROGRAMMER *pgm, unsigned char report[65]) {
|
||||||
{
|
|
||||||
// endpoint 1 IN??
|
// endpoint 1 IN??
|
||||||
return usb_interrupt_read(PDATA(pgm)->usb_handle, USB_ENDPOINT_IN | 1, (char*)(report+1), 64, PDATA(pgm)->transaction_timeout);
|
return usb_interrupt_read(PDATA(pgm)->usb_handle, USB_ENDPOINT_IN | 1, (char*)(report+1), 64, PDATA(pgm)->transaction_timeout);
|
||||||
}
|
}
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
static int pickit2_parseextparams(struct programmer_t * pgm, LISTID extparms)
|
static int pickit2_parseextparams(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||||
{
|
|
||||||
LNODEID ln;
|
LNODEID ln;
|
||||||
const char *extended_param;
|
const char *extended_param;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
@ -1209,8 +1182,7 @@ static int pickit2_parseextparams(struct programmer_t * pgm, LISTID extparms)
|
||||||
int clock_rate;
|
int clock_rate;
|
||||||
if (sscanf(extended_param, "clockrate=%i", &clock_rate) != 1 || clock_rate <= 0)
|
if (sscanf(extended_param, "clockrate=%i", &clock_rate) != 1 || clock_rate <= 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: pickit2_parseextparms(): invalid clockrate '%s'\n",
|
pmsg_error("invalid clockrate '%s'\n", extended_param);
|
||||||
progname, extended_param);
|
|
||||||
rv = -1;
|
rv = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1218,8 +1190,7 @@ static int pickit2_parseextparams(struct programmer_t * pgm, LISTID extparms)
|
||||||
int clock_period = MIN(1000000 / clock_rate, 255); // max period is 255
|
int clock_period = MIN(1000000 / clock_rate, 255); // max period is 255
|
||||||
clock_rate = (int)(1000000 / (clock_period + 5e-7)); // assume highest speed is 2MHz - should probably check this
|
clock_rate = (int)(1000000 / (clock_period + 5e-7)); // assume highest speed is 2MHz - should probably check this
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: pickit2_parseextparms(): clockrate set to 0x%02x\n",
|
pmsg_notice2("pickit2_parseextparms(): clockrate set to 0x%02x\n", clock_rate);
|
||||||
progname, clock_rate);
|
|
||||||
PDATA(pgm)->clock_period = clock_period;
|
PDATA(pgm)->clock_period = clock_period;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
@ -1230,21 +1201,18 @@ static int pickit2_parseextparams(struct programmer_t * pgm, LISTID extparms)
|
||||||
int timeout;
|
int timeout;
|
||||||
if (sscanf(extended_param, "timeout=%i", &timeout) != 1 || timeout <= 0)
|
if (sscanf(extended_param, "timeout=%i", &timeout) != 1 || timeout <= 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: pickit2_parseextparms(): invalid timeout '%s'\n",
|
pmsg_error("invalid timeout '%s'\n", extended_param);
|
||||||
progname, extended_param);
|
|
||||||
rv = -1;
|
rv = -1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_NOTICE2, "%s: pickit2_parseextparms(): usb timeout set to 0x%02x\n",
|
pmsg_notice2("pickit2_parseextparms(): usb timeout set to 0x%02x\n", timeout);
|
||||||
progname, timeout);
|
|
||||||
PDATA(pgm)->transaction_timeout = timeout;
|
PDATA(pgm)->transaction_timeout = timeout;
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: pickit2_parseextparms(): invalid extended parameter '%s'\n",
|
pmsg_error("invalid extended parameter '%s'\n", extended_param);
|
||||||
progname, extended_param);
|
|
||||||
rv = -1;
|
rv = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1252,8 +1220,7 @@ static int pickit2_parseextparams(struct programmer_t * pgm, LISTID extparms)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pickit2_initpgm (PROGRAMMER * pgm)
|
void pickit2_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* mandatory functions - these are called without checking to see
|
* mandatory functions - these are called without checking to see
|
||||||
* whether they are assigned or not
|
* whether they are assigned or not
|
||||||
|
@ -1303,25 +1270,24 @@ void pickit2_initpgm (PROGRAMMER * pgm)
|
||||||
|
|
||||||
pgm->setup = pickit2_setup;
|
pgm->setup = pickit2_setup;
|
||||||
pgm->teardown = pickit2_teardown;
|
pgm->teardown = pickit2_teardown;
|
||||||
// pgm->page_size = 256; // not sure what this does... maybe the max page size that the page read/write function can handle
|
// pgm->page_size = 256; // not sure what this does ... maybe the max page size that the page read/write function can handle
|
||||||
|
|
||||||
strncpy(pgm->type, "pickit2", sizeof(pgm->type));
|
strncpy(pgm->type, "pickit2", sizeof(pgm->type));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static int pickit2_nousb_open (struct programmer_t *pgm, char * name) {
|
static int pickit2_nousb_open(PROGRAMMER *pgm, const char *name) {
|
||||||
avrdude_message(MSG_INFO,
|
pmsg_error(
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
"%s: error: no usb or hid support. Please compile again with libusb or HID support from Win32 DDK installed.\n",
|
"no usb or hid support; please compile again with libusb or HID support from Win32 DDK installed\n"
|
||||||
#else
|
#else
|
||||||
"%s: error: no usb support. Please compile again with libusb installed.\n",
|
"no usb support; please compile again with libusb installed\n"
|
||||||
#endif
|
#endif
|
||||||
progname);
|
);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pickit2_initpgm (PROGRAMMER * pgm)
|
void pickit2_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* mandatory functions - these are called without checking to see
|
* mandatory functions - these are called without checking to see
|
||||||
* whether they are assigned or not
|
* whether they are assigned or not
|
||||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char pickit2_desc[];
|
extern const char pickit2_desc[];
|
||||||
void pickit2_initpgm (PROGRAMMER * pgm);
|
void pickit2_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,10 +61,10 @@ void pin_clear_all(struct pindef_t * const pindef) {
|
||||||
static int pin_fill_old_pinno(const struct pindef_t * const pindef, unsigned int * const pinno) {
|
static int pin_fill_old_pinno(const struct pindef_t * const pindef, unsigned int * const pinno) {
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < PIN_MAX; i++) {
|
for(i = 0; i <= PIN_MAX; i++) {
|
||||||
if(pindef->mask[i / PIN_FIELD_ELEMENT_SIZE] & (1 << (i % PIN_FIELD_ELEMENT_SIZE))) {
|
if(pindef->mask[i / PIN_FIELD_ELEMENT_SIZE] & (1 << (i % PIN_FIELD_ELEMENT_SIZE))) {
|
||||||
if(found) {
|
if(found) {
|
||||||
avrdude_message(MSG_INFO, "Multiple pins found\n"); //TODO
|
pmsg_error("multiple pins found\n"); // TODO
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -89,23 +89,23 @@ static int pin_fill_old_pinlist(const struct pindef_t * const pindef, unsigned i
|
||||||
for(i = 0; i < PIN_FIELD_SIZE; i++) {
|
for(i = 0; i < PIN_FIELD_SIZE; i++) {
|
||||||
if(i == 0) {
|
if(i == 0) {
|
||||||
if((pindef->mask[i] & ~PIN_MASK) != 0) {
|
if((pindef->mask[i] & ~PIN_MASK) != 0) {
|
||||||
avrdude_message(MSG_INFO, "Pins of higher index than max field size for old pinno found\n");
|
pmsg_error("pins of higher index than max field size for old pinno found\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (pindef->mask[i] == 0) {
|
if (pindef->mask[i] == 0) {
|
||||||
/* this pin function is not using any pins */
|
/* this pin function is not using any pins */
|
||||||
*pinno = 0;
|
*pinno = NO_PIN;
|
||||||
} else if(pindef->mask[i] == pindef->inverse[i]) { /* all set bits in mask are set in inverse */
|
} else if(pindef->mask[i] == pindef->inverse[i]) { /* all set bits in mask are set in inverse */
|
||||||
*pinno = pindef->mask[i];
|
*pinno = pindef->mask[i];
|
||||||
*pinno |= PIN_INVERSE;
|
*pinno |= PIN_INVERSE;
|
||||||
} else if(pindef->mask[i] == ((~pindef->inverse[i]) & pindef->mask[i])) { /* all set bits in mask are cleared in inverse */
|
} else if(pindef->mask[i] == ((~pindef->inverse[i]) & pindef->mask[i])) { /* all set bits in mask are cleared in inverse */
|
||||||
*pinno = pindef->mask[i];
|
*pinno = pindef->mask[i];
|
||||||
} else {
|
} else {
|
||||||
avrdude_message(MSG_INFO, "pins have different polarity set\n");
|
pmsg_error("pins have different polarity set\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else if(pindef->mask[i] != 0) {
|
} else if(pindef->mask[i] != 0) {
|
||||||
avrdude_message(MSG_INFO, "Pins have higher number than fit in old format\n");
|
pmsg_error("pins have higher number than fit in old format\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ static int pin_fill_old_pinlist(const struct pindef_t * const pindef, unsigned i
|
||||||
*
|
*
|
||||||
* @param[inout] pgm programmer whose pins shall be converted.
|
* @param[inout] pgm programmer whose pins shall be converted.
|
||||||
*/
|
*/
|
||||||
int pgm_fill_old_pins(struct programmer_t * const pgm) {
|
int pgm_fill_old_pins(PROGRAMMER * const pgm) {
|
||||||
|
|
||||||
if (pin_fill_old_pinlist(&(pgm->pin[PPI_AVR_VCC]), &(pgm->pinno[PPI_AVR_VCC])) < 0)
|
if (pin_fill_old_pinlist(&(pgm->pin[PPI_AVR_VCC]), &(pgm->pinno[PPI_AVR_VCC])) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -128,9 +128,9 @@ int pgm_fill_old_pins(struct programmer_t * const pgm) {
|
||||||
return -1;
|
return -1;
|
||||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_AVR_SCK]), &(pgm->pinno[PIN_AVR_SCK])) < 0)
|
if (pin_fill_old_pinno(&(pgm->pin[PIN_AVR_SCK]), &(pgm->pinno[PIN_AVR_SCK])) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_AVR_MOSI]), &(pgm->pinno[PIN_AVR_MOSI])) < 0)
|
if (pin_fill_old_pinno(&(pgm->pin[PIN_AVR_SDO]), &(pgm->pinno[PIN_AVR_SDO])) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_AVR_MISO]), &(pgm->pinno[PIN_AVR_MISO])) < 0)
|
if (pin_fill_old_pinno(&(pgm->pin[PIN_AVR_SDI]), &(pgm->pinno[PIN_AVR_SDI])) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
if (pin_fill_old_pinno(&(pgm->pin[PIN_LED_ERR]), &(pgm->pinno[PIN_LED_ERR])) < 0)
|
if (pin_fill_old_pinno(&(pgm->pin[PIN_LED_ERR]), &(pgm->pinno[PIN_LED_ERR])) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -218,7 +218,7 @@ const char * pinmask_to_str(const pinmask_t * const pinmask) {
|
||||||
* @param[in] size the number of entries in checklist
|
* @param[in] size the number of entries in checklist
|
||||||
* @returns 0 if all pin definitions are valid, -1 otherwise
|
* @returns 0 if all pin definitions are valid, -1 otherwise
|
||||||
*/
|
*/
|
||||||
int pins_check(const struct programmer_t * const pgm, const struct pin_checklist_t * const checklist, const int size, const bool output) {
|
int pins_check(const PROGRAMMER *const pgm, const struct pin_checklist_t *const checklist, const int size, const bool output) {
|
||||||
static const struct pindef_t no_valid_pins = {{0}, {0}}; // default value if check list does not contain anything else
|
static const struct pindef_t no_valid_pins = {{0}, {0}}; // default value if check list does not contain anything else
|
||||||
int rv = 0; // return value
|
int rv = 0; // return value
|
||||||
int pinname; // loop counter through pinnames
|
int pinname; // loop counter through pinnames
|
||||||
|
@ -271,48 +271,46 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist
|
||||||
}
|
}
|
||||||
if(invalid) {
|
if(invalid) {
|
||||||
if(output) {
|
if(output) {
|
||||||
avrdude_message(MSG_INFO, "%s: %s: Following pins are not valid pins for this function: %s\n",
|
pmsg_error("%s: these pins are not valid pins for this function: %s\n",
|
||||||
progname, avr_pin_name(pinname), pinmask_to_str(invalid_used));
|
avr_pin_name(pinname), pinmask_to_str(invalid_used));
|
||||||
avrdude_message(MSG_NOTICE2, "%s: %s: Valid pins for this function are: %s\n",
|
pmsg_notice("%s: valid pins for this function are: %s\n",
|
||||||
progname, avr_pin_name(pinname), pinmask_to_str(valid_pins->mask));
|
avr_pin_name(pinname), pinmask_to_str(valid_pins->mask));
|
||||||
}
|
}
|
||||||
is_ok = false;
|
is_ok = false;
|
||||||
}
|
}
|
||||||
if(inverse) {
|
if(inverse) {
|
||||||
if(output) {
|
if(output) {
|
||||||
avrdude_message(MSG_INFO, "%s: %s: Following pins are not usable as inverse pins for this function: %s\n",
|
pmsg_error("%s: these pins are not usable as inverse pins for this function: %s\n",
|
||||||
progname, avr_pin_name(pinname), pinmask_to_str(inverse_used));
|
avr_pin_name(pinname), pinmask_to_str(inverse_used));
|
||||||
avrdude_message(MSG_NOTICE2, "%s: %s: Valid inverse pins for this function are: %s\n",
|
pmsg_notice("%s: valid inverse pins for this function are: %s\n",
|
||||||
progname, avr_pin_name(pinname), pinmask_to_str(valid_pins->inverse));
|
avr_pin_name(pinname), pinmask_to_str(valid_pins->inverse));
|
||||||
}
|
}
|
||||||
is_ok = false;
|
is_ok = false;
|
||||||
}
|
}
|
||||||
if(used) {
|
if(used) {
|
||||||
if(output) {
|
if(output) {
|
||||||
avrdude_message(MSG_INFO, "%s: %s: Following pins are set for other functions too: %s\n",
|
pmsg_error("%s: these pins are set for other functions too: %s\n",
|
||||||
progname, avr_pin_name(pinname), pinmask_to_str(already_used));
|
avr_pin_name(pinname), pinmask_to_str(already_used));
|
||||||
is_ok = false;
|
is_ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!mandatory_used && is_mandatory && !invalid) {
|
if(!mandatory_used && is_mandatory && !invalid) {
|
||||||
if(output) {
|
if(output) {
|
||||||
avrdude_message(MSG_INFO, "%s: %s: Mandatory pin is not defined.\n",
|
pmsg_error("%s: mandatory pin is not defined\n", avr_pin_name(pinname));
|
||||||
progname, avr_pin_name(pinname));
|
|
||||||
}
|
}
|
||||||
is_ok = false;
|
is_ok = false;
|
||||||
}
|
}
|
||||||
if(!is_ok) {
|
if(!is_ok) {
|
||||||
rv = -1;
|
rv = -1;
|
||||||
} else if(output) {
|
} else if(output) {
|
||||||
avrdude_message(MSG_DEBUG, "%s: %s: Pin is ok.\n",
|
pmsg_debug("%s: pin is OK\n", avr_pin_name(pinname));
|
||||||
progname, avr_pin_name(pinname));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function returns a string representation of defined pins eg. ~1,2,~4,~5,7
|
* This function returns a string of defined pins, eg, ~1,2,~4,~5,7 or " (not used)"
|
||||||
* Another execution of this function will overwrite the previous result in the static buffer.
|
* Another execution of this function will overwrite the previous result in the static buffer.
|
||||||
*
|
*
|
||||||
* @param[in] pindef the pin definition for which we want the string representation
|
* @param[in] pindef the pin definition for which we want the string representation
|
||||||
|
@ -346,6 +344,28 @@ const char * pins_to_str(const struct pindef_t * const pindef) {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function returns a string of defined pins, eg, ~1, 2, ~4, ~5, 7 or ""
|
||||||
|
*
|
||||||
|
* @param[in] pindef the pin definition for which we want the string representation
|
||||||
|
* @returns a pointer to a string, which was created by cfg_strdup()
|
||||||
|
*/
|
||||||
|
char *pins_to_strdup(const struct pindef_t * const pindef) {
|
||||||
|
char buf[6*(PIN_MAX+1)], *p = buf;
|
||||||
|
|
||||||
|
*buf = 0;
|
||||||
|
for(int pin = PIN_MIN; pin <= PIN_MAX; pin++) {
|
||||||
|
int index = pin / PIN_FIELD_ELEMENT_SIZE, bit = pin % PIN_FIELD_ELEMENT_SIZE;
|
||||||
|
if(pindef->mask[index] & (1 << bit)) {
|
||||||
|
if(*buf)
|
||||||
|
*p++ = ',', *p++=' ';
|
||||||
|
p += sprintf(p, pindef->inverse[index] & (1 << bit)? "~%d": "%d", pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cfg_strdup("pins_to_strdup()", buf);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of the pin as string.
|
* Returns the name of the pin as string.
|
||||||
*
|
*
|
||||||
|
@ -358,8 +378,8 @@ const char * avr_pin_name(int pinname) {
|
||||||
case PPI_AVR_BUFF : return "BUFF";
|
case PPI_AVR_BUFF : return "BUFF";
|
||||||
case PIN_AVR_RESET : return "RESET";
|
case PIN_AVR_RESET : return "RESET";
|
||||||
case PIN_AVR_SCK : return "SCK";
|
case PIN_AVR_SCK : return "SCK";
|
||||||
case PIN_AVR_MOSI : return "MOSI";
|
case PIN_AVR_SDO : return "SDO";
|
||||||
case PIN_AVR_MISO : return "MISO";
|
case PIN_AVR_SDI : return "SDI";
|
||||||
case PIN_LED_ERR : return "ERRLED";
|
case PIN_LED_ERR : return "ERRLED";
|
||||||
case PIN_LED_RDY : return "RDYLED";
|
case PIN_LED_RDY : return "RDYLED";
|
||||||
case PIN_LED_PGM : return "PGMLED";
|
case PIN_LED_PGM : return "PGMLED";
|
||||||
|
@ -369,3 +389,24 @@ const char * avr_pin_name(int pinname) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the name of the pin as string.
|
||||||
|
*
|
||||||
|
* @param pinname the pinname which we want as string.
|
||||||
|
* @returns a lowercase string with the pinname, or <unknown> if pinname is invalid.
|
||||||
|
*/
|
||||||
|
const char * avr_pin_lcname(int pinname) {
|
||||||
|
switch(pinname) {
|
||||||
|
case PPI_AVR_VCC : return "vcc";
|
||||||
|
case PPI_AVR_BUFF : return "buff";
|
||||||
|
case PIN_AVR_RESET : return "reset";
|
||||||
|
case PIN_AVR_SCK : return "sck";
|
||||||
|
case PIN_AVR_SDO : return "sdo";
|
||||||
|
case PIN_AVR_SDI : return "sdi";
|
||||||
|
case PIN_LED_ERR : return "errled";
|
||||||
|
case PIN_LED_RDY : return "rdyled";
|
||||||
|
case PIN_LED_PGM : return "pgmled";
|
||||||
|
case PIN_LED_VFY : return "vfyled";
|
||||||
|
default : return "<unknown>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
32
src/ppi.c
32
src/ppi.c
|
@ -51,7 +51,7 @@ enum {
|
||||||
PPI_SHADOWREAD
|
PPI_SHADOWREAD
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ppi_shadow_access(union filedescriptor *fdp, int reg,
|
static int ppi_shadow_access(const union filedescriptor *fdp, int reg,
|
||||||
unsigned char *v, unsigned char action)
|
unsigned char *v, unsigned char action)
|
||||||
{
|
{
|
||||||
static unsigned char shadow[3];
|
static unsigned char shadow[3];
|
||||||
|
@ -68,8 +68,7 @@ static int ppi_shadow_access(union filedescriptor *fdp, int reg,
|
||||||
shadow_num = 2;
|
shadow_num = 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
avrdude_message(MSG_INFO, "%s: avr_set(): invalid register=%d\n",
|
pmsg_error("invalid register=%d\n", reg);
|
||||||
progname, reg);
|
|
||||||
return -1;
|
return -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -93,8 +92,7 @@ static int ppi_shadow_access(union filedescriptor *fdp, int reg,
|
||||||
/*
|
/*
|
||||||
* set the indicated bit of the specified register.
|
* set the indicated bit of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_set(union filedescriptor *fdp, int reg, int bit)
|
int ppi_set(const union filedescriptor *fdp, int reg, int bit) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -112,8 +110,7 @@ int ppi_set(union filedescriptor *fdp, int reg, int bit)
|
||||||
/*
|
/*
|
||||||
* clear the indicated bit of the specified register.
|
* clear the indicated bit of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_clr(union filedescriptor *fdp, int reg, int bit)
|
int ppi_clr(const union filedescriptor *fdp, int reg, int bit) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -131,8 +128,7 @@ int ppi_clr(union filedescriptor *fdp, int reg, int bit)
|
||||||
/*
|
/*
|
||||||
* get the indicated bit of the specified register.
|
* get the indicated bit of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_get(union filedescriptor *fdp, int reg, int bit)
|
int ppi_get(const union filedescriptor *fdp, int reg, int bit) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -148,8 +144,7 @@ int ppi_get(union filedescriptor *fdp, int reg, int bit)
|
||||||
/*
|
/*
|
||||||
* toggle the indicated bit of the specified register.
|
* toggle the indicated bit of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_toggle(union filedescriptor *fdp, int reg, int bit)
|
int ppi_toggle(const union filedescriptor *fdp, int reg, int bit) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -167,8 +162,7 @@ int ppi_toggle(union filedescriptor *fdp, int reg, int bit)
|
||||||
/*
|
/*
|
||||||
* get all bits of the specified register.
|
* get all bits of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_getall(union filedescriptor *fdp, int reg)
|
int ppi_getall(const union filedescriptor *fdp, int reg) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -183,8 +177,7 @@ int ppi_getall(union filedescriptor *fdp, int reg)
|
||||||
/*
|
/*
|
||||||
* set all bits of the specified register to val.
|
* set all bits of the specified register to val.
|
||||||
*/
|
*/
|
||||||
int ppi_setall(union filedescriptor *fdp, int reg, int val)
|
int ppi_setall(const union filedescriptor *fdp, int reg, int val) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -198,15 +191,13 @@ int ppi_setall(union filedescriptor *fdp, int reg, int val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ppi_open(char * port, union filedescriptor *fdp)
|
void ppi_open(const char *port, union filedescriptor *fdp) {
|
||||||
{
|
|
||||||
int fd;
|
int fd;
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
|
|
||||||
fd = open(port, O_RDWR);
|
fd = open(port, O_RDWR);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: can't open device \"%s\": %s\n",
|
pmsg_ext_error("cannot open port %s: %s\n", port, strerror(errno));
|
||||||
progname, port, strerror(errno));
|
|
||||||
fdp->ifd = -1;
|
fdp->ifd = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -225,8 +216,7 @@ void ppi_open(char * port, union filedescriptor *fdp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ppi_close(union filedescriptor *fdp)
|
void ppi_close(const union filedescriptor *fdp) {
|
||||||
{
|
|
||||||
ppi_release (fdp->ifd);
|
ppi_release (fdp->ifd);
|
||||||
close(fdp->ifd);
|
close(fdp->ifd);
|
||||||
}
|
}
|
||||||
|
|
16
src/ppi.h
16
src/ppi.h
|
@ -34,21 +34,21 @@ enum {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ppi_get (union filedescriptor *fdp, int reg, int bit);
|
int ppi_get (const union filedescriptor *fdp, int reg, int bit);
|
||||||
|
|
||||||
int ppi_set (union filedescriptor *fdp, int reg, int bit);
|
int ppi_set (const union filedescriptor *fdp, int reg, int bit);
|
||||||
|
|
||||||
int ppi_clr (union filedescriptor *fdp, int reg, int bit);
|
int ppi_clr (const union filedescriptor *fdp, int reg, int bit);
|
||||||
|
|
||||||
int ppi_getall (union filedescriptor *fdp, int reg);
|
int ppi_getall (const union filedescriptor *fdp, int reg);
|
||||||
|
|
||||||
int ppi_setall (union filedescriptor *fdp, int reg, int val);
|
int ppi_setall (const union filedescriptor *fdp, int reg, int val);
|
||||||
|
|
||||||
int ppi_toggle (union filedescriptor *fdp, int reg, int bit);
|
int ppi_toggle (const union filedescriptor *fdp, int reg, int bit);
|
||||||
|
|
||||||
void ppi_open (char * port, union filedescriptor *fdp);
|
void ppi_open (const char *port, union filedescriptor *fdp);
|
||||||
|
|
||||||
void ppi_close (union filedescriptor *fdp);
|
void ppi_close (const union filedescriptor *fdp);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
46
src/ppiwin.c
46
src/ppiwin.c
|
@ -84,8 +84,7 @@ static void outb(unsigned char value, unsigned short port);
|
||||||
|
|
||||||
/* FUNCTION DEFINITIONS */
|
/* FUNCTION DEFINITIONS */
|
||||||
|
|
||||||
void ppi_open(char *port, union filedescriptor *fdp)
|
void ppi_open(const char *port, union filedescriptor *fdp) {
|
||||||
{
|
|
||||||
unsigned char i;
|
unsigned char i;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
@ -93,7 +92,7 @@ void ppi_open(char *port, union filedescriptor *fdp)
|
||||||
|
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: can't open device \"giveio\"\n\n", progname);
|
pmsg_ext_error("cannot open device \"giveio\"\n\n"); // giveio?!? FIXME!
|
||||||
fdp->ifd = -1;
|
fdp->ifd = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -121,14 +120,13 @@ void ppi_open(char *port, union filedescriptor *fdp)
|
||||||
fd = strtol(port, &cp, 0);
|
fd = strtol(port, &cp, 0);
|
||||||
if(*port == '\0' || *cp != '\0')
|
if(*port == '\0' || *cp != '\0')
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: port name \"%s\" is neither lpt1/2/3 nor valid number\n",
|
pmsg_error("port %s is neither lpt1/2/3 nor valid number\n", port);
|
||||||
progname, port);
|
|
||||||
fd = -1;
|
fd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: can't open device \"%s\"\n\n", progname, port);
|
pmsg_ext_error("cannot open port %s\n\n", port);
|
||||||
fdp->ifd = -1;
|
fdp->ifd = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -138,8 +136,7 @@ void ppi_open(char *port, union filedescriptor *fdp)
|
||||||
|
|
||||||
|
|
||||||
#define DRIVERNAME "\\\\.\\giveio"
|
#define DRIVERNAME "\\\\.\\giveio"
|
||||||
static int winnt_pp_open(void)
|
static int winnt_pp_open(void) {
|
||||||
{
|
|
||||||
// Only try to use giveio under Windows NT/2000/XP.
|
// Only try to use giveio under Windows NT/2000/XP.
|
||||||
OSVERSIONINFO ver_info;
|
OSVERSIONINFO ver_info;
|
||||||
|
|
||||||
|
@ -178,8 +175,7 @@ static int winnt_pp_open(void)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ppi_close(union filedescriptor *fdp)
|
void ppi_close(const union filedescriptor *fdp) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,8 +184,7 @@ void ppi_close(union filedescriptor *fdp)
|
||||||
/*
|
/*
|
||||||
* set the indicated bit of the specified register.
|
* set the indicated bit of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_set(union filedescriptor *fdp, int reg, int bit)
|
int ppi_set(const union filedescriptor *fdp, int reg, int bit) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
|
|
||||||
|
@ -204,8 +199,7 @@ int ppi_set(union filedescriptor *fdp, int reg, int bit)
|
||||||
/*
|
/*
|
||||||
* clear the indicated bit of the specified register.
|
* clear the indicated bit of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_clr(union filedescriptor *fdp, int reg, int bit)
|
int ppi_clr(const union filedescriptor *fdp, int reg, int bit) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
|
|
||||||
|
@ -221,8 +215,7 @@ int ppi_clr(union filedescriptor *fdp, int reg, int bit)
|
||||||
/*
|
/*
|
||||||
* get the indicated bit of the specified register.
|
* get the indicated bit of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_get(union filedescriptor *fdp, int reg, int bit)
|
int ppi_get(const union filedescriptor *fdp, int reg, int bit) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
|
|
||||||
v = inb(port_get(fdp, reg));
|
v = inb(port_get(fdp, reg));
|
||||||
|
@ -237,8 +230,7 @@ int ppi_get(union filedescriptor *fdp, int reg, int bit)
|
||||||
/*
|
/*
|
||||||
* toggle the indicated bit of the specified register.
|
* toggle the indicated bit of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_toggle(union filedescriptor *fdp, int reg, int bit)
|
int ppi_toggle(const union filedescriptor *fdp, int reg, int bit) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
unsigned short port;
|
unsigned short port;
|
||||||
|
|
||||||
|
@ -255,8 +247,7 @@ int ppi_toggle(union filedescriptor *fdp, int reg, int bit)
|
||||||
/*
|
/*
|
||||||
* get all bits of the specified register.
|
* get all bits of the specified register.
|
||||||
*/
|
*/
|
||||||
int ppi_getall(union filedescriptor *fdp, int reg)
|
int ppi_getall(const union filedescriptor *fdp, int reg) {
|
||||||
{
|
|
||||||
unsigned char v;
|
unsigned char v;
|
||||||
|
|
||||||
v = inb(port_get(fdp, reg));
|
v = inb(port_get(fdp, reg));
|
||||||
|
@ -270,8 +261,7 @@ int ppi_getall(union filedescriptor *fdp, int reg)
|
||||||
/*
|
/*
|
||||||
* set all bits of the specified register to val.
|
* set all bits of the specified register to val.
|
||||||
*/
|
*/
|
||||||
int ppi_setall(union filedescriptor *fdp, int reg, int val)
|
int ppi_setall(const union filedescriptor *fdp, int reg, int val) {
|
||||||
{
|
|
||||||
outb((unsigned char)val, port_get(fdp, reg));
|
outb((unsigned char)val, port_get(fdp, reg));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -280,15 +270,13 @@ int ppi_setall(union filedescriptor *fdp, int reg, int val)
|
||||||
|
|
||||||
|
|
||||||
/* Calculate port address to access. */
|
/* Calculate port address to access. */
|
||||||
static unsigned short port_get(union filedescriptor *fdp, int reg)
|
static unsigned short port_get(const union filedescriptor *fdp, int reg) {
|
||||||
{
|
|
||||||
return((unsigned short)(fdp->ifd + reg2offset(reg)));
|
return((unsigned short)(fdp->ifd + reg2offset(reg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Convert register enum to offset of base address. */
|
/* Convert register enum to offset of base address. */
|
||||||
static unsigned char reg2offset(int reg)
|
static unsigned char reg2offset(int reg) {
|
||||||
{
|
|
||||||
unsigned char offset = 0;
|
unsigned char offset = 0;
|
||||||
|
|
||||||
switch(reg)
|
switch(reg)
|
||||||
|
@ -315,8 +303,7 @@ static unsigned char reg2offset(int reg)
|
||||||
|
|
||||||
|
|
||||||
/* Read in value from port. */
|
/* Read in value from port. */
|
||||||
static unsigned char inb(unsigned short port)
|
static unsigned char inb(unsigned short port) {
|
||||||
{
|
|
||||||
unsigned char t;
|
unsigned char t;
|
||||||
|
|
||||||
asm volatile ("in %1, %0"
|
asm volatile ("in %1, %0"
|
||||||
|
@ -328,8 +315,7 @@ static unsigned char inb(unsigned short port)
|
||||||
|
|
||||||
|
|
||||||
/* Write value to port. */
|
/* Write value to port. */
|
||||||
static void outb(unsigned char value, unsigned short port)
|
static void outb(unsigned char value, unsigned short port) {
|
||||||
{
|
|
||||||
asm volatile ("out %1, %0"
|
asm volatile ("out %1, %0"
|
||||||
:
|
:
|
||||||
: "d" (port), "a" (value) );
|
: "d" (port), "a" (value) );
|
||||||
|
|
|
@ -65,16 +65,15 @@ static int avrdoperRxPosition = 0; /* amount of bytes already consu
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
static int usbOpenDevice(union filedescriptor *fdp, int vendor, char *vendorName,
|
static int usbOpenDevice(union filedescriptor *fdp, int vendor, const char *vendorName,
|
||||||
int product, char *productName, int doReportIDs)
|
int product, const char *productName, int doReportIDs)
|
||||||
{
|
{
|
||||||
hid_device *dev;
|
hid_device *dev;
|
||||||
|
|
||||||
dev = hid_open(vendor, product, NULL);
|
dev = hid_open(vendor, product, NULL);
|
||||||
if (dev == NULL)
|
if (dev == NULL)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: usbOpenDevice(): No device found\n",
|
pmsg_ext_error("no device found\n");
|
||||||
progname);
|
|
||||||
return USB_ERROR_NOTFOUND;
|
return USB_ERROR_NOTFOUND;
|
||||||
}
|
}
|
||||||
fdp->usb.handle = dev;
|
fdp->usb.handle = dev;
|
||||||
|
@ -96,8 +95,7 @@ static void usbCloseDevice(union filedescriptor *fdp)
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer, int len)
|
static int usbSetReport(const union filedescriptor *fdp, int reportType, char *buffer, int len) {
|
||||||
{
|
|
||||||
hid_device *udev = (hid_device *)fdp->usb.handle;
|
hid_device *udev = (hid_device *)fdp->usb.handle;
|
||||||
int bytesSent = -1;
|
int bytesSent = -1;
|
||||||
|
|
||||||
|
@ -114,7 +112,7 @@ static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer,
|
||||||
|
|
||||||
if(bytesSent != len){
|
if(bytesSent != len){
|
||||||
if(bytesSent < 0)
|
if(bytesSent < 0)
|
||||||
avrdude_message(MSG_INFO, "Error sending message: %s\n", hid_error(udev));
|
pmsg_error("unable to send message: %ls\n", hid_error(udev));
|
||||||
return USB_ERROR_IO;
|
return USB_ERROR_IO;
|
||||||
}
|
}
|
||||||
return USB_ERROR_NONE;
|
return USB_ERROR_NONE;
|
||||||
|
@ -122,7 +120,7 @@ static int usbSetReport(union filedescriptor *fdp, int reportType, char *buffer,
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNumber,
|
static int usbGetReport(const union filedescriptor *fdp, int reportType, int reportNumber,
|
||||||
char *buffer, int *len)
|
char *buffer, int *len)
|
||||||
{
|
{
|
||||||
hid_device *udev = (hid_device *)fdp->usb.handle;
|
hid_device *udev = (hid_device *)fdp->usb.handle;
|
||||||
|
@ -139,7 +137,7 @@ static int usbGetReport(union filedescriptor *fdp, int reportType, int reportNum
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(bytesReceived < 0){
|
if(bytesReceived < 0){
|
||||||
avrdude_message(MSG_INFO, "Error sending message: %s\n", hid_error(udev));
|
pmsg_error("unable to send message: %ls\n", hid_error(udev));
|
||||||
return USB_ERROR_IO;
|
return USB_ERROR_IO;
|
||||||
}
|
}
|
||||||
*len = bytesReceived;
|
*len = bytesReceived;
|
||||||
|
@ -161,42 +159,30 @@ static void dumpBlock(const char *prefix, const unsigned char *buf, int len)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(len <= 8){ /* more compact format for short blocks */
|
if(len <= 8){ /* more compact format for short blocks */
|
||||||
avrdude_message(MSG_INFO, "%s: %d bytes: ", prefix, len);
|
msg_info("%s: %d bytes: ", prefix, len);
|
||||||
for(i = 0; i < len; i++){
|
for(i = 0; i < len; i++){
|
||||||
avrdude_message(MSG_INFO, "%02x ", buf[i]);
|
msg_info("%02x ", buf[i]);
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_INFO, " \"");
|
msg_info(" \"");
|
||||||
for(i = 0; i < len; i++){
|
for(i = 0; i < len; i++)
|
||||||
if(buf[i] >= 0x20 && buf[i] < 0x7f){
|
msg_info("%c", buf[i] >= 0x20 && buf[i] < 0x7f? buf[i]: '.');
|
||||||
fputc(buf[i], stderr);
|
msg_info("\"\n");
|
||||||
}else{
|
|
||||||
fputc('.', stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_INFO, "\"\n");
|
|
||||||
}else{
|
}else{
|
||||||
avrdude_message(MSG_INFO, "%s: %d bytes:\n", prefix, len);
|
msg_info("%s: %d bytes:\n", prefix, len);
|
||||||
while(len > 0){
|
while(len > 0){
|
||||||
for(i = 0; i < 16; i++){
|
for(i = 0; i < 16; i++){
|
||||||
if(i < len){
|
if(i < len){
|
||||||
avrdude_message(MSG_INFO, "%02x ", buf[i]);
|
msg_info("%02x ", buf[i]);
|
||||||
}else{
|
}else{
|
||||||
avrdude_message(MSG_INFO, " ");
|
msg_info(" ");
|
||||||
}
|
}
|
||||||
if(i == 7)
|
if(i == 7)
|
||||||
fputc(' ', stderr);
|
msg_info(" ");
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_INFO, " \"");
|
msg_info(" \"");
|
||||||
for(i = 0; i < 16; i++){
|
for(i = 0; i < 16 && i < len; i++)
|
||||||
if(i < len){
|
msg_info("%c", buf[i] >= 0x20 && buf[i] < 0x7f? buf[i]: '.');
|
||||||
if(buf[i] >= 0x20 && buf[i] < 0x7f){
|
msg_info("\"\n");
|
||||||
fputc(buf[i], stderr);
|
|
||||||
}else{
|
|
||||||
fputc('.', stderr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
avrdude_message(MSG_INFO, "\"\n");
|
|
||||||
buf += 16;
|
buf += 16;
|
||||||
len -= 16;
|
len -= 16;
|
||||||
}
|
}
|
||||||
|
@ -208,20 +194,20 @@ static char *usbErrorText(int usbErrno)
|
||||||
static char buffer[32];
|
static char buffer[32];
|
||||||
|
|
||||||
switch(usbErrno){
|
switch(usbErrno){
|
||||||
case USB_ERROR_NONE: return "Success.";
|
case USB_ERROR_NONE: return "Success";
|
||||||
case USB_ERROR_ACCESS: return "Access denied.";
|
case USB_ERROR_ACCESS: return "Access denied";
|
||||||
case USB_ERROR_NOTFOUND:return "Device not found.";
|
case USB_ERROR_NOTFOUND:return "Device not found";
|
||||||
case USB_ERROR_BUSY: return "Device is busy.";
|
case USB_ERROR_BUSY: return "Device is busy";
|
||||||
case USB_ERROR_IO: return "I/O Error.";
|
case USB_ERROR_IO: return "I/O Error";
|
||||||
default:
|
default:
|
||||||
sprintf(buffer, "Unknown error %d.", usbErrno);
|
sprintf(buffer, "Unknown error %d", usbErrno);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int avrdoper_open(char *port, union pinfo pinfo, union filedescriptor *fdp)
|
static int avrdoper_open(const char *port, union pinfo pinfo, union filedescriptor *fdp)
|
||||||
{
|
{
|
||||||
int rval;
|
int rval;
|
||||||
char *vname = "obdev.at";
|
char *vname = "obdev.at";
|
||||||
|
@ -229,7 +215,7 @@ static int avrdoper_open(char *port, union pinfo pinfo, union filedescriptor *fd
|
||||||
|
|
||||||
rval = usbOpenDevice(fdp, USB_VENDOR_ID, vname, USB_PRODUCT_ID, devname, 1);
|
rval = usbOpenDevice(fdp, USB_VENDOR_ID, vname, USB_PRODUCT_ID, devname, 1);
|
||||||
if(rval != 0){
|
if(rval != 0){
|
||||||
avrdude_message(MSG_INFO, "%s: avrdoper_open(): %s\n", progname, usbErrorText(rval));
|
pmsg_ext_error("%s\n", usbErrorText(rval));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -255,7 +241,7 @@ static int chooseDataSize(int len)
|
||||||
return i - 1;
|
return i - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrdoper_send(union filedescriptor *fdp, const unsigned char *buf, size_t buflen)
|
static int avrdoper_send(const union filedescriptor *fdp, const unsigned char *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
if(verbose > 3)
|
if(verbose > 3)
|
||||||
dumpBlock("Send", buf, buflen);
|
dumpBlock("Send", buf, buflen);
|
||||||
|
@ -267,11 +253,11 @@ static int avrdoper_send(union filedescriptor *fdp, const unsigned char *buf, si
|
||||||
buffer[0] = lenIndex + 1; /* report ID */
|
buffer[0] = lenIndex + 1; /* report ID */
|
||||||
buffer[1] = thisLen;
|
buffer[1] = thisLen;
|
||||||
memcpy(buffer + 2, buf, thisLen);
|
memcpy(buffer + 2, buf, thisLen);
|
||||||
avrdude_message(MSG_TRACE, "Sending %d bytes data chunk\n", thisLen);
|
msg_trace("Sending %d bytes data chunk\n", thisLen);
|
||||||
rval = usbSetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, (char *)buffer,
|
rval = usbSetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, (char *)buffer,
|
||||||
reportDataSizes[lenIndex] + 2);
|
reportDataSizes[lenIndex] + 2);
|
||||||
if(rval != 0){
|
if(rval != 0){
|
||||||
avrdude_message(MSG_INFO, "%s: avrdoper_send(): %s\n", progname, usbErrorText(rval));
|
pmsg_error("%s\n", usbErrorText(rval));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
buflen -= thisLen;
|
buflen -= thisLen;
|
||||||
|
@ -282,8 +268,7 @@ static int avrdoper_send(union filedescriptor *fdp, const unsigned char *buf, si
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int avrdoperFillBuffer(union filedescriptor *fdp)
|
static int avrdoperFillBuffer(const union filedescriptor *fdp) {
|
||||||
{
|
|
||||||
int bytesPending = reportDataSizes[1]; /* guess how much data is buffered in device */
|
int bytesPending = reportDataSizes[1]; /* guess how much data is buffered in device */
|
||||||
|
|
||||||
avrdoperRxPosition = avrdoperRxLength = 0;
|
avrdoperRxPosition = avrdoperRxLength = 0;
|
||||||
|
@ -297,17 +282,16 @@ static int avrdoperFillBuffer(union filedescriptor *fdp)
|
||||||
usbErr = usbGetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, lenIndex + 1,
|
usbErr = usbGetReport(fdp, USB_HID_REPORT_TYPE_FEATURE, lenIndex + 1,
|
||||||
(char *)buffer, &len);
|
(char *)buffer, &len);
|
||||||
if(usbErr != 0){
|
if(usbErr != 0){
|
||||||
avrdude_message(MSG_INFO, "%s: avrdoperFillBuffer(): %s\n", progname, usbErrorText(usbErr));
|
pmsg_error("%s\n", usbErrorText(usbErr));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE, "Received %d bytes data chunk of total %d\n", len - 2, buffer[1]);
|
msg_trace("Received %d bytes data chunk of total %d\n", len - 2, buffer[1]);
|
||||||
len -= 2; /* compensate for report ID and length byte */
|
len -= 2; /* compensate for report ID and length byte */
|
||||||
bytesPending = buffer[1] - len; /* amount still buffered */
|
bytesPending = buffer[1] - len; /* amount still buffered */
|
||||||
if(len > buffer[1]) /* cut away padding */
|
if(len > buffer[1]) /* cut away padding */
|
||||||
len = buffer[1];
|
len = buffer[1];
|
||||||
if(avrdoperRxLength + len > sizeof(avrdoperRxBuffer)){
|
if(avrdoperRxLength + len > sizeof(avrdoperRxBuffer)){
|
||||||
avrdude_message(MSG_INFO, "%s: avrdoperFillBuffer(): internal error: buffer overflow\n",
|
pmsg_error("buffer overflow\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
memcpy(avrdoperRxBuffer + avrdoperRxLength, buffer + 2, len);
|
memcpy(avrdoperRxBuffer + avrdoperRxLength, buffer + 2, len);
|
||||||
|
@ -316,7 +300,7 @@ static int avrdoperFillBuffer(union filedescriptor *fdp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int avrdoper_recv(union filedescriptor *fdp, unsigned char *buf, size_t buflen)
|
static int avrdoper_recv(const union filedescriptor *fdp, unsigned char *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
unsigned char *p = buf;
|
unsigned char *p = buf;
|
||||||
int remaining = buflen;
|
int remaining = buflen;
|
||||||
|
@ -341,7 +325,7 @@ static int avrdoper_recv(union filedescriptor *fdp, unsigned char *buf, size_t b
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int avrdoper_drain(union filedescriptor *fdp, int display)
|
static int avrdoper_drain(const union filedescriptor *fdp, int display)
|
||||||
{
|
{
|
||||||
do{
|
do{
|
||||||
if (avrdoperFillBuffer(fdp) < 0)
|
if (avrdoperFillBuffer(fdp) < 0)
|
||||||
|
@ -352,9 +336,9 @@ static int avrdoper_drain(union filedescriptor *fdp, int display)
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static int avrdoper_set_dtr_rts(union filedescriptor *fdp, int is_on)
|
static int avrdoper_set_dtr_rts(const union filedescriptor *fdp, int is_on)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: AVR-Doper doesn't support DTR/RTS setting\n", progname);
|
pmsg_error("AVR-Doper does not support DTR/RTS setting\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
167
src/ser_posix.c
167
src/ser_posix.c
|
@ -36,6 +36,7 @@
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/select.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
|
||||||
|
@ -51,6 +52,7 @@
|
||||||
#include "libavrdude.h"
|
#include "libavrdude.h"
|
||||||
|
|
||||||
long serial_recv_timeout = 5000; /* ms */
|
long serial_recv_timeout = 5000; /* ms */
|
||||||
|
long serial_drain_timeout = 250; /* ms */
|
||||||
|
|
||||||
struct baud_mapping {
|
struct baud_mapping {
|
||||||
long baud;
|
long baud;
|
||||||
|
@ -76,6 +78,45 @@ static struct baud_mapping baud_lookup_table [] = {
|
||||||
#endif
|
#endif
|
||||||
#ifdef B230400
|
#ifdef B230400
|
||||||
{ 230400, 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
|
#endif
|
||||||
{ 0, 0 } /* Terminator. */
|
{ 0, 0 } /* Terminator. */
|
||||||
};
|
};
|
||||||
|
@ -83,8 +124,7 @@ static struct baud_mapping baud_lookup_table [] = {
|
||||||
static struct termios original_termios;
|
static struct termios original_termios;
|
||||||
static int saved_original_termios;
|
static int saved_original_termios;
|
||||||
|
|
||||||
static speed_t serial_baud_lookup(long baud, bool *nonstandard)
|
static speed_t serial_baud_lookup(long baud, bool *nonstandard) {
|
||||||
{
|
|
||||||
struct baud_mapping *map = baud_lookup_table;
|
struct baud_mapping *map = baud_lookup_table;
|
||||||
|
|
||||||
*nonstandard = false;
|
*nonstandard = false;
|
||||||
|
@ -99,16 +139,14 @@ static speed_t serial_baud_lookup(long baud, bool *nonstandard)
|
||||||
* If a non-standard BAUD rate is used, issue
|
* If a non-standard BAUD rate is used, issue
|
||||||
* a warning (if we are verbose) and return the raw rate
|
* a warning (if we are verbose) and return the raw rate
|
||||||
*/
|
*/
|
||||||
avrdude_message(MSG_NOTICE, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld\n",
|
pmsg_notice("serial_baud_lookup(): using non-standard baud rate: %ld\n", baud);
|
||||||
progname, baud);
|
|
||||||
|
|
||||||
*nonstandard = true;
|
*nonstandard = true;
|
||||||
|
|
||||||
return baud;
|
return baud;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cflags)
|
static int ser_setparams(const union filedescriptor *fd, long baud, unsigned long cflags) {
|
||||||
{
|
|
||||||
int rc;
|
int rc;
|
||||||
struct termios termios;
|
struct termios termios;
|
||||||
bool nonstandard;
|
bool nonstandard;
|
||||||
|
@ -122,9 +160,9 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla
|
||||||
*/
|
*/
|
||||||
rc = tcgetattr(fd->ifd, &termios);
|
rc = tcgetattr(fd->ifd, &termios);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_setparams(): tcgetattr() failed",
|
int ret = -errno;
|
||||||
progname);
|
pmsg_ext_error("tcgetattr() failed\n");
|
||||||
return -errno;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -217,18 +255,18 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla
|
||||||
|
|
||||||
rc = tcsetattr(fd->ifd, TCSANOW, &termios);
|
rc = tcsetattr(fd->ifd, TCSANOW, &termios);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_setparams(): tcsetattr() failed\n",
|
int ret = -errno;
|
||||||
progname);
|
pmsg_ext_error("tcsetattr() failed\n");
|
||||||
return -errno;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
// handle nonstandard speed values the MacOS way
|
// handle nonstandard speed values the MacOS way
|
||||||
if (nonstandard) {
|
if (nonstandard) {
|
||||||
if (ioctl(fd->ifd, IOSSIOSPEED, &speed) < 0) {
|
if (ioctl(fd->ifd, IOSSIOSPEED, &speed) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_setparams(): ioctrl(IOSSIOSPEED) failed\n",
|
int ret = -errno;
|
||||||
progname);
|
pmsg_ext_error("ioctrl(IOSSIOSPEED) failed\n");
|
||||||
return -errno;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // __APPLE__
|
#endif // __APPLE__
|
||||||
|
@ -244,17 +282,14 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla
|
||||||
* terminal/console server with serial parameters configured
|
* terminal/console server with serial parameters configured
|
||||||
* appropriately (e. g. 115200-8-N-1 for a STK500.)
|
* appropriately (e. g. 115200-8-N-1 for a STK500.)
|
||||||
*/
|
*/
|
||||||
static int
|
static int net_open(const char *port, union filedescriptor *fdp) {
|
||||||
net_open(const char *port, union filedescriptor *fdp)
|
|
||||||
{
|
|
||||||
char *hp, *hstr, *pstr;
|
char *hp, *hstr, *pstr;
|
||||||
int s, fd, ret = -1;
|
int s, fd, ret = -1;
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
struct addrinfo *result, *rp;
|
struct addrinfo *result, *rp;
|
||||||
|
|
||||||
if ((hstr = hp = strdup(port)) == NULL) {
|
if ((hstr = hp = strdup(port)) == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Out of memory!\n",
|
pmsg_error("out of memory\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,8 +299,7 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||||
* service name from the host or IP address.
|
* service name from the host or IP address.
|
||||||
*/
|
*/
|
||||||
if (((pstr = strrchr(hstr, ':')) == NULL) || (pstr == hstr)) {
|
if (((pstr = strrchr(hstr, ':')) == NULL) || (pstr == hstr)) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Mangled host:port string \"%s\"\n",
|
pmsg_error("mangled host:port string %s\n", hstr);
|
||||||
progname, hstr);
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,10 +322,8 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||||
s = getaddrinfo(hstr, pstr, &hints, &result);
|
s = getaddrinfo(hstr, pstr, &hints, &result);
|
||||||
|
|
||||||
if (s != 0) {
|
if (s != 0) {
|
||||||
avrdude_message(MSG_INFO,
|
pmsg_ext_error("cannot resolve host=\"%s\", port=\"%s\": %s\n",
|
||||||
"%s: net_open(): Cannot resolve "
|
hstr, pstr, gai_strerror(s));
|
||||||
"host=\"%s\", port=\"%s\": %s\n",
|
|
||||||
progname, hstr, pstr, gai_strerror(s));
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
for (rp = result; rp != NULL; rp = rp->ai_next) {
|
||||||
|
@ -307,8 +339,7 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
if (rp == NULL) {
|
if (rp == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Cannot connect: %s\n",
|
pmsg_ext_error("cannot connect: %s\n", strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fdp->ifd = fd;
|
fdp->ifd = fd;
|
||||||
|
@ -322,14 +353,13 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ser_set_dtr_rts(union filedescriptor *fdp, int is_on)
|
static int ser_set_dtr_rts(const union filedescriptor *fdp, int is_on) {
|
||||||
{
|
|
||||||
unsigned int ctl;
|
unsigned int ctl;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = ioctl(fdp->ifd, TIOCMGET, &ctl);
|
r = ioctl(fdp->ifd, TIOCMGET, &ctl);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
perror("ioctl(\"TIOCMGET\")");
|
pmsg_ext_error("ioctl(\"TIOCMGET\"): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,15 +374,14 @@ static int ser_set_dtr_rts(union filedescriptor *fdp, int is_on)
|
||||||
|
|
||||||
r = ioctl(fdp->ifd, TIOCMSET, &ctl);
|
r = ioctl(fdp->ifd, TIOCMSET, &ctl);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
perror("ioctl(\"TIOCMSET\")");
|
pmsg_ext_error("ioctl(\"TIOCMSET\"): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
static int ser_open(const char *port, union pinfo pinfo, union filedescriptor *fdp) {
|
||||||
{
|
|
||||||
int rc;
|
int rc;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
|
@ -369,8 +398,7 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||||
*/
|
*/
|
||||||
fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
fd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n",
|
pmsg_ext_error("cannot open port %s: %s\n", port, strerror(errno));
|
||||||
progname, port, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,24 +409,21 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||||
*/
|
*/
|
||||||
rc = ser_setparams(fdp, pinfo.serialinfo.baud, pinfo.serialinfo.cflags);
|
rc = ser_setparams(fdp, pinfo.serialinfo.baud, pinfo.serialinfo.cflags);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't set attributes for device \"%s\": %s\n",
|
pmsg_ext_error("cannot set attributes for port %s: %s\n", port, strerror(-rc));
|
||||||
progname, port, strerror(-rc));
|
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ser_close(union filedescriptor *fd)
|
static void ser_close(union filedescriptor *fd) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
* restore original termios settings from ser_open
|
* restore original termios settings from ser_open
|
||||||
*/
|
*/
|
||||||
if (saved_original_termios) {
|
if (saved_original_termios) {
|
||||||
int rc = tcsetattr(fd->ifd, TCSANOW | TCSADRAIN, &original_termios);
|
int rc = tcsetattr(fd->ifd, TCSANOW | TCSADRAIN, &original_termios);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_close(): can't reset attributes for device: %s\n",
|
pmsg_ext_error("cannot reset attributes for device: %s\n", strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
}
|
}
|
||||||
saved_original_termios = 0;
|
saved_original_termios = 0;
|
||||||
}
|
}
|
||||||
|
@ -407,8 +432,7 @@ static void ser_close(union filedescriptor *fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t buflen)
|
static int ser_send(const union filedescriptor *fd, const unsigned char * buf, size_t buflen) {
|
||||||
{
|
|
||||||
int rc;
|
int rc;
|
||||||
const unsigned char * p = buf;
|
const unsigned char * p = buf;
|
||||||
size_t len = buflen;
|
size_t len = buflen;
|
||||||
|
@ -418,30 +442,29 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||||
|
|
||||||
if (verbose > 3)
|
if (verbose > 3)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_TRACE, "%s: Send: ", progname);
|
pmsg_trace("send: ");
|
||||||
|
|
||||||
while (buflen) {
|
while (buflen) {
|
||||||
unsigned char c = *buf;
|
unsigned char c = *buf;
|
||||||
if (isprint(c)) {
|
if (isprint(c)) {
|
||||||
avrdude_message(MSG_TRACE, "%c ", c);
|
msg_trace("%c ", c);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
avrdude_message(MSG_TRACE, ". ");
|
msg_trace(". ");
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE, "[%02x] ", c);
|
msg_trace("[%02x] ", c);
|
||||||
|
|
||||||
buf++;
|
buf++;
|
||||||
buflen--;
|
buflen--;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_TRACE, "\n");
|
msg_trace("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
rc = write(fd->ifd, p, (len > 1024) ? 1024 : len);
|
rc = write(fd->ifd, p, (len > 1024) ? 1024 : len);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n",
|
pmsg_ext_error("unable to write: %s\n", strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p += rc;
|
p += rc;
|
||||||
|
@ -452,8 +475,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
static int ser_recv(const union filedescriptor *fd, unsigned char * buf, size_t buflen) {
|
||||||
{
|
|
||||||
struct timeval timeout, to2;
|
struct timeval timeout, to2;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
int nfds;
|
int nfds;
|
||||||
|
@ -472,27 +494,23 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
||||||
|
|
||||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
||||||
if (nfds == 0) {
|
if (nfds == 0) {
|
||||||
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
|
pmsg_notice2("ser_recv(): programmer is not responding\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else if (nfds == -1) {
|
else if (nfds == -1) {
|
||||||
if (errno == EINTR || errno == EAGAIN) {
|
if (errno == EINTR || errno == EAGAIN) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): programmer is not responding,reselecting\n",
|
pmsg_warning("programmer is not responding, reselecting\n");
|
||||||
progname);
|
|
||||||
goto reselect;
|
goto reselect;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n",
|
pmsg_ext_error("select(): %s\n", strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = read(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len);
|
rc = read(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n",
|
pmsg_ext_error("unable to read: %s\n", strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
p += rc;
|
p += rc;
|
||||||
|
@ -503,30 +521,29 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
||||||
|
|
||||||
if (verbose > 3)
|
if (verbose > 3)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_TRACE, "%s: Recv: ", progname);
|
pmsg_trace("recv: ");
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
unsigned char c = *p;
|
unsigned char c = *p;
|
||||||
if (isprint(c)) {
|
if (isprint(c)) {
|
||||||
avrdude_message(MSG_TRACE, "%c ", c);
|
msg_trace("%c ", c);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
avrdude_message(MSG_TRACE, ". ");
|
msg_trace(". ");
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE, "[%02x] ", c);
|
msg_trace("[%02x] ", c);
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE, "\n");
|
msg_trace("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ser_drain(union filedescriptor *fd, int display)
|
static int ser_drain(const union filedescriptor *fd, int display) {
|
||||||
{
|
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
int nfds;
|
int nfds;
|
||||||
|
@ -534,10 +551,10 @@ static int ser_drain(union filedescriptor *fd, int display)
|
||||||
unsigned char buf;
|
unsigned char buf;
|
||||||
|
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = 0;
|
||||||
timeout.tv_usec = 250000;
|
timeout.tv_usec = serial_drain_timeout*1000L;
|
||||||
|
|
||||||
if (display) {
|
if (display) {
|
||||||
avrdude_message(MSG_INFO, "drain>");
|
msg_info("drain>");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -548,7 +565,7 @@ static int ser_drain(union filedescriptor *fd, int display)
|
||||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
|
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
|
||||||
if (nfds == 0) {
|
if (nfds == 0) {
|
||||||
if (display) {
|
if (display) {
|
||||||
avrdude_message(MSG_INFO, "<drain\n");
|
msg_info("<drain\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -558,20 +575,18 @@ static int ser_drain(union filedescriptor *fd, int display)
|
||||||
goto reselect;
|
goto reselect;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): select(): %s\n",
|
pmsg_ext_error("select(): %s\n", strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = read(fd->ifd, &buf, 1);
|
rc = read(fd->ifd, &buf, 1);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n",
|
pmsg_ext_error("unable to read: %s\n", strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (display) {
|
if (display) {
|
||||||
avrdude_message(MSG_INFO, "%02x ", buf);
|
msg_info("%02x ", buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
179
src/ser_win32.c
179
src/ser_win32.c
|
@ -41,6 +41,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
long serial_recv_timeout = 5000; /* ms */
|
long serial_recv_timeout = 5000; /* ms */
|
||||||
|
long serial_drain_timeout = 250; /* ms */
|
||||||
|
|
||||||
#define W32SERBUFSIZE 1024
|
#define W32SERBUFSIZE 1024
|
||||||
|
|
||||||
|
@ -81,8 +82,7 @@ static DWORD serial_baud_lookup(long baud)
|
||||||
* If a non-standard BAUD rate is used, issue
|
* If a non-standard BAUD rate is used, issue
|
||||||
* a warning (if we are verbose) and return the raw rate
|
* a warning (if we are verbose) and return the raw rate
|
||||||
*/
|
*/
|
||||||
avrdude_message(MSG_NOTICE, "%s: serial_baud_lookup(): Using non-standard baud rate: %ld",
|
pmsg_notice("serial_baud_lookup(): using non-standard baud rate: %ld", baud);
|
||||||
progname, baud);
|
|
||||||
|
|
||||||
return baud;
|
return baud;
|
||||||
}
|
}
|
||||||
|
@ -99,8 +99,7 @@ static BOOL serial_w32SetTimeOut(HANDLE hComPort, DWORD timeout) // in ms
|
||||||
return SetCommTimeouts(hComPort, &ctmo);
|
return SetCommTimeouts(hComPort, &ctmo);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cflags)
|
static int ser_setparams(const union filedescriptor *fd, long baud, unsigned long cflags) {
|
||||||
{
|
|
||||||
if (serial_over_ethernet) {
|
if (serial_over_ethernet) {
|
||||||
return -ENOTTY;
|
return -ENOTTY;
|
||||||
} else {
|
} else {
|
||||||
|
@ -154,9 +153,7 @@ static int ser_setparams(union filedescriptor *fd, long baud, unsigned long cfla
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int net_open(const char *port, union filedescriptor *fdp) {
|
||||||
net_open(const char *port, union filedescriptor *fdp)
|
|
||||||
{
|
|
||||||
WSADATA wsaData;
|
WSADATA wsaData;
|
||||||
LPVOID lpMsgBuf;
|
LPVOID lpMsgBuf;
|
||||||
|
|
||||||
|
@ -167,17 +164,17 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||||
struct hostent *hp;
|
struct hostent *hp;
|
||||||
|
|
||||||
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
|
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): WSAStartup() failed\n", progname);
|
pmsg_error("WSAStartup() failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hstr = strdup(port)) == NULL) {
|
if ((hstr = strdup(port)) == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Out of memory!\n", progname);
|
pmsg_error("out of memory\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((pstr = strchr(hstr, ':')) == NULL) || (pstr == hstr)) {
|
if (((pstr = strchr(hstr, ':')) == NULL) || (pstr == hstr)) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Mangled host:port string \"%s\"\n", progname, hstr);
|
pmsg_error("mangled host:port string %s\n", hstr);
|
||||||
free(hstr);
|
free(hstr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -190,13 +187,13 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||||
pnum = strtoul(pstr, &end, 10);
|
pnum = strtoul(pstr, &end, 10);
|
||||||
|
|
||||||
if ((*pstr == '\0') || (*end != '\0') || (pnum == 0) || (pnum > 65535)) {
|
if ((*pstr == '\0') || (*end != '\0') || (pnum == 0) || (pnum > 65535)) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Bad port number \"%s\"\n", progname, pstr);
|
pmsg_error("bad port number %s\n", pstr);
|
||||||
free(hstr);
|
free(hstr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((hp = gethostbyname(hstr)) == NULL) {
|
if ((hp = gethostbyname(hstr)) == NULL) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): unknown host \"%s\"\n", progname, hstr);
|
pmsg_error("unknown host %s\n", hstr);
|
||||||
free(hstr);
|
free(hstr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +211,7 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||||
(LPTSTR)&lpMsgBuf,
|
(LPTSTR)&lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Cannot open socket: %s\n", progname, (char *)lpMsgBuf);
|
pmsg_error("cannot open socket: %s\n", (char *) lpMsgBuf);
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -235,7 +232,7 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||||
(LPTSTR)&lpMsgBuf,
|
(LPTSTR)&lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: net_open(): Connect failed: %s\n", progname, (char *)lpMsgBuf);
|
pmsg_error("connect failed: %s\n", (char *) lpMsgBuf);
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -247,8 +244,7 @@ net_open(const char *port, union filedescriptor *fdp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
static int ser_open(const char *port, union pinfo pinfo, union filedescriptor *fdp) {
|
||||||
{
|
|
||||||
LPVOID lpMsgBuf;
|
LPVOID lpMsgBuf;
|
||||||
HANDLE hComPort=INVALID_HANDLE_VALUE;
|
HANDLE hComPort=INVALID_HANDLE_VALUE;
|
||||||
char *newname = 0;
|
char *newname = 0;
|
||||||
|
@ -274,8 +270,7 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||||
newname = malloc(strlen("\\\\.\\") + strlen(port) + 1);
|
newname = malloc(strlen("\\\\.\\") + strlen(port) + 1);
|
||||||
|
|
||||||
if (newname == 0) {
|
if (newname == 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): out of memory\n",
|
pmsg_error("out of memory\n");
|
||||||
progname);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
strcpy(newname, "\\\\.\\");
|
strcpy(newname, "\\\\.\\");
|
||||||
|
@ -298,8 +293,7 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||||
(LPTSTR) &lpMsgBuf,
|
(LPTSTR) &lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n",
|
pmsg_error("cannot open port %s: %s\n", port, (char*) lpMsgBuf);
|
||||||
progname, port, (char*)lpMsgBuf);
|
|
||||||
LocalFree( lpMsgBuf );
|
LocalFree( lpMsgBuf );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -307,8 +301,7 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||||
if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE))
|
if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE))
|
||||||
{
|
{
|
||||||
CloseHandle(hComPort);
|
CloseHandle(hComPort);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't set buffers for \"%s\"\n",
|
pmsg_error("cannot set buffers for %s\n", port);
|
||||||
progname, port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,16 +309,14 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||||
if (ser_setparams(fdp, pinfo.serialinfo.baud, pinfo.serialinfo.cflags) != 0)
|
if (ser_setparams(fdp, pinfo.serialinfo.baud, pinfo.serialinfo.cflags) != 0)
|
||||||
{
|
{
|
||||||
CloseHandle(hComPort);
|
CloseHandle(hComPort);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't set com-state for \"%s\"\n",
|
pmsg_error("cannot set com-state for %s\n", port);
|
||||||
progname, port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!serial_w32SetTimeOut(hComPort,0))
|
if (!serial_w32SetTimeOut(hComPort,0))
|
||||||
{
|
{
|
||||||
CloseHandle(hComPort);
|
CloseHandle(hComPort);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't set initial timeout for \"%s\"\n",
|
pmsg_error("cannot set initial timeout for %s\n", port);
|
||||||
progname, port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,8 +327,7 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ser_close(union filedescriptor *fd)
|
static void ser_close(union filedescriptor *fd) {
|
||||||
{
|
|
||||||
if (serial_over_ethernet) {
|
if (serial_over_ethernet) {
|
||||||
closesocket(fd->ifd);
|
closesocket(fd->ifd);
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
|
@ -350,8 +340,7 @@ static void ser_close(union filedescriptor *fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ser_set_dtr_rts(union filedescriptor *fd, int is_on)
|
static int ser_set_dtr_rts(const union filedescriptor *fd, int is_on) {
|
||||||
{
|
|
||||||
if (serial_over_ethernet) {
|
if (serial_over_ethernet) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -368,15 +357,14 @@ static int ser_set_dtr_rts(union filedescriptor *fd, int is_on)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t buflen)
|
static int net_send(const union filedescriptor *fd, const unsigned char * buf, size_t buflen) {
|
||||||
{
|
|
||||||
LPVOID lpMsgBuf;
|
LPVOID lpMsgBuf;
|
||||||
int rc;
|
int rc;
|
||||||
const unsigned char *p = buf;
|
const unsigned char *p = buf;
|
||||||
size_t len = buflen;
|
size_t len = buflen;
|
||||||
|
|
||||||
if (fd->ifd < 0) {
|
if (fd->ifd < 0) {
|
||||||
avrdude_message(MSG_NOTICE, "%s: net_send(): connection not open\n", progname);
|
pmsg_notice("net_send(): connection not open\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,26 +373,26 @@ static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose > 3) {
|
if (verbose > 3) {
|
||||||
avrdude_message(MSG_TRACE, "%s: Send: ", progname);
|
pmsg_trace("send: ");
|
||||||
|
|
||||||
while (buflen) {
|
while (buflen) {
|
||||||
unsigned char c = *buf;
|
unsigned char c = *buf;
|
||||||
if (isprint(c)) {
|
if (isprint(c)) {
|
||||||
avrdude_message(MSG_TRACE, "%c ", c);
|
msg_trace("%c ", c);
|
||||||
} else {
|
} else {
|
||||||
avrdude_message(MSG_TRACE, ". ");
|
msg_trace(". ");
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE, "[%02x] ", c);
|
msg_trace("[%02x] ", c);
|
||||||
|
|
||||||
buf++;
|
buf++;
|
||||||
buflen--;
|
buflen--;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_TRACE, "\n");
|
msg_trace("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
rc = send(fd->ifd, p, (len > 1024) ? 1024 : len, 0);
|
rc = send(fd->ifd, (const char *) p, (len > 1024)? 1024: len, 0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
FormatMessage(
|
FormatMessage(
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
@ -416,7 +404,7 @@ static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||||
(LPTSTR)&lpMsgBuf,
|
(LPTSTR)&lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: net_send(): send error: %s\n", progname, (char *)lpMsgBuf);
|
pmsg_error("unable to send: %s\n", (char *) lpMsgBuf);
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -428,8 +416,7 @@ static int net_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t buflen)
|
static int ser_send(const union filedescriptor *fd, const unsigned char * buf, size_t buflen) {
|
||||||
{
|
|
||||||
if (serial_over_ethernet) {
|
if (serial_over_ethernet) {
|
||||||
return net_send(fd, buf, buflen);
|
return net_send(fd, buf, buflen);
|
||||||
}
|
}
|
||||||
|
@ -442,8 +429,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||||
|
|
||||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_send(): port not open\n",
|
pmsg_error("port not open\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,34 +438,32 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||||
|
|
||||||
if (verbose > 3)
|
if (verbose > 3)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_TRACE, "%s: Send: ", progname);
|
pmsg_trace("send: ");
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
c = *b;
|
c = *b;
|
||||||
if (isprint(c)) {
|
if (isprint(c)) {
|
||||||
avrdude_message(MSG_TRACE, "%c ", c);
|
msg_trace("%c ", c);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
avrdude_message(MSG_TRACE, ". ");
|
msg_trace(". ");
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE, "[%02x] ", c);
|
msg_trace("[%02x] ", c);
|
||||||
b++;
|
b++;
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_trace("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_w32SetTimeOut(hComPort,500);
|
serial_w32SetTimeOut(hComPort,500);
|
||||||
|
|
||||||
if (!WriteFile (hComPort, buf, buflen, &written, NULL)) {
|
if (!WriteFile (hComPort, buf, buflen, &written, NULL)) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_send(): write error: %s\n",
|
pmsg_error("unable to write: %s\n", "sorry no info avail"); // TODO
|
||||||
progname, "sorry no info avail"); // TODO
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (written != buflen) {
|
if (written != buflen) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_send(): size/send mismatch\n",
|
pmsg_error("size/send mismatch\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,8 +471,7 @@ static int ser_send(union filedescriptor *fd, const unsigned char * buf, size_t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
static int net_recv(const union filedescriptor *fd, unsigned char * buf, size_t buflen) {
|
||||||
{
|
|
||||||
LPVOID lpMsgBuf;
|
LPVOID lpMsgBuf;
|
||||||
struct timeval timeout, to2;
|
struct timeval timeout, to2;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
|
@ -498,7 +481,7 @@ static int net_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
|
|
||||||
if (fd->ifd < 0) {
|
if (fd->ifd < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: net_recv(): connection not open\n", progname);
|
pmsg_error("connection not open\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,12 +497,12 @@ reselect:
|
||||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
|
||||||
if (nfds == 0) {
|
if (nfds == 0) {
|
||||||
if (verbose > 1) {
|
if (verbose > 1) {
|
||||||
avrdude_message(MSG_NOTICE, "%s: ser_recv(): programmer is not responding\n", progname);
|
pmsg_notice("net_recv(): programmer is not responding\n");
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
} else if (nfds == -1) {
|
} else if (nfds == -1) {
|
||||||
if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS) {
|
if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS) {
|
||||||
avrdude_message(MSG_NOTICE, "%s: ser_recv(): programmer is not responding, reselecting\n", progname);
|
pmsg_notice("net_recv(): programmer is not responding, reselecting\n");
|
||||||
goto reselect;
|
goto reselect;
|
||||||
} else {
|
} else {
|
||||||
FormatMessage(
|
FormatMessage(
|
||||||
|
@ -532,13 +515,13 @@ reselect:
|
||||||
(LPTSTR)&lpMsgBuf,
|
(LPTSTR)&lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): select(): %s\n", progname, (char *)lpMsgBuf);
|
pmsg_error("select(): %s\n", (char *) lpMsgBuf);
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = recv(fd->ifd, p, (buflen - len > 1024) ? 1024 : buflen - len, 0);
|
rc = recv(fd->ifd, (char *) p, (buflen - len > 1024)? 1024: buflen - len, 0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
FormatMessage(
|
FormatMessage(
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
@ -550,7 +533,7 @@ reselect:
|
||||||
(LPTSTR)&lpMsgBuf,
|
(LPTSTR)&lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n", progname, (char *)lpMsgBuf);
|
pmsg_error("unable to read: %s\n", (char *) lpMsgBuf);
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -561,28 +544,27 @@ reselect:
|
||||||
p = buf;
|
p = buf;
|
||||||
|
|
||||||
if (verbose > 3) {
|
if (verbose > 3) {
|
||||||
avrdude_message(MSG_TRACE, "%s: Recv: ", progname);
|
pmsg_trace("Recv: ");
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
unsigned char c = *p;
|
unsigned char c = *p;
|
||||||
if (isprint(c)) {
|
if (isprint(c)) {
|
||||||
avrdude_message(MSG_TRACE, "%c ", c);
|
msg_trace("%c ", c);
|
||||||
} else {
|
} else {
|
||||||
avrdude_message(MSG_TRACE, ". ");
|
msg_trace(". ");
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE, "[%02x] ", c);
|
msg_trace("[%02x] ", c);
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
len--;
|
len--;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE, "\n");
|
msg_trace("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen)
|
static int ser_recv(const union filedescriptor *fd, unsigned char * buf, size_t buflen) {
|
||||||
{
|
|
||||||
if (serial_over_ethernet) {
|
if (serial_over_ethernet) {
|
||||||
return net_recv(fd, buf, buflen);
|
return net_recv(fd, buf, buflen);
|
||||||
}
|
}
|
||||||
|
@ -594,8 +576,7 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
||||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||||
|
|
||||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_read(): port not open\n",
|
pmsg_error("port not open\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,16 +594,14 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
||||||
(LPTSTR) &lpMsgBuf,
|
(LPTSTR) &lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL );
|
NULL );
|
||||||
avrdude_message(MSG_INFO, "%s: ser_recv(): read error: %s\n",
|
pmsg_error("unable to read: %s\n", (char*) lpMsgBuf);
|
||||||
progname, (char*)lpMsgBuf);
|
|
||||||
LocalFree( lpMsgBuf );
|
LocalFree( lpMsgBuf );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* time out detected */
|
/* time out detected */
|
||||||
if (read == 0) {
|
if (read < buflen) {
|
||||||
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
|
pmsg_notice2("ser_recv(): programmer is not responding\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,28 +609,27 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
|
||||||
|
|
||||||
if (verbose > 3)
|
if (verbose > 3)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_TRACE, "%s: Recv: ", progname);
|
pmsg_trace("recv: ");
|
||||||
|
|
||||||
while (read) {
|
while (read) {
|
||||||
c = *p;
|
c = *p;
|
||||||
if (isprint(c)) {
|
if (isprint(c)) {
|
||||||
avrdude_message(MSG_TRACE, "%c ", c);
|
msg_trace("%c ", c);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
avrdude_message(MSG_TRACE, ". ");
|
msg_trace(". ");
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE, "[%02x] ", c);
|
msg_trace("[%02x] ", c);
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
read--;
|
read--;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_INFO, "\n");
|
msg_trace("\n");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int net_drain(union filedescriptor *fd, int display)
|
static int net_drain(const union filedescriptor *fd, int display) {
|
||||||
{
|
|
||||||
LPVOID lpMsgBuf;
|
LPVOID lpMsgBuf;
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
|
@ -660,16 +638,16 @@ static int net_drain(union filedescriptor *fd, int display)
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (fd->ifd < 0) {
|
if (fd->ifd < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): connection not open\n", progname);
|
pmsg_error("connection not open\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display) {
|
if (display) {
|
||||||
avrdude_message(MSG_INFO, "drain>");
|
msg_info("drain>");
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout.tv_sec = 0;
|
timeout.tv_sec = 0;
|
||||||
timeout.tv_usec = 250000;
|
timeout.tv_usec = serial_drain_timeout*1000L;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
|
@ -679,13 +657,13 @@ static int net_drain(union filedescriptor *fd, int display)
|
||||||
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
|
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &timeout);
|
||||||
if (nfds == 0) {
|
if (nfds == 0) {
|
||||||
if (display) {
|
if (display) {
|
||||||
avrdude_message(MSG_INFO, "<drain\n");
|
msg_info("<drain\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (nfds == -1) {
|
else if (nfds == -1) {
|
||||||
if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS) {
|
if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEINPROGRESS) {
|
||||||
avrdude_message(MSG_NOTICE, "%s: ser_drain(): programmer is not responding, reselecting\n", progname);
|
pmsg_notice("ser_drain(): programmer is not responding, reselecting\n");
|
||||||
goto reselect;
|
goto reselect;
|
||||||
} else {
|
} else {
|
||||||
FormatMessage(
|
FormatMessage(
|
||||||
|
@ -698,13 +676,13 @@ static int net_drain(union filedescriptor *fd, int display)
|
||||||
(LPTSTR)&lpMsgBuf,
|
(LPTSTR)&lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): select(): %s\n", progname, (char *)lpMsgBuf);
|
pmsg_error("select(): %s\n", (char *) lpMsgBuf);
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = recv(fd->ifd, &buf, 1, 0);
|
rc = recv(fd->ifd, (char *) &buf, 1, 0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
FormatMessage(
|
FormatMessage(
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
|
@ -716,21 +694,20 @@ static int net_drain(union filedescriptor *fd, int display)
|
||||||
(LPTSTR)&lpMsgBuf,
|
(LPTSTR)&lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n", progname, (char *)lpMsgBuf);
|
pmsg_error("unable to read: %s\n", (char *) lpMsgBuf);
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (display) {
|
if (display) {
|
||||||
avrdude_message(MSG_INFO, "%02x ", buf);
|
msg_info("%02x ", buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ser_drain(union filedescriptor *fd, int display)
|
static int ser_drain(const union filedescriptor *fd, int display) {
|
||||||
{
|
|
||||||
if (serial_over_ethernet) {
|
if (serial_over_ethernet) {
|
||||||
return net_drain(fd, display);
|
return net_drain(fd, display);
|
||||||
}
|
}
|
||||||
|
@ -743,15 +720,14 @@ static int ser_drain(union filedescriptor *fd, int display)
|
||||||
HANDLE hComPort=(HANDLE)fd->pfd;
|
HANDLE hComPort=(HANDLE)fd->pfd;
|
||||||
|
|
||||||
if (hComPort == INVALID_HANDLE_VALUE) {
|
if (hComPort == INVALID_HANDLE_VALUE) {
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): port not open\n",
|
pmsg_error("port not open\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_w32SetTimeOut(hComPort,250);
|
serial_w32SetTimeOut(hComPort, serial_drain_timeout);
|
||||||
|
|
||||||
if (display) {
|
if (display) {
|
||||||
avrdude_message(MSG_INFO, "drain>");
|
msg_info("drain>");
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
@ -768,17 +744,18 @@ static int ser_drain(union filedescriptor *fd, int display)
|
||||||
(LPTSTR) &lpMsgBuf,
|
(LPTSTR) &lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL );
|
NULL );
|
||||||
avrdude_message(MSG_INFO, "%s: ser_drain(): read error: %s\n",
|
pmsg_error("unable to read: %s\n", (char*) lpMsgBuf);
|
||||||
progname, (char*)lpMsgBuf);
|
|
||||||
LocalFree( lpMsgBuf );
|
LocalFree( lpMsgBuf );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (read) { // data avail
|
if (read) { // data avail
|
||||||
if (display) avrdude_message(MSG_INFO, "%02x ", buf[0]);
|
if (display)
|
||||||
|
msg_info("%02x ", buf[0]);
|
||||||
}
|
}
|
||||||
else { // no more data
|
else { // no more data
|
||||||
if (display) avrdude_message(MSG_INFO, "<drain\n");
|
if (display)
|
||||||
|
msg_info("<drain\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} // while
|
} // while
|
||||||
|
|
|
@ -26,7 +26,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char serbb_desc[];
|
extern const char serbb_desc[];
|
||||||
void serbb_initpgm (PROGRAMMER * pgm);
|
void serbb_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,10 +70,13 @@ static char *serpins[DB9PINS + 1] =
|
||||||
{ "NONE", "CD", "RXD", "TXD", "DTR", "GND", "DSR", "RTS", "CTS", "RI" };
|
{ "NONE", "CD", "RXD", "TXD", "DTR", "GND", "DSR", "RTS", "CTS", "RI" };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int serbb_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
static int serbb_setpin(const PROGRAMMER *pgm, int pinfunc, int value) {
|
||||||
{
|
|
||||||
unsigned int ctl;
|
unsigned int ctl;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
int pin = pgm->pinno[pinfunc]; // get its value
|
int pin = pgm->pinno[pinfunc]; // get its value
|
||||||
|
|
||||||
if (pin & PIN_INVERSE)
|
if (pin & PIN_INVERSE)
|
||||||
|
@ -86,39 +89,39 @@ static int serbb_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("%s to %d\n",serpins[pin],value);
|
msg_info("%s to %d\n", serpins[pin], value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch ( pin )
|
switch ( pin )
|
||||||
{
|
{
|
||||||
case 3: /* txd */
|
case 3: /* txd */
|
||||||
r = ioctl(pgm->fd.ifd, value ? TIOCSBRK : TIOCCBRK, 0);
|
r = ioctl(pgm->fd.ifd, value ? TIOCSBRK : TIOCCBRK, 0);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
perror("ioctl(\"TIOCxBRK\")");
|
pmsg_ext_error("ioctl(\"TIOCxBRK\"): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: /* dtr */
|
case 4: /* dtr */
|
||||||
case 7: /* rts */
|
case 7: /* rts */
|
||||||
r = ioctl(pgm->fd.ifd, TIOCMGET, &ctl);
|
r = ioctl(pgm->fd.ifd, TIOCMGET, &ctl);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
perror("ioctl(\"TIOCMGET\")");
|
pmsg_ext_error("ioctl(\"TIOCMGET\"): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ( value )
|
if (value)
|
||||||
ctl |= serregbits[pin];
|
ctl |= serregbits[pin];
|
||||||
else
|
else
|
||||||
ctl &= ~(serregbits[pin]);
|
ctl &= ~(serregbits[pin]);
|
||||||
r = ioctl(pgm->fd.ifd, TIOCMSET, &ctl);
|
r = ioctl(pgm->fd.ifd, TIOCMSET, &ctl);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
perror("ioctl(\"TIOCMSET\")");
|
pmsg_ext_error("ioctl(\"TIOCMSET\"): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* impossible */
|
default: /* impossible */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pgm->ispdelay > 1)
|
if (pgm->ispdelay > 1)
|
||||||
|
@ -127,11 +130,14 @@ static int serbb_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serbb_getpin(PROGRAMMER * pgm, int pinfunc)
|
static int serbb_getpin(const PROGRAMMER *pgm, int pinfunc) {
|
||||||
{
|
|
||||||
unsigned int ctl;
|
unsigned int ctl;
|
||||||
unsigned char invert;
|
unsigned char invert;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
int pin = pgm->pinno[pinfunc]; // get its value
|
int pin = pgm->pinno[pinfunc]; // get its value
|
||||||
|
|
||||||
if (pin & PIN_INVERSE)
|
if (pin & PIN_INVERSE)
|
||||||
|
@ -147,39 +153,41 @@ static int serbb_getpin(PROGRAMMER * pgm, int pinfunc)
|
||||||
switch ( pin )
|
switch ( pin )
|
||||||
{
|
{
|
||||||
case 2: /* rxd, currently not implemented, FIXME */
|
case 2: /* rxd, currently not implemented, FIXME */
|
||||||
return(-1);
|
return(-1);
|
||||||
|
|
||||||
case 1: /* cd */
|
case 1: /* cd */
|
||||||
case 6: /* dsr */
|
case 6: /* dsr */
|
||||||
case 8: /* cts */
|
case 8: /* cts */
|
||||||
case 9: /* ri */
|
case 9: /* ri */
|
||||||
r = ioctl(pgm->fd.ifd, TIOCMGET, &ctl);
|
r = ioctl(pgm->fd.ifd, TIOCMGET, &ctl);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
perror("ioctl(\"TIOCMGET\")");
|
pmsg_ext_error("ioctl(\"TIOCMGET\"): %s\n", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ( !invert )
|
if ( !invert )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("%s is %d\n",serpins[pin],(ctl & serregbits[pin]) ? 1 : 0 );
|
msg_info("%s is %d\n", serpins[pin], ctl & serregbits[pin]? 1: 0);
|
||||||
#endif
|
#endif
|
||||||
return ( (ctl & serregbits[pin]) ? 1 : 0 );
|
return ctl & serregbits[pin]? 1: 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
printf("%s is %d (~)\n",serpins[pin],(ctl & serregbits[pin]) ? 0 : 1 );
|
msg_info("%s is %d (~)\n", serpins[pin], ctl & serregbits[pin]? 0: 1);
|
||||||
#endif
|
#endif
|
||||||
return (( ctl & serregbits[pin]) ? 0 : 1 );
|
return ctl & serregbits[pin]? 0: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: /* impossible */
|
default: /* impossible */
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serbb_highpulsepin(PROGRAMMER * pgm, int pinfunc)
|
static int serbb_highpulsepin(const PROGRAMMER *pgm, int pinfunc) {
|
||||||
{
|
if (pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
int pin = pgm->pinno[pinfunc]; // replace pin name by its value
|
int pin = pgm->pinno[pinfunc]; // replace pin name by its value
|
||||||
|
|
||||||
if ( (pin & PIN_MASK) < 1 || (pin & PIN_MASK) > DB9PINS )
|
if ( (pin & PIN_MASK) < 1 || (pin & PIN_MASK) > DB9PINS )
|
||||||
|
@ -193,33 +201,27 @@ static int serbb_highpulsepin(PROGRAMMER * pgm, int pinfunc)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void serbb_display(PROGRAMMER *pgm, const char *p)
|
static void serbb_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
|
||||||
/* MAYBE */
|
/* MAYBE */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_enable(PROGRAMMER *pgm)
|
static void serbb_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_disable(PROGRAMMER *pgm)
|
static void serbb_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_powerup(PROGRAMMER *pgm)
|
static void serbb_powerup(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_powerdown(PROGRAMMER *pgm)
|
static void serbb_powerdown(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serbb_open(PROGRAMMER *pgm, char *port)
|
static int serbb_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
struct termios mode;
|
struct termios mode;
|
||||||
int flags;
|
int flags;
|
||||||
int r;
|
int r;
|
||||||
|
@ -232,14 +234,13 @@ static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||||
pgm->fd.ifd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
pgm->fd.ifd = open(port, O_RDWR | O_NOCTTY | O_NONBLOCK);
|
||||||
|
|
||||||
if (pgm->fd.ifd < 0) {
|
if (pgm->fd.ifd < 0) {
|
||||||
perror(port);
|
pmsg_ext_error("%s: %s\n", port, strerror(errno));
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
r = tcgetattr(pgm->fd.ifd, &mode);
|
r = tcgetattr(pgm->fd.ifd, &mode);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ", port);
|
pmsg_ext_error("%s, tcgetattr(): %s\n", port, strerror(errno));
|
||||||
perror("tcgetattr");
|
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
oldmode = mode;
|
oldmode = mode;
|
||||||
|
@ -252,8 +253,7 @@ static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||||
|
|
||||||
r = tcsetattr(pgm->fd.ifd, TCSANOW, &mode);
|
r = tcsetattr(pgm->fd.ifd, TCSANOW, &mode);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: ", port);
|
pmsg_ext_error("%s, tcsetattr(): %s", port, strerror(errno));
|
||||||
perror("tcsetattr");
|
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,23 +261,20 @@ static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||||
flags = fcntl(pgm->fd.ifd, F_GETFL, 0);
|
flags = fcntl(pgm->fd.ifd, F_GETFL, 0);
|
||||||
if (flags == -1)
|
if (flags == -1)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Can not get flags: %s\n",
|
pmsg_ext_error("cannot get flags: %s\n", strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
flags &= ~O_NONBLOCK;
|
flags &= ~O_NONBLOCK;
|
||||||
if (fcntl(pgm->fd.ifd, F_SETFL, flags) == -1)
|
if (fcntl(pgm->fd.ifd, F_SETFL, flags) == -1)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Can not clear nonblock flag: %s\n",
|
pmsg_ext_error("cannot clear nonblock flag: %s\n", strerror(errno));
|
||||||
progname, strerror(errno));
|
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_close(PROGRAMMER *pgm)
|
static void serbb_close(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
if (pgm->fd.ifd != -1)
|
if (pgm->fd.ifd != -1)
|
||||||
{
|
{
|
||||||
(void)tcsetattr(pgm->fd.ifd, TCSANOW, &oldmode);
|
(void)tcsetattr(pgm->fd.ifd, TCSANOW, &oldmode);
|
||||||
|
@ -289,8 +286,7 @@ static void serbb_close(PROGRAMMER *pgm)
|
||||||
|
|
||||||
const char serbb_desc[] = "Serial port bitbanging";
|
const char serbb_desc[] = "Serial port bitbanging";
|
||||||
|
|
||||||
void serbb_initpgm(PROGRAMMER *pgm)
|
void serbb_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "SERBB");
|
strcpy(pgm->type, "SERBB");
|
||||||
|
|
||||||
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
||||||
|
|
|
@ -61,8 +61,10 @@ static int dtr, rts, txd;
|
||||||
|
|
||||||
#define DB9PINS 9
|
#define DB9PINS 9
|
||||||
|
|
||||||
static int serbb_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
static int serbb_setpin(const PROGRAMMER *pgm, int pinfunc, int value) {
|
||||||
{
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
int pin = pgm->pinno[pinfunc];
|
int pin = pgm->pinno[pinfunc];
|
||||||
HANDLE hComPort = (HANDLE)pgm->fd.pfd;
|
HANDLE hComPort = (HANDLE)pgm->fd.pfd;
|
||||||
LPVOID lpMsgBuf;
|
LPVOID lpMsgBuf;
|
||||||
|
@ -98,12 +100,10 @@ static int serbb_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
avrdude_message(MSG_NOTICE, "%s: serbb_setpin(): unknown pin %d\n",
|
pmsg_notice("serbb_setpin(): unknown pin %d\n", pin + 1);
|
||||||
progname, pin + 1);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE2, "%s: serbb_setpin(): EscapeCommFunction(%s)\n",
|
pmsg_trace2("serbb_setpin(): EscapeCommFunction(%s)\n", name);
|
||||||
progname, name);
|
|
||||||
if (!EscapeCommFunction(hComPort, dwFunc))
|
if (!EscapeCommFunction(hComPort, dwFunc))
|
||||||
{
|
{
|
||||||
FormatMessage(
|
FormatMessage(
|
||||||
|
@ -116,8 +116,7 @@ static int serbb_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
||||||
(LPTSTR) &lpMsgBuf,
|
(LPTSTR) &lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: serbb_setpin(): SetCommState() failed: %s\n",
|
pmsg_error("SetCommState() failed: %s\n", (char *) lpMsgBuf);
|
||||||
progname, (char *)lpMsgBuf);
|
|
||||||
CloseHandle(hComPort);
|
CloseHandle(hComPort);
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -129,8 +128,10 @@ static int serbb_setpin(PROGRAMMER * pgm, int pinfunc, int value)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serbb_getpin(PROGRAMMER * pgm, int pinfunc)
|
static int serbb_getpin(const PROGRAMMER *pgm, int pinfunc) {
|
||||||
{
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
int pin = pgm->pinno[pinfunc];
|
int pin = pgm->pinno[pinfunc];
|
||||||
HANDLE hComPort = (HANDLE)pgm->fd.pfd;
|
HANDLE hComPort = (HANDLE)pgm->fd.pfd;
|
||||||
LPVOID lpMsgBuf;
|
LPVOID lpMsgBuf;
|
||||||
|
@ -162,14 +163,12 @@ static int serbb_getpin(PROGRAMMER * pgm, int pinfunc)
|
||||||
(LPTSTR) &lpMsgBuf,
|
(LPTSTR) &lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: serbb_setpin(): GetCommModemStatus() failed: %s\n",
|
pmsg_error("GetCommModemStatus() failed: %s\n", (char *) lpMsgBuf);
|
||||||
progname, (char *)lpMsgBuf);
|
|
||||||
CloseHandle(hComPort);
|
CloseHandle(hComPort);
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE2, "%s: serbb_getpin(): GetCommState() => 0x%lx\n",
|
pmsg_trace2("serbb_getpin(): GetCommState() => 0x%lx\n", modemstate);
|
||||||
progname, modemstate);
|
|
||||||
switch (pin)
|
switch (pin)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -204,21 +203,21 @@ static int serbb_getpin(PROGRAMMER * pgm, int pinfunc)
|
||||||
name = "RTS";
|
name = "RTS";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
avrdude_message(MSG_NOTICE, "%s: serbb_getpin(): unknown pin %d\n",
|
pmsg_notice("serbb_getpin(): unknown pin %d\n", pin + 1);
|
||||||
progname, pin + 1);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_TRACE2, "%s: serbb_getpin(): return cached state for %s\n",
|
pmsg_trace2("serbb_getpin(): return cached state for %s\n", name);
|
||||||
progname, name);
|
|
||||||
if (invert)
|
if (invert)
|
||||||
rv = !rv;
|
rv = !rv;
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serbb_highpulsepin(PROGRAMMER * pgm, int pinfunc)
|
static int serbb_highpulsepin(const PROGRAMMER *pgm, int pinfunc) {
|
||||||
{
|
if(pinfunc < 0 || pinfunc >= N_PINS)
|
||||||
int pin = pgm->pinno[pinfunc];
|
return -1;
|
||||||
|
|
||||||
|
int pin = pgm->pinno[pinfunc];
|
||||||
if ( (pin & PIN_MASK) < 1 || (pin & PIN_MASK) > DB9PINS )
|
if ( (pin & PIN_MASK) < 1 || (pin & PIN_MASK) > DB9PINS )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -229,33 +228,27 @@ static int serbb_highpulsepin(PROGRAMMER * pgm, int pinfunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void serbb_display(PROGRAMMER *pgm, const char *p)
|
static void serbb_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
|
||||||
/* MAYBE */
|
/* MAYBE */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_enable(PROGRAMMER *pgm)
|
static void serbb_enable(PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_disable(PROGRAMMER *pgm)
|
static void serbb_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_powerup(PROGRAMMER *pgm)
|
static void serbb_powerup(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_powerdown(PROGRAMMER *pgm)
|
static void serbb_powerdown(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* nothing */
|
/* nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serbb_open(PROGRAMMER *pgm, char *port)
|
static int serbb_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
DCB dcb;
|
DCB dcb;
|
||||||
LPVOID lpMsgBuf;
|
LPVOID lpMsgBuf;
|
||||||
HANDLE hComPort = INVALID_HANDLE_VALUE;
|
HANDLE hComPort = INVALID_HANDLE_VALUE;
|
||||||
|
@ -277,8 +270,7 @@ static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||||
(LPTSTR) &lpMsgBuf,
|
(LPTSTR) &lpMsgBuf,
|
||||||
0,
|
0,
|
||||||
NULL);
|
NULL);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't open device \"%s\": %s\n",
|
pmsg_error("cannot open port %s: %s\n", port, (char*) lpMsgBuf);
|
||||||
progname, port, (char*)lpMsgBuf);
|
|
||||||
LocalFree(lpMsgBuf);
|
LocalFree(lpMsgBuf);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -286,8 +278,7 @@ static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||||
if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE))
|
if (!SetupComm(hComPort, W32SERBUFSIZE, W32SERBUFSIZE))
|
||||||
{
|
{
|
||||||
CloseHandle(hComPort);
|
CloseHandle(hComPort);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't set buffers for \"%s\"\n",
|
pmsg_error("cannot set buffers for %s\n", port);
|
||||||
progname, port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,12 +296,10 @@ static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||||
if (!SetCommState(hComPort, &dcb))
|
if (!SetCommState(hComPort, &dcb))
|
||||||
{
|
{
|
||||||
CloseHandle(hComPort);
|
CloseHandle(hComPort);
|
||||||
avrdude_message(MSG_INFO, "%s: ser_open(): can't set com-state for \"%s\"\n",
|
pmsg_error("cannot set com-state for %s\n", port);
|
||||||
progname, port);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_DEBUG, "%s: ser_open(): opened comm port \"%s\", handle 0x%zx\n",
|
pmsg_debug("ser_open(): opened comm port %s, handle 0x%zx\n", port, (INT_PTR) hComPort);
|
||||||
progname, port, (INT_PTR)hComPort);
|
|
||||||
|
|
||||||
pgm->fd.pfd = (void *)hComPort;
|
pgm->fd.pfd = (void *)hComPort;
|
||||||
|
|
||||||
|
@ -319,24 +308,21 @@ static int serbb_open(PROGRAMMER *pgm, char *port)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serbb_close(PROGRAMMER *pgm)
|
static void serbb_close(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
HANDLE hComPort=(HANDLE)pgm->fd.pfd;
|
HANDLE hComPort=(HANDLE)pgm->fd.pfd;
|
||||||
if (hComPort != INVALID_HANDLE_VALUE)
|
if (hComPort != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
pgm->setpin(pgm, PIN_AVR_RESET, 1);
|
pgm->setpin(pgm, PIN_AVR_RESET, 1);
|
||||||
CloseHandle (hComPort);
|
CloseHandle (hComPort);
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_DEBUG, "%s: ser_close(): closed comm port handle 0x%zx\n",
|
pmsg_debug("ser_close(): closed comm port handle 0x%zx\n", (INT_PTR) hComPort);
|
||||||
progname, (INT_PTR)hComPort);
|
|
||||||
|
|
||||||
hComPort = INVALID_HANDLE_VALUE;
|
hComPort = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char serbb_desc[] = "Serial port bitbanging";
|
const char serbb_desc[] = "Serial port bitbanging";
|
||||||
|
|
||||||
void serbb_initpgm(PROGRAMMER *pgm)
|
void serbb_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "SERBB");
|
strcpy(pgm->type, "SERBB");
|
||||||
|
|
||||||
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
|
||||||
|
|
278
src/serialupdi.c
278
src/serialupdi.c
|
@ -43,15 +43,13 @@
|
||||||
#include "updi_nvm.h"
|
#include "updi_nvm.h"
|
||||||
#include "updi_constants.h"
|
#include "updi_constants.h"
|
||||||
|
|
||||||
static int serialupdi_enter_progmode(PROGRAMMER * pgm);
|
static int serialupdi_enter_progmode(const PROGRAMMER *pgm);
|
||||||
static int serialupdi_leave_progmode(PROGRAMMER * pgm);
|
static int serialupdi_leave_progmode(const PROGRAMMER *pgm);
|
||||||
|
|
||||||
static void serialupdi_setup(PROGRAMMER * pgm)
|
static void serialupdi_setup(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
if ((pgm->cookie = malloc(sizeof(updi_state))) == 0) {
|
if ((pgm->cookie = malloc(sizeof(updi_state))) == 0) {
|
||||||
avrdude_message(MSG_INFO,
|
pmsg_error("out of memory allocating private data\n");
|
||||||
"%s: serialupdi_setup(): Out of memory allocating private data\n",
|
|
||||||
progname);
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
memset(pgm->cookie, 0, sizeof(updi_state));
|
memset(pgm->cookie, 0, sizeof(updi_state));
|
||||||
|
@ -64,8 +62,7 @@ static void serialupdi_teardown(PROGRAMMER * pgm)
|
||||||
free(pgm->cookie);
|
free(pgm->cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_open(PROGRAMMER * pgm, char * port)
|
static int serialupdi_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
strcpy(pgm->port, port);
|
strcpy(pgm->port, port);
|
||||||
return updi_link_open(pgm);
|
return updi_link_open(pgm);
|
||||||
}
|
}
|
||||||
|
@ -75,8 +72,7 @@ typedef enum {
|
||||||
RELEASE_RESET
|
RELEASE_RESET
|
||||||
} reset_mode;
|
} reset_mode;
|
||||||
|
|
||||||
static int serialupdi_reset(PROGRAMMER * pgm, reset_mode mode)
|
static int serialupdi_reset(const PROGRAMMER *pgm, reset_mode mode) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
def reset(self, apply_reset):
|
def reset(self, apply_reset):
|
||||||
"""
|
"""
|
||||||
|
@ -93,36 +89,34 @@ static int serialupdi_reset(PROGRAMMER * pgm, reset_mode mode)
|
||||||
*/
|
*/
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case APPLY_RESET:
|
case APPLY_RESET:
|
||||||
avrdude_message(MSG_DEBUG, "%s: Sending reset request\n", progname);
|
pmsg_debug("sending reset request\n");
|
||||||
return updi_write_cs(pgm, UPDI_ASI_RESET_REQ, UPDI_RESET_REQ_VALUE);
|
return updi_write_cs(pgm, UPDI_ASI_RESET_REQ, UPDI_RESET_REQ_VALUE);
|
||||||
case RELEASE_RESET:
|
case RELEASE_RESET:
|
||||||
avrdude_message(MSG_DEBUG, "%s: Sending release reset request\n", progname);
|
pmsg_debug("sending release reset request\n");
|
||||||
return updi_write_cs(pgm, UPDI_ASI_RESET_REQ, 0x00);
|
return updi_write_cs(pgm, UPDI_ASI_RESET_REQ, 0x00);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_reset_connection(PROGRAMMER * pgm)
|
static int serialupdi_reset_connection(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
pmsg_error("apply reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
pmsg_error("release reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return updi_link_init(pgm);
|
return updi_link_init(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_decode_sib(PROGRAMMER * pgm, updi_sib_info * sib_info)
|
static int serialupdi_decode_sib(const PROGRAMMER *pgm, updi_sib_info *sib_info) {
|
||||||
{
|
|
||||||
char * str_ptr;
|
char * str_ptr;
|
||||||
|
|
||||||
sib_info->sib_string[SIB_INFO_STRING_LENGTH]=0;
|
sib_info->sib_string[SIB_INFO_STRING_LENGTH]=0;
|
||||||
avrdude_message(MSG_DEBUG, "%s: Received SIB: [%s]\n", progname, sib_info->sib_string);
|
pmsg_debug("received SIB: [%s]\n", sib_info->sib_string);
|
||||||
memset(sib_info->family_string, 0, SIB_INFO_FAMILY_LENGTH+1);
|
memset(sib_info->family_string, 0, SIB_INFO_FAMILY_LENGTH+1);
|
||||||
memset(sib_info->nvm_string, 0, SIB_INFO_NVM_LENGTH+1);
|
memset(sib_info->nvm_string, 0, SIB_INFO_NVM_LENGTH+1);
|
||||||
memset(sib_info->debug_string, 0, SIB_INFO_DEBUG_LENGTH+1);
|
memset(sib_info->debug_string, 0, SIB_INFO_DEBUG_LENGTH+1);
|
||||||
|
@ -138,41 +132,41 @@ static int serialupdi_decode_sib(PROGRAMMER * pgm, updi_sib_info * sib_info)
|
||||||
|
|
||||||
str_ptr = strstr(sib_info->nvm_string, ":");
|
str_ptr = strstr(sib_info->nvm_string, ":");
|
||||||
if (!str_ptr) {
|
if (!str_ptr) {
|
||||||
avrdude_message(MSG_INFO, "%s: Incorrect format of NVM string\n", progname);
|
pmsg_error("incorrect format of NVM string\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sib_info->nvm_version = *(str_ptr+1);
|
sib_info->nvm_version = *(str_ptr+1);
|
||||||
|
|
||||||
str_ptr = strstr(sib_info->debug_string, ":");
|
str_ptr = strstr(sib_info->debug_string, ":");
|
||||||
if (!str_ptr) {
|
if (!str_ptr) {
|
||||||
avrdude_message(MSG_INFO, "%s: Incorrect format of DEBUG string\n", progname);
|
pmsg_error("incorrect format of DEBUG string\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
sib_info->debug_version = *(str_ptr+1);
|
sib_info->debug_version = *(str_ptr+1);
|
||||||
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: Device family ID: %s\n", progname, sib_info->family_string);
|
pmsg_debug("Device family ID: %s\n", sib_info->family_string);
|
||||||
avrdude_message(MSG_DEBUG, "%s: NVM interface: %s\n", progname, sib_info->nvm_string);
|
pmsg_debug("NVM interface: %s\n", sib_info->nvm_string);
|
||||||
avrdude_message(MSG_DEBUG, "%s: Debug interface: %s\n", progname, sib_info->debug_string);
|
pmsg_debug("Debug interface: %s\n", sib_info->debug_string);
|
||||||
avrdude_message(MSG_DEBUG, "%s: PDI oscillator: %s\n", progname, sib_info->pdi_string);
|
pmsg_debug("PDI oscillator: %s\n", sib_info->pdi_string);
|
||||||
avrdude_message(MSG_DEBUG, "%s: Extra information: %s\n", progname, sib_info->extra_string);
|
pmsg_debug("Extra information: %s\n", sib_info->extra_string);
|
||||||
switch (sib_info->nvm_version) {
|
switch (sib_info->nvm_version) {
|
||||||
case '0':
|
case '0':
|
||||||
avrdude_message(MSG_INFO, "%s: NVM type 0: 16-bit, page oriented write\n", progname);
|
pmsg_notice("NVM type 0: 16-bit, page oriented write\n");
|
||||||
updi_set_nvm_mode(pgm, UPDI_NVM_MODE_V0);
|
updi_set_nvm_mode(pgm, UPDI_NVM_MODE_V0);
|
||||||
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT);
|
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT);
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
avrdude_message(MSG_INFO, "%s: NVM type 2: 24-bit, word oriented write\n", progname);
|
pmsg_notice("NVM type 2: 24-bit, word oriented write\n");
|
||||||
updi_set_nvm_mode(pgm, UPDI_NVM_MODE_V2);
|
updi_set_nvm_mode(pgm, UPDI_NVM_MODE_V2);
|
||||||
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_24BIT);
|
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_24BIT);
|
||||||
break;
|
break;
|
||||||
case '3':
|
case '3':
|
||||||
avrdude_message(MSG_INFO, "%s: NVM type 3: 16-bit, page oriented\n", progname);
|
pmsg_notice("NVM type 3: 16-bit, page oriented\n");
|
||||||
updi_set_nvm_mode(pgm, UPDI_NVM_MODE_V3);
|
updi_set_nvm_mode(pgm, UPDI_NVM_MODE_V3);
|
||||||
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT);
|
updi_set_datalink_mode(pgm, UPDI_LINK_MODE_16BIT);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
avrdude_message(MSG_INFO, "%s: Unsupported NVM type: %c, please update software\n", progname, sib_info->nvm_version);
|
pmsg_warning("unsupported NVM type: %c, please update software\n", sib_info->nvm_version);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -180,19 +174,19 @@ static int serialupdi_decode_sib(PROGRAMMER * pgm, updi_sib_info * sib_info)
|
||||||
|
|
||||||
static void serialupdi_close(PROGRAMMER * pgm)
|
static void serialupdi_close(PROGRAMMER * pgm)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: Leaving NVM programming mode\n", progname);
|
pmsg_notice("leaving NVM programming mode\n");
|
||||||
|
|
||||||
if (serialupdi_leave_progmode(pgm) < 0) {
|
if (serialupdi_leave_progmode(pgm) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Unable to leave NVM programming mode\n", progname);
|
pmsg_error("unable to leave NVM programming mode\n");
|
||||||
}
|
}
|
||||||
if (updi_get_rts_mode(pgm) != RTS_MODE_DEFAULT) {
|
if (updi_get_rts_mode(pgm) != RTS_MODE_DEFAULT) {
|
||||||
avrdude_message(MSG_INFO, "%s: Releasing DTR/RTS handshake lines\n", progname);
|
pmsg_warning("releasing DTR/RTS handshake lines\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
updi_link_close(pgm);
|
updi_link_close(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_wait_for_unlock(PROGRAMMER * pgm, unsigned int ms) {
|
static int serialupdi_wait_for_unlock(const PROGRAMMER *pgm, unsigned int ms) {
|
||||||
/*
|
/*
|
||||||
def wait_unlocked(self, timeout_ms):
|
def wait_unlocked(self, timeout_ms):
|
||||||
"""
|
"""
|
||||||
|
@ -213,21 +207,18 @@ static int serialupdi_wait_for_unlock(PROGRAMMER * pgm, unsigned int ms) {
|
||||||
*/
|
*/
|
||||||
unsigned long start_time;
|
unsigned long start_time;
|
||||||
unsigned long current_time;
|
unsigned long current_time;
|
||||||
struct timeval tv;
|
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
gettimeofday (&tv, NULL);
|
start_time = avr_ustimestamp();
|
||||||
start_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
|
||||||
do {
|
do {
|
||||||
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &status) >= 0) {
|
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &status) >= 0) {
|
||||||
if (!(status & (1 << UPDI_ASI_SYS_STATUS_LOCKSTATUS))) {
|
if (!(status & (1 << UPDI_ASI_SYS_STATUS_LOCKSTATUS))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gettimeofday (&tv, NULL);
|
current_time = avr_ustimestamp();
|
||||||
current_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
|
||||||
} while ((current_time - start_time) < (ms * 1000));
|
} while ((current_time - start_time) < (ms * 1000));
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: Timeout waiting for device to unlock\n", progname);
|
pmsg_error("timeout waiting for device to unlock\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,7 +227,7 @@ typedef enum {
|
||||||
WAIT_FOR_UROW_HIGH
|
WAIT_FOR_UROW_HIGH
|
||||||
} urow_wait_mode;
|
} urow_wait_mode;
|
||||||
|
|
||||||
static int serialupdi_wait_for_urow(PROGRAMMER * pgm, unsigned int ms, urow_wait_mode mode) {
|
static int serialupdi_wait_for_urow(const PROGRAMMER *pgm, unsigned int ms, urow_wait_mode mode) {
|
||||||
/*
|
/*
|
||||||
def wait_urow_prog(self, timeout_ms, wait_for_high):
|
def wait_urow_prog(self, timeout_ms, wait_for_high):
|
||||||
"""
|
"""
|
||||||
|
@ -262,10 +253,8 @@ static int serialupdi_wait_for_urow(PROGRAMMER * pgm, unsigned int ms, urow_wait
|
||||||
*/
|
*/
|
||||||
unsigned long start_time;
|
unsigned long start_time;
|
||||||
unsigned long current_time;
|
unsigned long current_time;
|
||||||
struct timeval tv;
|
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
gettimeofday (&tv, NULL);
|
start_time = avr_ustimestamp();
|
||||||
start_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
|
||||||
do {
|
do {
|
||||||
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &status) >= 0) {
|
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &status) >= 0) {
|
||||||
if (mode == WAIT_FOR_UROW_HIGH) {
|
if (mode == WAIT_FOR_UROW_HIGH) {
|
||||||
|
@ -278,16 +267,14 @@ static int serialupdi_wait_for_urow(PROGRAMMER * pgm, unsigned int ms, urow_wait
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gettimeofday (&tv, NULL);
|
current_time = avr_ustimestamp();
|
||||||
current_time = (tv.tv_sec * 1000000) + tv.tv_usec;
|
|
||||||
} while ((current_time - start_time) < (ms * 1000));
|
} while ((current_time - start_time) < (ms * 1000));
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: Timeout waiting for device to complete UROW WRITE\n", progname);
|
pmsg_error("timeout waiting for device to complete UROW WRITE\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_in_prog_mode(PROGRAMMER * pgm, uint8_t * in_prog_mode)
|
static int serialupdi_in_prog_mode(const PROGRAMMER *pgm, uint8_t *in_prog_mode) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
def in_prog_mode(self):
|
def in_prog_mode(self):
|
||||||
"""
|
"""
|
||||||
|
@ -303,7 +290,7 @@ static int serialupdi_in_prog_mode(PROGRAMMER * pgm, uint8_t * in_prog_mode)
|
||||||
rc = updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value);
|
rc = updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value);
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Read CS operation failed\n", progname);
|
pmsg_error("read CS operation failed\n");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,8 +302,7 @@ static int serialupdi_in_prog_mode(PROGRAMMER * pgm, uint8_t * in_prog_mode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_enter_progmode(PROGRAMMER * pgm)
|
static int serialupdi_enter_progmode(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
def enter_progmode(self):
|
def enter_progmode(self):
|
||||||
"""
|
"""
|
||||||
|
@ -360,63 +346,62 @@ def enter_progmode(self):
|
||||||
uint8_t key_status;
|
uint8_t key_status;
|
||||||
|
|
||||||
if (serialupdi_in_prog_mode(pgm, &in_prog_mode) < 0) {
|
if (serialupdi_in_prog_mode(pgm, &in_prog_mode) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Checking UPDI NVM prog mode failed\n", progname);
|
pmsg_error("checking UPDI NVM prog mode failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (in_prog_mode) {
|
if (in_prog_mode) {
|
||||||
avrdude_message(MSG_DEBUG, "%s: Already in prog mode\n", progname);
|
pmsg_debug("already in prog mode\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(buffer, UPDI_KEY_NVM, sizeof(buffer));
|
memcpy(buffer, UPDI_KEY_NVM, sizeof(buffer));
|
||||||
if (updi_write_key(pgm, buffer, UPDI_KEY_64, sizeof(buffer)) < 0) {
|
if (updi_write_key(pgm, buffer, UPDI_KEY_64, sizeof(buffer)) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Writing NVM KEY failed\n", progname);
|
pmsg_error("writing NVM KEY failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_read_cs(pgm, UPDI_ASI_KEY_STATUS, &key_status) < 0) {
|
if (updi_read_cs(pgm, UPDI_ASI_KEY_STATUS, &key_status) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Checking KEY status failed\n", progname);
|
pmsg_error("checking KEY status failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_DEBUG, "%s: Key status: 0x%02X\n", progname, key_status);
|
pmsg_debug("key status: 0x%02X\n", key_status);
|
||||||
|
|
||||||
if (!(key_status & (1 << UPDI_ASI_KEY_STATUS_NVMPROG))) {
|
if (!(key_status & (1 << UPDI_ASI_KEY_STATUS_NVMPROG))) {
|
||||||
avrdude_message(MSG_INFO, "%s: Key was not accepted\n", progname);
|
pmsg_error("key was not accepted\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
pmsg_error("apply reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
pmsg_error("release reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_wait_for_unlock(pgm, 100) < 0) {
|
if (serialupdi_wait_for_unlock(pgm, 100) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Failed to enter NVM programming mode: device is locked\n", progname);
|
pmsg_error("unable to enter NVM programming mode: device is locked\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_in_prog_mode(pgm, &in_prog_mode) < 0) {
|
if (serialupdi_in_prog_mode(pgm, &in_prog_mode) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Checking UPDI NVM prog mode failed\n", progname);
|
pmsg_error("checking UPDI NVM prog mode failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in_prog_mode) {
|
if (!in_prog_mode) {
|
||||||
avrdude_message(MSG_INFO, "%s: Failed to enter NVM programming mode\n", progname);
|
pmsg_error("unable to enter NVM programming mode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_DEBUG, "%s: Entered NVM programming mode\n", progname);
|
pmsg_debug("entered NVM programming mode\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_leave_progmode(PROGRAMMER * pgm)
|
static int serialupdi_leave_progmode(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
def leave_progmode(self):
|
def leave_progmode(self):
|
||||||
"""
|
"""
|
||||||
|
@ -429,19 +414,19 @@ static int serialupdi_leave_progmode(PROGRAMMER * pgm)
|
||||||
(1 << constants.UPDI_CTRLB_UPDIDIS_BIT) | (1 << constants.UPDI_CTRLB_CCDETDIS_BIT))
|
(1 << constants.UPDI_CTRLB_UPDIDIS_BIT) | (1 << constants.UPDI_CTRLB_CCDETDIS_BIT))
|
||||||
*/
|
*/
|
||||||
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
pmsg_error("apply reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
pmsg_error("release reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return updi_write_cs(pgm, UPDI_CS_CTRLB, (1 << UPDI_CTRLB_UPDIDIS_BIT) | (1 << UPDI_CTRLB_CCDETDIS_BIT));
|
return updi_write_cs(pgm, UPDI_CS_CTRLB, (1 << UPDI_CTRLB_UPDIDIS_BIT) | (1 << UPDI_CTRLB_CCDETDIS_BIT));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_write_userrow(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int serialupdi_write_userrow(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
|
@ -498,74 +483,74 @@ static int serialupdi_write_userrow(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
|
|
||||||
memcpy(buffer, UPDI_KEY_UROW, sizeof(buffer));
|
memcpy(buffer, UPDI_KEY_UROW, sizeof(buffer));
|
||||||
if (updi_write_key(pgm, buffer, UPDI_KEY_64, sizeof(buffer)) < 0) {
|
if (updi_write_key(pgm, buffer, UPDI_KEY_64, sizeof(buffer)) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Writing USERROW KEY failed\n", progname);
|
pmsg_error("writing USERROW KEY failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_read_cs(pgm, UPDI_ASI_KEY_STATUS, &key_status) < 0) {
|
if (updi_read_cs(pgm, UPDI_ASI_KEY_STATUS, &key_status) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Checking KEY status failed\n", progname);
|
pmsg_error("checking KEY status failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_DEBUG, "%s: Key status: 0x%02X\n", progname, key_status);
|
pmsg_debug("key status: 0x%02X\n", key_status);
|
||||||
|
|
||||||
if (!(key_status & (1 << UPDI_ASI_KEY_STATUS_UROWWRITE))) {
|
if (!(key_status & (1 << UPDI_ASI_KEY_STATUS_UROWWRITE))) {
|
||||||
avrdude_message(MSG_INFO, "%s: Key was not accepted\n", progname);
|
pmsg_error("key was not accepted\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
pmsg_error("apply reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
pmsg_error("release reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_wait_for_urow(pgm, 500, WAIT_FOR_UROW_HIGH) < 0) {
|
if (serialupdi_wait_for_urow(pgm, 500, WAIT_FOR_UROW_HIGH) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Failed to enter USERROW programming mode\n", progname);
|
pmsg_error("unable to enter USERROW programming mode\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_write_data(pgm, m->offset+addr, m->buf + addr, n_bytes) < 0) {
|
if (updi_write_data(pgm, m->offset+addr, m->buf + addr, n_bytes) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Writing USER ROW failed\n", progname);
|
pmsg_error("writing USER ROW failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_write_cs(pgm, UPDI_ASI_SYS_CTRLA, (1 << UPDI_ASI_SYS_CTRLA_UROW_FINAL) |
|
if (updi_write_cs(pgm, UPDI_ASI_SYS_CTRLA, (1 << UPDI_ASI_SYS_CTRLA_UROW_FINAL) |
|
||||||
(1 << UPDI_CTRLB_CCDETDIS_BIT)) < 0) {
|
(1 << UPDI_CTRLB_CCDETDIS_BIT)) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Failed trying to commit user row write\n", progname);
|
pmsg_error("unable to commit user row write\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_wait_for_urow(pgm, 500, WAIT_FOR_UROW_LOW) < 0) {
|
if (serialupdi_wait_for_urow(pgm, 500, WAIT_FOR_UROW_LOW) < 0) {
|
||||||
avrdude_message(MSG_DEBUG, "%s: Failed to exit USERROW programming mode\n", progname);
|
pmsg_debug("unable to exit USERROW programming mode\n");
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
pmsg_error("apply reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
pmsg_error("release reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_write_cs(pgm, UPDI_ASI_KEY_STATUS, (1 << UPDI_ASI_KEY_STATUS_UROWWRITE) |
|
if (updi_write_cs(pgm, UPDI_ASI_KEY_STATUS, (1 << UPDI_ASI_KEY_STATUS_UROWWRITE) |
|
||||||
(1 << UPDI_CTRLB_CCDETDIS_BIT)) < 0) {
|
(1 << UPDI_CTRLB_CCDETDIS_BIT)) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Failed trying to complete user row write\n", progname);
|
pmsg_error("unable to complete user row write\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
pmsg_error("apply reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
pmsg_error("release reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,19 +561,18 @@ static int serialupdi_write_userrow(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
static int serialupdi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
uint8_t reset_link_required=0;
|
uint8_t reset_link_required=0;
|
||||||
|
|
||||||
if (updi_link_init(pgm) < 0) {
|
if (updi_link_init(pgm) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: UPDI link initialization failed\n", progname);
|
pmsg_error("UPDI link initialization failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_INFO, "%s: UPDI link initialization OK\n", progname);
|
pmsg_notice2("UPDI link initialization OK\n");
|
||||||
|
|
||||||
if (updi_get_rts_mode(pgm) != RTS_MODE_DEFAULT) {
|
if (updi_get_rts_mode(pgm) != RTS_MODE_DEFAULT) {
|
||||||
avrdude_message(MSG_INFO, "%s: Forcing serial DTR/RTS handshake lines %s\n", progname, updi_get_rts_mode(pgm) == RTS_MODE_LOW ? "LOW" : "HIGH");
|
pmsg_warning("forcing serial DTR/RTS handshake lines %s\n", updi_get_rts_mode(pgm) == RTS_MODE_LOW ? "LOW" : "HIGH");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
|
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
|
||||||
|
@ -599,33 +583,33 @@ static int serialupdi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
|
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Read CS operation during initialization failed\n", progname);
|
pmsg_error("read CS operation during initialization failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (value & (1 << UPDI_ASI_SYS_STATUS_LOCKSTATUS)) {
|
if (value & (1 << UPDI_ASI_SYS_STATUS_LOCKSTATUS)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Device is locked\n", progname);
|
pmsg_notice("device is locked\n");
|
||||||
}
|
}
|
||||||
if (value & (1 << UPDI_ASI_SYS_STATUS_UROWPROG)) {
|
if (value & (1 << UPDI_ASI_SYS_STATUS_UROWPROG)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Device in USER ROW programming state, leaving programming mode\n", progname);
|
pmsg_notice("device in USER ROW programming state, leaving programming mode\n");
|
||||||
reset_link_required = 1;
|
reset_link_required = 1;
|
||||||
}
|
}
|
||||||
if (value & (1 << UPDI_ASI_SYS_STATUS_NVMPROG)) {
|
if (value & (1 << UPDI_ASI_SYS_STATUS_NVMPROG)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Device in NVM programming state, leaving programming mode\n", progname);
|
pmsg_notice("device in NVM programming state, leaving programming mode\n");
|
||||||
reset_link_required = 1;
|
reset_link_required = 1;
|
||||||
}
|
}
|
||||||
if (value & (1 << UPDI_ASI_SYS_STATUS_INSLEEP)) {
|
if (value & (1 << UPDI_ASI_SYS_STATUS_INSLEEP)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Device is in SLEEP mode\n", progname);
|
pmsg_notice("device is in SLEEP mode\n");
|
||||||
}
|
}
|
||||||
if (value & (1 << UPDI_ASI_SYS_STATUS_RSTSYS)) {
|
if (value & (1 << UPDI_ASI_SYS_STATUS_RSTSYS)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Device in reset status, trying to release it\n", progname);
|
pmsg_notice("device in reset status, trying to release it\n");
|
||||||
if (serialupdi_reset(pgm, RELEASE_RESET)<0) {
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (reset_link_required) {
|
if (reset_link_required) {
|
||||||
if (serialupdi_reset_connection(pgm) < 0) {
|
if (serialupdi_reset_connection(pgm) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: UPDI link reset failed\n", progname);
|
pmsg_error("UPDI link reset failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -635,72 +619,66 @@ static int serialupdi_initialize(PROGRAMMER * pgm, AVRPART * p)
|
||||||
if (updi_read_sib(pgm, sib_info->sib_string, 32) < 0) {
|
if (updi_read_sib(pgm, sib_info->sib_string, 32) < 0) {
|
||||||
/* this should never happen, let's try to reset connection and try again */
|
/* this should never happen, let's try to reset connection and try again */
|
||||||
if (serialupdi_reset_connection(pgm) < 0) {
|
if (serialupdi_reset_connection(pgm) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: SerialUPDI reset connection failed\n", progname);
|
pmsg_error("SerialUPDI reset connection failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (updi_read_sib(pgm, sib_info->sib_string, 32) < 0) {
|
if (updi_read_sib(pgm, sib_info->sib_string, 32) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Read SIB operation failed\n", progname);
|
pmsg_error("read SIB operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (serialupdi_decode_sib(pgm, sib_info) < 0) {
|
if (serialupdi_decode_sib(pgm, sib_info) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Decode SIB_INFO failed\n", progname);
|
pmsg_error("decode SIB_INFO failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_link_init(pgm) < 0) {
|
if (updi_link_init(pgm) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: UPDI link initialization failed\n", progname);
|
pmsg_error("UPDI link initialization failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: Entering NVM programming mode\n", progname);
|
pmsg_notice("entering NVM programming mode\n");
|
||||||
/* try, but ignore failure */
|
/* try, but ignore failure */
|
||||||
serialupdi_enter_progmode(pgm);
|
serialupdi_enter_progmode(pgm);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serialupdi_disable(PROGRAMMER * pgm)
|
static void serialupdi_disable(const PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serialupdi_enable(PROGRAMMER * pgm)
|
static void serialupdi_enable(PROGRAMMER * pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void serialupdi_display(PROGRAMMER * pgm, const char * p)
|
static void serialupdi_display(const PROGRAMMER *pgm, const char *p) {
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_cmd(PROGRAMMER * pgm, const unsigned char * cmd,
|
static int serialupdi_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
|
||||||
unsigned char * res)
|
unsigned char * res)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: error: cmd %s[%s] not implemented yet\n",
|
pmsg_error("cmd %s[%s] not implemented yet\n", cmd, res);
|
||||||
progname, cmd, res);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_program_enable(PROGRAMMER * pgm, AVRPART * p)
|
static int serialupdi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
pmsg_error("program enable not implemented yet\n");
|
||||||
avrdude_message(MSG_INFO, "%s: error: program enable not implemented yet\n",
|
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
static int serialupdi_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char * value)
|
unsigned long addr, unsigned char * value)
|
||||||
{
|
{
|
||||||
return updi_read_byte(pgm, mem->offset + addr, value);
|
return updi_read_byte(pgm, mem->offset + addr, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
static int serialupdi_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
|
||||||
unsigned long addr, unsigned char value)
|
unsigned long addr, unsigned char value)
|
||||||
{
|
{
|
||||||
if (strstr(mem->desc, "fuse") != 0) {
|
if (strstr(mem->desc, "fuse") != 0) {
|
||||||
|
@ -723,7 +701,7 @@ static int serialupdi_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int serialupdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int serialupdi_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
|
@ -736,7 +714,7 @@ static int serialupdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
rc = updi_read_data(pgm, m->offset + read_offset, m->buf + read_offset,
|
rc = updi_read_data(pgm, m->offset + read_offset, m->buf + read_offset,
|
||||||
remaining_bytes > m->readsize ? m->readsize : remaining_bytes);
|
remaining_bytes > m->readsize ? m->readsize : remaining_bytes);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Paged load operation failed\n", progname);
|
pmsg_error("paged load operation failed\n");
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
read_bytes+=rc;
|
read_bytes+=rc;
|
||||||
|
@ -750,7 +728,7 @@ static int serialupdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int serialupdi_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int page_size,
|
unsigned int page_size,
|
||||||
unsigned int addr, unsigned int n_bytes)
|
unsigned int addr, unsigned int n_bytes)
|
||||||
{
|
{
|
||||||
|
@ -771,15 +749,15 @@ static int serialupdi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
rc = serialupdi_write_userrow(pgm, p, m, page_size, write_offset,
|
rc = serialupdi_write_userrow(pgm, p, m, page_size, write_offset,
|
||||||
remaining_bytes > m->page_size ? m->page_size : remaining_bytes);
|
remaining_bytes > m->page_size ? m->page_size : remaining_bytes);
|
||||||
} else if (strcmp(m->desc, "fuses")==0) {
|
} else if (strcmp(m->desc, "fuses")==0) {
|
||||||
avrdude_message(MSG_DEBUG, "%s: Page write operation requested for fuses, falling back to byte-level write\n", progname);
|
pmsg_debug("page write operation requested for fuses, falling back to byte-level write\n");
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
avrdude_message(MSG_INFO, "%s: Invalid memory type: <%s:%d>, 0x%06X, %d (0x%04X)\n", progname, m->desc, page_size, addr, n_bytes, n_bytes);
|
pmsg_error("invalid memory type: <%s:%d>, 0x%06X, %d (0x%04X)\n", m->desc, page_size, addr, n_bytes, n_bytes);
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Paged write operation failed\n", progname);
|
pmsg_error("paged write operation failed\n");
|
||||||
return rc;
|
return rc;
|
||||||
} else {
|
} else {
|
||||||
write_bytes+=rc;
|
write_bytes+=rc;
|
||||||
|
@ -796,18 +774,17 @@ static int serialupdi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
||||||
} else if (strcmp(m->desc, "userrow")==0) {
|
} else if (strcmp(m->desc, "userrow")==0) {
|
||||||
rc = serialupdi_write_userrow(pgm, p, m, page_size, addr, n_bytes);
|
rc = serialupdi_write_userrow(pgm, p, m, page_size, addr, n_bytes);
|
||||||
} else if (strcmp(m->desc, "fuses")==0) {
|
} else if (strcmp(m->desc, "fuses")==0) {
|
||||||
avrdude_message(MSG_DEBUG, "%s: Page write operation requested for fuses, falling back to byte-level write\n", progname);
|
pmsg_debug("page write operation requested for fuses, falling back to byte-level write\n");
|
||||||
rc = -1;
|
rc = -1;
|
||||||
} else {
|
} else {
|
||||||
avrdude_message(MSG_INFO, "%s: Invalid memory type: <%s:%d>, 0x%06X, %d (0x%04X)\n", progname, m->desc, page_size, addr, n_bytes, n_bytes);
|
pmsg_error("invalid memory type: <%s:%d>, 0x%06X, %d (0x%04X)\n", m->desc, page_size, addr, n_bytes, n_bytes);
|
||||||
rc = -1;
|
rc = -1;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_unlock(PROGRAMMER * pgm, AVRPART * p)
|
static int serialupdi_unlock(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
/*
|
/*
|
||||||
def unlock(self):
|
def unlock(self):
|
||||||
"""
|
"""
|
||||||
|
@ -837,57 +814,56 @@ static int serialupdi_unlock(PROGRAMMER * pgm, AVRPART * p)
|
||||||
memcpy(buffer, UPDI_KEY_CHIPERASE, sizeof(buffer));
|
memcpy(buffer, UPDI_KEY_CHIPERASE, sizeof(buffer));
|
||||||
|
|
||||||
if (updi_write_key(pgm, buffer, UPDI_KEY_64, sizeof(buffer)) < 0) {
|
if (updi_write_key(pgm, buffer, UPDI_KEY_64, sizeof(buffer)) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Writing NVM KEY failed\n", progname);
|
pmsg_error("writing NVM KEY failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_read_cs(pgm, UPDI_ASI_KEY_STATUS, &key_status) < 0) {
|
if (updi_read_cs(pgm, UPDI_ASI_KEY_STATUS, &key_status) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Checking KEY status failed\n", progname);
|
pmsg_error("checking KEY status failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
avrdude_message(MSG_DEBUG, "%s: Key status: 0x%02X\n", progname, key_status);
|
pmsg_debug("key status: 0x%02X\n", key_status);
|
||||||
|
|
||||||
if (!(key_status & (1 << UPDI_ASI_KEY_STATUS_CHIPERASE))) {
|
if (!(key_status & (1 << UPDI_ASI_KEY_STATUS_CHIPERASE))) {
|
||||||
avrdude_message(MSG_INFO, "%s: Key not accepted\n", progname);
|
pmsg_error("key not accepted\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
if (serialupdi_reset(pgm, APPLY_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Apply reset operation failed\n", progname);
|
pmsg_error("apply reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
if (serialupdi_reset(pgm, RELEASE_RESET) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Release reset operation failed\n", progname);
|
pmsg_error("release reset operation failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (serialupdi_wait_for_unlock(pgm, 500) < 0) {
|
if (serialupdi_wait_for_unlock(pgm, 500) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Waiting for unlock failed\n", progname);
|
pmsg_error("waiting for unlock failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updi_link_init(pgm) < 0) {
|
if (updi_link_init(pgm) < 0) {
|
||||||
avrdude_message(MSG_INFO, "%s: UPDI link reinitialization failed\n", progname);
|
pmsg_error("UPDI link reinitialization failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return serialupdi_enter_progmode(pgm);
|
return serialupdi_enter_progmode(pgm);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
static int serialupdi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
|
||||||
{
|
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
||||||
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
|
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Read CS operation during chip erase failed\n", progname);
|
pmsg_error("read CS operation during chip erase failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value & (1 << UPDI_ASI_SYS_STATUS_LOCKSTATUS)) {
|
if (value & (1 << UPDI_ASI_SYS_STATUS_LOCKSTATUS)) {
|
||||||
avrdude_message(MSG_INFO, "%s: Device is locked\n", progname);
|
pmsg_warning("device is locked\n");
|
||||||
if (ovsigck) {
|
if (ovsigck) {
|
||||||
avrdude_message(MSG_INFO, "%s: Attempting device erase\n", progname);
|
pmsg_warning("attempting device erase\n");
|
||||||
return serialupdi_unlock(pgm, p);
|
return serialupdi_unlock(pgm, p);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -896,20 +872,18 @@ static int serialupdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
|
static int serialupdi_page_erase(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
|
||||||
unsigned int baseaddr)
|
unsigned int baseaddr)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: error: page erase not implemented yet\n",
|
return updi_nvm_erase_flash_page(pgm, p, m->offset + baseaddr);
|
||||||
progname);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_read_signature(PROGRAMMER * pgm, AVRPART *p, AVRMEM *m) {
|
static int serialupdi_read_signature(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m) {
|
||||||
|
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
||||||
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
|
if (updi_read_cs(pgm, UPDI_ASI_SYS_STATUS, &value)<0) {
|
||||||
avrdude_message(MSG_INFO, "%s: Read CS operation during signature read failed\n", progname);
|
pmsg_error("read CS operation during signature read failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -917,6 +891,7 @@ static int serialupdi_read_signature(PROGRAMMER * pgm, AVRPART *p, AVRMEM *m) {
|
||||||
m->buf[0]=0x00;
|
m->buf[0]=0x00;
|
||||||
m->buf[1]=0x00;
|
m->buf[1]=0x00;
|
||||||
m->buf[2]=0x00;
|
m->buf[2]=0x00;
|
||||||
|
return LIBAVRDUDE_SOFTFAIL;
|
||||||
} else {
|
} else {
|
||||||
updi_read_byte(pgm, m->offset + 0, m->buf);
|
updi_read_byte(pgm, m->offset + 0, m->buf);
|
||||||
updi_read_byte(pgm, m->offset + 1, m->buf+1);
|
updi_read_byte(pgm, m->offset + 1, m->buf+1);
|
||||||
|
@ -926,7 +901,7 @@ static int serialupdi_read_signature(PROGRAMMER * pgm, AVRPART *p, AVRMEM *m) {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_read_sib(PROGRAMMER * pgm, AVRPART *p, char *sib) {
|
static int serialupdi_read_sib(const PROGRAMMER *pgm, const AVRPART *p, char *sib) {
|
||||||
|
|
||||||
updi_sib_info * sib_info = updi_get_sib_info(pgm);
|
updi_sib_info * sib_info = updi_get_sib_info(pgm);
|
||||||
|
|
||||||
|
@ -935,8 +910,7 @@ static int serialupdi_read_sib(PROGRAMMER * pgm, AVRPART *p, char *sib) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int serialupdi_parseextparms(PROGRAMMER * pgm, LISTID extparms)
|
static int serialupdi_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
|
||||||
{
|
|
||||||
LNODEID ln;
|
LNODEID ln;
|
||||||
const char *extended_param;
|
const char *extended_param;
|
||||||
char rts_mode[5];
|
char rts_mode[5];
|
||||||
|
@ -951,22 +925,20 @@ static int serialupdi_parseextparms(PROGRAMMER * pgm, LISTID extparms)
|
||||||
} else if (strcasecmp(rts_mode, "high") == 0) {
|
} else if (strcasecmp(rts_mode, "high") == 0) {
|
||||||
updi_set_rts_mode(pgm, RTS_MODE_HIGH);
|
updi_set_rts_mode(pgm, RTS_MODE_HIGH);
|
||||||
} else {
|
} else {
|
||||||
avrdude_message(MSG_INFO, "%s: RTS/DTR mode must be LOW or HIGH\n", progname);
|
pmsg_error("RTS/DTR mode must be LOW or HIGH\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: serialupdi_parseextparms(): invalid extended parameter '%s'\n",
|
pmsg_error("invalid extended parameter '%s'\n", extended_param);
|
||||||
progname, extended_param);
|
|
||||||
rv = -1;
|
rv = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serialupdi_initpgm(PROGRAMMER * pgm)
|
void serialupdi_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "serialupdi");
|
strcpy(pgm->type, "serialupdi");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -34,7 +34,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char serialupdi_desc[];
|
extern const char serialupdi_desc[];
|
||||||
void serialupdi_initpgm (PROGRAMMER * pgm);
|
void serialupdi_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
513
src/stk500.c
513
src/stk500.c
File diff suppressed because it is too large
Load Diff
16
src/stk500.h
16
src/stk500.h
|
@ -26,16 +26,26 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const char stk500_desc[];
|
extern const char stk500_desc[];
|
||||||
void stk500_initpgm (PROGRAMMER * pgm);
|
void stk500_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
/* used by arduino.c to avoid duplicate code */
|
/* used by arduino.c to avoid duplicate code */
|
||||||
int stk500_getsync(PROGRAMMER * pgm);
|
int stk500_getsync(const PROGRAMMER *pgm);
|
||||||
int stk500_drain(PROGRAMMER * pgm, int display);
|
int stk500_drain(const PROGRAMMER *pgm, int display);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "xbee.h"
|
||||||
|
|
||||||
|
struct pdata {
|
||||||
|
unsigned char ext_addr_byte; // Record ext-addr byte set in the target device (if used)
|
||||||
|
int retry_attempts; // Number of connection attempts provided by the user
|
||||||
|
int xbeeResetPin; // Piggy back variable used by xbee programmmer
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PDATA(pgm) ((struct pdata *)(pgm->cookie))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,13 +38,11 @@
|
||||||
#include "stk500.h"
|
#include "stk500.h"
|
||||||
#include "stk500v2.h"
|
#include "stk500v2.h"
|
||||||
|
|
||||||
static int stk500generic_open(PROGRAMMER * pgm, char * port)
|
static int stk500generic_open(PROGRAMMER *pgm, const char *port) {
|
||||||
{
|
|
||||||
stk500_initpgm(pgm);
|
stk500_initpgm(pgm);
|
||||||
if (pgm->open(pgm, port) >= 0)
|
if (pgm->open(pgm, port) >= 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: successfully opened stk500v1 device -- please use -c stk500v1\n",
|
pmsg_info("successfully opened stk500v1 device -- please use -c stk500v1\n");
|
||||||
progname);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +51,11 @@ static int stk500generic_open(PROGRAMMER * pgm, char * port)
|
||||||
stk500v2_initpgm(pgm);
|
stk500v2_initpgm(pgm);
|
||||||
if (pgm->open(pgm, port) >= 0)
|
if (pgm->open(pgm, port) >= 0)
|
||||||
{
|
{
|
||||||
avrdude_message(MSG_INFO, "%s: successfully opened stk500v2 device -- please use -c stk500v2\n",
|
pmsg_info("successfully opened stk500v2 device -- please use -c stk500v2\n");
|
||||||
progname);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
avrdude_message(MSG_INFO, "%s: cannot open either stk500v1 or stk500v2 programmer\n",
|
pmsg_error("cannot open either stk500v1 or stk500v2 programmer\n");
|
||||||
progname);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,8 +76,7 @@ static void stk500generic_teardown(PROGRAMMER * pgm)
|
||||||
|
|
||||||
const char stk500generic_desc[] = "Atmel STK500, autodetect firmware version";
|
const char stk500generic_desc[] = "Atmel STK500, autodetect firmware version";
|
||||||
|
|
||||||
void stk500generic_initpgm(PROGRAMMER * pgm)
|
void stk500generic_initpgm(PROGRAMMER *pgm) {
|
||||||
{
|
|
||||||
strcpy(pgm->type, "STK500GENERIC");
|
strcpy(pgm->type, "STK500GENERIC");
|
||||||
|
|
||||||
pgm->open = stk500generic_open;
|
pgm->open = stk500generic_open;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
#define stk500generic_h__
|
#define stk500generic_h__
|
||||||
|
|
||||||
extern const char stk500generic_desc[];
|
extern const char stk500generic_desc[];
|
||||||
void stk500generic_initpgm (PROGRAMMER * pgm);
|
void stk500generic_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
1110
src/stk500v2.c
1110
src/stk500v2.c
File diff suppressed because it is too large
Load Diff
|
@ -37,22 +37,22 @@ extern const char stk500v2_jtag3_desc[];
|
||||||
extern const char stk600_desc[];
|
extern const char stk600_desc[];
|
||||||
extern const char stk600hvsp_desc[];
|
extern const char stk600hvsp_desc[];
|
||||||
extern const char stk600pp_desc[];
|
extern const char stk600pp_desc[];
|
||||||
void stk500v2_initpgm (PROGRAMMER * pgm);
|
void stk500v2_initpgm(PROGRAMMER *pgm);
|
||||||
void stk500hvsp_initpgm (PROGRAMMER * pgm);
|
void stk500hvsp_initpgm(PROGRAMMER *pgm);
|
||||||
void stk500pp_initpgm (PROGRAMMER * pgm);
|
void stk500pp_initpgm(PROGRAMMER *pgm);
|
||||||
void stk500v2_jtagmkII_initpgm(PROGRAMMER * pgm);
|
void stk500v2_jtagmkII_initpgm(PROGRAMMER *pgm);
|
||||||
void stk500v2_jtag3_initpgm(PROGRAMMER * pgm);
|
void stk500v2_jtag3_initpgm(PROGRAMMER *pgm);
|
||||||
void stk500v2_dragon_hvsp_initpgm(PROGRAMMER * pgm);
|
void stk500v2_dragon_hvsp_initpgm(PROGRAMMER *pgm);
|
||||||
void stk500v2_dragon_isp_initpgm(PROGRAMMER * pgm);
|
void stk500v2_dragon_isp_initpgm(PROGRAMMER *pgm);
|
||||||
void stk500v2_dragon_pp_initpgm(PROGRAMMER * pgm);
|
void stk500v2_dragon_pp_initpgm(PROGRAMMER *pgm);
|
||||||
void stk600_initpgm (PROGRAMMER * pgm);
|
void stk600_initpgm(PROGRAMMER *pgm);
|
||||||
void stk600hvsp_initpgm (PROGRAMMER * pgm);
|
void stk600hvsp_initpgm(PROGRAMMER *pgm);
|
||||||
void stk600pp_initpgm (PROGRAMMER * pgm);
|
void stk600pp_initpgm(PROGRAMMER *pgm);
|
||||||
|
|
||||||
void stk500v2_setup(PROGRAMMER * pgm);
|
void stk500v2_setup(PROGRAMMER * pgm);
|
||||||
void stk500v2_teardown(PROGRAMMER * pgm);
|
void stk500v2_teardown(PROGRAMMER * pgm);
|
||||||
int stk500v2_drain(PROGRAMMER * pgm, int display);
|
int stk500v2_drain(const PROGRAMMER *pgm, int display);
|
||||||
int stk500v2_getsync(PROGRAMMER * pgm);
|
int stk500v2_getsync(const PROGRAMMER *pgm);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,10 +138,13 @@
|
||||||
#define STATUS_CKSUM_ERROR 0xC1
|
#define STATUS_CKSUM_ERROR 0xC1
|
||||||
#define STATUS_CMD_UNKNOWN 0xC9
|
#define STATUS_CMD_UNKNOWN 0xC9
|
||||||
#define STATUS_CMD_ILLEGAL_PARAMETER 0xCA
|
#define STATUS_CMD_ILLEGAL_PARAMETER 0xCA
|
||||||
|
#define STATUS_PHY_ERROR 0xCB
|
||||||
|
#define STATUS_CLOCK_ERROR 0xCC
|
||||||
|
#define STATUS_BAUD_INVALID 0xCD
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
#define STATUS_ISP_READY 0x00
|
#define STATUS_ISP_READY 0x00
|
||||||
#define STATUS_CONN_FAIL_MOSI 0x01
|
#define STATUS_CONN_FAIL_SDO 0x01
|
||||||
#define STATUS_CONN_FAIL_RST 0x02
|
#define STATUS_CONN_FAIL_RST 0x02
|
||||||
#define STATUS_CONN_FAIL_SCK 0x04
|
#define STATUS_CONN_FAIL_SCK 0x04
|
||||||
#define STATUS_TGT_NOT_DETECTED 0x10
|
#define STATUS_TGT_NOT_DETECTED 0x10
|
||||||
|
@ -149,8 +152,8 @@
|
||||||
|
|
||||||
// hw_status
|
// hw_status
|
||||||
// Bits in status variable
|
// Bits in status variable
|
||||||
// Bit 0-3: Slave MCU
|
// Bit 0-3: Periphery MCU
|
||||||
// Bit 4-7: Master MCU
|
// Bit 4-7: Controller MCU
|
||||||
|
|
||||||
#define STATUS_AREF_ERROR 0
|
#define STATUS_AREF_ERROR 0
|
||||||
// Set to '1' if AREF is short circuited
|
// Set to '1' if AREF is short circuited
|
||||||
|
@ -191,10 +194,10 @@
|
||||||
#define PARAM_SOCKETCARD_ID 0xA5
|
#define PARAM_SOCKETCARD_ID 0xA5
|
||||||
#define PARAM_ROUTINGCARD_ID 0xA6
|
#define PARAM_ROUTINGCARD_ID 0xA6
|
||||||
#define PARAM_EXPCARD_ID 0xA7
|
#define PARAM_EXPCARD_ID 0xA7
|
||||||
#define PARAM_SW_MAJOR_SLAVE1 0xA8
|
#define PARAM_SW_MAJOR_PERIPHERY1 0xA8
|
||||||
#define PARAM_SW_MINOR_SLAVE1 0xA9
|
#define PARAM_SW_MINOR_PERIPHERY1 0xA9
|
||||||
#define PARAM_SW_MAJOR_SLAVE2 0xAA
|
#define PARAM_SW_MAJOR_PERIPHERY2 0xAA
|
||||||
#define PARAM_SW_MINOR_SLAVE2 0xAB
|
#define PARAM_SW_MINOR_PERIPHERY2 0xAB
|
||||||
#define PARAM_BOARD_ID_STATUS 0xAD
|
#define PARAM_BOARD_ID_STATUS 0xAD
|
||||||
#define PARAM_RESET 0xB4
|
#define PARAM_RESET 0xB4
|
||||||
|
|
||||||
|
@ -223,35 +226,6 @@
|
||||||
#define XPRG_MODE_JTAG 1
|
#define XPRG_MODE_JTAG 1
|
||||||
#define XPRG_MODE_TPI 2
|
#define XPRG_MODE_TPI 2
|
||||||
|
|
||||||
// XPROG commands
|
|
||||||
#define XPRG_CMD_ENTER_PROGMODE 0x01
|
|
||||||
#define XPRG_CMD_LEAVE_PROGMODE 0x02
|
|
||||||
#define XPRG_CMD_ERASE 0x03
|
|
||||||
#define XPRG_CMD_WRITE_MEM 0x04
|
|
||||||
#define XPRG_CMD_READ_MEM 0x05
|
|
||||||
#define XPRG_CMD_CRC 0x06
|
|
||||||
#define XPRG_CMD_SET_PARAM 0x07
|
|
||||||
|
|
||||||
// Memory types
|
|
||||||
#define XPRG_MEM_TYPE_APPL 1
|
|
||||||
#define XPRG_MEM_TYPE_BOOT 2
|
|
||||||
#define XPRG_MEM_TYPE_EEPROM 3
|
|
||||||
#define XPRG_MEM_TYPE_FUSE 4
|
|
||||||
#define XPRG_MEM_TYPE_LOCKBITS 5
|
|
||||||
#define XPRG_MEM_TYPE_USERSIG 6
|
|
||||||
#define XPRG_MEM_TYPE_FACTORY_CALIBRATION 7
|
|
||||||
|
|
||||||
// Erase types
|
|
||||||
#define XPRG_ERASE_CHIP 1
|
|
||||||
#define XPRG_ERASE_APP 2
|
|
||||||
#define XPRG_ERASE_BOOT 3
|
|
||||||
#define XPRG_ERASE_EEPROM 4
|
|
||||||
#define XPRG_ERASE_APP_PAGE 5
|
|
||||||
#define XPRG_ERASE_BOOT_PAGE 6
|
|
||||||
#define XPRG_ERASE_EEPROM_PAGE 7
|
|
||||||
#define XPRG_ERASE_USERSIG 8
|
|
||||||
#define XPRG_ERASE_CONFIG 9 // TPI only, prepare fuse write
|
|
||||||
|
|
||||||
// Write mode flags
|
// Write mode flags
|
||||||
#define XPRG_MEM_WRITE_ERASE 0
|
#define XPRG_MEM_WRITE_ERASE 0
|
||||||
#define XPRG_MEM_WRITE_WRITE 1
|
#define XPRG_MEM_WRITE_WRITE 1
|
||||||
|
@ -261,22 +235,6 @@
|
||||||
#define XPRG_CRC_BOOT 2
|
#define XPRG_CRC_BOOT 2
|
||||||
#define XPRG_CRC_FLASH 3
|
#define XPRG_CRC_FLASH 3
|
||||||
|
|
||||||
// Error codes
|
|
||||||
#define XPRG_ERR_OK 0
|
|
||||||
#define XPRG_ERR_FAILED 1
|
|
||||||
#define XPRG_ERR_COLLISION 2
|
|
||||||
#define XPRG_ERR_TIMEOUT 3
|
|
||||||
|
|
||||||
// XPROG parameters of different sizes
|
|
||||||
// 4-byte address
|
|
||||||
#define XPRG_PARAM_NVMBASE 0x01
|
|
||||||
// 2-byte page size
|
|
||||||
#define XPRG_PARAM_EEPPAGESIZE 0x02
|
|
||||||
// 1-byte, undocumented TPI param
|
|
||||||
#define XPRG_PARAM_TPI_3 0x03
|
|
||||||
// 1-byte, undocumented TPI param
|
|
||||||
#define XPRG_PARAM_TPI_4 0x04
|
|
||||||
|
|
||||||
// *****************[ STK answer constants ]***************************
|
// *****************[ STK answer constants ]***************************
|
||||||
|
|
||||||
#define ANSWER_CKSUM_ERROR 0xB0
|
#define ANSWER_CKSUM_ERROR 0xB0
|
||||||
|
@ -312,7 +270,7 @@ struct pdata
|
||||||
}
|
}
|
||||||
pgmtype;
|
pgmtype;
|
||||||
|
|
||||||
AVRPART *lastpart;
|
const AVRPART *lastpart;
|
||||||
|
|
||||||
/* Start address of Xmega boot area */
|
/* Start address of Xmega boot area */
|
||||||
unsigned long boot_start;
|
unsigned long boot_start;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue