2 Commits
main ... docs

Author SHA1 Message Date
Marius Greuel
21dd63c82f Update 2022-01-06 21:10:13 +01:00
Marius Greuel
b4a980e659 Add rst documentation 2022-01-06 18:26:07 +01:00
153 changed files with 28747 additions and 42638 deletions

View File

@@ -1,293 +0,0 @@
#
# build.yml - GitHub build action for AVRDUDE
# Copyright (C) 2021 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/>.
#
name: Build
on:
push:
branches-ignore:
- 'onlinedocs'
pull_request:
branches-ignore:
- 'onlinedocs'
workflow_call:
env:
BUILD_TYPE: RelWithDebInfo
jobs:
linux-x86_64:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install prerequisites
run: >-
sudo apt-get update
sudo apt-get install -y
build-essential
cmake
flex
bison
libelf-dev
libusb-dev
libusb-1.0-0-dev
libhidapi-dev
libftdi1-dev
libreadline-dev
texinfo
texlive
texi2html
- name: Configure
run: >-
cmake
-D BUILD_DOC=1
-D DEBUG_CMAKE=1
-D HAVE_LINUXGPIO=1
-D HAVE_LINUXSPI=1
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-B build
- name: Build
run: cmake --build build
- name: Archive build artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: build-linux-x86_64
path: |
build/
!**/*.d
!**/*.o
- name: Archive executables
uses: actions/upload-artifact@v3
with:
name: avrdude-linux-x86_64
path: |
build/src/avrdude
build/src/avrdude.conf
linux:
runs-on: ubuntu-latest
container: debian:11
strategy:
matrix:
include:
- { arch: i386, processor: i686, prefix: i686-linux-gnu, inc-lib: i386-linux-gnu }
- { 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 }
steps:
- uses: actions/checkout@v3
- name: Add architecture
run: |
dpkg --add-architecture ${{matrix.arch}}
apt-get update
- name: Install prerequisites
run: >-
apt-get update
apt-get install -y
git
cmake
flex
bison
crossbuild-essential-${{matrix.arch}}
libelf-dev:${{matrix.arch}}
libusb-dev:${{matrix.arch}}
libusb-1.0-0-dev:${{matrix.arch}}
libhidapi-dev:${{matrix.arch}}
libftdi1-dev:${{matrix.arch}}
libreadline-dev:${{matrix.arch}}
- name: Configure
run: >-
cmake
-D DEBUG_CMAKE=1
-D HAVE_LINUXGPIO=1
-D HAVE_LINUXSPI=1
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-D CMAKE_SYSTEM_NAME=Linux
-D CMAKE_SYSTEM_PROCESSOR=${{matrix.processor}}
-D CMAKE_C_COMPILER=${{matrix.prefix}}-gcc
-D CMAKE_FIND_ROOT_PATH=/usr/${{matrix.prefix}}
-D CMAKE_INCLUDE_PATH=/usr/include/${{matrix.inc-lib}}
-D CMAKE_LIBRARY_PATH=/usr/lib/${{matrix.inc-lib}}
-B build
- name: Build
run: cmake --build build
- name: Archive build artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: build-linux-${{matrix.processor}}
path: |
build/
!**/*.d
!**/*.o
- name: Archive executables
uses: actions/upload-artifact@v3
with:
name: avrdude-linux-${{matrix.processor}}
path: |
build/src/avrdude
build/src/avrdude.conf
macos-x86_64:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- name: Install prerequisites
run: >-
# brew update
brew install
cmake
flex
bison
libelf
libusb
hidapi
libftdi
readline
- name: Configure
run: >-
cmake
-D CMAKE_C_FLAGS=-I/usr/local/include
-D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar
-D DEBUG_CMAKE=1
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-B build
- name: Build
run: cmake --build build
- name: Archive build artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: build-macos-x86_64
path: |
build/
!**/*.d
!**/*.o
- name: Archive executables
uses: actions/upload-artifact@v3
with:
name: avrdude-macos-x86_64
path: |
build/src/avrdude
build/src/avrdude.conf
msvc:
runs-on: windows-latest
strategy:
matrix:
include:
- { arch: x86, platform: Win32 }
- { arch: x64, platform: x64 }
- { arch: arm64, platform: ARM64 }
steps:
- uses: actions/checkout@v3
- name: Install prerequisites
# As Chocolatey is notoriously unreliable, install winflexbison3 directly from GitHub.
# run: choco install winflexbison3
run: |
curl https://github.com/lexxmark/winflexbison/releases/download/v2.5.24/win_flex_bison-2.5.24.zip --location --output winflexbison.zip
unzip winflexbison.zip -d ${{github.workspace}}\winflexbison
echo "${{github.workspace}}\winflexbison" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Configure
run: >-
cmake
-A ${{matrix.platform}}
-D DEBUG_CMAKE=1
-D CMAKE_SYSTEM_VERSION=11
-D CMAKE_C_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 HAVE_LIBREADLINE=HAVE_LIBREADLINE-NOTFOUND
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-D USE_EXTERNAL_LIBS=1
-B build
- name: Build
run: cmake --build build --config ${{env.BUILD_TYPE}}
- name: Archive build artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: build-msvc-${{matrix.arch}}
path: |
build/
!**/_deps/
!**/*.obj
- name: Move executables
run: |
mv build/src/RelWithDebInfo/avrdude.exe build/src
mv build/src/RelWithDebInfo/avrdude.pdb build/src
- name: Archive executables
uses: actions/upload-artifact@v3
with:
name: avrdude-msvc-${{matrix.arch}}
path: |
build/src/avrdude.exe
build/src/avrdude.pdb
build/src/avrdude.conf
mingw:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
strategy:
matrix:
include:
- { sys: mingw32, env: i686 }
- { sys: mingw64, env: x86_64 }
steps:
- uses: actions/checkout@v3
- uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.sys}}
update: true
install: >-
base-devel
mingw-w64-${{matrix.env}}-gcc
mingw-w64-${{matrix.env}}-cmake
mingw-w64-${{matrix.env}}-libelf
mingw-w64-${{matrix.env}}-libusb
mingw-w64-${{matrix.env}}-libusb-compat-git
mingw-w64-${{matrix.env}}-hidapi
mingw-w64-${{matrix.env}}-libftdi
- name: Configure
run: >-
cmake
-G"MSYS Makefiles"
-D DEBUG_CMAKE=1
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-B build
- name: Build
run: cmake --build build
- name: Archive build artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: build-mingw-${{matrix.env}}
path: |
build/
- name: Archive executables
uses: actions/upload-artifact@v3
with:
name: avrdude-mingw-${{matrix.env}}
path: |
build/src/avrdude.exe
build/src/avrdude.conf

139
.github/workflows/build_cmake.yml vendored Normal file
View File

@@ -0,0 +1,139 @@
#
# build_cmake.yml - GitHub build action for AVRDUDE
# Copyright (C) 2021 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/>.
#
name: Build
on:
push:
pull_request:
workflow_call:
env:
BUILD_TYPE: RelWithDebInfo
jobs:
linux-x86_64:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./src
steps:
- uses: actions/checkout@v2
- name: Install prerequisites
run: >-
sudo apt-get install -y
build-essential
cmake
flex
bison
libelf-dev
libusb-dev
libftdi1-dev
libhidapi-dev
- name: Configure
run: >-
cmake
-D DEBUG_CMAKE=1
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-B ${{github.workspace}}/build
- name: Build
run: cmake --build ${{github.workspace}}/build
- name: Archive build artifacts
if: always()
uses: actions/upload-artifact@v2
with:
name: linux-x86_64
path: |
${{github.workspace}}/build/*
macos-x86_64:
runs-on: macos-latest
defaults:
run:
working-directory: ./src
steps:
- uses: actions/checkout@v2
- name: Install prerequisites
run: >-
brew install
cmake
flex
bison
libelf
libusb
libftdi
hidapi
- name: Configure
run: >-
cmake
-D CMAKE_C_FLAGS=-I/usr/local/include
-D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar
-D DEBUG_CMAKE=1
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-B ${{github.workspace}}/build
- name: Build
run: cmake --build ${{github.workspace}}/build
- name: Archive build artifacts
if: always()
uses: actions/upload-artifact@v2
with:
name: macos-x86_64
path: |
${{github.workspace}}/build/*
mingw:
runs-on: windows-latest
defaults:
run:
shell: msys2 {0}
working-directory: ./src
strategy:
matrix:
include:
- { sys: mingw32, env: i686 }
- { sys: mingw64, env: x86_64 }
steps:
- uses: actions/checkout@v2
- uses: msys2/setup-msys2@v2
with:
msystem: ${{matrix.sys}}
update: true
install: >-
base-devel
mingw-w64-${{matrix.env}}-gcc
mingw-w64-${{matrix.env}}-cmake
mingw-w64-${{matrix.env}}-libelf
mingw-w64-${{matrix.env}}-libusb
mingw-w64-${{matrix.env}}-libusb-compat-git
mingw-w64-${{matrix.env}}-hidapi
mingw-w64-${{matrix.env}}-libftdi
- name: Configure
run: >-
cmake
-G"MSYS Makefiles"
-D DEBUG_CMAKE=1
-D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
-B ../build
- name: Build
run: cmake --build ../build
- name: Archive build artifacts
if: always()
uses: actions/upload-artifact@v2
with:
name: mingw-${{matrix.env}}
path: |
${{github.workspace}}/build/*

View File

@@ -1,78 +0,0 @@
#
# deploy.yml - GitHub deploy action for AVRDUDE
# Copyright (C) 2021 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/>.
#
name: Deploy
on:
push:
tags:
- 'v*'
jobs:
build:
uses: avrdudes/avrdude/.github/workflows/build.yml@main
release:
needs: build
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
with:
tag_name: ${{github.ref}}
release_name: AVRDUDE ${{github.ref}}
body: "See **[Release Notes](https://github.com/avrdudes/avrdude/blob/main/NEWS)** for changes"
draft: false
prerelease: false
asset-msvc:
needs: release
runs-on: ubuntu-latest
strategy:
matrix:
include:
- { arch: x86 }
- { arch: x64 }
- { arch: arm64 }
steps:
- name: Download artifact
uses: actions/download-artifact@v2
with:
name: avrdude-msvc-${{matrix.arch}}
- name: Create release asset
run: >-
zip -j asset.zip
avrdude.exe
avrdude.pdb
avrdude.conf
- name: Upload release asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
with:
upload_url: ${{needs.release.outputs.upload_url}}
asset_path: ./asset.zip
asset_name: avrdude-${{github.ref_name}}-windows-${{matrix.arch}}.zip
asset_content_type: application/zip

2
.gitignore vendored
View File

@@ -14,7 +14,6 @@ INSTALL
Makefile.in
Makefile
ac_cfg.h.in
ac_cfg.h.in~
aclocal.m4
autom4te.cache
configure
@@ -39,7 +38,6 @@ libtool
ltmain.sh
ylwrap
tags
cscope.out
*.o
*.lo

15
AUTHORS
View File

@@ -2,14 +2,6 @@ AVRDUDE was written by:
Brian S. Dean <bsd@bdmicro.com>
AVRDUDE is currently maintained by:
Hans Eirik Bull
Stefan Rueger
Xiaofan Chen
Marius Greuel
Joerg Wunsch
Contributors:
Joerg Wunsch <j@uriah.heep.sax.de>
@@ -34,11 +26,6 @@ Contributors:
Jan Egil Ruud <janegil.ruud@microchip.com>
David Mosberger <davidm@egauge.net>
David Sainty
Marius Greuel <greuelm@mgtek.com>
Dawid Buchwald <dawid.buchwald@hotmail.com>
Hans Eirik Bull
Stefan Rueger
Xiaofan Chen
Contributors to code no longer present:
@@ -46,5 +33,5 @@ Contributors to code no longer present:
Paula Tomlinson for the loaddrv sources
Chris Liechti for loaddrv modifications
For minor contributions, please see the ChangeLog files / Git log.
For minor contributions, please see the ChangeLog files.

View File

@@ -1,396 +0,0 @@
#
# CMakeLists.txt - CMake project for AVRDUDE
# Copyright (C) 2021 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/>.
#
# Typical usage:
# cmake -B build
# cmake --build build
cmake_minimum_required(VERSION 3.14)
project(avrdude VERSION 7.1 LANGUAGES C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)
option(BUILD_DOC "Enable building documents" OFF)
option(HAVE_LINUXGPIO "Enable Linux sysfs GPIO support" OFF)
option(HAVE_LINUXSPI "Enable Linux SPI support" OFF)
option(HAVE_PARPORT "Enable parallel port support" OFF)
option(USE_EXTERNAL_LIBS "Use external libraries from AVRDUDE GitHub repositories" OFF)
option(USE_LIBUSBWIN32 "Prefer libusb-win32 over libusb" OFF)
option(DEBUG_CMAKE "Enable debugging output for this CMake project" OFF)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
if(WIN32)
# Prefer static libraries over DLLs on Windows
option(USE_STATIC_LIBS "Use static libraries" ON)
else()
option(USE_STATIC_LIBS "Use static libraries" OFF)
endif()
include(CheckIncludeFile)
include(CheckSymbolExists)
include(FetchContent)
include(FindPackageMessage)
include(GNUInstallDirs)
set(CONFIG_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}")
set(AVRDUDE_FULL_VERSION ${CMAKE_PROJECT_VERSION})
# =====================================
# Get Git commit info
# =====================================
# GIT_COMMIT_HASH -> hash of latest commit, e.g. b8b859f5
# GIT_COMMIT_DATE -> date of latest commit, e.g. 20201231
# GIT_COMMIT_YEAR -> year of latest commit, e.g. 2020
find_package(Git)
if(Git_FOUND)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --format=%h
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_COMMIT_HASH
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --format=%ad --date=format:%Y%m%d
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_COMMIT_DATE
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --format=%ad --date=format:%Y
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_COMMIT_YEAR
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --tags --format=%h
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_TAG_HASH
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
# If the commit is not tagged, include the date and commit hash in the full version string.
if(NOT GIT_COMMIT_HASH STREQUAL GIT_TAG_HASH)
set(AVRDUDE_FULL_VERSION "${CMAKE_PROJECT_VERSION}-${GIT_COMMIT_DATE} (${GIT_COMMIT_HASH})")
endif()
endif()
find_package(FLEX)
if(NOT FLEX_FOUND)
message(SEND_ERROR "This CMake project requires 'flex', which is not installed on your system." )
endif()
find_package(BISON QUIET)
if(BISON_FOUND)
find_package_message(BISON "Found BISON: ${BISON_EXECUTABLE} (found version \"${BISON_VERSION}\")" "[${BISON_EXECUTABLE}][${BISON_VERSION}]")
else()
find_program(YACC_EXECUTABLE NAMES yacc byacc DOC "path to the yacc executable")
mark_as_advanced(YACC_EXECUTABLE)
if(YACC_EXECUTABLE)
find_package_message(YACC "Found YACC: ${YACC_EXECUTABLE}" "[${YACC_EXECUTABLE}]")
else()
message(SEND_ERROR "This CMake project requires 'bison', 'yacc', or 'byacc', which is not installed on your system." )
endif()
endif()
# =====================================
# Detect installed libraries
# =====================================
if(USE_STATIC_LIBS)
set(PREFERRED_LIBELF libelf.a elf)
set(PREFERRED_LIBUSB libusb.a usb)
set(PREFERRED_LIBUSB_1_0 libusb-1.0.a usb-1.0)
set(PREFERRED_LIBHIDAPI libhidapi.a libhidapi-libusb.a libhidapi-hidraw.a hidapi hidapi-libusb hidapi-hidraw)
set(PREFERRED_LIBFTDI libftdi.a ftdi)
set(PREFERRED_LIBFTDI1 libftdi1.a ftdi1)
set(PREFERRED_LIBREADLINE libreadline.a)
else()
set(PREFERRED_LIBELF elf)
set(PREFERRED_LIBUSB usb)
set(PREFERRED_LIBUSB_1_0 usb-1.0)
set(PREFERRED_LIBHIDAPI hidapi hidapi-libusb hidapi-hidraw)
set(PREFERRED_LIBFTDI ftdi)
set(PREFERRED_LIBFTDI1 ftdi1)
set(PREFERRED_LIBREADLINE readline)
endif()
# -------------------------------------
# Find libelf
find_library(HAVE_LIBELF NAMES ${PREFERRED_LIBELF})
if(HAVE_LIBELF)
set(LIB_LIBELF ${HAVE_LIBELF})
check_include_file(libelf.h HAVE_LIBELF_H)
check_include_file(libelf/libelf.h HAVE_LIBELF_LIBELF_H)
endif()
# -------------------------------------
# Find libusb
find_library(HAVE_LIBUSB NAMES ${PREFERRED_LIBUSB})
if(HAVE_LIBUSB)
set(LIB_LIBUSB ${HAVE_LIBUSB})
endif()
find_library(HAVE_LIBUSB_1_0 NAMES ${PREFERRED_LIBUSB_1_0})
if(HAVE_LIBUSB_1_0)
set(LIB_LIBUSB_1_0 ${HAVE_LIBUSB_1_0})
endif()
# FreeBSD's library 'libusb' supports both the libusb-0.1 and libusb-1.0 API.
if (HAVE_LIBUSB AND CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set(HAVE_LIBUSB_1_0 ${HAVE_LIBUSB})
endif()
find_library(HAVE_LIBUSB_WIN32 NAMES libusb0.a usb0)
if(HAVE_LIBUSB OR HAVE_LIBUSB_1_0 OR HAVE_LIBUSB_WIN32)
check_include_file(usb.h HAVE_USB_H)
check_include_file(lusb0_usb.h HAVE_LUSB0_USB_H)
check_include_file(libusb.h HAVE_LIBUSB_H)
check_include_file(libusb-1.0/libusb.h HAVE_LIBUSB_1_0_LIBUSB_H)
if((USE_LIBUSBWIN32 OR NOT HAVE_LIBUSB) AND HAVE_LIBUSB_WIN32)
set(HAVE_LIBUSB ${HAVE_LIBUSB_WIN32})
set(LIB_LIBUSB ${HAVE_LIBUSB_WIN32})
unset(HAVE_USB_H CACHE)
elseif(NOT HAVE_USB_H)
find_path(LIBUSB_COMPAT_DIR libusb-compat/usb.h)
if(LIBUSB_COMPAT_DIR)
set(LIBUSB_COMPAT_DIR ${LIBUSB_COMPAT_DIR}/libusb-compat)
set(HAVE_USB_H 1)
else()
unset(LIBUSB_COMPAT_DIR CACHE)
endif()
endif()
endif()
# -------------------------------------
# Find libhidapi
find_library(HAVE_LIBHID NAMES hid)
if(HAVE_LIBHID)
set(LIB_LIBHID ${HAVE_LIBHID})
endif()
find_library(HAVE_LIBHIDAPI NAMES ${PREFERRED_LIBHIDAPI})
if(HAVE_LIBHIDAPI)
set(LIB_LIBHIDAPI ${HAVE_LIBHIDAPI})
check_include_file(hidapi/hidapi.h HAVE_HIDAPI_HIDAPI_H)
endif()
# -------------------------------------
# Find libftdi
find_library(HAVE_LIBFTDI NAMES ${PREFERRED_LIBFTDI})
if(HAVE_LIBFTDI)
set(LIB_LIBFTDI ${HAVE_LIBFTDI})
set(HAVE_LIBFTDI_TYPE_232H 1)
endif()
find_library(HAVE_LIBFTDI1 NAMES ${PREFERRED_LIBFTDI1})
if(HAVE_LIBFTDI1)
set(LIB_LIBFTDI1 ${HAVE_LIBFTDI1})
set(HAVE_LIBFTDI_TYPE_232H 1)
set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIBFTDI1} ${LIB_LIBUSB} ${LIB_LIBUSB_1_0})
check_symbol_exists(ftdi_tcioflush "libftdi1/ftdi.h" HAVE_FTDI_TCIOFLUSH)
endif()
# -------------------------------------
# Find libreadline
find_library(HAVE_LIBREADLINE NAMES ${PREFERRED_LIBREADLINE})
if(HAVE_LIBREADLINE)
set(LIB_LIBREADLINE ${HAVE_LIBREADLINE})
elseif(MSVC)
set(HAVE_LIBREADLINE 1)
endif()
# =====================================
# Use external libraries if requested
# =====================================
if(USE_EXTERNAL_LIBS)
FetchContent_Declare(libelf
GIT_REPOSITORY https://github.com/avrdudes/libelf.git
GIT_TAG e5a39bf19bd6598c42e09172be5a78ceec2a065c
)
FetchContent_Declare(libusb
GIT_REPOSITORY https://github.com/avrdudes/libusb.git
GIT_TAG 632bc25d04eff563cc00de29435b9a7ed6f4654c
)
FetchContent_Declare(libhidapi
GIT_REPOSITORY https://github.com/avrdudes/libhidapi.git
GIT_TAG d1307487973c857bc158e27ecc99644b2f5e68ea
)
FetchContent_Declare(libftdi
GIT_REPOSITORY https://github.com/avrdudes/libftdi.git
GIT_TAG f9fe6e96b97c3a08efd081632c1859cb83aa14e3
)
message(STATUS "Fetching external libraries, please wait...")
FetchContent_MakeAvailable(
libelf
libusb
libhidapi
libftdi
)
message(STATUS "Using external library 'libelf'")
set(LIB_LIBELF libelf)
set(HAVE_LIBELF 1)
set(HAVE_LIBELF_H 1)
message(STATUS "Using external library 'libusb'")
set(LIB_LIBUSB libusb)
set(HAVE_LIBUSB 1)
set(HAVE_LUSB0_USB_H 1)
message(STATUS "Using external library 'libhidapi'")
set(LIB_LIBHIDAPI libhidapi)
set(HAVE_LIBHIDAPI 1)
set(HAVE_HIDAPI_HIDAPI_H 1)
message(STATUS "Using external library 'libftdi'")
set(LIB_LIBFTDI libftdi)
set(HAVE_LIBFTDI 1)
set(HAVE_LIBFTDI_TYPE_232H 1)
endif()
add_subdirectory(src)
if(BUILD_DOC)
add_subdirectory(src/doc)
endif()
# =====================================
# Configuration
# =====================================
message(STATUS "Configuration summary:")
message(STATUS "----------------------")
if (DEBUG_CMAKE)
message(STATUS "CMAKE_HOST_SYSTEM: ${CMAKE_HOST_SYSTEM}")
message(STATUS "CMAKE_SYSTEM: ${CMAKE_SYSTEM}")
message(STATUS "CMAKE_FIND_ROOT_PATH: ${CMAKE_FIND_ROOT_PATH}")
message(STATUS "CMAKE_C_COMPILER: ${CMAKE_C_COMPILER}")
message(STATUS "CONFIG_DIR: ${CONFIG_DIR}")
message(STATUS "AVRDUDE_FULL_VERSION: ${AVRDUDE_FULL_VERSION}")
message(STATUS "USE_EXTERNAL_LIBS: ${USE_EXTERNAL_LIBS}")
message(STATUS "USE_LIBUSBWIN32: ${USE_LIBUSBWIN32}")
message(STATUS "HAVE_LIBELF: ${HAVE_LIBELF}")
message(STATUS "HAVE_LIBUSB: ${HAVE_LIBUSB}")
message(STATUS "HAVE_LIBUSB_1_0: ${HAVE_LIBUSB_1_0}")
message(STATUS "HAVE_LIBUSB_WIN32: ${HAVE_LIBUSB_WIN32}")
message(STATUS "HAVE_LIBHID: ${HAVE_LIBHID}")
message(STATUS "HAVE_LIBHIDAPI: ${HAVE_LIBHIDAPI}")
message(STATUS "HAVE_LIBFTDI: ${HAVE_LIBFTDI}")
message(STATUS "HAVE_LIBFTDI1: ${HAVE_LIBFTDI1}")
message(STATUS "HAVE_LIBREADLINE: ${HAVE_LIBREADLINE}")
message(STATUS "HAVE_LIBELF_H: ${HAVE_LIBELF_H}")
message(STATUS "HAVE_LIBELF_LIBELF_H: ${HAVE_LIBELF_LIBELF_H}")
message(STATUS "HAVE_USB_H: ${HAVE_USB_H}")
message(STATUS "HAVE_LUSB0_USB_H: ${HAVE_LUSB0_USB_H}")
message(STATUS "HAVE_LIBUSB_H: ${HAVE_LIBUSB_H}")
message(STATUS "HAVE_LIBUSB_1_0_LIBUSB_H: ${HAVE_LIBUSB_1_0_LIBUSB_H}")
message(STATUS "HAVE_HIDAPI_HIDAPI_H: ${HAVE_HIDAPI_HIDAPI_H}")
message(STATUS "LIBUSB_COMPAT_DIR: ${LIBUSB_COMPAT_DIR}")
message(STATUS "----------------------")
endif()
if(HAVE_LIBELF)
message(STATUS "DO HAVE libelf")
else()
message(STATUS "DON'T HAVE libelf")
endif()
if(HAVE_LIBUSB)
message(STATUS "DO HAVE libusb")
else()
message(STATUS "DON'T HAVE libusb")
endif()
if(HAVE_LIBUSB_1_0)
message(STATUS "DO HAVE libusb_1_0")
else()
message(STATUS "DON'T HAVE libusb_1_0")
endif()
if(HAVE_LIBHIDAPI)
message(STATUS "DO HAVE libhidapi")
else()
message(STATUS "DON'T HAVE libhidapi")
endif()
if(HAVE_LIBFTDI)
if(HAVE_LIBFTDI1)
message(STATUS "DO HAVE libftdi (but prefer to use libftdi1)")
else()
message(STATUS "DO HAVE libftdi")
endif()
else()
message(STATUS "DON'T HAVE libftdi")
endif()
if(HAVE_LIBFTDI1)
message(STATUS "DO HAVE libftdi1")
else()
message(STATUS "DON'T HAVE libftdi1")
endif()
if(HAVE_LIBREADLINE)
message(STATUS "DO HAVE libreadline")
else()
message(STATUS "DON'T HAVE libreadline")
endif()
if(BUILD_DOC)
message(STATUS "ENABLED doc")
else()
message(STATUS "DISABLED doc")
endif()
if(HAVE_PARPORT)
message(STATUS "ENABLED parport")
else()
message(STATUS "DISABLED parport")
endif()
if(HAVE_LINUXGPIO)
message(STATUS "ENABLED linuxgpio")
else()
message(STATUS "DISABLED linuxgpio")
endif()
if(HAVE_LINUXSPI)
message(STATUS "ENABLED linuxspi")
else()
message(STATUS "DISABLED linuxspi")
endif()
message(STATUS "----------------------")

View File

@@ -1,76 +0,0 @@
{
"configurations": [
{
"name": "x64-Debug",
"generator": "Ninja",
"configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"variables": [
{
"name": "USE_EXTERNAL_LIBS",
"value": "true",
"type": "BOOL"
}
]
},
{
"name": "x64-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x64_x64" ],
"variables": [
{
"name": "USE_EXTERNAL_LIBS",
"value": "true",
"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_LIBS",
"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": "USE_EXTERNAL_LIBS",
"value": "true",
"type": "BOOL"
}
]
}
]
}

449
NEWS
View File

@@ -5,366 +5,19 @@ Approximate change log for AVRDUDE by version.
(For detailed changes, see the version control system logs.)
----------------------------------------------------------------------
Changes since version 7.1:
Changes since version 6.4:
* 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:
* Major changes compared to the previous version:
- Completely revamped Windows support, including MSVC
- Started to add CMake (by now, parallel with autoconf/automake)
- New-architecture devices (AVR8X mega and tiny) can access all
fuses, and memory display shows meaningful alias names
- The "safemode" feature has been removed. The major class of
programmers it has been designed for (lowlevel bitbang
programmers on parallel or serial ports) virtually doesn't exist
anymore, and the fuse combination that was covered by it do not
match the fuses of modern AVR devices anyway.
- avrdude.conf is now being looked up in the location of the
executable file first, before considering the configured default
location; this eases a "portable use" where the entire suite is
not installed into its configured default location. (Basically
only relevant for unixoid systems; on Windows, this search order
has been used for many years already.)
* New devices supported:
- ATtiny828, ATtiny87, ATtiny167, ATtiny48, ATtiny102, ATtiny104
- LGT8F88P, LGT8F168P, LGT8F328P (fixed names of these parts)
- ATmeg164A, ATmega169A, ATmega169P, ATmega169PA, ATmega329A,
ATmega329PA, ATmega3290, ATmega3290A, ATmega3290PA, ATmega649A,
ATmega649P, ATmega6490A, ATmega6490P, ATmega165, ATmega165A,
ATmega165P, ATmega165PA, ATmega325A, ATmega325P, ATmega325PA,
ATmega645A, ATmega645P, ATmega3250A, ATmega3250P, ATmega3250PA,
ATmega6450A, ATmega6450P
- ATmega48A/48PA/88A/88PA/168A/168PA, ATmega164A/644A/644PA,
ATmega16A/32A/64A/128A, ATtiny13A, ATtiny24A/44A/84A,
ATtiny261A/461A/861A, ATtiny828R, ATtiny2313A, ATtiny1634R
- ATtiny3224, ATtiny3226 and ATtiny3227
- AVR16DD14/20/28/32, AVR32DD14/20/28/32 and AVR64DD14/20/28/32
- AVR8EA28/32, AVR16EA28/32/48, AVR32EA28/32/48 and AVR64EA28/32/64
- ATmega16U4
* New programmers supported:
- SerialUPDI (UPDI devices connected to serial port with few
passive parts)
- PicKit4 / SNAP (now also in ISP and PDI mode)
- Teensy bootloader (PR #802)
- Micronucleus bootloader (PR #786)
- ft232h (generic variant, PR #842)
- Kristech KT-LINK FT2232H interface with IO switching and voltage
buffers (PR #930)
* Issues fixed:
@@ -376,34 +29,6 @@ Changes in version 7.0:
- CMake doesn't correctly handle conditionals in avrdude.conf.in
#776
- CMake: Recognize more than just bison #785
- [bug #26007] ATTiny167 not supported #150
- [bug #47375] ATtiny102/104 descriptions missing in configuration
file #409
- No error message when connecting to a not-connected AVRISP mkII
programmer #813
- [bug #53180] missing programmer or bad -P option argument
doesn't result in error message #471
- ATmega328P reported as lgt8fx328p #812
- [bug #48004] Dead link for linuxgpio in avrdude description #419
- Segmentation fault when writing ATtiny104 fuse #823
- USBasp returns ERANGE for unknown error #848
- Compiler warnings #856
- Can't get serialupdi to work #874
- Rework HID support for Windows #881
- List of signing keys? #884
- Pickit4 UPDI is writing at offset 0x4000 into flash instead of 0x0000. #892
- SerialUPDI programmer can't write to usersig/userrow in terminal mode #889
- Signature read command for ATmega165* was wrong (no-id)
- Cannot use non-standard baud rates for uploading on MacOS #771
- Wrong values in avrdude.conf #897
- AVR-Eclipse plugin broken by missing -u commandline option #890
- Timeout passed to hid_read_timeout() is too short for instances
where the EDBG AVRISP 'Enter Programming Mode' command fails #900
- Terminal write mode doesn't support string input (yet) #913
- Terminal mode: memory fill with strings may cause Avrdude to crash. #922
- Some parts have wrong or missing ISP commands #915
- Incorrect -b conversion for linuxspi programmer #927
- ATtiny43U calibration memory size #921
* Pull requests:
@@ -425,80 +50,10 @@ Changes in version 7.0:
- buspirate: fix -Wtautological-constant-out-of-range-compare #796
- avrftdi: don't use the deprecated ftdi_usb_purge_buffers routine #792
- Ignore ctags index file #804
- term: fix memleakOnRealloc #806
- Add missing ATtiny targets to avrdude.conf #803
- Add support for Teensy bootloader #802
- Conffile clean up #801
- Fix typos all over the code #807
- Add MSVC builds and better WinUSB/FTDI support #798
- buspirate: fix invalidScanfArgType_int warning #808
- Ignore ac_cfg.h.in~ #810
- Notify open failure #814
- Print expected part #817
- pindefs: conform to the function declaration #818
- Add support for Micronucleus bootloader #786
- Remove ac_cfg.h from libavrdude.h #820
- CMake: enable dynamic-link library for libavrdude #826
- Fix for TPI fuse write (issue #823) #828
- Add missing ATmega__5 and ATmega__9 targets to avrdude.conf #809
- Add missing ATmega and ATtiny targets #832
- Added missing RTS/DTR management feature to serialupdi
programmer #811
- Add missing tinyAVR-2, AVR DD and AVR EA targets #836
- Add a new programmer ft232h #842
- Reduce verbosity when setting fuses and uploading programs #845
- jtagmkii: Reduce the number of sync attempts to 10 + print
number of attempts #844
- CMake: add initial support for installing lib and include files #829
- Add SPI support to USBtiny #816
- Add more memory sections to read from #815
- Add a build script for Unix-like systems #849
- Fix receive buffer implementation in ftdi_syncbb programmer #843
- CMake: split configuration in two files #852
- Set number of connection retry attempts for Arduino/STK500
programmer #854
- Fix libusb-1.0 error strings #850
- Assign proper type to msg[] in errstr() #857
- Fix Arduino retry attempts #855
- CMake: use CMAKE_CURRENT_BINARY_DIR to locate avrdude.conf #858
- Remove the "safemode" feature. #859
- Add support for reading from more memory sections #863
- Alias keyword #868
- Add fuse name aliases to avrdude.conf + tweak update.c #869
- Print JTAG3 clocks after configuration + string formatting #853
- Tweak programmer info formatting strings #872
- Remove libhid support in ser_avrdoper.c in favor of libhidapi #882
- Reduce jtag3 output verbosity #877
- Fix Curiosity Nano target voltage #878
- Smallest possible fix for PL2303HX #885
- Add missing USBtiny derived programmers #873
- Cleanup of POSIX serial init code #886
- Avrdude terminal write improvements #880
- Add userrow and usersig aliases #888
- For UPDI devices do not add offset when accessing flash. #895
- Support both userrow and usersig names #893
- Fix ugly terminal write bug #896
- Improve terminal read functionality #894
- Macos nonstandard baudrates #898
- Fix errors in Avrdude.conf #899
- Minor terminal write improvements #902
- Term docs #903
- Add progressbar for read and write command #912
- Add MacOS serial/parallel port note #908
- Add ATmega16U4 to avrdude.conf #910
- Mask out unused ATmega32U4 efuse bits #909
- Increased timeout passed to hid_read_timeout() #901
- Add terminal write string functionality #914
- Update documentation link to new URL #929
- Fix terminal write buffer overflow issue #924
- Fix linuxspi baud to clock period calculation #931
- Added KT-LINK FT2232H interface with IO switching and voltage buffers. #930
* Internals:
- Development moved to Github
- Addition of "alias" keyword to avrdude.conf.in syntax; used
for fuse name aliases right now
Version 6.4:
@@ -1239,7 +794,7 @@ Version 4.3.0:
* Added "Troubleshooting"-Appendix to the manual.
* Add ATmega8515 support.
Contributed by: Matthias Weißer <matthias@matwei.de>
Contributed by: Matthias Wei<EFBFBD>er <matthias@matwei.de>
* Add ATmega64 support.
Contributed by: Erik Christiansen <erik@dd.nec.com.au>

144
README.md
View File

@@ -1,7 +1,5 @@
# AVRDUDE
[![Build Status](https://github.com/avrdudes/avrdude/actions/workflows/build.yml/badge.svg)](https://github.com/avrdudes/avrdude/actions/workflows/build.yml)
AVRDUDE - AVR Downloader Uploader - is a program for downloading and uploading
the on-chip memories of Microchips [AVR microcontrollers](https://en.wikipedia.org/wiki/AVR_microcontrollers).
It can program the Flash and EEPROM, and where supported by the programming
@@ -16,15 +14,11 @@ with the help of [various contributors](./AUTHORS).
The latest version of AVRDUDE is always available here:\
<https://github.com/avrdudes/avrdude>
## Documentation
Documentation for current and previous releases is [on Github Pages](https://avrdudes.github.io/avrdude/).
## Getting AVRDUDE for Windows
To get AVRDUDE for Windows, install the latest version from the [Releases](https://github.com/avrdudes/avrdude/releases) page.
To get AVRDUDE for Windows, install the latest version from the [Releases](http://download.savannah.gnu.org/releases/avrdude/) page.
Alternatively, you may [build AVRDUDE](https://github.com/avrdudes/avrdude/wiki) yourself from source.
Alternatively, you may [build AVRDUDE](#building-avrdude-for-windows) yourself from source.
## Getting AVRDUDE for Linux
@@ -34,13 +28,13 @@ To install AVRDUDE for Linux, install the package `avrdude` by running the follo
sudo apt-get install avrdude
```
Alternatively, you may [build AVRDUDE](https://github.com/avrdudes/avrdude/wiki) yourself from source.
Alternatively, you may [build AVRDUDE](#building-avrdude-for-linux) yourself from source.
## Getting AVRDUDE for MacOS
On MacOS, AVRDUDE can be installed through Mac Ports.
Alternatively, you may [build AVRDUDE](https://github.com/avrdudes/avrdude/wiki) yourself from source.
Alternatively, you may [build AVRDUDE](#building-avrdude-for-macos) yourself from source.
## Using AVRDUDE
@@ -60,5 +54,133 @@ avrdude -c arduino -P COM1 -b 115200 -p atmega328p -D -U flash:w:objs/blink.hex:
```
There are many different programmers and options that may be required for the programming to succeed.
For more information, refer to the [AVRDUDE documentation](#todo).
## General build instructions
### Prerequisites
Depending on your requirements, the following prerequisites are
needed:
* libelf including header files (for directly reading ELF files)
* libusb 0.1 or 1.0 (or compatible), including header files
* libftdi or libftdi1 (for direct access to FTDI devices)
* libhidapi or libhid (for access to recent Atmel/Microchip dongles)
### Building
All source code is located in the `src/` subdirectory. Thus all
instructions are relative to that directory.
Source-code releases contain an up-to-date configure script that
can be run to generate the required Makefiles:
```console
cd src && ./configure && make && sudo make install
```
At the end of the configure script, a configuration summary is issued,
like this:
```console
Configuration summary:
----------------------
DO HAVE libelf
DO HAVE libusb
DO HAVE libusb_1_0
DO HAVE libftdi1
DON'T HAVE libftdi
DON'T HAVE libhid
DO HAVE libhidapi
DO HAVE pthread
DISABLED doc
DISABLED parport
DISABLED linuxgpio
DISABLED linuxspi
```
Make sure all the features you are interested in have been found.
Building the development source tree might possibly require to
re-generate the configure script using the autoconf/automake
tools. This can be done using the `bootstrap` script:
```console
cd src && ./bootstrap
```
## Building AVRDUDE for Windows
### Windows Prerequisites
TODO.
### Windows Build Instructions
TODO.
## Building AVRDUDE for Linux
### Linux Prerequisites
To build AVRDUDE for Linux, you need to install the following packages:
```console
sudo apt-get install build-essential git automake libtool flex bison libelf-dev libusb-dev libftdi1-dev libhidapi-dev
```
To build the documentation, you need to install the following packages:
```console
sudo apt-get install texlive texi2html
```
### Linux Build Instructions
To build AVRDUDE for Linux, run the following commands:
```console
git clone https://github.com/avrdudes/avrdude
cd avrdude
./bootstrap
./configure
make
```
To build the documentation for AVRDUDE, run the following commands:
```console
cd doc
make all
```
## Building AVRDUDE for MacOS
### Prerequisites
The following things are needed to build AVRDUDE on MacOS:
* a C compiler; either full XCode, or the XCode Command Line tools
* autoconf, automake, libtool, hidapi, libftdi1, libusb, libelf;
they can be installed e.g. from Mac Ports using
```console
port install autoconf automake \
libtool hidapi libftdi1 libusb libelf
```
### Compilation
Depending on the location of the prerequisites, the `CPPFLAGS` and
`LDFLAGS` variables need to be set accordingly. Mac Ports installs
everything under `/opt/local`, so use
```console
./configure CPPFLAGS=-I/opt/local/include LDFLAGS=-L/opt/local/lib
```
MacOS Brew requires
```console
./configure CPPFLAGS=-I/usr/local/include LDFLAGS=-L/usr/local/Cellar
```
For more information, refer to the [AVRDUDE documentation](https://avrdudes.github.io/avrdude/).

View File

@@ -1,92 +0,0 @@
#!/bin/sh
#
# Build script for Unix-like systems, using the CMake subsystem
#
# This script covers some common cases. It does *not* install any
# prerequisites though.
#
# For documentation of AVRDUDE's build system, please refer to the
# Wiki:
#
# https://github.com/avrdudes/avrdude/wiki
# Determine OS type
#
# So far, this script tries to handle three different Unix-like
# systems:
#
# Linux
# FreeBSD
# Darwin (aka. MacOS)
#
# On Linux, if the machine is ARM-based, LINUXSPI and LINUXGPIO are
# enabled.
# On MacOS, an attempt is made to find out whether Mac ports or brew
# are in place, and are assumed to have install the prerequisites.
ostype=$(uname | tr '[A-Z]' '[a-z]')
build_type=RelWithDebInfo
# 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=""
build_flags=""
case "${ostype}" in
linux)
# try to find out whether this is an Embedded Linux
# platform (e.g. Raspberry Pi)
machine=$(uname -m)
if expr "${machine}" : '^\(arm\|aarch\)' >/dev/null
then
extra_enable="${extra_enable} -D HAVE_LINUXGPIO=1 -D HAVE_LINUXSPI=1"
fi
;;
darwin)
# determine whether we are running using Mac Ports
# if not, assume Mac Brew
if [ -f /opt/local/bin/port ]
then
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/local/lib"
else
# Apple M1 (may be new version of homebrew also)
if [ -d /opt/homebrew ]
then
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/opt/homebrew/include -D CMAKE_EXE_LINKER_FLAGS=-L/opt/homebrew/Cellar"
else
build_flags="${build_flags} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/Cellar"
fi
fi
;;
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"
;;
esac
cmake ${build_flags} ${extra_enable} -D CMAKE_BUILD_TYPE=${build_type} -B build_${ostype} ||\
{ echo "CMake failed."; exit 1; }
cmake --build build_${ostype} ||\
{ echo "Build failed."; exit 1; }
cat <<EOF
Build succeeded.
Run
sudo cmake --build build_${ostype} --target install
to install.
EOF

2
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
build/
_build/

231
docs/1-Introduction.rst Normal file
View File

@@ -0,0 +1,231 @@
************
Introduction
************
.. index:: introduction
AVRDUDE - AVR Downloader Uploader - is a program for downloading and
uploading the on-chip memories of Atmel's AVR microcontrollers. It can
program the Flash and EEPROM, and where supported by the serial
programming protocol, it can program fuse and lock bits. AVRDUDE also
supplies a direct instruction mode allowing one to issue any programming
instruction to the AVR chip regardless of whether AVRDUDE implements
that specific feature of a particular chip.
AVRDUDE can be used effectively via the command line to read or write
all chip memory types (eeprom, flash, fuse bits, lock bits, signature
bytes) or via an interactive (terminal) mode. Using AVRDUDE from the
command line works well for programming the entire memory of the chip
from the contents of a file, while interactive mode is useful for
exploring memory contents, modifying individual bytes of eeprom,
programming fuse/lock bits, etc.
AVRDUDE supports the following basic programmer types: Atmel's STK500,
Atmel's AVRISP and AVRISP mkII devices,
Atmel's STK600,
Atmel's JTAG ICE (the original one, mkII, and 3, the latter two also in ISP mode), appnote
avr910, appnote avr109 (including the AVR Butterfly),
serial bit-bang adapters,
and the PPI (parallel port interface). PPI represents a class
of simple programmers where the programming lines are directly
connected to the PC parallel port. Several pin configurations exist
for several variations of the PPI programmers, and AVRDUDE can be
configured to work with them by either specifying the appropriate
programmer on the command line or by creating a new entry in its
configuration file. All that's usually required for a new entry is to
tell AVRDUDE which pins to use for each programming function.
A number of equally simple bit-bang programming adapters that connect
to a serial port are supported as well, among them the popular
Ponyprog serial adapter, and the DASA and DASA3 adapters that used to
be supported by uisp(1). Note that these adapters are meant to be
attached to a physical serial port. Connecting to a serial port
emulated on top of USB is likely to not work at all, or to work
abysmally slow.
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
any additional hardware - just connect them to the MOSI, MISO, RESET
and SCK pins on the AVR and use the linuxgpio programmer type. It bitbangs
the lines using the Linux sysfs GPIO interface. Of course, care should
be taken about voltage level compatibility. Also, although not strictly
required, it is strongly advisable to protect the GPIO pins from
overcurrent situations in some way. The simplest would be to just put
some resistors in series or better yet use a 3-state buffer driver like
the 74HC244. Have a look at http://kolev.info/avrdude-linuxgpio for a more
detailed tutorial about using this programmer type.
Under a Linux installation with direct access to the SPI bus and GPIO
pins, such as would be found on a Raspberry Pi, the ``linuxspi``
programmer type can be used to directly connect to and program a chip
using the built in interfaces on the computer. The requirements to use
this type are that an SPI interface is exposed along with one GPIO
pin. The GPIO serves as the reset output since the Linux SPI drivers
do not hold slave select down when a transfer is not occuring and thus
it cannot be used as the reset pin. A readily available level
translator should be used between the SPI bus/reset GPIO and the chip
to avoid potentially damaging the computer's SPI controller in the
event that the chip is running at 5V and the SPI runs at 3.3V. The
GPIO chosen for reset can be configured in the avrdude configuration
file using the `reset` entry under the linuxspi programmer, or
directly in the port specification. An external pull-up resistor
should be connected between the AVR's reset pin and Vcc. If Vcc is not
the same as the SPI voltage, this should be done on the AVR side of
the level translator to protect the hardware from damage.
On a Raspberry Pi, header J8 provides access to the SPI and GPIO
lines.
Typically, pins 19, 21, and 23 are SPI MOSI, MISO, and SCK, while
pins 24 and 26 would serve as CE outputs. So, close to these pins
is pin 22 as GPIO25 which can be used as /RESET, and pin 25 can
be used as GND.
A typical programming cable would then look like:
======== ========= ==================
J8 pin ISP pin Name
======== ========= ==================
21 1 MISO
- 2 Vcc - leave open
23 3 SCK
19 4 MOSI
22 5 /RESET
25 6 GND
======== ========= ==================
(Mind the 3.3 V voltage level of the Raspberry Pi!)
The `-P `portname`` option defaults to
``/dev/spidev0.0:/dev/gpiochip0`` for this programmer.
The STK500, JTAG ICE, avr910, and avr109/butterfly use the serial port to communicate with the PC.
The STK600, JTAG ICE mkII/3, AVRISP mkII, USBasp, avrftdi (and derivatives), and USBtinyISP
programmers communicate through the USB, using `libusb` as a
platform abstraction layer.
The avrftdi adds support for the FT2232C/D, FT2232H, and FT4232H devices. These all use
the MPSSE mode, which has a specific pin mapping. Bit 1 (the lsb of the byte in the config
file) is SCK. Bit 2 is MOSI, and Bit 3 is MISO. Bit 4 usually reset. The 2232C/D parts
are only supported on interface A, but the H parts can be either A or B (specified by the
usbdev config parameter).
The STK500, STK600, JTAG ICE, and avr910 contain on-board logic to control the programming of the target
device.
The avr109 bootloader implements a protocol similar to avr910, but is
actually implemented in the boot area of the target's flash ROM, as
opposed to being an external device.
The fundamental difference between the two types lies in the
protocol used to control the programmer. The avr910 protocol is very
simplistic and can easily be used as the basis for a simple, home made
programmer since the firmware is available online. On the other hand,
the STK500 protocol is more robust and complicated and the firmware is
not openly available.
The JTAG ICE also uses a serial communication protocol which is similar
to the STK500 firmware version 2 one. However, as the JTAG ICE is
intended to allow on-chip debugging as well as memory programming, the
protocol is more sophisticated.
(The JTAG ICE mkII protocol can also be run on top of USB.)
Only the memory programming functionality of the JTAG ICE is supported
by AVRDUDE.
For the JTAG ICE mkII/3, JTAG, debugWire and ISP mode are supported, provided
it has a firmware revision of at least 4.14 (decimal).
See below for the limitations of debugWire.
For ATxmega devices, the JTAG ICE mkII/3 is supported in PDI mode, provided it
has a revision 1 hardware and firmware version of at least 5.37 (decimal).
The Atmel-ICE (ARM/AVR) is supported (JTAG, PDI for Xmega, debugWIRE, ISP modes).
Atmel's XplainedPro boards, using EDBG protocol (CMSIS-DAP compliant), are
supported by the 'jtag3' programmer type.
Atmel's XplainedMini boards, using mEDBG protocol, are also
supported by the 'jtag3' programmer type.
The AVR Dragon is supported in all modes (ISP, JTAG, PDI, HVSP, PP, debugWire).
When used in JTAG and debugWire mode, the AVR Dragon behaves similar to a
JTAG ICE mkII, so all device-specific comments for that device
will apply as well.
When used in ISP and PDI mode, the AVR Dragon behaves similar to an
AVRISP mkII (or JTAG ICE mkII in ISP mode), so all device-specific
comments will apply there.
In particular, the Dragon starts out with a rather fast ISP clock
frequency, so the `-B `bitclock``
option might be required to achieve a stable ISP communication.
For ATxmega devices, the AVR Dragon is supported in PDI mode, provided it
has a firmware version of at least 6.11 (decimal).
Wiring boards (e.g. Arduino Mega 2560 Rev3) are supported, utilizing
STK500 V2.x protocol, but a simple DTR/RTS toggle to set the boards
into programming mode. The programmer type is 'wiring'. Note that
the -D option will likely be required in this case, because the
bootloader will rewrite the program memory, but no true chip erase can
be performed.
The Arduino (which is very similar to the STK500 1.x) is supported via
its own programmer type specification 'arduino'. This programmer works for
the Arduino Uno Rev3.
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
the section on
*extended parameters*
below for details.
The USBasp ISP and USBtinyISP adapters are also supported, provided AVRDUDE
has been compiled with libusb support.
They both feature simple firmware-only USB implementations, running on
an ATmega8 (or ATmega88), or ATtiny2313, respectively.
The Atmel DFU bootloader is supported in both, FLIP protocol version 1
(AT90USB* and ATmega*U* devices), as well as version 2 (Xmega devices).
See below for some hints about FLIP version 1 protocol behaviour.
The MPLAB(R) PICkit 4 and MPLAB(R) SNAP are supported in ISP, PDI and UPDI mode.
The Curiosity Nano board is supported in UPDI mode. It is dubbed ``PICkit on
Board'', thus the name `pkobn_updi`.
SerialUPDI programmer implementation is based on Microchip's
*pymcuprog* (`https://github.com/microchip-pic-avr-tools/pymcuprog <https://github.com/microchip-pic-avr-tools/pymcuprog>`_)
utility, but it also contains some performance improvements included in
Spence Kohde's *DxCore* Arduino core (`https://github.com/SpenceKonde/DxCore <https://github.com/SpenceKonde/DxCore>`_).
In a nutshell, this programmer consists of simple USB->UART adapter, diode
and couple of resistors. It uses serial connection to provide UPDI interface.
:ref:`SerialUPDI_programmer` for more details and known issues.
The jtag2updi programmer is supported,
and can program AVRs with a UPDI interface.
Jtag2updi is just a firmware that can be uploaded to an AVR,
which enables it to interface with avrdude using the jtagice mkii protocol
via a serial link (`https://github.com/ElTangas/jtag2updi <https://github.com/ElTangas/jtag2updi>`_).
The Micronucleus bootloader is supported for both protocol version V1
and V2. As the bootloader does not support reading from flash memory,
use the `-V` option to prevent AVRDUDE from verifing the flash memory.
See the section on *extended parameters*
below for Micronucleus specific options.
.. _History_and_Credits:
History and Credits
===================
AVRDUDE was written by Brian S. Dean under the name of AVRPROG to run on
the FreeBSD Operating System. Brian renamed the software to be called
AVRDUDE when interest grew in a Windows port of the software so that the
name did not conflict with AVRPROG.EXE which is the name of Atmel's
Windows programming software.
The AVRDUDE source now resides in the public CVS repository on
savannah.gnu.org (`http://savannah.gnu.org/projects/avrdude/ <http://savannah.gnu.org/projects/avrdude/>`_),
where it continues to be enhanced and ported to other systems. In
addition to FreeBSD, AVRDUDE now runs on Linux and Windows. The
developers behind the porting effort primarily were Ted Roth, Eric
Weddington, and Joerg Wunsch.
And in the spirit of many open source projects, this manual also draws
on the work of others. The initial revision was composed of parts of
the original Unix manual page written by Joerg Wunsch, the original web
site documentation by Brian Dean, and from the comments describing the
fields in the AVRDUDE configuration file by Brian Dean. The texi
formatting was modeled after that of the Simulavr documentation by Ted
Roth.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,241 @@
.. _Terminal_Mode_Operation:
***********************
Terminal Mode Operation
***********************
AVRDUDE has an interactive mode called `terminal mode` that is
enabled by the *-t* option. This mode allows one to enter
interactive commands to display and modify the various device memories,
perform a chip erase, display the device signature bytes and part
parameters, and to send raw programming commands. Commands and
parameters may be abbreviated to their shortest unambiguous form.
Terminal mode also supports a command history so that previously entered
commands can be recalled and edited.
.. _Terminal_Mode_Commands:
Terminal Mode Commands
======================
The following commands are implemented:
*dump `memtype` `addr` `nbytes`*
Read `nbytes` from the specified memory area, and display them in
the usual hexadecimal and ASCII form.
*dump*
Continue dumping the memory contents for another `nbytes` where the
previous dump command left off.
*write `memtype` `addr` `byte1` ... `byteN`*
Manually program the respective memory cells, starting at address addr,
using the values `byte1` through `byteN`. This feature is not
implemented for bank-addressed memories such as the flash memory of
ATMega devices.
*erase*
Perform a chip erase.
*send `b1` `b2` `b3` `b4`*
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 AVRDUDE, this
command allows you to use it, even though AVRDUDE does not implement the
command. When using direct SPI mode, up to 3 bytes
can be omitted.
*sig*
Display the device signature bytes.
*spi*
Enter direct SPI mode. The *pgmled* pin acts as slave select.
*Only supported on parallel bitbang programmers.*
*part*
Display the current part settings and parameters. Includes chip
specific information including all memory types supported by the
device, read/write timing, etc.
*pgm*
Return to programming mode (from direct SPI mode).
*verbose [`level`]*
Change (when `level` is provided), or display the verbosity
level.
The initial verbosity level is controlled by the number of `-v` options
given on the command line.
*?*
*help*
Give a short on-line summary of the available commands.
*quit*
Leave terminal mode and thus AVRDUDE.
In addition, the following commands are supported on the STK500
and STK600 programmer:
*vtarg `voltage`*
Set the target's supply voltage to `voltage` Volts.
*varef [`channel`] `voltage`*
Set the adjustable voltage source to `voltage` Volts.
This voltage is normally used to drive the target's
*Aref* input on the STK500 and STK600.
The STK600 offers two reference voltages, which can be
selected by the optional parameter `channel` (either
0 or 1).
*fosc `freq`[`M`|`k`]*
Set the master oscillator to `freq` Hz.
An optional trailing letter `M`
multiplies by 1E6, a trailing letter `k` by 1E3.
*fosc off*
Turn the master oscillator off.
*sck `period`*
*STK500 and STK600 only:*
Set the SCK clock period to `period` microseconds.
*JTAG ICE only:*
Set the JTAG ICE bit clock period to `period` microseconds.
Note that unlike STK500 settings, this setting will be reverted to
its default value (approximately 1 microsecond) when the programming
software signs off from the JTAG ICE.
This parameter can also be used on the JTAG ICE mkII/3 to specify the
ISP clock period when operating the ICE in ISP mode.
*parms*
*STK500 and STK600 only:*
Display the current voltage and master oscillator parameters.
*JTAG ICE only:*
Display the current target supply voltage and JTAG bit clock rate/period.
.. _Terminal_Mode_Examples:
Terminal Mode Examples
======================
Display part parameters, modify eeprom cells, perform a chip erase:
::
@cartouche
% avrdude -p m128 -c stk500 -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e9702
avrdude: current erase-rewrite cycle count is 52 (if being tracked)
avrdude> part
>>> part
AVR Part : ATMEGA128
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PA0
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Memory Detail :
Page Polled
Memory Type Paged Size Size #Pages MinW MaxW ReadBack
----------- ------ ------ ---- ------ ----- ----- ---------
eeprom no 4096 8 0 9000 9000 0xff 0xff
flash yes 131072 256 512 4500 9000 0xff 0x00
lfuse no 1 0 0 0 0 0x00 0x00
hfuse no 1 0 0 0 0 0x00 0x00
efuse no 1 0 0 0 0 0x00 0x00
lock no 1 0 0 0 0 0x00 0x00
calibration no 1 0 0 0 0 0x00 0x00
signature no 3 0 0 0 0 0x00 0x00
avrdude> dump eeprom 0 16
>>> dump eeprom 0 16
0000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
avrdude> write eeprom 0 1 2 3 4
>>> write eeprom 0 1 2 3 4
avrdude> dump eeprom 0 16
>>> dump eeprom 0 16
0000 01 02 03 04 ff ff ff ff ff ff ff ff ff ff ff ff |................|
avrdude> erase
>>> erase
avrdude: erasing chip
avrdude> dump eeprom 0 16
>>> dump eeprom 0 16
0000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................|
avrdude>
@end cartouche
Program the fuse bits of an ATmega128 (disable M103 compatibility,
enable high speed external crystal, enable brown-out detection, slowly
rising power). Note since we are working with fuse bits the -u (unsafe)
option is specified, which allows you to modify the fuse bits. First
display the factory defaults, then reprogram:
::
@cartouche
% avrdude -p m128 -u -c stk500 -t
avrdude: AVR device initialized and ready to accept instructions
avrdude: Device signature = 0x1e9702
avrdude: current erase-rewrite cycle count is 52 (if being tracked)
avrdude> d efuse
>>> d efuse
0000 fd |. |
avrdude> d hfuse
>>> d hfuse
0000 99 |. |
avrdude> d lfuse
>>> d lfuse
0000 e1 |. |
avrdude> w efuse 0 0xff
>>> w efuse 0 0xff
avrdude> w hfuse 0 0x89
>>> w hfuse 0 0x89
avrdude> w lfuse 0 0x2f
>>> w lfuse 0 0x2f
avrdude>
@end cartouche

View File

@@ -0,0 +1,382 @@
.. _Configuration_File:
******************
Configuration File
******************
AVRDUDE reads a configuration file upon startup which describes all of
the parts and programmers that it knows about. The advantage of this is
that if you have a chip that is not currently supported by AVRDUDE, you
can add it to the configuration file without waiting for a new release
of AVRDUDE. Likewise, if you have a parallel port programmer that is
not supported by AVRDUDE, chances are good that you can copy and
existing programmer definition, and with only a few changes, make your
programmer work with AVRDUDE.
AVRDUDE first looks for a system wide configuration file in a platform
dependent location. On Unix, this is usually
`/usr/local/etc/avrdude.conf`, while on Windows it is usually in the
same location as the executable file. The name of this file can be
changed using the *-C* command line option. After the system wide
configuration file is parsed, AVRDUDE looks for a per-user configuration
file to augment or override the system wide defaults. On Unix, the
per-user file is `.avrduderc` within the user's home directory. On
Windows, this file is the `avrdude.rc` file located in the same
directory as the executable.
.. _AVRDUDE_Defaults:
AVRDUDE Defaults
================
*default_parallel = "`default-parallel-device`";*
Assign the default parallel port device. Can be overridden using the
*-P* option.
*default_serial = "`default-serial-device`";*
Assign the default serial port device. Can be overridden using the
*-P* option.
*default_programmer = "`default-programmer-id`";*
Assign the default programmer id. Can be overridden using the *-c*
option.
*default_bitclock = "`default-bitclock`";*
Assign the default bitclock value. Can be overridden using the *-B*
option.
.. _Programmer_Definitions:
Programmer Definitions
======================
The format of the programmer definition is as follows:
::
programmer
parent <id> # <id> is a quoted string
id = <id1> [, <id2> [, <id3>] ...] ; # <idN> are quoted strings
desc = <description> ; # quoted string
type = "par" | "stk500" | ... ; # programmer type (see below for a list)
baudrate = <num> ; # baudrate for serial ports
vcc = <num1> [, <num2> ... ] ; # pin number(s)
buff = <num1> [, <num2> ... ] ; # pin number(s)
reset = <num> ; # pin number
sck = <num> ; # pin number
mosi = <num> ; # pin number
miso = <num> ; # pin number
errled = <num> ; # pin number
rdyled = <num> ; # pin number
pgmled = <num> ; # pin number
vfyled = <num> ; # pin number
usbvid = <hexnum>; # USB VID (Vendor ID)
usbpid = <hexnum> [, <hexnum> ...]; # USB PID (Product ID)
usbdev = <interface>; # USB interface or other device info
usbvendor = <vendorname>; # USB Vendor Name
usbproduct = <productname>; # USB Product Name
usbsn = <serialno>; # USB Serial Number
;
If a parent is specified, all settings of it (except its ids) are used for the new
programmer. These values can be changed by new setting them for the new programmer.
To invert a bit in the pin definitions, use `= ~ <num>`.
Not all programmer types can handle a list of USB PIDs.
Following programmer types are currently implemented:
@multitable @columnfractions .25 .6
* `arduino` @tab Arduino programmer
* `avr910` @tab Serial programmers using protocol described in application note AVR910
* `avrftdi` @tab Interface to the MPSSE Engine of FTDI Chips using libftdi.
* `buspirate` @tab Using the Bus Pirate's SPI interface for programming
* `buspirate_bb` @tab Using the Bus Pirate's bitbang interface for programming
* `butterfly` @tab Atmel Butterfly evaluation board; Atmel AppNotes AVR109, AVR911
* `butterfly_mk` @tab Mikrokopter.de Butterfly
* `dragon_dw` @tab Atmel AVR Dragon in debugWire mode
* `dragon_hvsp` @tab Atmel AVR Dragon in HVSP mode
* `dragon_isp` @tab Atmel AVR Dragon in ISP mode
* `dragon_jtag` @tab Atmel AVR Dragon in JTAG mode
* `dragon_pdi` @tab Atmel AVR Dragon in PDI mode
* `dragon_pp` @tab Atmel AVR Dragon in PP mode
* `flip1` @tab FLIP USB DFU protocol version 1 (doc7618)
* `flip2` @tab FLIP USB DFU protocol version 2 (AVR4023)
* `ftdi_syncbb` @tab FT245R/FT232R Synchronous BitBangMode Programmer
* `jtagmki` @tab Atmel JTAG ICE mkI
* `jtagmkii` @tab Atmel JTAG ICE mkII
* `jtagmkii_avr32` @tab Atmel JTAG ICE mkII in AVR32 mode
* `jtagmkii_dw` @tab Atmel JTAG ICE mkII in debugWire mode
* `jtagmkii_isp` @tab Atmel JTAG ICE mkII in ISP mode
* `jtagmkii_pdi` @tab Atmel JTAG ICE mkII in PDI mode
* `jtagice3` @tab Atmel JTAGICE3
* `jtagice3_pdi` @tab Atmel JTAGICE3 in PDI mode
* `jtagice3_updi` @tab Atmel JTAGICE3 in UPDI mode
* `jtagice3_dw` @tab Atmel JTAGICE3 in debugWire mode
* `jtagice3_isp` @tab Atmel JTAGICE3 in ISP mode
* `linuxgpio` @tab GPIO bitbanging using the Linux sysfs interface (not available)
* `linuxspi` @tab SPI using Linux spidev driver (not available)
* `micronucleus` @tab Micronucleus Bootloader
* `par` @tab Parallel port bitbanging
* `pickit2` @tab Microchip's PICkit2 Programmer
* `serbb` @tab Serial port bitbanging
* `serialupdi` @tab Driver for SerialUPDI programmers
* `stk500` @tab Atmel STK500 Version 1.x firmware
* `stk500generic` @tab Atmel STK500, autodetect firmware version
* `stk500v2` @tab Atmel STK500 Version 2.x firmware
* `stk500hvsp` @tab Atmel STK500 V2 in high-voltage serial programming mode
* `stk500pp` @tab Atmel STK500 V2 in parallel programming mode
* `stk600` @tab Atmel STK600
* `stk600hvsp` @tab Atmel STK600 in high-voltage serial programming mode
* `stk600pp` @tab Atmel STK600 in parallel programming mode
* `teensy` @tab Teensy Bootloader
* `usbasp` @tab USBasp programmer, see `http://www.fischl.de/usbasp/ <http://www.fischl.de/usbasp/>`_
* `usbtiny` @tab Driver for "usbtiny"-type programmers
* `wiring` @tab `http://wiring.org.co/ <http://wiring.org.co/>`_, Basically STK500v2 protocol, with some glue to trigger the bootloader.
* `xbee` @tab XBee Series 2 Over-The-Air (XBeeBoot)
@end multitable
.. _Part_Definitions:
Part Definitions
================
::
part
id = <id> ; # quoted string
desc = <description> ; # quoted string
family_id = <description> ; # quoted string
has_jtag = <yes/no> ; # part has JTAG i/f
has_debugwire = <yes/no> ; # part has debugWire i/f
has_pdi = <yes/no> ; # part has PDI i/f
has_updi = <yes/no> ; # part has UPDI i/f
has_tpi = <yes/no> ; # part has TPI i/f
devicecode = <num> ; # numeric
stk500_devcode = <num> ; # numeric
avr910_devcode = <num> ; # numeric
signature = <num> <num> <num> ; # signature bytes
usbpid = <num> ; # DFU USB PID
reset = dedicated | io;
retry_pulse = reset | sck;
pgm_enable = <instruction format> ;
chip_erase = <instruction format> ;
chip_erase_delay = <num> ; # micro-seconds
# STK500 parameters (parallel programming IO lines)
pagel = <num> ; # pin name in hex, i.e., 0xD7
bs2 = <num> ; # pin name in hex, i.e., 0xA0
serial = <yes/no> ; # can use serial downloading
parallel = <yes/no/pseudo>; # can use par. programming
# STK500v2 parameters, to be taken from Atmel's XML files
timeout = <num> ;
stabdelay = <num> ;
cmdexedelay = <num> ;
synchloops = <num> ;
bytedelay = <num> ;
pollvalue = <num> ;
pollindex = <num> ;
predelay = <num> ;
postdelay = <num> ;
pollmethod = <num> ;
mode = <num> ;
delay = <num> ;
blocksize = <num> ;
readsize = <num> ;
hvspcmdexedelay = <num> ;
# STK500v2 HV programming parameters, from XML
pp_controlstack = <num>, <num>, ...; # PP only
hvsp_controlstack = <num>, <num>, ...; # HVSP only
hventerstabdelay = <num>;
progmodedelay = <num>; # PP only
latchcycles = <num>;
togglevtg = <num>;
poweroffdelay = <num>;
resetdelayms = <num>;
resetdelayus = <num>;
hvleavestabdelay = <num>;
resetdelay = <num>;
synchcycles = <num>; # HVSP only
chiperasepulsewidth = <num>; # PP only
chiperasepolltimeout = <num>;
chiperasetime = <num>; # HVSP only
programfusepulsewidth = <num>; # PP only
programfusepolltimeout = <num>;
programlockpulsewidth = <num>; # PP only
programlockpolltimeout = <num>;
# JTAG ICE mkII parameters, also from XML files
allowfullpagebitstream = <yes/no> ;
enablepageprogramming = <yes/no> ;
idr = <num> ; # IO addr of IDR (OCD) reg.
rampz = <num> ; # IO addr of RAMPZ reg.
spmcr = <num> ; # mem addr of SPMC[S]R reg.
eecr = <num> ; # mem addr of EECR reg.
# (only when != 0x3c)
is_at90s1200 = <yes/no> ; # AT90S1200 part
is_avr32 = <yes/no> ; # AVR32 part
memory <memtype>
paged = <yes/no> ; # yes / no
size = <num> ; # bytes
page_size = <num> ; # bytes
num_pages = <num> ; # numeric
min_write_delay = <num> ; # micro-seconds
max_write_delay = <num> ; # micro-seconds
readback_p1 = <num> ; # byte value
readback_p2 = <num> ; # byte value
pwroff_after_write = <yes/no> ; # yes / no
read = <instruction format> ;
write = <instruction format> ;
read_lo = <instruction format> ;
read_hi = <instruction format> ;
write_lo = <instruction format> ;
write_hi = <instruction format> ;
loadpage_lo = <instruction format> ;
loadpage_hi = <instruction format> ;
writepage = <instruction format> ;
;
;
.. _Parent_Part:
Parent Part
-----------
Parts can also inherit parameters from previously defined parts
using the following syntax. In this case specified integer and
string values override parameter values from the parent part. New
memory definitions are added to the definitions inherited from the
parent.
::
part parent <id> # quoted string
id = <id> ; # quoted string
<any set of other parameters from the list above>
;
.. _Instruction_Format:
Instruction Format
------------------
Instruction formats are specified as a comma separated list of string
values containing information (bit specifiers) about each of the 32 bits
of the instruction. Bit specifiers may be one of the following formats:
*1*
The bit is always set on input as well as output
*0*
the bit is always clear on input as well as output
*x*
the bit is ignored on input and output
*a*
the bit is an address bit, the bit-number matches this bit specifier's
position within the current instruction byte
*a`N`*
the bit is the `N`th address bit, bit-number = N, i.e., `a12`
is address bit 12 on input, `a0` is address bit 0.
*i*
the bit is an input data bit
*o*
the bit is an output data bit
Each instruction must be composed of 32 bit specifiers. The instruction
specification closely follows the instruction data provided in Atmel's
data sheets for their parts. For example, the EEPROM read and write
instruction for an AT90S2313 AVR part could be encoded as:
::
read = "1 0 1 0 0 0 0 0 x x x x x x x x",
"x a6 a5 a4 a3 a2 a1 a0 o o o o o o o o";
write = "1 1 0 0 0 0 0 0 x x x x x x x x",
"x a6 a5 a4 a3 a2 a1 a0 i i i i i i i i";
.. _Other_Notes:
Other Notes
===========
*
The `devicecode` parameter is the device code used by the STK500
and is obtained from the software section (`avr061.zip`) of
Atmel's AVR061 application note available from
`http://www.atmel.com/dyn/resources/prod_documents/doc2525.pdf <http://www.atmel.com/dyn/resources/prod_documents/doc2525.pdf>`_.
*
Not all memory types will implement all instructions.
*
AVR Fuse bits and Lock bits are implemented as a type of memory.
*
Example memory types are: `flash`, `eeprom`, `fuse`,
`lfuse` (low fuse), `hfuse` (high fuse), `efuse`
(extended fuse), `signature`, `calibration`, `lock`.
*
The memory type specified on the AVRDUDE command line must match one of
the memory types defined for the specified chip.
*
The `pwroff_after_write` flag causes AVRDUDE to attempt to power
the device off and back on after an unsuccessful write to the affected
memory area if VCC programmer pins are defined. If VCC pins are not
defined for the programmer, a message indicating that the device needs a
power-cycle is printed out. This flag was added to work around a
problem with the at90s4433/2333's; see the at90s4433 errata at:
`http://www.atmel.com/dyn/resources/prod_documents/doc1280.pdf <http://www.atmel.com/dyn/resources/prod_documents/doc1280.pdf>`_
*
The boot loader from application note AVR109 (and thus also the AVR
Butterfly) does not support writing of fuse bits. Writing lock bits
is supported, but is restricted to the boot lock bits (BLBxx). These
are restrictions imposed by the underlying SPM instruction that is used
to program the device from inside the boot loader. Note that programming
the boot lock bits can result in a 'shoot-into-your-foot' scenario as
the only way to unprogram these bits is a chip erase, which will also
erase the boot loader code.
The boot loader implements the 'chip erase' function by erasing the
flash pages of the application section.
Reading fuse and lock bits is fully supported.
Note that due to the inability to write the fuse bits, the safemode
functionality does not make sense for these boot loaders.

View File

@@ -0,0 +1,843 @@
.. _Programmer_Specific_Information:
*******************************
Programmer Specific Information
*******************************
.. _Atmel_STK600:
Atmel STK600
============
The following devices are supported by the respective STK600 routing
and socket card:
@multitable @columnfractions .25 .25 .5
@headitem Routing card @tab Socket card @tab Devices
* `} @tab @code{STK600-ATTINY10` @tab ATtiny4 ATtiny5 ATtiny9 ATtiny10
* `STK600-RC008T-2` @tab `STK600-DIP` @tab ATtiny11 ATtiny12 ATtiny13 ATtiny13A ATtiny25 ATtiny45 ATtiny85
* `STK600-RC008T-7` @tab `STK600-DIP` @tab ATtiny15
* `STK600-RC014T-42` @tab `STK600-SOIC` @tab ATtiny20
* `STK600-RC020T-1` @tab `STK600-DIP` @tab ATtiny2313 ATtiny2313A ATtiny4313
* `} @tab @code{STK600-TinyX3U` @tab ATtiny43U
* `STK600-RC014T-12` @tab `STK600-DIP` @tab ATtiny24 ATtiny44 ATtiny84 ATtiny24A ATtiny44A
* `STK600-RC020T-8` @tab `STK600-DIP` @tab ATtiny26 ATtiny261 ATtiny261A ATtiny461 ATtiny861 ATtiny861A
* `STK600-RC020T-43` @tab `STK600-SOIC` @tab ATtiny261 ATtiny261A ATtiny461 ATtiny461A ATtiny861 ATtiny861A
* `STK600-RC020T-23` @tab `STK600-SOIC` @tab ATtiny87 ATtiny167
* `STK600-RC028T-3` @tab `STK600-DIP` @tab ATtiny28
* `STK600-RC028M-6` @tab `STK600-DIP` @tab ATtiny48 ATtiny88 ATmega8 ATmega8A ATmega48 ATmega88 ATmega168 ATmega48P ATmega48PA ATmega88P ATmega88PA ATmega168P ATmega168PA ATmega328P
* `} @tab @code{QT600-ATTINY88-QT8` @tab ATtiny88
* `STK600-RC040M-4` @tab `STK600-DIP` @tab ATmega8515 ATmega162
* `STK600-RC044M-30` @tab `STK600-TQFP44` @tab ATmega8515 ATmega162
* `STK600-RC040M-5` @tab `STK600-DIP` @tab ATmega8535 ATmega16 ATmega16A ATmega32 ATmega32A ATmega164P ATmega164PA ATmega324P ATmega324PA ATmega644 ATmega644P ATmega644PA ATmega1284P
* `STK600-RC044M-31` @tab `STK600-TQFP44` @tab ATmega8535 ATmega16 ATmega16A ATmega32 ATmega32A ATmega164P ATmega164PA ATmega324P ATmega324PA ATmega644 ATmega644P ATmega644PA ATmega1284P
* `} @tab @code{QT600-ATMEGA324-QM64` @tab ATmega324PA
* `STK600-RC032M-29` @tab `STK600-TQFP32` @tab ATmega8 ATmega8A ATmega48 ATmega88 ATmega168 ATmega48P ATmega48PA ATmega88P ATmega88PA ATmega168P ATmega168PA ATmega328P
* `STK600-RC064M-9` @tab `STK600-TQFP64` @tab ATmega64 ATmega64A ATmega128 ATmega128A ATmega1281 ATmega2561 AT90CAN32 AT90CAN64 AT90CAN128
* `STK600-RC064M-10` @tab `STK600-TQFP64` @tab ATmega165 ATmega165P ATmega169 ATmega169P ATmega169PA ATmega325 ATmega325P ATmega329 ATmega329P ATmega645 ATmega649 ATmega649P
* `STK600-RC100M-11` @tab `STK600-TQFP100` @tab ATmega640 ATmega1280 ATmega2560
* `} @tab @code{STK600-ATMEGA2560` @tab ATmega2560
* `STK600-RC100M-18` @tab `STK600-TQFP100` @tab ATmega3250 ATmega3250P ATmega3290 ATmega3290P ATmega6450 ATmega6490
* `STK600-RC032U-20` @tab `STK600-TQFP32` @tab AT90USB82 AT90USB162 ATmega8U2 ATmega16U2 ATmega32U2
* `STK600-RC044U-25` @tab `STK600-TQFP44` @tab ATmega16U4 ATmega32U4
* `STK600-RC064U-17` @tab `STK600-TQFP64` @tab ATmega32U6 AT90USB646 AT90USB1286 AT90USB647 AT90USB1287
* `STK600-RCPWM-22` @tab `STK600-TQFP32` @tab ATmega32C1 ATmega64C1 ATmega16M1 ATmega32M1 ATmega64M1
* `STK600-RCPWM-19` @tab `STK600-SOIC` @tab AT90PWM2 AT90PWM3 AT90PWM2B AT90PWM3B AT90PWM216 AT90PWM316
* `STK600-RCPWM-26` @tab `STK600-SOIC` @tab AT90PWM81
* `STK600-RC044M-24` @tab `STK600-TSSOP44` @tab ATmega16HVB ATmega32HVB
* `} @tab @code{STK600-HVE2` @tab ATmega64HVE
* `} @tab @code{STK600-ATMEGA128RFA1` @tab ATmega128RFA1
* `STK600-RC100X-13` @tab `STK600-TQFP100` @tab ATxmega64A1 ATxmega128A1 ATxmega128A1_revD ATxmega128A1U
* `} @tab @code{STK600-ATXMEGA1281A1` @tab ATxmega128A1
* `} @tab @code{QT600-ATXMEGA128A1-QT16` @tab ATxmega128A1
* `STK600-RC064X-14` @tab `STK600-TQFP64` @tab ATxmega64A3 ATxmega128A3 ATxmega256A3 ATxmega64D3 ATxmega128D3 ATxmega192D3 ATxmega256D3
* `STK600-RC064X-14` @tab `STK600-MLF64` @tab ATxmega256A3B
* `STK600-RC044X-15` @tab `STK600-TQFP44` @tab ATxmega32A4 ATxmega16A4 ATxmega16D4 ATxmega32D4
* `} @tab @code{STK600-ATXMEGAT0` @tab ATxmega32T0
* `} @tab @code{STK600-uC3-144` @tab AT32UC3A0512 AT32UC3A0256 AT32UC3A0128
* `STK600-RCUC3A144-33` @tab `STK600-TQFP144` @tab AT32UC3A0512 AT32UC3A0256 AT32UC3A0128
* `STK600-RCuC3A100-28` @tab `STK600-TQFP100` @tab AT32UC3A1512 AT32UC3A1256 AT32UC3A1128
* `STK600-RCuC3B0-21` @tab `STK600-TQFP64-2` @tab AT32UC3B0256 AT32UC3B0512RevC AT32UC3B0512 AT32UC3B0128 AT32UC3B064 AT32UC3D1128
* `STK600-RCuC3B48-27` @tab `STK600-TQFP48` @tab AT32UC3B1256 AT32UC3B164
* `STK600-RCUC3A144-32` @tab `STK600-TQFP144` @tab AT32UC3A3512 AT32UC3A3256 AT32UC3A3128 AT32UC3A364 AT32UC3A3256S AT32UC3A3128S AT32UC3A364S
* `STK600-RCUC3C0-36` @tab `STK600-TQFP144` @tab AT32UC3C0512 AT32UC3C0256 AT32UC3C0128 AT32UC3C064
* `STK600-RCUC3C1-38` @tab `STK600-TQFP100` @tab AT32UC3C1512 AT32UC3C1256 AT32UC3C1128 AT32UC3C164
* `STK600-RCUC3C2-40` @tab `STK600-TQFP64-2` @tab AT32UC3C2512 AT32UC3C2256 AT32UC3C2128 AT32UC3C264
* `STK600-RCUC3C0-37` @tab `STK600-TQFP144` @tab AT32UC3C0512 AT32UC3C0256 AT32UC3C0128 AT32UC3C064
* `STK600-RCUC3C1-39` @tab `STK600-TQFP100` @tab AT32UC3C1512 AT32UC3C1256 AT32UC3C1128 AT32UC3C164
* `STK600-RCUC3C2-41` @tab `STK600-TQFP64-2` @tab AT32UC3C2512 AT32UC3C2256 AT32UC3C2128 AT32UC3C264
* `STK600-RCUC3L0-34` @tab `STK600-TQFP48` @tab AT32UC3L064 AT32UC3L032 AT32UC3L016
* `} @tab @code{QT600-AT32UC3L-QM64` @tab AT32UC3L064
@end multitable
Ensure the correct socket and routing card are mounted *before*
powering on the STK600. While the STK600 firmware ensures the socket
and routing card mounted match each other (using a table stored
internally in nonvolatile memory), it cannot handle the case where a
wrong routing card is used, e. g. the routing card
`STK600-RC040M-5` (which is meant for 40-pin DIP AVRs that have
an ADC, with the power supply pins in the center of the package) was
used but an ATmega8515 inserted (which uses the 'industry standard'
pinout with Vcc and GND at opposite corners).
Note that for devices that use the routing card `STK600-RC008T-2`,
in order to use ISP mode, the jumper for `AREF0` must be removed
as it would otherwise block one of the ISP signals. High-voltage
serial programming can be used even with that jumper installed.
The ISP system of the STK600 contains a detection against shortcuts
and other wiring errors. AVRDUDE initiates a connection check before
trying to enter ISP programming mode, and display the result if the
target is not found ready to be ISP programmed.
High-voltage programming requires the target voltage to be set to at
least 4.5 V in order to work. This can be done using
*Terminal Mode*, see :ref:`Terminal_Mode_Operation`.
.. _Atmel_DFU_bootloader_using_FLIP_version_1:
Atmel DFU bootloader using FLIP version 1
=========================================
Bootloaders using the FLIP protocol version 1 experience some very
specific behaviour.
These bootloaders have no option to access memory areas other than
Flash and EEPROM.
When the bootloader is started, it enters a *security mode* where
the only acceptable access is to query the device configuration
parameters (which are used for the signature on AVR devices). The
only way to leave this mode is a *chip erase*. As a chip erase
is normally implied by the *-U* option when reprogramming the
flash, this peculiarity might not be very obvious immediately.
Sometimes, a bootloader with security mode already disabled seems to
no longer respond with sensible configuration data, but only 0xFF for
all queries. As these queries are used to obtain the equivalent of a
signature, AVRDUDE can only continue in that situation by forcing the
signature check to be overridden with the *-F* option.
A *chip erase* might leave the EEPROM unerased, at least on some
versions of the bootloader.
.. _SerialUPDI_programmer:
SerialUPDI programmer
=====================
SerialUPDI programmer can be used for programming UPDI-only devices
using very simple serial connection.
You can read more about the details here
`https://github.com/SpenceKonde/AVR-Guidance/blob/master/UPDI/jtag2updi.md <https://github.com/SpenceKonde/AVR-Guidance/blob/master/UPDI/jtag2updi.md>`_
SerialUPDI programmer has been tested using FT232RL USB->UART interface
with the following connection layout (copied from Spence Kohde's page linked
above):
::
-------------------- To Target device
DTR| __________________
Rx |--------------,------------------| UPDI---\\/\\/---------->
Tx---/\\/\\/\\---Tx |-------|<|---' .--------| Gnd 470 ohm
resistor Vcc|---------------------------------| Vcc
1k CTS| .` |__________________
Gnd|--------------------'
--------------------
There are several limitations in current SerialUPDI/AVRDUDE integration,
listed below.
At the end of each run there are fuse values being presented to the user.
For most of the UPDI-enabled devices these definitions (low fuse, high
fuse, extended fuse) have no meaning whatsoever, as they have been
simply replaced by array of fuses: fuse0..9. Therefore you can simply
ignore this particular line of AVRDUDE output.
In connection to the above, *safemode* has no meaning in context
of UPDI devices and should be ignored.
Currently available devices support only UPDI NVM programming model 0
and 2, but there is also experimental implementation of model 3 - not
yet tested.
One of the core AVRDUDE features is verification of the connection by
reading device signature prior to any operation, but this operation
is not possible on UPDI locked devices. Therefore, to be able to
connect to such a device, you have to provide *-F* to override
this check.
Please note: using *-F* during write operation to locked device
will force chip erase. Use carefully.
Another issue you might notice is slow performance of EEPROM writing
using SerialUPDI for AVR Dx devices. This can be addressed by changing
*avrdude.conf* section for this device - changing EEPROM page
size to 0x20 (instead of default 1), like so:
::
#------------------------------------------------------------
# AVR128DB28
#------------------------------------------------------------
part parent ".avrdx"
id = "avr128db28";
desc = "AVR128DB28";
signature = 0x1E 0x97 0x0E;
memory "flash"
size = 0x20000;
offset = 0x800000;
page_size = 0x200;
readsize = 0x100;
;
memory "eeprom"
size = 0x200;
offset = 0x1400;
page_size = 0x1;
readsize = 0x100;
;
;
USERROW memory has not been defined for new devices except for
experimental addition for AVR128DB28. The point of USERROW is to
provide ability to write configuration details to already locked
device and currently SerialUPDI interface supports this feature,
but it hasn't been tested on wide variety of chips. Treat this as
something experimental at this point. Please note: on locked devices
it's not possible to read back USERROW contents when written, so
the automatic verification will most likely fail and to prevent
error messages, use *-V*.
Please note that SerialUPDI interface is pretty new and some
issues are to be expected. In case you run into them, please
make sure to run the intended command with debug output enabled
(*-v -v -v*) and provide this verbose output with your
bug report. You can also try to perform the same action using
*pymcuprog* (`https://github.com/microchip-pic-avr-tools/pymcuprog <https://github.com/microchip-pic-avr-tools/pymcuprog>`_)
utility with *-v debug* and provide its output too.
You will notice that both outputs are pretty similar, and this
was implemented like that on purpose - it was supposed to make
analysis of UPDI protocol quirks easier.
@appendix Platform Dependent Information
.. _Unix:
Unix
====
.. _Unix_Installation:
Unix Installation
-----------------
To build and install from the source tarball on Unix like systems:
::
$ gunzip -c avrdude-6.99-20211218.tar.gz | tar xf -
$ cd avrdude-6.99-20211218
$ ./configure
$ make
$ su root -c 'make install'
The default location of the install is into `/usr/local` so you
will need to be sure that `/usr/local/bin` is in your `PATH`
environment variable.
If you do not have root access to your system, you can do the
following instead:
::
$ gunzip -c avrdude-6.99-20211218.tar.gz | tar xf -
$ cd avrdude-6.99-20211218
$ ./configure --prefix=$HOME/local
$ make
$ make install
.. _FreeBSD_Installation:
FreeBSD Installation
^^^^^^^^^^^^^^^^^^^^
AVRDUDE is installed via the FreeBSD Ports Tree as follows:
::
% su - root
# cd /usr/ports/devel/avrdude
# make install
If you wish to install from a pre-built package instead of the source,
you can use the following instead:
::
% su - root
# pkg_add -r avrdude
Of course, you must be connected to the Internet for these methods to
work, since that is where the source as well as the pre-built package is
obtained.
.. _Linux_Installation:
Linux Installation
^^^^^^^^^^^^^^^^^^
On rpm based Linux systems (such as RedHat, SUSE, Mandrake, etc.), you
can build and install the rpm binaries directly from the tarball:
::
$ su - root
# rpmbuild -tb avrdude-6.99-20211218.tar.gz
# rpm -Uvh /usr/src/redhat/RPMS/i386/avrdude-6.99-20211218-1.i386.rpm
Note that the path to the resulting rpm package, differs from system
to system. The above example is specific to RedHat.
.. _Unix_Configuration_Files:
Unix Configuration Files
------------------------
When AVRDUDE is build using the default *--prefix* configure
option, the default configuration file for a Unix system is located at
`/usr/local/etc/avrdude.conf`. This can be overridden by using the
*-C* command line option. Additionally, the user's home directory
is searched for a file named `.avrduderc`, and if found, is used to
augment the system default configuration file.
.. _FreeBSD_Configuration_Files:
FreeBSD Configuration Files
^^^^^^^^^^^^^^^^^^^^^^^^^^^
When AVRDUDE is installed using the FreeBSD ports system, the system
configuration file is always `/usr/local/etc/avrdude.conf`.
.. _Linux_Configuration_Files:
Linux Configuration Files
^^^^^^^^^^^^^^^^^^^^^^^^^
When AVRDUDE is installed using from an rpm package, the system
configuration file will be always be `/etc/avrdude.conf`.
.. _Unix_Port_Names:
Unix Port Names
---------------
The parallel and serial port device file names are system specific.
The following table lists the default names for a given system.
@multitable @columnfractions .30 .30 .30
* @strong{System}
@tab @strong{Default Parallel Port}
@tab @strong{Default Serial Port}
* FreeBSD
@tab `/dev/ppi0`
@tab `/dev/cuad0`
* Linux
@tab `/dev/parport0`
@tab `/dev/ttyS0`
* Solaris
@tab `/dev/printers/0`
@tab `/dev/term/a`
@end multitable
On FreeBSD systems, AVRDUDE uses the ppi(4) interface for
accessing the parallel port and the sio(4) driver for serial port
access.
On Linux systems, AVRDUDE uses the ppdev interface for
accessing the parallel port and the tty driver for serial port
access.
On Solaris systems, AVRDUDE uses the ecpp(7D) driver for
accessing the parallel port and the asy(7D) driver for serial port
access.
.. _Unix_Documentation:
Unix Documentation
------------------
AVRDUDE installs a manual page as well as info, HTML and PDF
documentation. The manual page is installed in
`/usr/local/man/man1` area, while the HTML and PDF documentation
is installed in `/usr/local/share/doc/avrdude` directory. The
info manual is installed in `/usr/local/info/avrdude.info`.
Note that these locations can be altered by various configure options
such as *--prefix*.
.. _Windows:
Windows
=======
.. _Installation:
Installation
------------
A Windows executable of avrdude is included in WinAVR which can be found at
`http://sourceforge.net/projects/winavr <http://sourceforge.net/projects/winavr>`_. WinAVR is a suite of executable,
open source software development tools for the AVR for the Windows platform.
There are two options to build avrdude from source under Windows.
The first one is to use Cygwin (`http://www.cygwin.com/ <http://www.cygwin.com/>`_).
To build and install from the source tarball for Windows (using Cygwin):
::
$ set PREFIX=<your install directory path>
$ export PREFIX
$ gunzip -c avrdude-6.99-20211218.tar.gz | tar xf -
$ cd avrdude-6.99-20211218
$ ./configure LDFLAGS="-static" --prefix=$PREFIX --datadir=$PREFIX
--sysconfdir=$PREFIX/bin --enable-versioned-doc=no
$ make
$ make install
Note that recent versions of Cygwin (starting with 1.7) removed the
MinGW support from the compiler that is needed in order to build a
native Win32 API binary that does not require to install the Cygwin
library `cygwin1.dll` at run-time. Either try using an older
compiler version that still supports MinGW builds, or use MinGW
(`http://www.mingw.org/ <http://www.mingw.org/>`_) directly.
.. _Configuration_Files:
Configuration Files
-------------------
.. _Configuration_file_names:
Configuration file names
^^^^^^^^^^^^^^^^^^^^^^^^
AVRDUDE on Windows looks for a system configuration file name of
`avrdude.conf` and looks for a user override configuration file of
`avrdude.rc`.
.. _How_AVRDUDE_finds_the_configuration_files.:
How AVRDUDE finds the configuration files.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AVRDUDE on Windows has a different way of searching for the system and
user configuration files. Below is the search method for locating the
configuration files:
*
Only for the system configuration file:
`<directory from which application loaded>/../etc/avrdude.conf`
*
The directory from which the application loaded.
*
The current directory.
*
The Windows system directory. On Windows NT, the name of this directory
is `SYSTEM32`.
*
Windows NT: The 16-bit Windows system directory. The name of this
directory is `SYSTEM`.
*
The Windows directory.
*
The directories that are listed in the PATH environment variable.
.. _Port_Names:
Port Names
----------
.. _Serial_Ports:
Serial Ports
^^^^^^^^^^^^
When you select a serial port (i.e. when using an STK500) use the
Windows serial port device names such as: com1, com2, etc.
.. _Parallel_Ports:
Parallel Ports
^^^^^^^^^^^^^^
AVRDUDE will accept 3 Windows parallel port names: lpt1, lpt2, or
lpt3. Each of these names corresponds to a fixed parallel port base
address:
*lpt1*
0x378
*lpt2*
0x278
*lpt3*
0x3BC
On your desktop PC, lpt1 will be the most common choice. If you are
using a laptop, you might have to use lpt3 instead of lpt1. Select the
name of the port the corresponds to the base address of the parallel
port that you want.
If the parallel port can be accessed through a different
address, this address can be specified directly, using the common C
language notation (i. e., hexadecimal values are prefixed by `0x`).
Documentation
-------------
AVRDUDE installs a manual page as well as info, HTML and PDF
documentation. The manual page is installed in
`/usr/local/man/man1` area, while the HTML and PDF documentation
is installed in `/usr/local/share/doc/avrdude` directory. The
info manual is installed in `/usr/local/info/avrdude.info`.
Note that these locations can be altered by various configure options
such as *--prefix* and *--datadir*.
@appendix Troubleshooting
In general, please report any bugs encountered via
@*
`http://savannah.nongnu.org/bugs/?group=avrdude <http://savannah.nongnu.org/bugs/?group=avrdude>`_.
*
Problem: I'm using a serial programmer under Windows and get the following
error:
`avrdude: serial_open(): can't set attributes for device "com1"`,
Solution: This problem seems to appear with certain versions of Cygwin. Specifying
`"/dev/com1"` instead of `"com1"` should help.
*
Problem: I'm using Linux and my AVR910 programmer is really slow.
Solution (short): `setserial `port` low_latency`
Solution (long):
There are two problems here. First, the system may wait some time before it
passes data from the serial port to the program. Under Linux the following
command works around this (you may need root privileges for this).
`setserial `port` low_latency`
Secondly, the serial interface chip may delay the interrupt for some time.
This behaviour can be changed by setting the FIFO-threshold to one. Under Linux this
can only be done by changing the kernel source in `drivers/char/serial.c`.
Search the file for `UART_FCR_TRIGGER_8` and replace it with `UART_FCR_TRIGGER_1`. Note that overall performance might suffer if there
is high throughput on serial lines. Also note that you are modifying the kernel at
your own risk.
*
Problem: I'm not using Linux and my AVR910 programmer is really slow.
Solutions: The reasons for this are the same as above.
If you know how to work around this on your OS, please let us know.
*
Problem: Updating the flash ROM from terminal mode does not work with the
JTAG ICEs.
Solution: None at this time. Currently, the JTAG ICE code cannot
write to the flash ROM one byte at a time.
*
Problem: Page-mode programming the EEPROM (using the -U option) does
not erase EEPROM cells before writing, and thus cannot overwrite any
previous value != 0xff.
Solution: None. This is an inherent feature of the way JTAG EEPROM
programming works, and is documented that way in the Atmel AVR
datasheets.
In order to successfully program the EEPROM that way, a prior chip
erase (with the EESAVE fuse unprogrammed) is required.
This also applies to the STK500 and STK600 in high-voltage programming mode.
*
Problem: How do I turn off the `DWEN` fuse?
Solution: If the `DWEN` (debugWire enable) fuse is activated,
the `/RESET` pin is not functional anymore, so normal ISP
communication cannot be established.
There are two options to deactivate that fuse again: high-voltage
programming, or getting the JTAG ICE mkII talk debugWire, and
prepare the target AVR to accept normal ISP communication again.
The first option requires a programmer that is capable of high-voltage
programming (either serial or parallel, depending on the AVR device),
for example the STK500. In high-voltage programming mode, the
`/RESET` pin is activated initially using a 12 V pulse (thus the
name *high voltage*), so the target AVR can subsequently be
reprogrammed, and the `DWEN` fuse can be cleared. Typically, this
operation cannot be performed while the AVR is located in the target
circuit though.
The second option requires a JTAG ICE mkII that can talk the debugWire
protocol. The ICE needs to be connected to the target using the
JTAG-to-ISP adapter, so the JTAG ICE mkII can be used as a debugWire
initiator as well as an ISP programmer. AVRDUDE will then be activated
using the `jtag2isp` programmer type. The initial ISP
communication attempt will fail, but AVRDUDE then tries to initiate a
debugWire reset. When successful, this will leave the target AVR in a
state where it can accept standard ISP communication. The ICE is then
signed off (which will make it signing off from the USB as well), so
AVRDUDE has to be called again afterwards. This time, standard ISP
communication can work, so the `DWEN` fuse can be cleared.
The pin mapping for the JTAG-to-ISP adapter is:
@multitable @columnfractions .2 .2
* @strong{JTAG pin} @tab @strong{ISP pin}
* 1 @tab 3
* 2 @tab 6
* 3 @tab 1
* 4 @tab 2
* 6 @tab 5
* 9 @tab 4
@end multitable
*
Problem: Multiple USBasp or USBtinyISP programmers connected simultaneously are not
found.
Solution: The USBtinyISP code supports distinguishing multiple
programmers based on their bus:device connection tuple that describes
their place in the USB hierarchy on a specific host. This tuple can
be added to the `-P usb` option, similar to adding a serial number
on other USB-based programmers.
The actual naming convention for the bus and device names is
operating-system dependent; AVRDUDE will print out what it found
on the bus when running it with (at least) one `-v` option.
By specifying a string that cannot match any existing device
(for example, `-P usb:xxx`), the scan will list all possible
candidate devices found on the bus.
Examples:
::
avrdude -c usbtiny -p atmega8 -P usb:003:025 (Linux)
avrdude -c usbtiny -p atmega8 -P usb:/dev/usb:/dev/ugen1.3 (FreeBSD 8+)
avrdude -c usbtiny -p atmega8 \\
-P usb:bus-0:\\\\.\\libusb0-0001--0x1781-0x0c9f (Windows)
*
Problem: I cannot do ... when the target is in debugWire mode.
Solution: debugWire mode imposes several limitations.
The debugWire protocol is Atmel's proprietary one-wire (plus ground)
protocol to allow an in-circuit emulation of the smaller AVR devices,
using the `/RESET` line.
DebugWire mode is initiated by activating the `DWEN`
fuse, and then power-cycling the target.
While this mode is mainly intended for debugging/emulation, it
also offers limited programming capabilities.
Effectively, the only memory areas that can be read or programmed
in this mode are flash ROM and EEPROM.
It is also possible to read out the signature.
All other memory areas cannot be accessed.
There is no
*chip erase*
functionality in debugWire mode; instead, while reprogramming the
flash ROM, each flash ROM page is erased right before updating it.
This is done transparently by the JTAG ICE mkII (or AVR Dragon).
The only way back from debugWire mode is to initiate a special
sequence of commands to the JTAG ICE mkII (or AVR Dragon), so the
debugWire mode will be temporarily disabled, and the target can
be accessed using normal ISP programming.
This sequence is automatically initiated by using the JTAG ICE mkII
or AVR Dragon in ISP mode, when they detect that ISP mode cannot be
entered.
*
Problem: I want to use my JTAG ICE mkII to program an
Xmega device through PDI. The documentation tells me to use the
*XMEGA PDI adapter for JTAGICE mkII* that is supposed to ship
with the kit, yet I don't have it.
Solution: Use the following pin mapping:
@multitable @columnfractions .2 .2 .2 .2
* @strong{JTAGICE} @tab @strong{Target} @tab @strong{Squid cab-} @tab @strong{PDI}
* @strong{mkII probe} @tab @strong{pins} @tab @strong{le colors} @tab @strong{header}
* 1 (TCK) @tab @tab Black @tab
* 2 (GND) @tab GND @tab White @tab 6
* 3 (TDO) @tab @tab Grey @tab
* 4 (VTref) @tab VTref @tab Purple @tab 2
* 5 (TMS) @tab @tab Blue @tab
* 6 (nSRST) @tab PDI_CLK @tab Green @tab 5
* 7 (N.C.) @tab @tab Yellow @tab
* 8 (nTRST) @tab @tab Orange @tab
* 9 (TDI) @tab PDI_DATA @tab Red @tab 1
* 10 (GND) @tab @tab Brown @tab
@end multitable
*
Problem: I want to use my AVR Dragon to program an
Xmega device through PDI.
Solution: Use the 6 pin ISP header on the Dragon and the following pin mapping:
@multitable @columnfractions .2 .2
* @strong{Dragon} @tab @strong{Target}
* @strong{ISP Header} @tab @strong{pins}
* 1 (MISO) @tab PDI_DATA
* 2 (VCC) @tab VCC
* 3 (SCK) @tab
* 4 (MOSI) @tab
* 5 (RESET) @tab PDI_CLK / RST
* 6 (GND) @tab GND
@end multitable
*
Problem: I want to use my AVRISP mkII to program an
ATtiny4/5/9/10 device through TPI. How to connect the pins?
Solution: Use the following pin mapping:
@multitable @columnfractions .2 .2 .2
* @strong{AVRISP} @tab @strong{Target} @tab @strong{ATtiny}
* @strong{connector} @tab @strong{pins} @tab @strong{pin #}
* 1 (MISO) @tab TPIDATA @tab 1
* 2 (VTref) @tab Vcc @tab 5
* 3 (SCK) @tab TPICLK @tab 3
* 4 (MOSI) @tab @tab
* 5 (RESET) @tab /RESET @tab 6
* 6 (GND) @tab GND @tab 2
@end multitable
*
Problem: I want to program an ATtiny4/5/9/10 device using a serial/parallel
bitbang programmer. How to connect the pins?
Solution: Since TPI has only 1 pin for bi-directional data transfer, both
`MISO` and `MOSI` pins should be connected to the `TPIDATA` pin
on the ATtiny device.
However, a 1K resistor should be placed between the `MOSI` and `TPIDATA`.
The `MISO` pin connects to `TPIDATA` directly.
The `SCK` pin is connected to `TPICLK`.
In addition, the `Vcc`, `/RESET` and `GND` pins should
be connected to their respective ports on the ATtiny device.
*
Problem: How can I use a FTDI FT232R USB-to-Serial device for bitbang programming?
Solution: When connecting the FT232 directly to the pins of the target Atmel device,
the polarity of the pins defined in the `programmer` definition should be
inverted by prefixing a tilde. For example, the `dasa` programmer would
look like this when connected via a FT232R device (notice the tildes in
front of pins 7, 4, 3 and 8):
::
programmer
id = "dasa_ftdi";
desc = "serial port banging, reset=rts sck=dtr mosi=txd miso=cts";
type = serbb;
reset = ~7;
sck = ~4;
mosi = ~3;
miso = ~8;
;
Note that this uses the FT232 device as a normal serial port, not using the
FTDI drivers in the special bitbang mode.
*
Problem: My ATtiny4/5/9/10 reads out fine, but any attempt to program
it (through TPI) fails. Instead, the memory retains the old contents.
Solution: Mind the limited programming supply voltage range of these
devices.
In-circuit programming through TPI is only guaranteed by the datasheet
at Vcc = 5 V.
*
Problem: My ATxmega...A1/A2/A3 cannot be programmed through PDI with
my AVR Dragon. Programming through a JTAG ICE mkII works though, as does
programming through JTAG.
Solution: None by this time (2010 Q1).
It is said that the AVR Dragon can only program devices from the A4
Xmega sub-family.
*
Problem: when programming with an AVRISPmkII or STK600, AVRDUDE hangs
when programming files of a certain size (e.g. 246 bytes). Other
(larger or smaller) sizes work though.
Solution: This is a bug caused by an incorrect handling of zero-length
packets (ZLPs) in some versions of the libusb 0.1 API wrapper that ships
with libusb 1.x in certain Linux distributions. All Linux systems with
kernel versions < 2.6.31 and libusb >= 1.0.0 < 1.0.3 are reported to be
affected by this.
See also: `http://www.libusb.org/ticket/6 <http://www.libusb.org/ticket/6>`_
*
Problem: after flashing a firmware that reduces the target's clock
speed (e.g. through the `CLKPR` register), further ISP connection
attempts fail.
Solution: Even though ISP starts with pulling `/RESET` low, the
target continues to run at the internal clock speed as defined by the
firmware running before. Therefore, the ISP clock speed must be
reduced appropriately (to less than 1/4 of the internal clock speed)
using the -B option before the ISP initialization sequence will
succeed.
As that slows down the entire subsequent ISP session, it might make
sense to just issue a *chip erase* using the slow ISP clock
(option `-e`), and then start a new session at higher speed.
Option `-D` might be used there, to prevent another unneeded
erase cycle.

35
docs/conf.py Normal file
View File

@@ -0,0 +1,35 @@
# Configuration file for the Sphinx documentation builder.
# -- Project information
project = 'AVRDUDE'
copyright = 'The AVRDUDE authors'
author = '2003-2005 Brian Dean, 2006-2022 Jörg Wunsch'
release = '0.1'
version = '0.1.0'
# -- General configuration
extensions = [
'sphinx.ext.duration',
'sphinx.ext.doctest',
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.intersphinx',
]
intersphinx_mapping = {
'python': ('https://docs.python.org/3/', None),
'sphinx': ('https://www.sphinx-doc.org/en/master/', None),
}
intersphinx_disabled_domains = ['std']
templates_path = ['_templates']
# -- Options for HTML output
html_theme = 'sphinx_rtd_theme'
# -- Options for EPUB output
epub_show_urls = 'footnote'

27
docs/index.rst Normal file
View File

@@ -0,0 +1,27 @@
AVRDUDE
=======
This file documents the avrdude program for downloading/uploading
programs to Microchip AVR microcontrollers.
For avrdude version 6.99-20211218, 6 January 2022.
Send comments on AVRDUDE to avrdude-dev@nongnu.org.
Use https://github.com/avrdudes/avrdude/issues to report bugs.
Copyright (C) 2003,2005 Brian S. Dean
Copyright (C) 2006 Jörg Wunsch
.. toctree::
:numbered:
:maxdepth: 3
1-Introduction
2-Command_Line_Options
3-Terminal_Mode_Operation
4-Configuration_File
5-Programmer_Specific_Information
6-Platform_Dependent_Information
7-Troubleshooting

View File

@@ -16,68 +16,257 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Typical usage:
# cmake -B build
# cmake --build build
cmake_minimum_required(VERSION 3.12)
project(avrdude VERSION 6.99)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)
option(BUILD_DOC "Enable building documents" OFF)
option(HAVE_LINUXGPIO "Enable Linux sysfs GPIO support" OFF)
option(HAVE_LINUXSPI "Enable Linux SPI support" OFF)
option(HAVE_PARPORT "Enable parallel port support" OFF)
option(USE_EXTERNAL "Use local code from the 'external' folder" OFF)
option(USE_LIBUSBWIN32 "Prefer libusb-win32 over libusb" OFF)
option(DEBUG_CMAKE "Enable debugging output for this CMake project" OFF)
include(CheckIncludeFile)
include(CheckFunctionExists)
include(CheckSymbolExists)
include(GNUInstallDirs)
include(FindPackageMessage)
set(CONFIG_DIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}")
set(AVRDUDE_FULL_VERSION ${CMAKE_PROJECT_VERSION})
set(AVRDUDE_EXTERNAL_PATH "${PROJECT_SOURCE_DIR}/external")
# =====================================
# Set up flex target
# Get Git commit info
# =====================================
FLEX_TARGET(Parser "lexer.l" "${PROJECT_BINARY_DIR}/lexer.c")
# GIT_COMMIT_HASH -> hash of latest commit, e.g. b8b859f5
# GIT_COMMIT_DATE -> date of latest commit, e.g. 20201231
# GIT_COMMIT_YEAR -> year of latest commit, e.g. 2020
if (FLEX_VERSION VERSION_GREATER_EQUAL 2.5.9)
set(HAVE_YYLEX_DESTROY 1)
find_package(Git)
if(Git_FOUND)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --format=%h
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_COMMIT_HASH
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --format=%ad --date=format:%Y%m%d
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_COMMIT_DATE
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --format=%ad --date=format:%Y
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_COMMIT_YEAR
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND "${GIT_EXECUTABLE}" log -1 --tags --format=%h
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
OUTPUT_VARIABLE GIT_TAG_HASH
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
)
# If the commit is not tagged, include the date and commit hash in the full version string.
if(NOT GIT_COMMIT_HASH STREQUAL GIT_TAG_HASH)
set(AVRDUDE_FULL_VERSION "${CMAKE_PROJECT_VERSION}-${GIT_COMMIT_DATE} (${GIT_COMMIT_HASH})")
endif()
endif()
# =====================================
# Set up yacc/bison target
# Detect flex and yacc/bison
# =====================================
find_package(FLEX)
if(FLEX_FOUND)
FLEX_TARGET(Parser lexer.l "${PROJECT_BINARY_DIR}/lexer.c")
if (FLEX_VERSION VERSION_GREATER_EQUAL 2.5.9)
set(HAVE_YYLEX_DESTROY 1)
endif()
else()
message(SEND_ERROR "This CMake project requires 'flex', which is not installed on your system." )
endif()
find_package(BISON QUIET)
if(BISON_FOUND)
find_package_message(BISON "Found BISON: ${BISON_EXECUTABLE} (found version \"${BISON_VERSION}\")" "[${BISON_EXECUTABLE}][${BISON_VERSION}]")
BISON_TARGET(Parser config_gram.y "${PROJECT_BINARY_DIR}/config_gram.c" DEFINES_FILE "${PROJECT_BINARY_DIR}/config_gram.h")
else()
set(YACC_TARGET_outputs "${PROJECT_BINARY_DIR}/config_gram.c")
add_custom_command(OUTPUT ${YACC_TARGET_outputs}
COMMAND ${YACC_EXECUTABLE} -d -o ${YACC_TARGET_outputs} config_gram.y
VERBATIM
COMMENT "[YACC][Parser] Building parser with yacc"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
set(BISON_Parser_OUTPUTS ${YACC_TARGET_outputs})
find_program(YACC_EXECUTABLE NAMES yacc byacc DOC "path to the yacc executable")
mark_as_advanced(YACC_EXECUTABLE)
if(YACC_EXECUTABLE)
find_package_message(YACC "Found YACC: ${YACC_EXECUTABLE}" "[${YACC_EXECUTABLE}]")
set(YACC_TARGET_outputs "${PROJECT_BINARY_DIR}/config_gram.c")
add_custom_command(OUTPUT ${YACC_TARGET_outputs}
COMMAND ${YACC_EXECUTABLE} -d -o ${YACC_TARGET_outputs} config_gram.y
VERBATIM
COMMENT "[YACC][Parser] Building parser with yacc"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
set(BISON_Parser_OUTPUTS ${YACC_TARGET_outputs})
else()
message(SEND_ERROR "This CMake project requires 'bison', 'yacc', or 'byacc', which is not installed on your system." )
endif()
endif()
# =====================================
# Detect headers
# =====================================
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stdlib.h HAVE_STDLIB_H)
check_include_file(inttypes.h HAVE_INTTYPES_H)
check_include_file(netinet/in.h HAVE_NETINET_IN_H)
# =====================================
# Detect functions
# =====================================
check_function_exists(usleep HAVE_USLEEP)
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
check_function_exists(gettimeofday HAVE_GETTIMEOFDAY)
check_function_exists(strcasecmp HAVE_STRCASECMP)
# =====================================
# Detect installed libraries
# =====================================
# Prefer static libraries over DLLs on Windows
if(WIN32)
set(PREFERRED_LIBELF libelf.a elf)
set(PREFERRED_LIBUSB libusb.a usb)
set(PREFERRED_LIBUSB_1_0 libusb-1.0.a usb-1.0)
set(PREFERRED_LIBHIDAPI libhidapi.a libhidapi-libusb.a libhidapi-hidraw.a hidapi hidapi-libusb hidapi-hidraw)
set(PREFERRED_LIBFTDI libftdi.a ftdi)
set(PREFERRED_LIBFTDI1 libftdi1.a ftdi1)
else()
set(PREFERRED_LIBELF elf)
set(PREFERRED_LIBUSB usb)
set(PREFERRED_LIBUSB_1_0 usb-1.0)
set(PREFERRED_LIBHIDAPI hidapi hidapi-libusb hidapi-hidraw)
set(PREFERRED_LIBFTDI ftdi)
set(PREFERRED_LIBFTDI1 ftdi1)
endif()
# -------------------------------------
# Find libelf
find_library(HAVE_LIBELF NAMES ${PREFERRED_LIBELF})
if(HAVE_LIBELF)
set(LIB_LIBELF ${HAVE_LIBELF})
check_include_file(libelf.h HAVE_LIBELF_H)
check_include_file(libelf/libelf.h HAVE_LIBELF_LIBELF_H)
endif()
# -------------------------------------
# Find libusb
find_library(HAVE_LIBUSB NAMES ${PREFERRED_LIBUSB})
if(HAVE_LIBUSB)
set(LIB_LIBUSB ${HAVE_LIBUSB})
endif()
find_library(HAVE_LIBUSB_1_0 NAMES ${PREFERRED_LIBUSB_1_0})
if(HAVE_LIBUSB_1_0)
set(LIB_LIBUSB_1_0 ${HAVE_LIBUSB_1_0})
endif()
# FreeBSD's library 'libusb' supports both the libusb-0.1 and libusb-1.0 API.
if (HAVE_LIBUSB AND CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
set(HAVE_LIBUSB_1_0 ${HAVE_LIBUSB})
endif()
find_library(HAVE_LIBUSB_WIN32 NAMES libusb0.a usb0)
if(HAVE_LIBUSB OR HAVE_LIBUSB_1_0 OR HAVE_LIBUSB_WIN32)
check_include_file(usb.h HAVE_USB_H)
check_include_file(lusb0_usb.h HAVE_LUSB0_USB_H)
check_include_file(libusb.h HAVE_LIBUSB_H)
check_include_file(libusb-1.0/libusb.h HAVE_LIBUSB_1_0_LIBUSB_H)
if((USE_LIBUSBWIN32 OR NOT HAVE_LIBUSB) AND HAVE_LIBUSB_WIN32)
set(HAVE_LIBUSB ${HAVE_LIBUSB_WIN32})
set(LIB_LIBUSB ${HAVE_LIBUSB_WIN32})
unset(HAVE_USB_H CACHE)
elseif(NOT HAVE_USB_H)
find_path(LIBUSB_COMPAT_DIR libusb-compat/usb.h)
if(LIBUSB_COMPAT_DIR)
set(LIBUSB_COMPAT_DIR ${LIBUSB_COMPAT_DIR}/libusb-compat)
set(HAVE_USB_H 1)
else()
unset(LIBUSB_COMPAT_DIR CACHE)
endif()
endif()
endif()
# -------------------------------------
# Find libhidapi
find_library(HAVE_LIBHIDAPI NAMES ${PREFERRED_LIBHIDAPI})
if(HAVE_LIBHIDAPI)
set(LIB_LIBHIDAPI ${HAVE_LIBHIDAPI})
check_include_file(hidapi/hidapi.h HAVE_HIDAPI_HIDAPI_H)
endif()
find_library(HAVE_LIBHID NAMES hid)
# -------------------------------------
# Find libftdi
find_library(HAVE_LIBFTDI NAMES ${PREFERRED_LIBFTDI})
if(HAVE_LIBFTDI)
set(LIB_LIBFTDI ${HAVE_LIBFTDI})
set(HAVE_LIBFTDI_TYPE_232H 1)
endif()
find_library(HAVE_LIBFTDI1 NAMES ${PREFERRED_LIBFTDI1})
if(HAVE_LIBFTDI1)
set(LIB_LIBFTDI1 ${HAVE_LIBFTDI1})
set(HAVE_LIBFTDI_TYPE_232H 1)
set(CMAKE_REQUIRED_LIBRARIES ${LIB_LIBFTDI1} ${LIB_LIBUSB} ${LIB_LIBUSB_1_0})
check_symbol_exists(ftdi_tcioflush "libftdi1/ftdi.h" HAVE_FTDI_TCIOFLUSH)
endif()
# -------------------------------------
# Find libreadline
find_library(HAVE_LIBREADLINE NAMES readline)
if(HAVE_LIBREADLINE)
set(LIB_LIBREADLINE ${HAVE_LIBREADLINE})
endif()
# =====================================
# Setup target specific options
# =====================================
include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR})
add_compile_definitions(CONFIG_DIR=\"${CONFIG_DIR}\")
if(WIN32)
set(EXTRA_WINDOWS_RESOURCES "${PROJECT_BINARY_DIR}/src/windows.rc")
set(HAVE_LIBWS2_32 1)
set(EXTRA_WINDOWS_SOURCES "${PROJECT_BINARY_DIR}/windows.rc")
set(EXTRA_WINDOWS_LIBRARIES setupapi ws2_32)
add_compile_definitions(WIN32NATIVE=1)
endif()
if(MSVC)
enable_language(CXX)
add_compile_definitions(_CRT_SECURE_NO_WARNINGS=1)
add_compile_definitions(_CRT_NONSTDC_NO_WARNINGS=1)
add_compile_definitions(_WINSOCK_DEPRECATED_NO_WARNINGS=1)
add_compile_options(/W3)
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(/wd4267) # warning C4267: conversion from '...' to '...', possible loss of data
set(EXTRA_WINDOWS_SOURCES ${EXTRA_WINDOWS_SOURCES}
"msvc/getopt.c"
"msvc/gettimeofday.c"
"msvc/usleep.cpp"
"msvc/readline.cpp"
)
set(EXTRA_WINDOWS_INCLUDES ${EXTRA_WINDOWS_INCLUDES}
"msvc"
)
else()
if(NOT WIN32)
set(LIB_MATH m)
add_compile_options(-Wall) # -Wextra
#add_compile_options(-Wall -Wextra -pedantic)
endif()
# =====================================
@@ -101,44 +290,142 @@ else()
set(DEFAULT_SER_PORT "unknown")
endif()
# =====================================
# Configuration
# =====================================
message(STATUS "Configuration summary:")
message(STATUS "----------------------")
if (DEBUG_CMAKE)
message(STATUS "CMAKE_HOST_SYSTEM: ${CMAKE_HOST_SYSTEM}")
message(STATUS "CMAKE_SYSTEM: ${CMAKE_SYSTEM}")
message(STATUS "CONFIG_DIR: ${CONFIG_DIR}")
message(STATUS "AVRDUDE_FULL_VERSION: ${AVRDUDE_FULL_VERSION}")
message(STATUS "USE_EXTERNAL: ${USE_EXTERNAL}")
message(STATUS "USE_LIBUSBWIN32: ${USE_LIBUSBWIN32}")
message(STATUS "HAVE_LIBELF: ${HAVE_LIBELF}")
message(STATUS "HAVE_LIBUSB: ${HAVE_LIBUSB}")
message(STATUS "HAVE_LIBUSB_1_0: ${HAVE_LIBUSB_1_0}")
message(STATUS "HAVE_LIBUSB_WIN32: ${HAVE_LIBUSB_WIN32}")
message(STATUS "HAVE_LIBHIDAPI: ${HAVE_LIBHIDAPI}")
message(STATUS "HAVE_LIBFTDI: ${HAVE_LIBFTDI}")
message(STATUS "HAVE_LIBFTDI1: ${HAVE_LIBFTDI1}")
message(STATUS "HAVE_LIBREADLINE: ${HAVE_LIBREADLINE}")
message(STATUS "HAVE_LIBWS2_32: ${HAVE_LIBWS2_32}")
message(STATUS "HAVE_LIBELF_H: ${HAVE_LIBELF_H}")
message(STATUS "HAVE_LIBELF_LIBELF_H: ${HAVE_LIBELF_LIBELF_H}")
message(STATUS "HAVE_USB_H: ${HAVE_USB_H}")
message(STATUS "HAVE_LUSB0_USB_H: ${HAVE_LUSB0_USB_H}")
message(STATUS "HAVE_LIBUSB_H: ${HAVE_LIBUSB_H}")
message(STATUS "HAVE_LIBUSB_1_0_LIBUSB_H: ${HAVE_LIBUSB_1_0_LIBUSB_H}")
message(STATUS "HAVE_HIDAPI_HIDAPI_H: ${HAVE_HIDAPI_HIDAPI_H}")
message(STATUS "LIBUSB_COMPAT_DIR: ${LIBUSB_COMPAT_DIR}")
message(STATUS "----------------------")
endif()
if(HAVE_LIBELF)
message(STATUS "DO HAVE libelf")
else()
message(STATUS "DON'T HAVE libelf")
endif()
if(HAVE_LIBUSB)
message(STATUS "DO HAVE libusb")
else()
message(STATUS "DON'T HAVE libusb")
endif()
if(HAVE_LIBUSB_1_0)
message(STATUS "DO HAVE libusb_1_0")
else()
message(STATUS "DON'T HAVE libusb_1_0")
endif()
if(HAVE_LIBHIDAPI)
message(STATUS "DO HAVE libhidapi")
else()
message(STATUS "DON'T HAVE libhidapi")
endif()
if(HAVE_LIBFTDI)
if(HAVE_LIBFTDI1)
message(STATUS "DO HAVE libftdi (but prefer to use libftdi1)")
else()
message(STATUS "DO HAVE libftdi")
endif()
else()
message(STATUS "DON'T HAVE libftdi")
endif()
if(HAVE_LIBFTDI1)
message(STATUS "DO HAVE libftdi1")
else()
message(STATUS "DON'T HAVE libftdi1")
endif()
if(BUILD_DOC)
message(STATUS "ENABLED doc")
else()
message(STATUS "DISABLED doc")
endif()
if(HAVE_PARPORT)
message(STATUS "ENABLED parport")
else()
message(STATUS "DISABLED parport")
endif()
if(HAVE_LINUXGPIO)
message(STATUS "ENABLED linuxgpio")
else()
message(STATUS "DISABLED linuxgpio")
endif()
if(HAVE_LINUXSPI)
message(STATUS "ENABLED linuxspi")
else()
message(STATUS "DISABLED linuxspi")
endif()
message(STATUS "----------------------")
# =====================================
# 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("${PROJECT_BINARY_DIR}/avrdude.conf.in" avrdude.conf)
configure_file(avrdude.spec.in avrdude.spec)
if(WIN32)
configure_file(windows.rc.in windows.rc)
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
# =====================================
add_library(libavrdude
add_library(libavrdude STATIC
ac_cfg.h
arduino.h
arduino.c
avr.c
avr910.c
avr910.h
avrcache.c
avrdude.h
avrftdi.c
avrftdi.h
@@ -185,6 +472,7 @@ add_library(libavrdude
lists.c
micronucleus.c
micronucleus.h
my_ddk_hidsdi.h
par.c
par.h
pgm.c
@@ -195,6 +483,7 @@ add_library(libavrdude
ppi.c
ppi.h
ppiwin.c
safemode.c
serbb.h
serbb_posix.c
serbb_win32.c
@@ -212,8 +501,6 @@ add_library(libavrdude
stk500v2_private.h
stk500generic.c
stk500generic.h
teensy.c
teensy.h
tpi.h
updi_constants.h
updi_link.c
@@ -224,10 +511,6 @@ add_library(libavrdude
updi_readwrite.h
updi_state.c
updi_state.h
urclock.c
urclock.h
urclock_hash.h
urclock_private.h
usbasp.c
usbasp.h
usbdevs.h
@@ -242,16 +525,8 @@ add_library(libavrdude
xbee.c
${FLEX_Parser_OUTPUTS}
${BISON_Parser_OUTPUTS}
"${EXTRA_WINDOWS_SOURCES}"
)
set_target_properties(libavrdude PROPERTIES
PREFIX ""
PUBLIC_HEADER "libavrdude.h"
VERSION 1.0.0
SOVERSION 1
)
target_include_directories(libavrdude
PUBLIC
"${PROJECT_SOURCE_DIR}"
@@ -266,7 +541,6 @@ target_link_libraries(libavrdude
${LIB_LIBELF}
${LIB_LIBUSB}
${LIB_LIBUSB_1_0}
${LIB_LIBHID}
${LIB_LIBHIDAPI}
${LIB_LIBFTDI}
${LIB_LIBFTDI1}
@@ -278,14 +552,9 @@ add_executable(avrdude
main.c
term.c
term.h
avrintel.c
avrintel.h
developer_opts.c
developer_opts.h
developer_opts_private.h
whereami.c
whereami.h
"${EXTRA_WINDOWS_RESOURCES}"
"${EXTRA_WINDOWS_SOURCES}"
)
target_link_libraries(avrdude PUBLIC libavrdude)
@@ -295,12 +564,5 @@ target_link_libraries(avrdude PUBLIC libavrdude)
# =====================================
install(TARGETS avrdude DESTINATION bin)
install(TARGETS libavrdude
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION include COMPONENT dev
)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/avrdude.conf" TYPE SYSCONF)
install(FILES "avrdude.1"
DESTINATION "${CMAKE_INSTALL_MANDIR}/man1"
)
install(FILES "${PROJECT_BINARY_DIR}/avrdude.conf" TYPE SYSCONF)
install(FILES avrdude.1 TYPE MAN)

View File

@@ -1,4 +1,3 @@
#
# avrdude - A Downloader/Uploader for AVR device programmers
# Copyright (C) 2003, 2004 Theodore A. Roth <troth@openavr.org>
@@ -93,7 +92,6 @@ libavrdude_a_SOURCES = \
avr.c \
avr910.c \
avr910.h \
avrcache.c \
avrdude.h \
avrftdi.c \
avrftdi.h \
@@ -140,6 +138,7 @@ libavrdude_a_SOURCES = \
lists.c \
micronucleus.c \
micronucleus.h \
my_ddk_hidsdi.h \
par.c \
par.h \
pgm.c \
@@ -150,6 +149,7 @@ libavrdude_a_SOURCES = \
ppi.c \
ppi.h \
ppiwin.c \
safemode.c \
serbb.h \
serbb_posix.c \
serbb_win32.c \
@@ -165,8 +165,6 @@ libavrdude_a_SOURCES = \
stk500v2_private.h \
stk500generic.c \
stk500generic.h \
teensy.c \
teensy.h \
tpi.h \
usbasp.c \
usbasp.h \
@@ -181,10 +179,6 @@ libavrdude_a_SOURCES = \
updi_readwrite.h \
updi_nvm.c \
updi_nvm.h \
urclock.c \
urclock.h \
urclock_hash.h \
urclock_private.h \
usbdevs.h \
usb_hidapi.c \
usb_libusb.c \
@@ -204,11 +198,6 @@ avrdude_SOURCES = \
main.c \
whereami.c \
whereami.h \
avrintel.c \
avrintel.h \
developer_opts.c \
developer_opts.h \
developer_opts_private.h \
term.c \
term.h

View File

@@ -38,13 +38,14 @@
#include "arduino.h"
/* read signature bytes - arduino version */
static int arduino_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m) {
static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
{
unsigned char buf[32];
/* Signature byte reads are always 3 bytes. */
if (m->size < 3) {
pmsg_error("memsize too small for sig byte read");
avrdude_message(MSG_INFO, "%s: memsize too small for sig byte read", progname);
return -1;
}
@@ -56,16 +57,19 @@ static int arduino_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const
if (serial_recv(&pgm->fd, buf, 5) < 0)
return -1;
if (buf[0] == Resp_STK_NOSYNC) {
pmsg_error("programmer is out of sync\n");
avrdude_message(MSG_INFO, "%s: stk500_cmd(): programmer is out of sync\n",
progname);
return -1;
} else if (buf[0] != Resp_STK_INSYNC) {
msg_error("\n");
pmsg_error("protocol expects sync byte 0x%02x but got 0x%02x\n", Resp_STK_INSYNC, buf[0]);
return -2;
avrdude_message(MSG_INFO, "\n%s: arduino_read_sig_bytes(): (a) protocol error, "
"expect=0x%02x, resp=0x%02x\n",
progname, Resp_STK_INSYNC, buf[0]);
return -2;
}
if (buf[4] != Resp_STK_OK) {
msg_error("\n");
pmsg_error("protocol expects OK byte 0x%02x but got 0x%02x\n", Resp_STK_OK, buf[4]);
avrdude_message(MSG_INFO, "\n%s: arduino_read_sig_bytes(): (a) protocol error, "
"expect=0x%02x, resp=0x%02x\n",
progname, Resp_STK_OK, buf[4]);
return -3;
}
@@ -76,7 +80,8 @@ static int arduino_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const
return 3;
}
static int arduino_open(PROGRAMMER *pgm, const char *port) {
static int arduino_open(PROGRAMMER * pgm, char * port)
{
union pinfo pinfo;
strcpy(pgm->port, port);
pinfo.serialinfo.baud = pgm->baudrate? pgm->baudrate: 115200;
@@ -113,7 +118,8 @@ static void arduino_close(PROGRAMMER * pgm)
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
differently than on real STK500v1
and the DTR signal is set when opening the serial port
@@ -124,6 +130,4 @@ void arduino_initpgm(PROGRAMMER *pgm) {
pgm->read_sig_bytes = arduino_read_sig_bytes;
pgm->open = arduino_open;
pgm->close = arduino_close;
disable_trailing_ff_removal(); /* so that arduino bootloader can ignore chip erase */
}

View File

@@ -22,7 +22,7 @@
#define arduino_h__
extern const char arduino_desc[];
void arduino_initpgm(PROGRAMMER *pgm);
void arduino_initpgm (PROGRAMMER * pgm);
#endif

923
src/avr.c

File diff suppressed because it is too large Load Diff

View File

@@ -57,7 +57,8 @@ struct pdata
static void avr910_setup(PROGRAMMER * pgm)
{
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
pmsg_error("out of memory allocating private data\n");
avrdude_message(MSG_INFO, "%s: avr910_setup(): Out of memory allocating private data\n",
progname);
exit(1);
}
memset(pgm->cookie, 0, sizeof(struct pdata));
@@ -70,34 +71,40 @@ static void avr910_teardown(PROGRAMMER * pgm)
}
static int avr910_send(const PROGRAMMER *pgm, char *buf, size_t len) {
static int avr910_send(PROGRAMMER * pgm, char * buf, size_t len)
{
return serial_send(&pgm->fd, (unsigned char *)buf, len);
}
static int avr910_recv(const PROGRAMMER *pgm, char *buf, size_t len) {
static int avr910_recv(PROGRAMMER * pgm, char * buf, size_t len)
{
int rv;
rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
if (rv < 0) {
pmsg_error("programmer is not responding\n");
avrdude_message(MSG_INFO, "%s: avr910_recv(): programmer is not responding\n",
progname);
return 1;
}
return 0;
}
static int avr910_drain(const PROGRAMMER *pgm, int display) {
static int avr910_drain(PROGRAMMER * pgm, int display)
{
return serial_drain(&pgm->fd, display);
}
static int avr910_vfy_cmd_sent(const PROGRAMMER *pgm, char *errmsg) {
static int avr910_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg)
{
char c;
avr910_recv(pgm, &c, 1);
if (c != '\r') {
pmsg_error("programmer did not respond to command: %s\n", errmsg);
avrdude_message(MSG_INFO, "%s: error: programmer did not respond to command: %s\n",
progname, errmsg);
return 1;
}
return 0;
@@ -107,7 +114,8 @@ static int avr910_vfy_cmd_sent(const PROGRAMMER *pgm, char *errmsg) {
/*
* issue the 'chip erase' command to the AVR device
*/
static int avr910_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
static int avr910_chip_erase(PROGRAMMER * pgm, AVRPART * p)
{
avr910_send(pgm, "e", 1);
if (avr910_vfy_cmd_sent(pgm, "chip erase") < 0)
return -1;
@@ -121,13 +129,15 @@ static int avr910_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
}
static int avr910_enter_prog_mode(const PROGRAMMER *pgm) {
static int avr910_enter_prog_mode(PROGRAMMER * pgm)
{
avr910_send(pgm, "P", 1);
return avr910_vfy_cmd_sent(pgm, "enter prog mode");
}
static int avr910_leave_prog_mode(const PROGRAMMER *pgm) {
static int avr910_leave_prog_mode(PROGRAMMER * pgm)
{
avr910_send(pgm, "L", 1);
return avr910_vfy_cmd_sent(pgm, "leave prog mode");
}
@@ -136,7 +146,8 @@ static int avr910_leave_prog_mode(const PROGRAMMER *pgm) {
/*
* issue the 'program enable' command to the AVR device
*/
static int avr910_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
static int avr910_program_enable(PROGRAMMER * pgm, AVRPART * p)
{
return -1;
}
@@ -144,7 +155,8 @@ static int avr910_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
/*
* initialize the AVR device and prepare it to accept commands
*/
static int avr910_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
static int avr910_initialize(PROGRAMMER * pgm, AVRPART * p)
{
char id[8];
char sw[2];
char hw[2];
@@ -173,16 +185,16 @@ static int avr910_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
avr910_send(pgm, "p", 1);
avr910_recv(pgm, &type, 1);
msg_notice("Programmer id = %s; type = %c\n", id, type);
msg_notice("Software version = %c.%c; ", sw[0], sw[1]);
msg_notice("Hardware version = %c.%c\n", hw[0], hw[1]);
avrdude_message(MSG_INFO, "Found programmer: Id = \"%s\"; type = %c\n", id, type);
avrdude_message(MSG_INFO, " Software Version = %c.%c; ", sw[0], sw[1]);
avrdude_message(MSG_INFO, "Hardware Version = %c.%c\n", hw[0], hw[1]);
/* See if programmer supports autoincrement of address. */
avr910_send(pgm, "a", 1);
avr910_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1);
if (PDATA(pgm)->has_auto_incr_addr == 'Y')
msg_notice("programmer supports auto addr increment\n");
avrdude_message(MSG_INFO, "Programmer supports auto addr increment.\n");
/* Check support for buffered memory access, ignore if not available */
@@ -194,8 +206,8 @@ static int avr910_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8;
avr910_recv(pgm, &c, 1);
PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c;
msg_notice("programmer supports buffered memory access with "
"buffersize = %u bytes\n",
avrdude_message(MSG_INFO, "Programmer supports buffered memory access with "
"buffersize = %u bytes.\n",
PDATA(pgm)->buffersize);
PDATA(pgm)->use_blockmode = 1;
} else {
@@ -212,7 +224,7 @@ static int avr910_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
/* Get list of devices that the programmer supports. */
avr910_send(pgm, "t", 1);
msg_notice2("\nProgrammer supports the following devices:\n");
avrdude_message(MSG_INFO, "\nProgrammer supports the following devices:\n");
devtype_1st = 0;
while (1) {
avr910_recv(pgm, &c, 1);
@@ -222,22 +234,20 @@ static int avr910_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
break;
part = locate_part_by_avr910_devcode(part_list, c);
msg_notice2(" Device code: 0x%02x = %s\n", c & 0xff, part? part->desc: "(unknown)");
avrdude_message(MSG_INFO, " Device code: 0x%02x = %s\n", c, part ? part->desc : "(unknown)");
/* FIXME: Need to lookup devcode and report the device. */
if (p->avr910_devcode == c)
dev_supported = 1;
};
msg_notice2("\n");
avrdude_message(MSG_INFO, "\n");
if (!dev_supported) {
if(ovsigck)
pmsg_warning("selected device is not supported by programmer %s\n", p->id);
else {
pmsg_error("selected device is not supported by programmer %s\n", p->id);
avrdude_message(MSG_INFO, "%s: %s: selected device is not supported by programmer: %s\n",
progname, ovsigck? "warning": "error", p->id);
if (!ovsigck)
return -1;
}
}
/* If the user forced the selection, use the first device
type that is supported by the programmer. */
@@ -254,7 +264,8 @@ static int avr910_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
avr910_send(pgm, buf, 2);
avr910_vfy_cmd_sent(pgm, "select device");
pmsg_notice("avr910_devcode selected: 0x%02x\n", (unsigned) buf[1]);
avrdude_message(MSG_NOTICE, "%s: avr910_devcode selected: 0x%02x\n",
progname, (unsigned)buf[1]);
avr910_enter_prog_mode(pgm);
@@ -262,14 +273,16 @@ static int avr910_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
}
static void avr910_disable(const PROGRAMMER *pgm) {
static void avr910_disable(PROGRAMMER * pgm)
{
/* Do nothing. */
return;
}
static void avr910_enable(PROGRAMMER *pgm, const AVRPART *p) {
static void avr910_enable(PROGRAMMER * pgm)
{
/* Do nothing. */
return;
@@ -280,7 +293,7 @@ static void avr910_enable(PROGRAMMER *pgm, const AVRPART *p) {
* transmit an AVR device command and return the results; 'cmd' and
* 'res' must point to at least a 4 byte data buffer
*/
static int avr910_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
static int avr910_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
unsigned char *res)
{
char buf[5];
@@ -305,7 +318,8 @@ static int avr910_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
}
static int avr910_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
static int avr910_parseextparms(PROGRAMMER * pgm, LISTID extparms)
{
LNODEID ln;
const char *extended_param;
int rv = 0;
@@ -317,23 +331,27 @@ static int avr910_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
int devcode;
if (sscanf(extended_param, "devcode=%i", &devcode) != 1 ||
devcode <= 0 || devcode > 255) {
pmsg_error("invalid devcode '%s'\n", extended_param);
avrdude_message(MSG_INFO, "%s: avr910_parseextparms(): invalid devcode '%s'\n",
progname, extended_param);
rv = -1;
continue;
}
pmsg_notice2("avr910_parseextparms(): devcode overwritten as 0x%02x\n", devcode);
avrdude_message(MSG_NOTICE2, "%s: avr910_parseextparms(): devcode overwritten as 0x%02x\n",
progname, devcode);
PDATA(pgm)->devcode = devcode;
continue;
}
if (strncmp(extended_param, "no_blockmode", strlen("no_blockmode")) == 0) {
pmsg_notice2("avr910_parseextparms(-x): no testing for Blockmode\n");
avrdude_message(MSG_NOTICE2, "%s: avr910_parseextparms(-x): no testing for Blockmode\n",
progname);
PDATA(pgm)->test_blockmode = 0;
continue;
}
pmsg_error("invalid extended parameter '%s'\n", extended_param);
avrdude_message(MSG_INFO, "%s: avr910_parseextparms(): invalid extended parameter '%s'\n",
progname, extended_param);
rv = -1;
}
@@ -341,7 +359,8 @@ static int avr910_parseextparms(const PROGRAMMER *pgm, const LISTID extparms) {
}
static int avr910_open(PROGRAMMER *pgm, const char *port) {
static int avr910_open(PROGRAMMER * pgm, char * port)
{
union pinfo pinfo;
/*
* If baudrate was not specified use 19.200 Baud
@@ -374,12 +393,14 @@ static void avr910_close(PROGRAMMER * pgm)
}
static void avr910_display(const PROGRAMMER *pgm, const char *p) {
static void avr910_display(PROGRAMMER * pgm, const char * p)
{
return;
}
static void avr910_set_addr(const PROGRAMMER *pgm, unsigned long addr) {
static void avr910_set_addr(PROGRAMMER * pgm, unsigned long addr)
{
char cmd[3];
cmd[0] = 'A';
@@ -391,7 +412,7 @@ static void avr910_set_addr(const PROGRAMMER *pgm, unsigned long addr) {
}
static int avr910_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avr910_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char value)
{
char cmd[2];
@@ -424,7 +445,7 @@ static int avr910_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRM
}
static int avr910_read_byte_flash(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avr910_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char * value)
{
char buf[2];
@@ -447,7 +468,7 @@ static int avr910_read_byte_flash(const PROGRAMMER *pgm, const AVRPART *p, const
}
static int avr910_read_byte_eeprom(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avr910_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char * value)
{
avr910_set_addr(pgm, addr);
@@ -458,7 +479,7 @@ static int avr910_read_byte_eeprom(const PROGRAMMER *pgm, const AVRPART *p, cons
}
static int avr910_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avr910_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char * value)
{
if (strcmp(m->desc, "flash") == 0) {
@@ -473,7 +494,7 @@ static int avr910_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRME
}
static int avr910_paged_write_flash(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avr910_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size,
unsigned int addr, unsigned int n_bytes)
{
@@ -532,8 +553,8 @@ static int avr910_paged_write_flash(const PROGRAMMER *pgm, const AVRPART *p, con
}
static int avr910_paged_write_eeprom(const PROGRAMMER *pgm, const AVRPART *p,
const AVRMEM * m,
static int avr910_paged_write_eeprom(PROGRAMMER * pgm, AVRPART * p,
AVRMEM * m,
unsigned int page_size,
unsigned int addr, unsigned int n_bytes)
{
@@ -561,7 +582,7 @@ static int avr910_paged_write_eeprom(const PROGRAMMER *pgm, const AVRPART *p,
}
static int avr910_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avr910_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size,
unsigned int addr, unsigned int n_bytes)
{
@@ -621,7 +642,7 @@ static int avr910_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVR
}
static int avr910_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avr910_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size,
unsigned int addr, unsigned int n_bytes)
{
@@ -698,11 +719,12 @@ static int avr910_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRM
/* Signature byte reads are always 3 bytes. */
static int avr910_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m) {
static int avr910_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
{
unsigned char tmp;
if (m->size < 3) {
pmsg_error("memsize too small for sig byte read");
avrdude_message(MSG_INFO, "%s: memsize too small for sig byte read", progname);
return -1;
}
@@ -718,7 +740,8 @@ static int avr910_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const
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");
/*

View File

@@ -26,7 +26,7 @@ extern "C" {
#endif
extern const char avr910_desc[];
void avr910_initpgm(PROGRAMMER *pgm);
void avr910_initpgm (PROGRAMMER * pgm);
#ifdef __cplusplus
}

View File

@@ -1,774 +0,0 @@
/*
* 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;
}

View File

@@ -18,7 +18,7 @@
.\"
.\" $Id$
.\"
.Dd July 12, 2022
.Dd DATE November 22, 2021
.Os
.Dt AVRDUDE 1
.Sh NAME
@@ -31,7 +31,6 @@
.Op Fl B Ar bitclock
.Op Fl c Ar programmer-id
.Op Fl C Ar config-file
.Op Fl A
.Op Fl D
.Op Fl e
.Oo Fl E Ar exitspec Ns
@@ -39,12 +38,14 @@
.Oc
.Op Fl F
.Op Fl i Ar delay
.Op Fl l Ar logfile
.Op Fl n logfile
.Op Fl n
.Op Fl O
.Op Fl P Ar port
.Op Fl q
.Op Fl s
.Op Fl t
.Op Fl u
.Op Fl U Ar memtype:op:filename:filefmt
.Op Fl v
.Op Fl x Ar extended_param
@@ -75,12 +76,10 @@ so, for the
based programmer, the MCU signals
.Ql /RESET ,
.Ql SCK ,
.Ql SDI
.Ql MISO
and
.Ql SDO
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
.Ql MOSI
need to be connected to the parallel port. Optionally, some otherwise
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
stand-alone programming device. Some status LEDs indicating the
@@ -100,14 +99,14 @@ work at all, or to work abysmally slow.
.Pp
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
any additional hardware - just connect them to the SDO, SDI, RESET
any additional hardware - just connect them to the MOSI, MISO, RESET
and SCK pins on the AVR and use the linuxgpio programmer type. It bitbangs
the lines using the Linux sysfs GPIO interface. Of course, care should
be taken about voltage level compatibility. Also, although not strictly
be taken about voltage level compatibility. Also, although not strictrly
required, it is strongly advisable to protect the GPIO pins from
overcurrent situations in some way. The simplest would be to just put
some resistors in series or better yet use a 3-state buffer driver like
the 74HC244. Have a look at http://kolev.info/blog/2013/01/06/avrdude-linuxgpio/ for a more
the 74HC244. Have a look at http://kolev.info/avrdude-linuxgpio for a more
detailed tutorial about using this programmer type.
.Pp
Under a Linux installation with direct access to the SPI bus and GPIO
@@ -116,7 +115,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
this type are that an SPI interface is exposed along with one GPIO
pin. The GPIO serves as the reset output since the Linux SPI drivers
do not hold chip select down when a transfer is not occurring and thus
do not hold slave select down when a transfer is not occuring and thus
it cannot be used as the reset pin. A readily available level
translator should be used between the SPI bus/reset GPIO and the chip
to avoid potentially damaging the computer's SPI controller in the
@@ -149,23 +148,9 @@ programming mode. The programmer type is ``wiring''. Note that the -D option
will likely be required in this case, because the bootloader will rewrite the
program memory, but no true chip erase can be performed.
.Pp
Serial bootloaders that run a skeleton of the STK500 1.x protocol are
supported via their own programmer type ``arduino''. This programmer works
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.
The Arduino (which is very similar to the STK500 1.x) is supported via
its own programmer type specification ``arduino''. This programmer works for
the Arduino Uno Rev3.
.Pp
The BusPirate is a versatile tool that can also be used as an AVR programmer.
A single BusPirate can be connected to up to 3 independent AVRs. See
@@ -194,7 +179,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.
.Pp
Atmel-ICE (ARM/AVR) is supported in all modes (JTAG, PDI for Xmega, debugWIRE,
ISP, UPDI).
ISP).
.Pp
Atmel's XplainedPro boards, using the EDBG protocol (CMSIS-DAP compatible),
are supported using the "jtag3" programmer type.
@@ -225,14 +210,13 @@ has been compiled in
.Nm avrdude ,
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)
SCK to bit 1, SDO to bit 2, and SDI to bit 3. Reset is usually bit 4.
SCK to bit 1, MOSI to bit 2, and MISO to bit 3. Reset is usually bit 4.
.Pp
The Atmel DFU bootloader is supported in both, FLIP protocol version 1
(AT90USB* and ATmega*U* devices), as well as version 2 (Xmega devices).
See below for some hints about FLIP version 1 protocol behaviour.
.Pp
The MPLAB(R) PICkit 4 and MPLAB(R) SNAP, are supported in JTAG, TPI, ISP,
PDI and UPDI mode.
The MPLAB(R) PICkit 4 and MPLAB(R) SNAP, are supported in ISP, PDI and UPDI mode.
The Curiosity Nano board is supported in UPDI mode. It is dubbed
.Dq PICkit on Board ,
thus the name
@@ -241,7 +225,7 @@ thus the name
SerialUPDI programmer implementation is based on Microchip's
.Em pymcuprog Li https://github.com/microchip-pic-avr-tools/pymcuprog
utility, but it also contains some performance improvements included in
Spence Konde's
Spence Kohde's
.Em DxCore
Arduino core
.Li https://github.com/SpenceKonde/DxCore .
@@ -260,20 +244,11 @@ The Micronucleus bootloader is supported for both protocol version V1
and V2. As the bootloader does not support reading from flash memory,
use the
.Fl V
option to prevent AVRDUDE from verifying the flash memory.
option to prevent AVRDUDE from verifing the flash memory.
See the section on
.Em extended parameters
for Micronucleus specific options.
.Pp
The Teensy bootloader is supported for all AVR boards.
As the bootloader does not support reading from flash memory,
use the
.Fl V
option to prevent AVRDUDE from verifying the flash memory.
See the section on
.Em extended parameters
for Teensy specific options.
.Pp
Input files can be provided, and output files can be written in
different file formats, such as raw binary files containing the data
to download to the chip, Intel hex format, or Motorola S-record
@@ -310,7 +285,7 @@ file. Finally, a ``terminal'' mode is available that allows one to
interactively communicate with the MCU, and to display or program
individual memory cells.
On the STK500 and STK600 programmer, several operational parameters (target supply
voltage, target Aref voltage, programming clock) can be examined and changed
voltage, target Aref voltage, master clock) can be examined and changed
from within terminal mode as well.
.Ss Options
In order to control all the different operation modi, a number of options
@@ -318,15 +293,10 @@ need to be specified to
.Nm avrdude .
.Bl -tag -offset indent -width indent
.It Fl p Ar partno
This option specifies the MCU connected to the programmer. The MCU
descriptions are read from the config file. For currently supported MCUs use
? as partno, which will print a list of partno ids and official part names.
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.
This is the only option that is mandatory for every invocation of
.Nm avrdude .
It specifies the type of the MCU connected to the programmer. These are read from the config file.
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.)
.Pp
Following parts need special attention:
.Bl -tag -width "ATmega1234"
@@ -345,29 +315,22 @@ and bit-bang programmers.
The ATtiny11 can only be
programmed in high-voltage serial mode.
.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
Override the RS-232 connection baud rate specified in the respective
programmer's entry of the configuration file.
.It Fl B Ar bitclock
Specify the bit clock period for the JTAG, PDI, TPI, UPDI, or ISP
interface. The value is a floating-point number in microseconds.
Alternatively, the value might be suffixed with "Hz", "kHz" or
"MHz" in order to specify the bit clock frequency rather than a
period. Some programmers default their bit clock value to a 1
microsecond bit clock period, suitable for target MCUs running at 4
MHz clock and above. Slower MCUs need a correspondingly higher bit
clock period. Some programmers reset their bit clock value to the
default value when the programming software signs off, whilst others
store the last used bit clock value. It is recommended to always
specify the bit clock if read/write speed is important.
Specify the bit clock period for the JTAG interface or the ISP clock (JTAG ICE only).
The value is a floating-point number in microseconds.
Alternatively, the value might be suffixed with "Hz", "kHz", or "MHz",
in order to specify the bit clock frequency, rather than a period.
The default value of the JTAG ICE results in about 1 microsecond bit
clock period, suitable for target MCUs running at 4 MHz clock and
above.
Unlike certain parameters in the STK500, the JTAG ICE resets all its
parameters to default values when the programming software signs
off from the ICE, so for MCUs running at lower clock speeds, this
parameter must be specified on the command-line.
You can use the 'default_bitclock' keyword in your
.Pa ${HOME}/.config/avrdude/avrdude.rc
or
.Pa ${HOME}/.avrduderc
file to assign a default value to keep from having to specify this
option on every invocation.
@@ -381,23 +344,11 @@ through the use of a config file to make
work with different programmers as long as the programmer supports the
Atmel AVR serial program method. You can use the 'default_programmer'
keyword in your
.Pa ${HOME}/.config/avrdude/avrdude.rc
or
.Pa ${HOME}/.avrduderc
file to assign a default programmer to keep from having to specify
this option on every invocation.
A full list of all supported programmers is output to the terminal
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
Use the specified config file to load configuration data. This file
contains all programmer and part definitions that
@@ -416,20 +367,6 @@ files. This can be used to add entries to the configuration
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
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
Disable auto erase for flash. When the
.Fl U
@@ -443,10 +380,6 @@ use page erase before writing each page so no explicit chip erase
is required.
Note however that any page not affected by the current operation
will retain its previous contents.
Setting
.Fl D
implies
.Fl A.
.It Fl e
Causes a chip erase to be executed. This will reset the contents of the
flash ROM and EEPROM to the value
@@ -459,7 +392,7 @@ contents would exclusively cause bits to be programmed from the value
.Ql 1
to
.Ql 0 .
Note that in order to reprogram EEPROM cells, no explicit prior chip
Note that in order to reprogram EERPOM cells, no explicit prior chip
erase is required since the MCU provides an auto-erase cycle in that
case before programming the cell.
.It Xo Fl E Ar exitspec Ns
@@ -492,17 +425,11 @@ MCU type, a previous invocation of
.Nm
with this option specified is one of the possible ways to guarantee this
condition.
.Em reset
is supported by the linuxspi and flip2 programmer options, as well as all
parallel port based programmers.
.It Ar noreset
The
.Ql /RESET
line will be deactivated at program exit, thus allowing the MCU target
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
This option will leave those parallel port pins active
.Pq \&i. \&e. Em high
@@ -538,8 +465,6 @@ actual connection to a target controller), this option can be used
together with
.Fl t
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
For bitbang-type programmers, delay for approximately
.Ar delay
@@ -624,9 +549,9 @@ be specified as
Libhidapi support is required on Unix and Mac OS but not on Windows. For more
information about AVR-Doper see http://www.obdev.at/avrusb/avrdoper.html.
.Pp
For the USBtinyISP, which is a simplistic device not implementing
For the USBtinyISP, which is a simplicistic device not implementing
serial numbers, multiple devices can be distinguished by their
location in the USB hierarchy. See the respective
location in the USB hierarchy. See the the respective
.Em Troubleshooting
entry in the detailed documentation for examples.
.Pp
@@ -672,15 +597,41 @@ Note: The ability to handle IPv6 hostnames and addresses is limited to
Posix systems (by now).
.It Fl q
Disable (or quell) output of the progress bar while reading or writing
to the device. Specify it 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.
to the device. Specify it a second time for even quieter operation.
.It Fl s
Disable safemode prompting. When safemode discovers that one or more
fuse bits have unintentionally changed, it will prompt for
confirmation regarding whether or not it should attempt to recover the
fuse bit(s). Specifying this flag disables the prompt and assumes
that the fuse bit(s) should be recovered without asking for
confirmation first.
.It Fl t
Tells
.Nm
to enter the interactive ``terminal'' mode instead of up- or downloading
files. See below for a detailed description of the terminal mode.
.It Fl u
Disable the safemode fuse bit checks. Safemode is enabled by default
and is intended to prevent unintentional fuse bit changes. When
enabled, safemode will issue a warning if the any fuse bits are found
to be different at program exit than they were when
.Nm
was invoked. Safemode won't alter fuse bits itself, but rather will
prompt for instructions, unless the terminal is non-interactive, in
which case safemode is disabled. See the
.Fl s
option to disable safemode prompting.
.Pp
If one of the configuration files has a line
.Dl "default_safemode = no;"
safemode is disabled by default.
The
.Fl u
option's effect is negated in that case, i. e. it
.Em enables
safemode.
.Pp
Safemode is always disabled for AVR32, Xmega and TPI devices.
.It Xo Fl U Ar memtype Ns
.Ar \&: Ns Ar op Ns
.Ar \&: Ns Ar filename Ns
@@ -759,8 +710,6 @@ can be one of:
.Bl -tag -width sss
.It Ar i
Intel Hex
.It Ar I
Intel Hex with comments on download and tolerance of checksum errors on upload
.It Ar s
Motorola S-record
.It Ar r
@@ -785,17 +734,14 @@ fuse bit settings.
hexadecimal; each value will get the string
.Em 0x
prepended.
Only valid on output.
.It Ar o
octal; each value will get a
.Em 0
prepended unless it is less than 8 in which case it gets no prefix.
Only valid on output.
.It Ar b
binary; each value will get the string
.Em 0b
prepended.
Only valid on output.
.El
.Pp
The default is to use auto detection for input files, and raw binary
@@ -845,128 +791,30 @@ abbreviated to the shortest unambiguous form. Terminal mode provides
a command history using
.Xr readline 3 ,
so previously entered command lines can be recalled and edited. The
following commands are currently implemented for all programmers:
following commands are currently implemented:
.Bl -tag -offset indent -width indent
.It Ar dump memory addr len
.It Ar dump memtype addr nbytes
Read
.Ar len
.Ar nbytes
bytes from the specified memory area, and display them in the usual
hexadecimal and ASCII form.
.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
.It Ar dump
Continue dumping the memory contents for another
.Ar 256
bytes where the previous
.Ar nbytes
where the previous
.Ar dump
command left off.
.It Ar read
can be used as an alias for dump
.It Ar write memory addr data[,] {data[,]}
.It Ar write memtype addr byte1 ... byteN
Manually program the respective memory cells, starting at address
.Ar addr ,
using the data items provided.
The terminal implements reading from and writing to flash and EEPROM type
memories normally through a cache and paged access functions. All other
memories are directly written to without use of a cache. Some
older parts without paged access will also have flash and EEPROM directly
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.
using the values
.Ar byte1
through
.Ar byteN .
This feature is not implemented for bank-addressed memories such as
the flash memory of ATMega devices.
.It Ar 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.
Perform a chip erase.
.It Ar send b1 b2 b3 b4
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
@@ -975,18 +823,24 @@ this command allows you to use it, even though
.Nm
does not implement the command. When using direct SPI mode, up to 3 bytes
can be omitted.
.It Ar sig
Display the device signature bytes.
.It Ar spi
Enter direct SPI mode. The
.Em pgmled
pin acts as chip select.
.Em Supported on parallel bitbang programmers, and partially by USBtiny.
pin acts as slave select.
.Em Only supported on parallel bitbang programmers.
.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
Return to programming mode (from direct SPI mode).
.It Ar vtarg voltage
Set the target's supply voltage to
.Ar voltage
Volts.
.Em Supported on the STK500 and STK600 programmer.
.Em Only supported on the STK500 and STK600 programmer.
.It Ar varef Oo Ar channel Oc Ar voltage
Set the adjustable voltage source to
.Ar voltage
@@ -998,9 +852,9 @@ On the Atmel STK600, two reference voltages are available, which
can be selected by the optional
.Ar channel
argument (either 0 or 1).
.Em Supported on the STK500 and STK600 programmer.
.Em Only supported on the STK500 and STK600 programmer.
.It Ar fosc freq Ns Op M Ns \&| Ns k
Set the programming oscillator to
Set the master oscillator to
.Ar freq
Hz.
An optional trailing letter
@@ -1008,16 +862,17 @@ An optional trailing letter
multiplies by 1E6, a trailing letter
.Ar \&k
by 1E3.
.Em Supported on the STK500 and STK600 programmer.
.Em Only supported on the STK500 and STK600 programmer.
.It Ar fosc off
Turn the programming oscillator off.
.Em Supported on the STK500 and STK600 programmer.
Turn the master oscillator off.
.Em Only supported on the STK500 and STK600 programmer.
.It Ar sck period
.Em STK500 and STK600 programmer:
.Em STK500 and STK600 programmer only:
Set the SCK clock period to
.Ar period
microseconds.
.Em JTAG ICE:
.Pp
.Em JTAG ICE only:
Set the JTAG ICE bit clock period to
.Ar period
microseconds.
@@ -1027,12 +882,24 @@ 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
ISP clock period when operating the ICE in ISP mode.
.It Ar parms
.Em STK500 and STK600 programmer:
Display the current voltage and programming oscillator parameters.
.Em JTAG ICE:
.Em STK500 and STK600 programmer only:
Display the current voltage and master oscillator parameters.
.Pp
.Em JTAG ICE only:
Display the current target supply voltage and JTAG bit clock rate/period.
.Em Other programmers:
Display the programmer specific parameters.
.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 \&?
.It Ar help
Give a short on-line summary of the available commands.
.It Ar quit
Leave terminal mode and thus
.Nm avrdude .
.El
.Ss Default Parallel port pin connections
(these can be changed, see the
@@ -1044,8 +911,8 @@ ll.
2-5 Vcc (optional power supply to MCU)
7 /RESET (to MCU)
8 SCK (to MCU)
9 SDO (to MCU)
10 SDI (from MCU)
9 MOSI (to MCU)
10 MISO (from MCU)
18-25 GND
.TE
.Ss debugWire limitations
@@ -1112,13 +979,9 @@ versions of the bootloader.
.It Ar JTAG ICE mkII
.It Ar JTAGICE3
.It Ar Atmel-ICE
.It Ar Power Debugger
.It Ar PICkit 4
.It Ar MPLAB SNAP
.It Ar AVR Dragon
When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE, PICkit 4, MPLAB SNAP,
Power Debugger or AVR Dragon in JTAG mode, the following extended parameter
is accepted:
When using the JTAG ICE mkII, JTAGICE3, Atmel-ICE or AVR Dragon in JTAG mode, the
following extended parameter is accepted:
.Bl -tag -offset indent -width indent
.It Ar jtagchain=UB,UA,BB,BA
Setup the JTAG scan chain for
@@ -1133,14 +996,6 @@ bits after the target AVR, respectively.
Each AVR unit within the chain shifts by 4 bits.
Other JTAG units might require a different bit shift count.
.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
.Bl -tag -offset indent -width indent
.It Ar devcode=VALUE
@@ -1166,125 +1021,12 @@ only if your
.Ar AVR910
programmer creates errors during initial sequence.
.El
.It Ar Arduino
.Bl -tag -offset indent -width indent
.It Ar attemps[=<1..99>]
Specify how many connection retry attemps to perform before exiting.
Defaults to 10 if not specified.
.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
.Bl -tag -offset indent -width indent
.It Ar reset={cs,aux,aux2}
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
connected to the same BP with SDI, SDO and SCK lines common for all of them.
connected to the same BP with MISO, MOSI and SCK lines common for all of them.
In such a case one AVR should have its RESET connected to BusPirate's
.Pa CS
pin, second AVR's RESET connected to BusPirate's
@@ -1368,16 +1110,6 @@ specifies the connection time-out in seconds.
If no time-out is specified, AVRDUDE will wait indefinitely until the
device is plugged in.
.El
.It Ar Teensy bootloader
.Bl -tag -offset indent -width indent
.It Ar wait[=<timeout>]
If the device is not connected, wait for the device to be plugged in.
The optional
.Ar timeout
specifies the connection time-out in seconds.
If no time-out is specified, AVRDUDE will wait indefinitely until the
device is plugged in.
.El
.It Ar Wiring
When using the Wiring programmer type, the
following optional extended parameter is accepted:
@@ -1397,9 +1129,9 @@ Connection to the PICkit2 programmer:
RST - VPP/MCLR (1)
VDD - VDD Target (2) -- possibly optional if AVR self powered
GND - GND (3)
SDI - PGD (4)
MISO - PGD (4)
SCLK - PDC (5)
SDO - AUX (6)
MOSI - AUX (6)
.Ed
Extended commandline parameters:
@@ -1435,39 +1167,14 @@ line, and the XBee DIN pin (pin 3) must be connected to the MCU's
.Ql TXD
line.
.El
.It Ar STK500
.Bl -tag -offset indent -width indent
.It Ar attemps[=<1..99>]
Specify how many connection retry attemps to perform before exiting.
Defaults to 10 if not specified.
.El
.It Ar serialupdi
Extended parameters:
.Bl -tag -offset indent -width indent
.It Ar rtsdtr=low|high
Forces RTS/DTR lines to assume low or high state during the whole
programming session. Some programmers might use this signal to
indicate UPDI programming state, but this is strictly hardware
specific.
.Pp
When not provided, driver/OS default value will be used.
.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
.Sh FILES
.Bl -tag -offset indent -width /dev/ppi0XXX
.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
.It Pa avrdude.conf
Programmer and parts configuration file
programmer and parts configuration file
.Pp
On Windows systems, this file is looked up in the same directory as the
executable file.
@@ -1476,22 +1183,14 @@ On all other systems, the file is first looked up in
relative to the path of the executable, then in the same directory as
the executable itself, and finally in the system default location
.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
Alternative location of the per-user configuration file if above file does not exist
programmer and parts configuration file (per-user overrides)
.It Pa ~/.inputrc
Initialization file for the
.Xr readline 3
library
.It Pa <prefix>/doc/avrdude/avrdude.pdf
User manual
.It Pa ${PREFIX}/share/doc/avrdude/avrdude.pdf
Schematic of programming hardware
.El
.\" .Sh EXAMPLES
.Sh DIAGNOSTICS
@@ -1538,7 +1237,7 @@ This man page by
.el Joerg Wunsch.
.Sh BUGS
Please report bugs via
.Dl "https://github.com/avrdudes/avrdude/issues"
.Dl "http://savannah.nongnu.org/bugs/?group=avrdude" .
.Pp
The JTAG ICE programmers currently cannot write to the flash ROM
one byte at a time.
@@ -1555,9 +1254,6 @@ The USBasp and USBtinyISP drivers do not offer any option to distinguish multipl
devices connected simultaneously, so effectively only a single device
is supported.
.Pp
Chip Select must be externally held low for direct SPI when
using USBtinyISP, and send must be a multiple of four bytes.
.Pp
The avrftdi driver allows one to select specific devices using any combination of vid,pid
serial number (usbsn) vendor description (usbvendoror part description (usbproduct)
as seen with lsusb or whatever tool used to view USB device information. Multiple

File diff suppressed because it is too large Load Diff

View File

@@ -16,82 +16,48 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* $Id$ */
/* $Id$ */
#ifndef avrdude_h
#define avrdude_h
#include <stdio.h>
extern char * progname; /* name of program, for messages */
extern char progbuf[]; /* spaces same length as progname */
#define SYSTEM_CONF_FILE "avrdude.conf"
#if defined(WIN32)
#define USER_CONF_FILE "avrdude.rc"
#else
#define USER_CONF_FILE ".avrduderc"
#define XDG_USER_CONF_FILE "avrdude/avrdude.rc"
extern int ovsigck; /* override signature check (-F) */
extern int verbose; /* verbosity level (-v, -vv, ...) */
extern int quell_progress; /* quiteness level (-q, -qq) */
int avrdude_message(const int msglvl, const char *format, ...);
#define MSG_INFO (0) /* no -v option, can be supressed with -qq */
#define MSG_NOTICE (1) /* displayed with -v */
#define MSG_NOTICE2 (2) /* displayed with -vv, used rarely */
#define MSG_DEBUG (3) /* displayed with -vvv */
#define MSG_TRACE (4) /* displayed with -vvvv, show trace commuication */
#define MSG_TRACE2 (5) /* displayed with -vvvvv */
#if defined(WIN32NATIVE)
#include "ac_cfg.h"
#include <windows.h>
#ifdef __cplusplus
extern "C" {
#endif
extern char *progname; // Name of program, for messages
extern char progbuf[]; // Spaces same length as progname
#if !defined(HAVE_USLEEP)
int usleep(unsigned int us);
#endif
extern int ovsigck; // Override signature check (-F)
extern int verbose; // Verbosity level (-v, -vv, ...)
extern int quell_progress; // Quell progress report -q, reduce effective verbosity level (-qq, -qqq)
extern const char *partdesc; // Part id
#if !defined(HAVE_GETTIMEOFDAY)
struct timezone;
int gettimeofday(struct timeval *tv, struct timezone *tz);
#endif /* HAVE_GETTIMEOFDAY */
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_EXT_ERROR (-3) // OS-type error, no -v option, can be suppressed with -qqqqq
#define MSG_ERROR (-2) // Avrdude error, no -v option, can be suppressed with -qqqq
#define MSG_WARNING (-1) // Warning, no -v option, can be suppressed with -qqq
#define MSG_INFO 0 // Commentary, no -v option, can be suppressed with -qq
#define MSG_NOTICE 1 // Displayed with -v
#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__)
#ifdef __cplusplus
}
#endif
#endif /* defined(WIN32NATIVE) */
#endif

View File

@@ -50,19 +50,23 @@
#ifdef DO_NOT_BUILD_AVRFTDI
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");
static int avrftdi_noftdi_open (struct programmer_t *pgm, char * name)
{
avrdude_message(MSG_INFO, "%s: Error: no libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.\n",
progname);
return -1;
}
void avrftdi_initpgm(PROGRAMMER *pgm) {
void avrftdi_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "avrftdi");
pgm->open = avrftdi_noftdi_open;
}
#else
enum { FTDI_SCK = 0, FTDI_SDO, FTDI_SDI, FTDI_RESET };
enum { FTDI_SCK = 0, FTDI_MOSI, FTDI_MISO, FTDI_RESET };
static int write_flush(avrftdi_t *);
@@ -138,14 +142,14 @@ void avrftdi_log(int level, const char * func, int line,
if(!skip_prefix)
{
switch(level) {
case ERR: msg_error("E "); break;
case WARN: msg_error("W "); break;
case INFO: msg_error("I "); break;
case DEBUG: msg_error("D "); break;
case TRACE: msg_error("T "); break;
default: msg_error(" "); break;
case ERR: avrdude_message(MSG_INFO, "E "); break;
case WARN: avrdude_message(MSG_INFO, "W "); break;
case INFO: avrdude_message(MSG_INFO, "I "); break;
case DEBUG: avrdude_message(MSG_INFO, "D "); break;
case TRACE: avrdude_message(MSG_INFO, "T "); break;
default: avrdude_message(MSG_INFO, " "); break;
}
msg_error("%s(%d): ", func, line);
avrdude_message(MSG_INFO, "%s(%d): ", func, line);
}
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
@@ -168,16 +172,16 @@ static void buf_dump(const unsigned char *buf, int len, char *desc,
int offset, int width)
{
int i;
msg_info("%s begin:\n", desc);
avrdude_message(MSG_INFO, "%s begin:\n", desc);
for (i = 0; i < offset; i++)
msg_info("%02x ", buf[i]);
msg_info("\n");
avrdude_message(MSG_INFO, "%02x ", buf[i]);
avrdude_message(MSG_INFO, "\n");
for (i++; i <= len; i++) {
msg_info("%02x ", buf[i-1]);
avrdude_message(MSG_INFO, "%02x ", buf[i-1]);
if((i-offset) != 0 && (i-offset)%width == 0)
msg_info("\n");
avrdude_message(MSG_INFO, "\n");
}
msg_info("%s end\n", desc);
avrdude_message(MSG_INFO, "%s end\n", desc);
}
/*
@@ -216,17 +220,15 @@ static int set_frequency(avrftdi_t* ftdi, uint32_t freq)
}
/*
* This function sets or clears any pin, except SCK, SDI and SDO. Depending
* This function sets or clears any pin, except SCK, MISO and MOSI. Depending
* 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
* inactive state.
* Because we configured the pin direction mask earlier, nothing bad can happen
* here.
*/
static int set_pin(const PROGRAMMER *pgm, int pinfunc, int value) {
if(pinfunc < 0 || pinfunc >= N_PINS)
return -1;
static int set_pin(PROGRAMMER * pgm, int pinfunc, int value)
{
avrftdi_t* pdata = to_pdata(pgm);
struct pindef_t pin = pgm->pin[pinfunc];
@@ -248,50 +250,54 @@ static int set_pin(const PROGRAMMER *pgm, int pinfunc, int value) {
/*
* Mandatory callbacks which boil down to GPIO.
*/
static int set_led_pgm(const PROGRAMMER *pgm, int value) {
static int set_led_pgm(struct programmer_t * pgm, int value)
{
return set_pin(pgm, PIN_LED_PGM, value);
}
static int set_led_rdy(const PROGRAMMER *pgm, int value) {
static int set_led_rdy(struct programmer_t * pgm, int value)
{
return set_pin(pgm, PIN_LED_RDY, value);
}
static int set_led_err(const PROGRAMMER *pgm, int value) {
static int set_led_err(struct programmer_t * pgm, int value)
{
return set_pin(pgm, PIN_LED_ERR, value);
}
static int set_led_vfy(const PROGRAMMER *pgm, int value) {
static int set_led_vfy(struct programmer_t * pgm, int value)
{
return set_pin(pgm, PIN_LED_VFY, value);
}
static void avrftdi_enable(PROGRAMMER *pgm, const AVRPART *p) {
static void avrftdi_enable(PROGRAMMER * pgm)
{
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(const PROGRAMMER *pgm) {
static void avrftdi_disable(PROGRAMMER * pgm)
{
set_pin(pgm, PPI_AVR_BUFF, OFF);
}
static void avrftdi_powerup(const PROGRAMMER *pgm) {
static void avrftdi_powerup(PROGRAMMER * pgm)
{
set_pin(pgm, PPI_AVR_VCC, ON);
}
static void avrftdi_powerdown(const PROGRAMMER *pgm) {
static void avrftdi_powerdown(PROGRAMMER * pgm)
{
set_pin(pgm, PPI_AVR_VCC, OFF);
}
static inline int set_data(const PROGRAMMER *pgm, unsigned char *buf, unsigned char data, bool read_data) {
static inline int set_data(PROGRAMMER * pgm, unsigned char *buf, unsigned char data, bool read_data) {
int j;
int buf_pos = 0;
unsigned char bit = 0x80;
avrftdi_t* pdata = to_pdata(pgm);
for (j=0; j<8; j++) {
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_MOSI,data & bit);
pdata->pin_value = SET_BITS_0(pdata->pin_value,pgm,PIN_AVR_SCK,0);
buf[buf_pos++] = SET_BITS_LOW;
buf[buf_pos++] = (pdata->pin_value) & 0xff;
@@ -318,7 +324,7 @@ static inline int set_data(const PROGRAMMER *pgm, unsigned char *buf, unsigned c
return buf_pos;
}
static inline unsigned char extract_data(const PROGRAMMER *pgm, unsigned char *buf, int offset) {
static inline unsigned char extract_data(PROGRAMMER * pgm, unsigned char *buf, int offset) {
int j;
unsigned char bit = 0x80;
unsigned char r = 0;
@@ -326,7 +332,7 @@ static inline unsigned char extract_data(const PROGRAMMER *pgm, unsigned char *b
buf += offset * 16; // 2 bytes per bit, 8 bits
for (j=0; j<8; j++) {
uint16_t in = buf[0] | (buf[1] << 8);
if (GET_BITS_0(in,pgm,PIN_AVR_SDI)) {
if (GET_BITS_0(in,pgm,PIN_AVR_MISO)) {
r |= bit;
}
buf += 2; // 2 bytes per input
@@ -336,7 +342,7 @@ static inline unsigned char extract_data(const PROGRAMMER *pgm, unsigned char *b
}
static int avrftdi_transmit_bb(const PROGRAMMER *pgm, unsigned char mode, const unsigned char *buf,
static int avrftdi_transmit_bb(PROGRAMMER * pgm, unsigned char mode, const unsigned char *buf,
unsigned char *data, int buf_size)
{
size_t remaining = buf_size;
@@ -345,13 +351,10 @@ static int avrftdi_transmit_bb(const PROGRAMMER *pgm, unsigned char mode, const
size_t blocksize = pdata->rx_buffer_size/2; // we are reading 2 bytes per data byte
// determine a maximum size of data block
size_t max_size = MIN(pdata->ftdic->max_packet_size, (unsigned int) pdata->tx_buffer_size);
size_t max_size = MIN(pdata->ftdic->max_packet_size,pdata->tx_buffer_size);
// 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)));
// msg_info("blocksize %d \n", blocksize);
unsigned char* send_buffer = alloca((8 * 2 * 6) * blocksize + (8 * 1 * 2) * blocksize + 7);
unsigned char* recv_buffer = alloca(2 * 16 * blocksize);
//avrdude_message(MSG_INFO, "blocksize %d \n",blocksize);
while(remaining)
{
@@ -361,9 +364,11 @@ static int avrftdi_transmit_bb(const PROGRAMMER *pgm, unsigned char mode, const
// (8*2) outputs per data byte, 6 transmit bytes per output (SET_BITS_LOW/HIGH),
// (8*1) inputs per data byte, 2 transmit bytes per input (GET_BITS_LOW/HIGH),
// 1x SEND_IMMEDIATE
unsigned char send_buffer[(8*2*6)*transfer_size+(8*1*2)*transfer_size+7];
int len = 0;
int i;
for(size_t i = 0 ; i < transfer_size; i++) {
for(i = 0 ; i< transfer_size; i++) {
len += set_data(pgm, send_buffer + len, buf[written+i], (mode & MPSSE_DO_READ) != 0);
}
@@ -379,15 +384,16 @@ static int avrftdi_transmit_bb(const PROGRAMMER *pgm, unsigned char mode, const
E(ftdi_write_data(pdata->ftdic, send_buffer, len) != len, pdata->ftdic);
if (mode & MPSSE_DO_READ) {
unsigned char recv_buffer[2*16*transfer_size];
int n;
size_t k = 0;
int k = 0;
do {
n = ftdi_read_data(pdata->ftdic, &recv_buffer[k], 2*16*transfer_size - k);
E(n < 0, pdata->ftdic);
k += n;
} while (k < transfer_size);
for(size_t i = 0 ; i< transfer_size; i++) {
for(i = 0 ; i< transfer_size; i++) {
data[written + i] = extract_data(pgm, recv_buffer, i);
}
}
@@ -430,7 +436,7 @@ static int avrftdi_transmit_mpsse(avrftdi_t* pdata, unsigned char mode, const un
{
size_t transfer_size = (remaining > blocksize) ? blocksize : remaining;
E((size_t) ftdi_write_data(pdata->ftdic, (unsigned char*)&buf[written], transfer_size) != transfer_size, pdata->ftdic);
E(ftdi_write_data(pdata->ftdic, (unsigned char*)&buf[written], transfer_size) != transfer_size, pdata->ftdic);
#if 0
if(remaining < blocksize)
E(ftdi_write_data(pdata->ftdic, &si, sizeof(si)) != sizeof(si), pdata->ftdic);
@@ -438,7 +444,7 @@ static int avrftdi_transmit_mpsse(avrftdi_t* pdata, unsigned char mode, const un
if (mode & MPSSE_DO_READ) {
int n;
size_t k = 0;
int k = 0;
do {
n = ftdi_read_data(pdata->ftdic, &data[written + k], transfer_size - k);
E(n < 0, pdata->ftdic);
@@ -454,7 +460,7 @@ static int avrftdi_transmit_mpsse(avrftdi_t* pdata, unsigned char mode, const un
return written;
}
static inline int avrftdi_transmit(const PROGRAMMER *pgm, unsigned char mode, const unsigned char *buf,
static inline int avrftdi_transmit(PROGRAMMER * pgm, unsigned char mode, const unsigned char *buf,
unsigned char *data, int buf_size)
{
avrftdi_t* pdata = to_pdata(pgm);
@@ -513,7 +519,8 @@ static int write_flush(avrftdi_t* pdata)
}
static int avrftdi_check_pins_bb(const PROGRAMMER *pgm, bool output) {
static int avrftdi_check_pins_bb(PROGRAMMER * pgm, bool output)
{
int pin;
/* pin checklist. */
@@ -540,7 +547,8 @@ static int avrftdi_check_pins_bb(const PROGRAMMER *pgm, bool output) {
return pins_check(pgm, pin_checklist, N_PINS, output);
}
static int avrftdi_check_pins_mpsse(const PROGRAMMER *pgm, bool output) {
static int avrftdi_check_pins_mpsse(PROGRAMMER * pgm, bool output)
{
int pin;
/* pin checklist. */
@@ -548,16 +556,16 @@ static int avrftdi_check_pins_mpsse(const PROGRAMMER *pgm, bool output) {
avrftdi_t* pdata = to_pdata(pgm);
/* SCK/SDO/SDI are fixed and not invertible? */
/* TODO: inverted SCK/SDI/SDO */
static const struct pindef_t valid_pins_SCK = {{0x01},{0x00}};
static const struct pindef_t valid_pins_SDO = {{0x02},{0x00}};
static const struct pindef_t valid_pins_SDI = {{0x04},{0x00}};
/* SCK/MOSI/MISO are fixed and not invertible?*/
/* TODO: inverted SCK/MISO/MOSI */
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_MISO = {{0x04},{0x00}} ;
/* value for 8/12/16 bit wide interface for other pins */
int valid_mask = ((1 << pdata->pin_limit) - 1);
/* mask out SCK/SDI/SDO */
valid_mask &= ~((1 << FTDI_SCK) | (1 << FTDI_SDO) | (1 << FTDI_SDI));
/* mask out SCK/MISO/MOSI */
valid_mask &= ~((1 << FTDI_SCK) | (1 << FTDI_MOSI) | (1 << FTDI_MISO));
log_debug("Using valid mask mpsse: 0x%08x\n", valid_mask);
static struct pindef_t valid_pins_others;
@@ -574,17 +582,18 @@ static int avrftdi_check_pins_mpsse(const PROGRAMMER *pgm, bool output) {
/* now set mpsse specific pins */
pin_checklist[PIN_AVR_SCK].mandatory = 1;
pin_checklist[PIN_AVR_SCK].valid_pins = &valid_pins_SCK;
pin_checklist[PIN_AVR_SDO].mandatory = 1;
pin_checklist[PIN_AVR_SDO].valid_pins = &valid_pins_SDO;
pin_checklist[PIN_AVR_SDI].mandatory = 1;
pin_checklist[PIN_AVR_SDI].valid_pins = &valid_pins_SDI;
pin_checklist[PIN_AVR_MOSI].mandatory = 1;
pin_checklist[PIN_AVR_MOSI].valid_pins = &valid_pins_MOSI;
pin_checklist[PIN_AVR_MISO].mandatory = 1;
pin_checklist[PIN_AVR_MISO].valid_pins = &valid_pins_MISO;
pin_checklist[PIN_AVR_RESET].mandatory = 1;
/* assumes all checklists above have same number of entries */
return pins_check(pgm, pin_checklist, N_PINS, output);
}
static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
static int avrftdi_pin_setup(PROGRAMMER * pgm)
{
int pin;
/*************
@@ -602,31 +611,30 @@ static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
avrftdi_check_pins_bb(pgm, true);
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),
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_SDO]),
pins_to_str(&pgm->pin[PIN_AVR_SDI]));
avr_pin_name(PIN_AVR_MOSI), avr_pin_name(PIN_AVR_MISO),
pins_to_str(&pgm->pin[PIN_AVR_SCK]),
pins_to_str(&pgm->pin[PIN_AVR_MOSI]),
pins_to_str(&pgm->pin[PIN_AVR_MISO]));
log_err("If other pin configuration is used, fallback to slower bitbanging mode is used.\n");
return -1;
}
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.
* Maybe we should only fail for SCK; SDI, SDO, RST (and probably
* Maybe we should only fail for SCK; MISO, MOSI, RST (and probably
* VCC and BUFF).
*/
/* everything is an output, except SDI */
/* everything is an output, except MISO */
for(pin = 0; pin < N_PINS; ++pin) {
pdata->pin_direction |= pgm->pin[pin].mask[0];
pdata->pin_value = SET_BITS_0(pdata->pin_value, pgm, pin, OFF);
}
pdata->pin_direction &= ~pgm->pin[PIN_AVR_SDI].mask[0];
pdata->pin_direction &= ~pgm->pin[PIN_AVR_MISO].mask[0];
for(pin = PIN_LED_ERR; pin < N_PINS; ++pin) {
pdata->led_mask |= pgm->pin[pin].mask[0];
@@ -639,9 +647,10 @@ static int avrftdi_pin_setup(const PROGRAMMER *pgm) {
return 0;
}
static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
static int avrftdi_open(PROGRAMMER * pgm, char *port)
{
int vid, pid, interface, index, err;
const char *serial, *desc;
char * serial, *desc;
avrftdi_t* pdata = to_pdata(pgm);
@@ -661,7 +670,8 @@ static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
if (usbpid) {
pid = *(int *)(ldata(usbpid));
if (lnext(usbpid))
pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid);
avrdude_message(MSG_INFO, "%s: Warning: using PID 0x%04x, ignoring remaining PIDs in list\n",
progname, pid);
} else
pid = USB_DEVICE_FT2232;
@@ -751,11 +761,7 @@ static int avrftdi_open(PROGRAMMER *pgm, const char *port) {
pdata->tx_buffer_size = 1024;
break;
#else
#ifdef _MSC_VER
#pragma message("No support for 232H, use a newer libftdi, version >= 0.20")
#else
#warning No support for 232H, use a newer libftdi, version >= 0.20
#endif
#endif
case TYPE_4232H:
pdata->pin_limit = 8;
@@ -806,10 +812,11 @@ static void avrftdi_close(PROGRAMMER * pgm)
return;
}
static int avrftdi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
static int avrftdi_initialize(PROGRAMMER * pgm, AVRPART * p)
{
avrftdi_powerup(pgm);
if(p->prog_modes & PM_TPI)
if(p->flags & AVRPART_HAS_TPI)
{
/* see avrftdi_tpi.c */
avrftdi_tpi_initialize(pgm, p);
@@ -835,18 +842,21 @@ static int avrftdi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
return pgm->program_enable(pgm, p);
}
static void avrftdi_display(const PROGRAMMER *pgm, const char *p) {
static void avrftdi_display(PROGRAMMER * pgm, const char *p)
{
// print the full pin definitions as in ft245r ?
return;
}
static int avrftdi_cmd(const PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res) {
static int avrftdi_cmd(PROGRAMMER * pgm, const unsigned char *cmd, unsigned char *res)
{
return avrftdi_transmit(pgm, MPSSE_DO_READ | MPSSE_DO_WRITE, cmd, res, 4);
}
static int avrftdi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
static int avrftdi_program_enable(PROGRAMMER * pgm, AVRPART * p)
{
int i;
unsigned char buf[4];
@@ -877,7 +887,8 @@ static int avrftdi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
}
static int avrftdi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
static int avrftdi_chip_erase(PROGRAMMER * pgm, AVRPART * p)
{
unsigned char cmd[4];
unsigned char res[4];
@@ -899,20 +910,10 @@ static int avrftdi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
/* Load extended address byte command */
static int
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);
avrftdi_lext(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m, unsigned int address)
{
unsigned char buf[] = { 0x00, 0x00, 0x00, 0x00 };
/* only send load extended address command if high byte changed */
if(pdata->lext_byte == (uint8_t) (address>>16))
return 0;
pdata->lext_byte = (uint8_t) (address>>16);
avr_set_bits(m->op[AVR_OP_LOAD_EXT_ADDR], buf);
avr_set_addr(m->op[AVR_OP_LOAD_EXT_ADDR], buf, address);
@@ -926,7 +927,7 @@ avrftdi_lext(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m, unsigned
return 0;
}
static int avrftdi_eeprom_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avrftdi_eeprom_write(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
unsigned int page_size, unsigned int addr, unsigned int len)
{
unsigned char cmd[] = { 0x00, 0x00, 0x00, 0x00 };
@@ -948,16 +949,14 @@ static int avrftdi_eeprom_write(const PROGRAMMER *pgm, const AVRPART *p, const A
return len;
}
static int avrftdi_eeprom_read(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avrftdi_eeprom_read(PROGRAMMER *pgm, AVRPART *p, AVRMEM *m,
unsigned int page_size, unsigned int addr, unsigned int len)
{
unsigned char cmd[4];
unsigned char buffer[len], *bufptr = buffer;
unsigned int add;
unsigned char* buffer = alloca(len);
unsigned char* bufptr = buffer;
memset(buffer, 0, len);
memset(buffer, 0, sizeof(buffer));
for (add = addr; add < addr + len; add++)
{
memset(cmd, 0, sizeof(cmd));
@@ -974,19 +973,20 @@ static int avrftdi_eeprom_read(const PROGRAMMER *pgm, const AVRPART *p, const AV
return len;
}
static int avrftdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avrftdi_flash_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int addr, unsigned int len)
{
int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
unsigned int word;
unsigned int poll_index;
unsigned int buf_size;
unsigned char poll_byte;
unsigned char *buffer = &m->buf[addr];
unsigned int buf_size = 4 * len + 4;
unsigned char* buf = alloca(buf_size);
unsigned char* bufptr = buf;
unsigned char buf[4*len+4], *bufptr = buf;
memset(buf, 0, buf_size);
memset(buf, 0, sizeof(buf));
/* pre-check opcodes */
if (m->op[AVR_OP_LOADPAGE_LO] == NULL) {
@@ -998,19 +998,29 @@ static int avrftdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AV
return -1;
}
if(page_size != (unsigned int) m->page_size) {
if(page_size != m->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);
}
page_size = m->page_size;
/* on large-flash devices > 128k issue extended address command when needed */
if(avrftdi_lext(pgm, p, m, addr/2) < 0)
return -1;
/* if we do cross a 64k word boundary (or write the
* first page), we need to issue a 'load extended
* address byte' command, which is defined as 0x4d
* 0x00 <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 */
/* addr is in bytes, but we program in words. */
/* addr is in bytes, but we program in words. addr/2 should be something
* like addr >> WORD_SHIFT, though */
for(word = addr/2; word < (len + addr)/2; word++)
{
log_debug("-< bytes = %d of %d\n", word * 2, len + addr);
@@ -1042,11 +1052,12 @@ static int avrftdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AV
/* find a poll byte. We cannot poll a value of 0xff, so look
* for a value != 0xff
*/
for(poll_index = addr+len-1; poll_index+1 > addr; poll_index--)
for(poll_index = addr+len-1; poll_index > addr-1; poll_index--)
if(m->buf[poll_index] != 0xff)
break;
if(poll_index+1 > addr) {
if((poll_index < addr + len) && m->buf[poll_index] != 0xff)
{
buf_size = bufptr - buf;
if(verbose > TRACE)
@@ -1083,18 +1094,21 @@ static int avrftdi_flash_write(const PROGRAMMER *pgm, const AVRPART *p, const AV
/*
*Reading from flash
*/
static int avrftdi_flash_read(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avrftdi_flash_read(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int addr, unsigned int len)
{
OPCODE * readop;
int byte, word;
int use_lext_address = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
unsigned int address = addr/2;
unsigned int buf_size = 4 * len + 4;
unsigned char* o_buf = alloca(buf_size);
unsigned char* i_buf = alloca(buf_size);
unsigned char o_buf[4*len+4];
unsigned char i_buf[4*len+4];
unsigned int index;
memset(o_buf, 0, buf_size);
memset(i_buf, 0, buf_size);
memset(o_buf, 0, sizeof(o_buf));
memset(i_buf, 0, sizeof(i_buf));
/* pre-check opcodes */
if (m->op[AVR_OP_READ_LO] == NULL) {
@@ -1106,11 +1120,13 @@ static int avrftdi_flash_read(const PROGRAMMER *pgm, const AVRPART *p, const AVR
return -1;
}
if(avrftdi_lext(pgm, p, m, addr/2) < 0)
return -1;
if(use_lext_address && ((address & 0xffff0000))) {
if (0 > avrftdi_lext(pgm, p, m, address))
return -1;
}
/* word addressing! */
for(unsigned int word = addr/2, index = 0; word < (addr + len)/2; word++)
for(word = addr/2, index = 0; word < (addr + len)/2; word++)
{
/* one byte is transferred via a 4-byte opcode.
* TODO: reduce magic numbers
@@ -1141,7 +1157,7 @@ static int avrftdi_flash_read(const PROGRAMMER *pgm, const AVRPART *p, const AVR
memset(&m->buf[addr], 0, page_size);
/* every (read) op is 4 bytes in size and yields one byte of memory data */
for(unsigned int byte = 0; byte < page_size; byte++) {
for(byte = 0; byte < page_size; byte++) {
if(byte & 1)
readop = m->op[AVR_OP_READ_HI];
else
@@ -1159,7 +1175,7 @@ static int avrftdi_flash_read(const PROGRAMMER *pgm, const AVRPART *p, const AVR
return len;
}
static int avrftdi_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avrftdi_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
{
if (strcmp(m->desc, "flash") == 0)
@@ -1170,7 +1186,7 @@ static int avrftdi_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AV
return -2;
}
static int avrftdi_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int avrftdi_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
{
if (strcmp(m->desc, "flash") == 0)
@@ -1186,11 +1202,7 @@ avrftdi_setup(PROGRAMMER * pgm)
{
avrftdi_t* pdata;
if(!(pgm->cookie = calloc(sizeof(avrftdi_t), 1))) {
log_err("Error allocating memory.\n");
exit(1);
}
pgm->cookie = malloc(sizeof(avrftdi_t));
pdata = to_pdata(pgm);
pdata->ftdic = ftdi_new();
@@ -1204,7 +1216,6 @@ avrftdi_setup(PROGRAMMER * pgm)
pdata->pin_value = 0;
pdata->pin_direction = 0;
pdata->led_mask = 0;
pdata->lext_byte = 0xff;
}
static void
@@ -1219,7 +1230,9 @@ avrftdi_teardown(PROGRAMMER * pgm)
}
}
void avrftdi_initpgm(PROGRAMMER *pgm) {
void avrftdi_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "avrftdi");
/*

View File

@@ -29,7 +29,7 @@ extern "C" {
extern const char avrftdi_desc[];
void avrftdi_initpgm(PROGRAMMER *pgm);
void avrftdi_initpgm (PROGRAMMER * pgm);
#ifdef __cplusplus
}

View File

@@ -12,15 +12,11 @@
# include <libftdi1/ftdi.h>
# undef HAVE_LIBFTDI_TYPE_232H
# define HAVE_LIBFTDI_TYPE_232H 1
#elif defined(HAVE_LIBFTDI)
#elif defined(HAVE_LIBFTDI) && defined(HAVE_USB_H)
/* ftdi.h includes usb.h */
#include <ftdi.h>
#else
#ifdef _MSC_VER
#pragma message("No libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.")
#else
#else
#warning No libftdi or libusb support. Install libftdi1/libusb-1.0 or libftdi/libusb and run configure/make again.
#endif
#define DO_NOT_BUILD_AVRFTDI
#endif
@@ -31,7 +27,7 @@ enum { ERR, WARN, INFO, DEBUG, TRACE };
#define __log(lvl, fmt, ...) \
do { \
avrftdi_log(lvl, __func__, __LINE__, fmt, ##__VA_ARGS__); \
} while(0)
} while(0)
#define log_err(fmt, ...) __log(ERR, fmt, ##__VA_ARGS__)
@@ -41,49 +37,47 @@ enum { ERR, WARN, INFO, DEBUG, TRACE };
#define log_trace(fmt, ...) __log(TRACE, fmt, ##__VA_ARGS__)
#define E(x, ftdi) \
do { \
if ((x)) \
{ \
msg_error("%s:%d %s() %s: %s (%d)\n\t%s\n", \
__FILE__, __LINE__, __FUNCTION__, \
#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); \
return -1; \
} \
} while(0)
do { \
if ((x)) \
{ \
avrdude_message(MSG_INFO, "%s:%d %s() %s: %s (%d)\n\t%s\n", \
__FILE__, __LINE__, __FUNCTION__, \
#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); \
return -1; \
} \
} while(0)
#define E_VOID(x, ftdi) \
do { \
if ((x)) \
{ \
msg_error("%s:%d %s() %s: %s (%d)\n\t%s\n", \
__FILE__, __LINE__, __FUNCTION__, \
#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); \
} \
} while(0)
do { \
if ((x)) \
{ \
avrdude_message(MSG_INFO, "%s:%d %s() %s: %s (%d)\n\t%s\n", \
__FILE__, __LINE__, __FUNCTION__, \
#x, strerror(errno), errno, ftdi_get_error_string(ftdi)); \
} \
} while(0)
#define to_pdata(pgm) \
((avrftdi_t *)((pgm)->cookie))
((avrftdi_t *)((pgm)->cookie))
typedef struct avrftdi_s {
/* pointer to struct maintained by libftdi to identify the device */
struct ftdi_context* ftdic;
/* bitmask of values for pins. bit 0 represents pin 0 ([A|B]DBUS0) */
uint16_t pin_value;
/* bitmask of pin direction. a '1' make a pin an output.
* bit 0 corresponds to pin 0. */
uint16_t pin_direction;
/* don't know. not useful. someone put it in. */
uint16_t led_mask;
/* total number of pins supported by a programmer. varies with FTDI chips */
int pin_limit;
/* internal RX buffer of the device. needed for INOUT transfers */
int rx_buffer_size;
int tx_buffer_size;
/* use bitbanging instead of mpsse spi */
bool use_bitbanging;
/* bits 16-23 of extended 24-bit word flash address for parts with flash > 128k */
uint8_t lext_byte;
/* pointer to struct maintained by libftdi to identify the device */
struct ftdi_context* ftdic;
/* bitmask of values for pins. bit 0 represents pin 0 ([A|B]DBUS0) */
uint16_t pin_value;
/* bitmask of pin direction. a '1' make a pin an output.
* bit 0 corresponds to pin 0. */
uint16_t pin_direction;
/* don't know. not useful. someone put it in. */
uint16_t led_mask;
/* total number of pins supported by a programmer. varies with FTDI chips */
int pin_limit;
/* internal RX buffer of the device. needed for INOUT transfers */
int rx_buffer_size;
int tx_buffer_size;
/* use bitbanging instead of mpsse spi */
bool use_bitbanging;
} avrftdi_t;
void avrftdi_log(int level, const char * func, int line, const char * fmt, ...);

View File

@@ -15,8 +15,8 @@
#ifndef DO_NOT_BUILD_AVRFTDI
static void avrftdi_tpi_disable(const PROGRAMMER *);
static int avrftdi_tpi_program_enable(const PROGRAMMER *pgm, const AVRPART *p);
static void avrftdi_tpi_disable(PROGRAMMER *);
static int avrftdi_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p);
#ifdef notyet
static void
@@ -63,16 +63,27 @@ avrftdi_debug_frame(uint16_t frame)
#endif /* notyet */
int
avrftdi_tpi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
avrftdi_tpi_initialize(PROGRAMMER * pgm, AVRPART * p)
{
int ret;
avrftdi_t* pdata = to_pdata(pgm);
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");
pgm->setpin(pgm, PIN_AVR_RESET, OFF);
pgm->setpin(pgm, PIN_AVR_SCK, OFF);
pgm->setpin(pgm, PIN_AVR_SDO, ON);
pgm->setpin(pgm, PIN_AVR_MOSI, ON);
usleep(20 * 1000);
pgm->setpin(pgm, PIN_AVR_RESET, ON);
@@ -90,44 +101,13 @@ avrftdi_tpi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
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
static inline int count1s(unsigned int x)
{
#if defined(__GNUC__)
return __builtin_popcount(x);
#else
int count = 0;
while (x)
{
count += x & 1;
x >>= 1;
}
return count;
#endif
}
static uint16_t
tpi_byte2frame(uint8_t byte)
{
uint16_t frame = 0xc00f;
int parity = count1s(byte) & 1;
int parity = __builtin_popcount(byte) & 1;
frame |= ((byte << 5) & 0x1fe0);
@@ -143,7 +123,7 @@ tpi_frame2byte(uint16_t frame, uint8_t * byte)
/* drop idle and start bit(s) */
*byte = (frame >> 5) & 0xff;
int parity = count1s(*byte) & 1;
int parity = __builtin_popcount(*byte) & 1;
int parity_rcvd = (frame & TPI_PARITY_MASK) ? 1 : 0;
return parity != parity_rcvd;
@@ -151,7 +131,8 @@ tpi_frame2byte(uint16_t frame, uint8_t * byte)
#ifdef notyet
static int
avrftdi_tpi_break(const PROGRAMMER *pgm) {
avrftdi_tpi_break(PROGRAMMER * pgm)
{
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);
@@ -160,7 +141,8 @@ avrftdi_tpi_break(const PROGRAMMER *pgm) {
#endif /* notyet */
static int
avrftdi_tpi_write_byte(const PROGRAMMER *pgm, unsigned char byte) {
avrftdi_tpi_write_byte(PROGRAMMER * pgm, unsigned char byte)
{
uint16_t frame;
struct ftdi_context* ftdic = to_pdata(pgm)->ftdic;
@@ -186,7 +168,8 @@ avrftdi_tpi_write_byte(const PROGRAMMER *pgm, unsigned char byte) {
#define TPI_IDLE_BITS 2
static int
avrftdi_tpi_read_byte(const PROGRAMMER *pgm, unsigned char *byte) {
avrftdi_tpi_read_byte(PROGRAMMER * pgm, unsigned char * byte)
{
uint16_t frame;
/* use 2 guard bits, 2 default idle bits + 12 frame bits = 16 bits total */
@@ -230,12 +213,13 @@ avrftdi_tpi_read_byte(const PROGRAMMER *pgm, unsigned char *byte) {
}
static int
avrftdi_tpi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
avrftdi_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p)
{
return avr_tpi_program_enable(pgm, p, TPIPCR_GT_2b);
}
int
avrftdi_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd, int cmd_len,
avrftdi_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd, int cmd_len,
unsigned char *res, int res_len)
{
int i, err = 0;
@@ -258,7 +242,8 @@ avrftdi_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd, int cmd_len,
}
static void
avrftdi_tpi_disable(const PROGRAMMER *pgm) {
avrftdi_tpi_disable(PROGRAMMER * pgm)
{
unsigned char cmd[] = {TPI_OP_SSTCS(TPIPCR), 0};
pgm->cmd_tpi(pgm, cmd, sizeof(cmd), NULL, 0);

View File

@@ -1,10 +1,9 @@
#pragma once
//int avrftdi_tpi_write_byte(PROGRAMMER *pgm, unsigned char byte);
//int avrftdi_tpi_read_byte(PROGRAMMER *pgm, unsigned char * byte);
int avrftdi_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd, int cmd_len,
//int avrftdi_tpi_write_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,
unsigned char *res, int res_len);
int avrftdi_tpi_initialize(const PROGRAMMER *pgm, const AVRPART *p);
void avrftdi_tpi_initpgm(PROGRAMMER *pgm);
int avrftdi_tpi_initialize(PROGRAMMER * pgm, AVRPART * p);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -17,7 +17,7 @@
* 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$ */
/* $Id$ */
#include "ac_cfg.h"
@@ -28,12 +28,9 @@
#include <unistd.h>
#include <errno.h>
#if defined(WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <signal.h>
#include <sys/time.h>
#if !defined(WIN32NATIVE)
# include <signal.h>
# include <sys/time.h>
#endif
#include "avrdude.h"
@@ -46,7 +43,7 @@
static int delay_decrement;
#if defined(WIN32)
#if defined(WIN32NATIVE)
static int has_perfcount;
static LARGE_INTEGER freq;
#else
@@ -60,14 +57,14 @@ static void alarmhandler(int signo)
done = 1;
signal(SIGALRM, saved_alarmhandler);
}
#endif /* WIN32 */
#endif /* WIN32NATIVE */
/*
* Calibrate the microsecond delay loop below.
*/
static void bitbang_calibrate_delay(void)
{
#if defined(WIN32)
#if defined(WIN32NATIVE)
/*
* If the hardware supports a high-resolution performance counter,
* we ultimately prefer that one, as it gives quite accurate delays
@@ -76,7 +73,8 @@ static void bitbang_calibrate_delay(void)
if (QueryPerformanceFrequency(&freq))
{
has_perfcount = 1;
pmsg_notice2("using performance counter for bitbang delays\n");
avrdude_message(MSG_NOTICE2, "%s: Using performance counter for bitbang delays\n",
progname);
}
else
{
@@ -89,14 +87,16 @@ static void bitbang_calibrate_delay(void)
* auto-calibration figures seen on various Unix systems on
* comparable hardware.
*/
pmsg_notice2("using guessed per-microsecond delay count for bitbang delays\n");
avrdude_message(MSG_NOTICE2, "%s: Using guessed per-microsecond delay count for bitbang delays\n",
progname);
delay_decrement = 100;
}
#else /* !WIN32 */
#else /* !WIN32NATIVE */
struct itimerval itv;
volatile int i;
pmsg_notice2("calibrating delay loop ...");
avrdude_message(MSG_NOTICE2, "%s: Calibrating delay loop...",
progname);
i = 0;
done = 0;
saved_alarmhandler = signal(SIGALRM, alarmhandler);
@@ -122,9 +122,9 @@ static void bitbang_calibrate_delay(void)
* Calculate back from 100 ms to 1 us.
*/
delay_decrement = -i / 100000;
msg_notice2(" calibrated to %d cycles per us\n",
avrdude_message(MSG_NOTICE2, " calibrated to %d cycles per us\n",
delay_decrement);
#endif /* WIN32 */
#endif /* WIN32NATIVE */
}
/*
@@ -134,7 +134,7 @@ static void bitbang_calibrate_delay(void)
*/
void bitbang_delay(unsigned int us)
{
#if defined(WIN32)
#if defined(WIN32NATIVE)
LARGE_INTEGER countNow, countEnd;
if (has_perfcount)
@@ -147,20 +147,21 @@ void bitbang_delay(unsigned int us)
}
else /* no performance counters -- run normal uncalibrated delay */
{
#endif /* WIN32 */
#endif /* WIN32NATIVE */
volatile unsigned int del = us * delay_decrement;
while (del > 0)
del--;
#if defined(WIN32)
#if defined(WIN32NATIVE)
}
#endif /* WIN32 */
#endif /* WIN32NATIVE */
}
/*
* transmit and receive a byte of data to/from the AVR device
*/
static unsigned char bitbang_txrx(const PROGRAMMER *pgm, unsigned char byte) {
static unsigned char bitbang_txrx(PROGRAMMER * pgm, unsigned char byte)
{
int i;
unsigned char r, b, rbyte;
@@ -172,9 +173,9 @@ static unsigned char bitbang_txrx(const PROGRAMMER *pgm, unsigned char byte) {
* one pgm->setpin()-call resp. par clrpin()-call, then
* - SCK is high for 2T
* - SCK is low for 2T
* - SDO setuptime is 1T
* - SDO holdtime is 3T
* - SCK low to SDI read is 2T to 3T
* - MOSI setuptime is 1T
* - MOSI holdtime is 3T
* - SCK low to MISO read is 2T to 3T
* So we are within programming specs (expect for AT90S1200),
* if and only if T>t_CLCL (t_CLCL=clock period of target system).
*
@@ -186,7 +187,7 @@ static unsigned char bitbang_txrx(const PROGRAMMER *pgm, unsigned char byte) {
b = (byte >> i) & 0x01;
/* set the data input line as desired */
pgm->setpin(pgm, PIN_AVR_SDO, b);
pgm->setpin(pgm, PIN_AVR_MOSI, b);
pgm->setpin(pgm, PIN_AVR_SCK, 1);
@@ -194,7 +195,7 @@ static unsigned char bitbang_txrx(const PROGRAMMER *pgm, unsigned char byte) {
* read the result bit (it is either valid from a previous falling
* edge or it is ignored in the current context)
*/
r = pgm->getpin(pgm, PIN_AVR_SDI);
r = pgm->getpin(pgm, PIN_AVR_MISO);
pgm->setpin(pgm, PIN_AVR_SCK, 0);
@@ -204,23 +205,25 @@ static unsigned char bitbang_txrx(const PROGRAMMER *pgm, unsigned char byte) {
return rbyte;
}
static int bitbang_tpi_clk(const PROGRAMMER *pgm) {
static int bitbang_tpi_clk(PROGRAMMER * pgm)
{
unsigned char r = 0;
pgm->setpin(pgm, PIN_AVR_SCK, 1);
r = pgm->getpin(pgm, PIN_AVR_SDI);
r = pgm->getpin(pgm, PIN_AVR_MISO);
pgm->setpin(pgm, PIN_AVR_SCK, 0);
return r;
}
void bitbang_tpi_tx(const PROGRAMMER *pgm, unsigned char byte) {
void bitbang_tpi_tx(PROGRAMMER * pgm, unsigned char byte)
{
int i;
unsigned char b, parity;
/* start bit */
pgm->setpin(pgm, PIN_AVR_SDO, 0);
pgm->setpin(pgm, PIN_AVR_MOSI, 0);
bitbang_tpi_clk(pgm);
parity = 0;
@@ -229,26 +232,27 @@ void bitbang_tpi_tx(const PROGRAMMER *pgm, unsigned char byte) {
parity ^= b;
/* set the data input line as desired */
pgm->setpin(pgm, PIN_AVR_SDO, b);
pgm->setpin(pgm, PIN_AVR_MOSI, b);
bitbang_tpi_clk(pgm);
}
/* parity bit */
pgm->setpin(pgm, PIN_AVR_SDO, parity);
pgm->setpin(pgm, PIN_AVR_MOSI, parity);
bitbang_tpi_clk(pgm);
/* 2 stop bits */
pgm->setpin(pgm, PIN_AVR_SDO, 1);
pgm->setpin(pgm, PIN_AVR_MOSI, 1);
bitbang_tpi_clk(pgm);
bitbang_tpi_clk(pgm);
}
int bitbang_tpi_rx(const PROGRAMMER *pgm) {
int bitbang_tpi_rx(PROGRAMMER * pgm)
{
int i;
unsigned char b, rbyte, parity;
/* make sure pin is on for "pullup" */
pgm->setpin(pgm, PIN_AVR_SDO, 1);
pgm->setpin(pgm, PIN_AVR_MOSI, 1);
/* wait for start bit (up to 10 bits) */
b = 1;
@@ -258,7 +262,7 @@ int bitbang_tpi_rx(const PROGRAMMER *pgm) {
break;
}
if (b != 0) {
pmsg_error("start bit not received correctly\n");
avrdude_message(MSG_INFO, "bitbang_tpi_rx: start bit not received correctly\n");
return -1;
}
@@ -273,7 +277,7 @@ int bitbang_tpi_rx(const PROGRAMMER *pgm) {
/* parity bit */
if (bitbang_tpi_clk(pgm) != parity) {
pmsg_error("parity bit is wrong\n");
avrdude_message(MSG_INFO, "bitbang_tpi_rx: parity bit is wrong\n");
return -1;
}
@@ -282,29 +286,33 @@ int bitbang_tpi_rx(const PROGRAMMER *pgm) {
b &= bitbang_tpi_clk(pgm);
b &= bitbang_tpi_clk(pgm);
if (b != 1) {
pmsg_error("stop bits not received correctly\n");
avrdude_message(MSG_INFO, "bitbang_tpi_rx: stop bits not received correctly\n");
return -1;
}
return rbyte;
}
int bitbang_rdy_led(const PROGRAMMER *pgm, int value) {
int bitbang_rdy_led(PROGRAMMER * pgm, int value)
{
pgm->setpin(pgm, PIN_LED_RDY, !value);
return 0;
}
int bitbang_err_led(const PROGRAMMER *pgm, int value) {
int bitbang_err_led(PROGRAMMER * pgm, int value)
{
pgm->setpin(pgm, PIN_LED_ERR, !value);
return 0;
}
int bitbang_pgm_led(const PROGRAMMER *pgm, int value) {
int bitbang_pgm_led(PROGRAMMER * pgm, int value)
{
pgm->setpin(pgm, PIN_LED_PGM, !value);
return 0;
}
int bitbang_vfy_led(const PROGRAMMER *pgm, int value) {
int bitbang_vfy_led(PROGRAMMER * pgm, int value)
{
pgm->setpin(pgm, PIN_LED_VFY, !value);
return 0;
}
@@ -314,7 +322,7 @@ int bitbang_vfy_led(const PROGRAMMER *pgm, int value) {
* transmit an AVR device command and return the results; 'cmd' and
* 'res' must point to at least a 4 byte data buffer
*/
int bitbang_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
int bitbang_cmd(PROGRAMMER * pgm, const unsigned char *cmd,
unsigned char *res)
{
int i;
@@ -325,21 +333,21 @@ int bitbang_cmd(const PROGRAMMER *pgm, const unsigned char *cmd,
if(verbose >= 2)
{
msg_notice2("bitbang_cmd(): [ ");
avrdude_message(MSG_NOTICE2, "bitbang_cmd(): [ ");
for(i = 0; i < 4; i++)
msg_notice2("%02X ", cmd[i]);
msg_notice2("] [ ");
avrdude_message(MSG_NOTICE2, "%02X ", cmd[i]);
avrdude_message(MSG_NOTICE2, "] [ ");
for(i = 0; i < 4; i++)
{
msg_notice2("%02X ", res[i]);
avrdude_message(MSG_NOTICE2, "%02X ", res[i]);
}
msg_notice2("]\n");
avrdude_message(MSG_NOTICE2, "]\n");
}
return 0;
}
int bitbang_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd,
int bitbang_cmd_tpi(PROGRAMMER * pgm, const unsigned char *cmd,
int cmd_len, unsigned char *res, int res_len)
{
int i, r;
@@ -360,15 +368,15 @@ int bitbang_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd,
if(verbose >= 2)
{
msg_notice2("bitbang_cmd_tpi(): [ ");
avrdude_message(MSG_NOTICE2, "bitbang_cmd_tpi(): [ ");
for(i = 0; i < cmd_len; i++)
msg_notice2("%02X ", cmd[i]);
msg_notice2("] [ ");
avrdude_message(MSG_NOTICE2, "%02X ", cmd[i]);
avrdude_message(MSG_NOTICE2, "] [ ");
for(i = 0; i < res_len; i++)
{
msg_notice2("%02X ", res[i]);
avrdude_message(MSG_NOTICE2, "%02X ", res[i]);
}
msg_notice2("]\n");
avrdude_message(MSG_NOTICE2, "]\n");
}
pgm->pgm_led(pgm, OFF);
@@ -381,7 +389,7 @@ int bitbang_cmd_tpi(const PROGRAMMER *pgm, const unsigned char *cmd,
* transmit bytes via SPI and return the results; 'cmd' and
* 'res' must point to data buffers
*/
int bitbang_spi(const PROGRAMMER *pgm, const unsigned char *cmd,
int bitbang_spi(PROGRAMMER * pgm, const unsigned char *cmd,
unsigned char *res, int count)
{
int i;
@@ -396,15 +404,15 @@ int bitbang_spi(const PROGRAMMER *pgm, const unsigned char *cmd,
if(verbose >= 2)
{
msg_notice2("bitbang_cmd(): [ ");
avrdude_message(MSG_NOTICE2, "bitbang_cmd(): [ ");
for(i = 0; i < count; i++)
msg_notice2("%02X ", cmd[i]);
msg_notice2("] [ ");
avrdude_message(MSG_NOTICE2, "%02X ", cmd[i]);
avrdude_message(MSG_NOTICE2, "] [ ");
for(i = 0; i < count; i++)
{
msg_notice2("%02X ", res[i]);
avrdude_message(MSG_NOTICE2, "%02X ", res[i]);
}
msg_notice2("]\n");
avrdude_message(MSG_NOTICE2, "]\n");
}
return 0;
@@ -414,12 +422,13 @@ int bitbang_spi(const PROGRAMMER *pgm, const unsigned char *cmd,
/*
* issue the 'chip erase' command to the AVR device
*/
int bitbang_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
int bitbang_chip_erase(PROGRAMMER * pgm, AVRPART * p)
{
unsigned char cmd[4];
unsigned char res[4];
AVRMEM *mem;
if (p->prog_modes & PM_TPI) {
if (p->flags & AVRPART_HAS_TPI) {
pgm->pgm_led(pgm, ON);
while (avr_tpi_poll_nvmbsy(pgm));
@@ -431,7 +440,8 @@ int bitbang_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
/* Set Pointer Register */
mem = avr_locate_mem(p, "flash");
if (mem == NULL) {
pmsg_error("no flash memory to erase for part %s\n", p->desc);
avrdude_message(MSG_INFO, "No flash memory to erase for part %s\n",
p->desc);
return -1;
}
bitbang_tpi_tx(pgm, TPI_CMD_SSTPR | 0);
@@ -451,7 +461,8 @@ int bitbang_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
}
if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
pmsg_error("chip erase instruction not defined for part %s\n", p->desc);
avrdude_message(MSG_INFO, "chip erase instruction not defined for part \"%s\"\n",
p->desc);
return -1;
}
@@ -472,12 +483,13 @@ int bitbang_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
/*
* issue the 'program enable' command to the AVR device
*/
int bitbang_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
int bitbang_program_enable(PROGRAMMER * pgm, AVRPART * p)
{
unsigned char cmd[4];
unsigned char res[4];
int i;
if (p->prog_modes & PM_TPI) {
if (p->flags & AVRPART_HAS_TPI) {
/* enable NVM programming */
bitbang_tpi_tx(pgm, TPI_CMD_SKEY);
for (i = sizeof(tpi_skey) - 1; i >= 0; i--)
@@ -490,7 +502,8 @@ int bitbang_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
}
if (p->op[AVR_OP_PGM_ENABLE] == NULL) {
pmsg_error("program enable instruction not defined for part %s\n", p->desc);
avrdude_message(MSG_INFO, "program enable instruction not defined for part \"%s\"\n",
p->desc);
return -1;
}
@@ -507,7 +520,8 @@ int bitbang_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
/*
* initialize the AVR device and prepare it to accept commands
*/
int bitbang_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
int bitbang_initialize(PROGRAMMER * pgm, AVRPART * p)
{
int rc;
int tries;
int i;
@@ -517,11 +531,12 @@ int bitbang_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
pgm->powerup(pgm);
usleep(20000);
/* TPIDATA is a single line, so SDI & SDO should be connected */
if (p->prog_modes & PM_TPI) {
/* TPIDATA is a single line, so MISO & MOSI should be connected */
if (p->flags & AVRPART_HAS_TPI) {
/* make sure cmd_tpi() is defined */
if (pgm->cmd_tpi == NULL) {
pmsg_error("%s programmer does not support TPI\n", pgm->type);
avrdude_message(MSG_INFO, "%s: Error: %s programmer does not support TPI\n",
progname, pgm->type);
return -1;
}
@@ -532,29 +547,29 @@ int bitbang_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
/* RESET must be LOW in case the existing code is driving the TPI pins: */
pgm->setpin(pgm, PIN_AVR_RESET, 0);
msg_notice2("doing SDO-SDI link check\n");
avrdude_message(MSG_NOTICE2, "doing MOSI-MISO link check\n");
pgm->setpin(pgm, PIN_AVR_SDO, 0);
if (pgm->getpin(pgm, PIN_AVR_SDI) != 0) {
pmsg_error("SDO->SDI 0 failed\n");
pgm->setpin(pgm, PIN_AVR_MOSI, 0);
if (pgm->getpin(pgm, PIN_AVR_MISO) != 0) {
avrdude_message(MSG_INFO, "MOSI->MISO 0 failed\n");
return -1;
}
pgm->setpin(pgm, PIN_AVR_SDO, 1);
if (pgm->getpin(pgm, PIN_AVR_SDI) != 1) {
pmsg_error("SDO->SDI 1 failed\n");
pgm->setpin(pgm, PIN_AVR_MOSI, 1);
if (pgm->getpin(pgm, PIN_AVR_MISO) != 1) {
avrdude_message(MSG_INFO, "MOSI->MISO 1 failed\n");
return -1;
}
msg_notice2("SDO-SDI link present\n");
avrdude_message(MSG_NOTICE2, "MOSI-MISO link present\n");
}
pgm->setpin(pgm, PIN_AVR_SCK, 0);
pgm->setpin(pgm, PIN_AVR_RESET, 0);
usleep(20000);
if (p->prog_modes & PM_TPI) {
if (p->flags & AVRPART_HAS_TPI) {
/* keep TPIDATA high for 16 clock cycles */
pgm->setpin(pgm, PIN_AVR_SDO, 1);
pgm->setpin(pgm, PIN_AVR_MOSI, 1);
for (i = 0; i < 16; i++)
pgm->highpulsepin(pgm, PIN_AVR_SCK);
@@ -566,7 +581,7 @@ int bitbang_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
bitbang_tpi_tx(pgm, TPI_CMD_SLDCS | TPI_REG_TPIIR);
rc = bitbang_tpi_rx(pgm);
if (rc != 0x80) {
pmsg_error("TPIIR not correct\n");
avrdude_message(MSG_INFO, "TPIIR not correct\n");
return -1;
}
} else {
@@ -600,7 +615,7 @@ int bitbang_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
* can't sync with the device, maybe it's not attached?
*/
if (rc) {
pmsg_error("AVR device not responding\n");
avrdude_message(MSG_INFO, "%s: AVR device not responding\n", progname);
return -1;
}
}
@@ -608,14 +623,11 @@ int bitbang_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
return 0;
}
static int verify_pin_assigned(const PROGRAMMER *pgm, int pinfunc, char *desc) {
if(pinfunc < 0 || pinfunc >= N_PINS) {
pmsg_error("invalid pin function number %d\n", pinfunc);
return -1;
}
if ((pgm->pinno[pinfunc] & PIN_MASK) > PIN_MAX) {
pmsg_error("no pin has been assigned for %s\n", desc);
static int verify_pin_assigned(PROGRAMMER * pgm, int pin, char * desc)
{
if (pgm->pinno[pin] == 0) {
avrdude_message(MSG_INFO, "%s: error: no pin has been assigned for %s\n",
progname, desc);
return -1;
}
return 0;
@@ -625,19 +637,21 @@ static int verify_pin_assigned(const PROGRAMMER *pgm, int pinfunc, char *desc) {
/*
* Verify all prerequisites for a bit-bang programmer are present.
*/
int bitbang_check_prerequisites(const PROGRAMMER *pgm) {
int bitbang_check_prerequisites(PROGRAMMER *pgm)
{
if (verify_pin_assigned(pgm, PIN_AVR_RESET, "AVR RESET") < 0)
return -1;
if (verify_pin_assigned(pgm, PIN_AVR_SCK, "AVR SCK") < 0)
return -1;
if (verify_pin_assigned(pgm, PIN_AVR_SDI, "AVR SDI") < 0)
if (verify_pin_assigned(pgm, PIN_AVR_MISO, "AVR MISO") < 0)
return -1;
if (verify_pin_assigned(pgm, PIN_AVR_SDO, "AVR SDO") < 0)
if (verify_pin_assigned(pgm, PIN_AVR_MOSI, "AVR MOSI") < 0)
return -1;
if (pgm->cmd == NULL) {
pmsg_error("no cmd() method defined for bitbang programmer\n");
avrdude_message(MSG_INFO, "%s: error: no cmd() method defined for bitbang programmer\n",
progname);
return -1;
}
return 0;

View File

@@ -31,25 +31,25 @@ int bitbang_getpin(int fd, int pin);
int bitbang_highpulsepin(int fd, int pin);
void bitbang_delay(unsigned int us);
int bitbang_check_prerequisites(const PROGRAMMER *pgm);
int bitbang_check_prerequisites(PROGRAMMER *pgm);
int bitbang_rdy_led (const PROGRAMMER *pgm, int value);
int bitbang_err_led (const PROGRAMMER *pgm, int value);
int bitbang_pgm_led (const PROGRAMMER *pgm, int value);
int bitbang_vfy_led (const PROGRAMMER *pgm, int value);
int bitbang_cmd (const PROGRAMMER *pgm, const unsigned char *cmd,
int bitbang_rdy_led (PROGRAMMER * pgm, int value);
int bitbang_err_led (PROGRAMMER * pgm, int value);
int bitbang_pgm_led (PROGRAMMER * pgm, int value);
int bitbang_vfy_led (PROGRAMMER * pgm, int value);
int bitbang_cmd (PROGRAMMER * pgm, const unsigned char *cmd,
unsigned char *res);
int bitbang_cmd_tpi (const PROGRAMMER *pgm, const unsigned char *cmd,
int bitbang_cmd_tpi (PROGRAMMER * pgm, const unsigned char *cmd,
int cmd_len, unsigned char *res, int res_len);
int bitbang_spi (const PROGRAMMER *pgm, const unsigned char *cmd,
int bitbang_spi (PROGRAMMER * pgm, const unsigned char *cmd,
unsigned char *res, int count);
int bitbang_chip_erase (const PROGRAMMER *pgm, const AVRPART *p);
int bitbang_program_enable (const PROGRAMMER *pgm, const AVRPART *p);
void bitbang_powerup (const PROGRAMMER *pgm);
void bitbang_powerdown (const PROGRAMMER *pgm);
int bitbang_initialize (const PROGRAMMER *pgm, const AVRPART *p);
void bitbang_disable (const PROGRAMMER *pgm);
void bitbang_enable (PROGRAMMER *pgm, const AVRPART *p);
int bitbang_chip_erase (PROGRAMMER * pgm, AVRPART * p);
int bitbang_program_enable (PROGRAMMER * pgm, AVRPART * p);
void bitbang_powerup (PROGRAMMER * pgm);
void bitbang_powerdown (PROGRAMMER * pgm);
int bitbang_initialize (PROGRAMMER * pgm, AVRPART * p);
void bitbang_disable (PROGRAMMER * pgm);
void bitbang_enable (PROGRAMMER * pgm);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,7 @@
extern const char buspirate_desc[];
extern const char buspirate_bb_desc[];
void buspirate_initpgm(PROGRAMMER *pgm);
void buspirate_bb_initpgm(PROGRAMMER *pgm);
void buspirate_initpgm (struct programmer_t *pgm);
void buspirate_bb_initpgm (struct programmer_t *pgm);
#endif

View File

@@ -63,7 +63,8 @@ struct pdata
static void butterfly_setup(PROGRAMMER * pgm)
{
if ((pgm->cookie = malloc(sizeof(struct pdata))) == 0) {
pmsg_error("out of memory allocating private data\n");
avrdude_message(MSG_INFO, "%s: butterfly_setup(): Out of memory allocating private data\n",
progname);
exit(1);
}
memset(pgm->cookie, 0, sizeof(struct pdata));
@@ -74,62 +75,72 @@ static void butterfly_teardown(PROGRAMMER * pgm)
free(pgm->cookie);
}
static int butterfly_send(const PROGRAMMER *pgm, char *buf, size_t len) {
static int butterfly_send(PROGRAMMER * pgm, char * buf, size_t len)
{
return serial_send(&pgm->fd, (unsigned char *)buf, len);
}
static int butterfly_recv(const PROGRAMMER *pgm, char *buf, size_t len) {
static int butterfly_recv(PROGRAMMER * pgm, char * buf, size_t len)
{
int rv;
rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
if (rv < 0) {
pmsg_error("programmer is not responding\n");
avrdude_message(MSG_INFO, "%s: butterfly_recv(): programmer is not responding\n",
progname);
return -1;
}
return 0;
}
static int butterfly_drain(const PROGRAMMER *pgm, int display) {
static int butterfly_drain(PROGRAMMER * pgm, int display)
{
return serial_drain(&pgm->fd, display);
}
static int butterfly_vfy_cmd_sent(const PROGRAMMER *pgm, char *errmsg) {
static int butterfly_vfy_cmd_sent(PROGRAMMER * pgm, char * errmsg)
{
char c;
butterfly_recv(pgm, &c, 1);
if (c != '\r') {
pmsg_error("programmer did not respond to command: %s\n", errmsg);
avrdude_message(MSG_INFO, "%s: error: programmer did not respond to command: %s\n",
progname, errmsg);
return -1;
}
return 0;
}
static int butterfly_rdy_led(const PROGRAMMER *pgm, int value) {
static int butterfly_rdy_led(PROGRAMMER * pgm, int value)
{
/* Do nothing. */
return 0;
}
static int butterfly_err_led(const PROGRAMMER *pgm, int value) {
static int butterfly_err_led(PROGRAMMER * pgm, int value)
{
/* Do nothing. */
return 0;
}
static int butterfly_pgm_led(const PROGRAMMER *pgm, int value) {
static int butterfly_pgm_led(PROGRAMMER * pgm, int value)
{
/* Do nothing. */
return 0;
}
static int butterfly_vfy_led(const PROGRAMMER *pgm, int value) {
static int butterfly_vfy_led(PROGRAMMER * pgm, int value)
{
/* Do nothing. */
return 0;
@@ -139,7 +150,8 @@ static int butterfly_vfy_led(const PROGRAMMER *pgm, int value) {
/*
* issue the 'chip erase' command to the butterfly board
*/
static int butterfly_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
static int butterfly_chip_erase(PROGRAMMER * pgm, AVRPART * p)
{
butterfly_send(pgm, "e", 1);
if (butterfly_vfy_cmd_sent(pgm, "chip erase") < 0)
return -1;
@@ -148,13 +160,15 @@ static int butterfly_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
}
static void butterfly_enter_prog_mode(const PROGRAMMER *pgm) {
static void butterfly_enter_prog_mode(PROGRAMMER * pgm)
{
butterfly_send(pgm, "P", 1);
butterfly_vfy_cmd_sent(pgm, "enter prog mode");
}
static void butterfly_leave_prog_mode(const PROGRAMMER *pgm) {
static void butterfly_leave_prog_mode(PROGRAMMER * pgm)
{
butterfly_send(pgm, "L", 1);
butterfly_vfy_cmd_sent(pgm, "leave prog mode");
}
@@ -163,7 +177,8 @@ static void butterfly_leave_prog_mode(const PROGRAMMER *pgm) {
/*
* issue the 'program enable' command to the AVR device
*/
static int butterfly_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
static int butterfly_program_enable(PROGRAMMER * pgm, AVRPART * p)
{
return -1;
}
@@ -171,7 +186,8 @@ static int butterfly_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
/*
* apply power to the AVR processor
*/
static void butterfly_powerup(const PROGRAMMER *pgm) {
static void butterfly_powerup(PROGRAMMER * pgm)
{
/* Do nothing. */
return;
@@ -181,7 +197,8 @@ static void butterfly_powerup(const PROGRAMMER *pgm) {
/*
* remove power from the AVR processor
*/
static void butterfly_powerdown(const PROGRAMMER *pgm) {
static void butterfly_powerdown(PROGRAMMER * pgm)
{
/* Do nothing. */
return;
@@ -192,7 +209,8 @@ static void butterfly_powerdown(const PROGRAMMER *pgm) {
/*
* initialize the AVR device and prepare it to accept commands
*/
static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
static int butterfly_initialize(PROGRAMMER * pgm, AVRPART * p)
{
char id[8];
char sw[2];
char hw[2];
@@ -204,13 +222,13 @@ static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
* Send some ESC to activate butterfly bootloader. This is not needed
* for plain avr109 bootloaders but does not harm there either.
*/
msg_notice("connecting to programmer: ");
avrdude_message(MSG_INFO, "Connecting to programmer: ");
if (pgm->flag & IS_BUTTERFLY_MK)
{
char mk_reset_cmd[6] = {"#aR@S\r"};
unsigned char mk_timeout = 0;
msg_notice(".");
putc('.', stderr);
butterfly_send(pgm, mk_reset_cmd, sizeof(mk_reset_cmd));
usleep(20000);
@@ -222,15 +240,13 @@ static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
c = 0xaa;
usleep(80000);
butterfly_send(pgm, &c, 1);
if (mk_timeout % 10 == 0)
msg_notice(".");
if (mk_timeout % 10 == 0) putc('.', stderr);
} while (mk_timeout++ < 10);
butterfly_recv(pgm, &c, 1);
if ( c != 'M' && c != '?')
{
msg_error("\n");
pmsg_error("connection failed");
avrdude_message(MSG_INFO, "\nConnection FAILED.");
return -1;
}
else
@@ -241,13 +257,13 @@ static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
else
{
do {
msg_notice(".");
putc('.', stderr);
butterfly_send(pgm, "\033", 1);
butterfly_drain(pgm, 0);
butterfly_send(pgm, "S", 1);
butterfly_recv(pgm, &c, 1);
if (c != '?') {
msg_notice("\n");
putc('\n', stderr);
/*
* Got a useful response, continue getting the programmer
* identifier. Programmer returns exactly 7 chars _without_
@@ -277,12 +293,12 @@ static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
butterfly_send(pgm, "p", 1);
butterfly_recv(pgm, &type, 1);
msg_notice("Programmer id = %s; type = %c\n", id, type);
msg_notice("Software version = %c.%c; ", sw[0], sw[1]);
avrdude_message(MSG_INFO, "Found programmer: Id = \"%s\"; type = %c\n", id, type);
avrdude_message(MSG_INFO, " Software Version = %c.%c; ", sw[0], sw[1]);
if (hw[0]=='?') {
msg_notice("no hardware version given\n");
avrdude_message(MSG_INFO, "No Hardware Version given.\n");
} else {
msg_notice("Hardware version = %c.%c\n", hw[0], hw[1]);
avrdude_message(MSG_INFO, "Hardware Version = %c.%c\n", hw[0], hw[1]);
};
/* See if programmer supports autoincrement of address. */
@@ -290,28 +306,28 @@ static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
butterfly_send(pgm, "a", 1);
butterfly_recv(pgm, &PDATA(pgm)->has_auto_incr_addr, 1);
if (PDATA(pgm)->has_auto_incr_addr == 'Y')
msg_notice("programmer supports auto addr increment\n");
avrdude_message(MSG_INFO, "Programmer supports auto addr increment.\n");
/* Check support for buffered memory access, abort if not available */
butterfly_send(pgm, "b", 1);
butterfly_recv(pgm, &c, 1);
if (c != 'Y') {
pmsg_notice("buffered memory access not supported; maybe it isn't\n"\
"a butterfly/AVR109 but a AVR910 device?\n");
avrdude_message(MSG_INFO, "%s: error: buffered memory access not supported. Maybe it isn't\n"\
"a butterfly/AVR109 but a AVR910 device?\n", progname);
return -1;
};
butterfly_recv(pgm, &c, 1);
PDATA(pgm)->buffersize = (unsigned int)(unsigned char)c<<8;
butterfly_recv(pgm, &c, 1);
PDATA(pgm)->buffersize += (unsigned int)(unsigned char)c;
msg_notice("programmer supports buffered memory access with buffersize=%i bytes\n",
avrdude_message(MSG_INFO, "Programmer supports buffered memory access with buffersize=%i bytes.\n",
PDATA(pgm)->buffersize);
/* Get list of devices that the programmer supports. */
butterfly_send(pgm, "t", 1);
msg_notice2("\nProgrammer supports the following devices:\n");
avrdude_message(MSG_INFO, "\nProgrammer supports the following devices:\n");
devtype_1st = 0;
while (1) {
butterfly_recv(pgm, &c, 1);
@@ -320,9 +336,9 @@ static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
if (c == 0)
break;
msg_notice2(" Device code: 0x%02x\n", (unsigned int) (unsigned char) c);
avrdude_message(MSG_INFO, " Device code: 0x%02x\n", (unsigned int)(unsigned char)c);
};
msg_notice2("\n");
avrdude_message(MSG_INFO, "\n");
/* Tell the programmer which part we selected.
According to the AVR109 code, this is ignored by the bootloader. As
@@ -339,7 +355,9 @@ static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
if (butterfly_vfy_cmd_sent(pgm, "select device") < 0)
return -1;
pmsg_notice("devcode selected: 0x%02x\n", (unsigned) buf[1]);
if (verbose)
avrdude_message(MSG_INFO, "%s: devcode selected: 0x%02x\n",
progname, (unsigned)buf[1]);
butterfly_enter_prog_mode(pgm);
butterfly_drain(pgm, 0);
@@ -349,19 +367,22 @@ static int butterfly_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
static void butterfly_disable(const PROGRAMMER *pgm) {
static void butterfly_disable(PROGRAMMER * pgm)
{
butterfly_leave_prog_mode(pgm);
return;
}
static void butterfly_enable(PROGRAMMER *pgm, const AVRPART *p) {
static void butterfly_enable(PROGRAMMER * pgm)
{
return;
}
static int butterfly_open(PROGRAMMER *pgm, const char *port) {
static int butterfly_open(PROGRAMMER * pgm, char * port)
{
union pinfo pinfo;
strcpy(pgm->port, port);
/*
@@ -396,36 +417,27 @@ static void butterfly_close(PROGRAMMER * pgm)
}
static void butterfly_display(const PROGRAMMER *pgm, const char *p) {
static void butterfly_display(PROGRAMMER * pgm, const char * p)
{
return;
}
static void butterfly_set_addr(const PROGRAMMER *pgm, unsigned long addr) {
if( addr < 0x10000 ) {
char cmd[3];
static void butterfly_set_addr(PROGRAMMER * pgm, unsigned long addr)
{
char cmd[3];
cmd[0] = 'A';
cmd[1] = (addr >> 8) & 0xff;
cmd[2] = addr & 0xff;
cmd[0] = 'A';
cmd[1] = (addr >> 8) & 0xff;
cmd[2] = addr & 0xff;
butterfly_send(pgm, cmd, sizeof(cmd));
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");
}
butterfly_send(pgm, cmd, sizeof(cmd));
butterfly_vfy_cmd_sent(pgm, "set addr");
}
static void butterfly_set_extaddr(const PROGRAMMER *pgm, unsigned long addr) {
static void butterfly_set_extaddr(PROGRAMMER * pgm, unsigned long addr)
{
char cmd[4];
cmd[0] = 'H';
@@ -439,7 +451,7 @@ static void butterfly_set_extaddr(const PROGRAMMER *pgm, unsigned long addr) {
static int butterfly_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int butterfly_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char value)
{
char cmd[6];
@@ -483,7 +495,7 @@ static int butterfly_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const A
}
static int butterfly_read_byte_flash(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int butterfly_read_byte_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char * value)
{
static int cached = 0;
@@ -503,13 +515,9 @@ static int butterfly_read_byte_flash(const PROGRAMMER *pgm, const AVRPART *p, co
} else {
butterfly_set_addr(pgm, addr >> 1);
}
// Defaults to flash read ('F')
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);
butterfly_send(pgm, "g\000\002F", 4);
/* Read back the program mem word (MSB first) */
butterfly_recv(pgm, buf, sizeof(buf));
@@ -528,7 +536,7 @@ static int butterfly_read_byte_flash(const PROGRAMMER *pgm, const AVRPART *p, co
}
static int butterfly_read_byte_eeprom(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int butterfly_read_byte_eeprom(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char * value)
{
butterfly_set_addr(pgm, addr);
@@ -537,14 +545,23 @@ static int butterfly_read_byte_eeprom(const PROGRAMMER *pgm, const AVRPART *p, c
return 0;
}
static int butterfly_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int butterfly_page_erase(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned int addr)
{
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)
{
char cmd;
if (strcmp(m->desc, "flash") == 0 ||
strcmp(m->desc, "prodsig") == 0 ||
strcmp(m->desc, "usersig") == 0) {
if (strcmp(m->desc, "flash") == 0) {
return butterfly_read_byte_flash(pgm, p, m, addr, value);
}
@@ -575,7 +592,7 @@ static int butterfly_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AV
static int butterfly_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int butterfly_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size,
unsigned int addr, unsigned int n_bytes)
{
@@ -585,9 +602,7 @@ static int butterfly_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const
int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
unsigned int wr_size = 2;
if (strcmp(m->desc, "flash") &&
strcmp(m->desc, "eeprom") &&
strcmp(m->desc, "usersig"))
if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom"))
return -2;
if (m->desc[0] == 'e')
@@ -632,7 +647,7 @@ static int butterfly_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const
static int butterfly_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m,
static int butterfly_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size,
unsigned int addr, unsigned int n_bytes)
{
@@ -641,10 +656,8 @@ static int butterfly_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const A
int blocksize = PDATA(pgm)->buffersize;
int use_ext_addr = m->op[AVR_OP_LOAD_EXT_ADDR] != NULL;
/* check parameter syntax: only "flash", "eeprom" or "usersig" is allowed */
if (strcmp(m->desc, "flash") &&
strcmp(m->desc, "eeprom") &&
strcmp(m->desc, "usersig"))
/* check parameter syntax: only "flash" or "eeprom" is allowed */
if (strcmp(m->desc, "flash") && strcmp(m->desc, "eeprom"))
return -2;
if (m->desc[0] == 'e')
@@ -680,11 +693,12 @@ static int butterfly_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const A
/* Signature byte reads are always 3 bytes. */
static int butterfly_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *m) {
static int butterfly_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
{
unsigned char tmp;
if (m->size < 3) {
pmsg_error("memsize too small for sig byte read");
avrdude_message(MSG_INFO, "%s: memsize too small for sig byte read", progname);
return -1;
}
@@ -700,7 +714,8 @@ static int butterfly_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, con
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");
/*
@@ -727,6 +742,7 @@ void butterfly_initpgm(PROGRAMMER *pgm) {
* optional functions
*/
pgm->page_erase = butterfly_page_erase;
pgm->paged_write = butterfly_paged_write;
pgm->paged_load = butterfly_paged_load;
@@ -739,7 +755,8 @@ void butterfly_initpgm(PROGRAMMER *pgm) {
const char butterfly_mk_desc[] = "Mikrokopter.de Butterfly";
void butterfly_mk_initpgm(PROGRAMMER *pgm) {
void butterfly_mk_initpgm(PROGRAMMER * pgm)
{
butterfly_initpgm(pgm);
strcpy(pgm->type, "butterfly_mk");
pgm->flag = IS_BUTTERFLY_MK;

View File

@@ -27,8 +27,8 @@ extern "C" {
extern const char butterfly_desc[];
extern const char butterfly_mk_desc[];
void butterfly_initpgm(PROGRAMMER *pgm);
void butterfly_mk_initpgm(PROGRAMMER *pgm);
void butterfly_initpgm (PROGRAMMER * pgm);
void butterfly_mk_initpgm (PROGRAMMER * pgm);
#ifdef __cplusplus
}

View File

@@ -35,6 +35,18 @@
/* ----- Functions ----- */
/* Define to 1 if you have the `usleep' function. */
#cmakedefine HAVE_USLEEP 1
/* Define to 1 if you have the `getaddrinfo' function. */
#cmakedefine HAVE_GETADDRINFO 1
/* Define to 1 if you have the `gettimeofday' function. */
#cmakedefine HAVE_GETTIMEOFDAY 1
/* Define to 1 if you have the `strcasecmp' function. */
#cmakedefine HAVE_STRCASECMP 1
/* Define if lex/flex has yylex_destroy */
#cmakedefine HAVE_YYLEX_DESTROY 1
@@ -49,6 +61,15 @@
/* Define to 1 if the system has the type `ulong_t'. */
#cmakedefine HAVE_ULONG_T 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine HAVE_STDLIB_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine HAVE_INTTYPES_H 1
/* Define if ELF support is enabled via libelf */
#cmakedefine HAVE_LIBELF 1
@@ -99,3 +120,9 @@
/* Define to 1 if you have the `readline' library (-lreadline). */
#cmakedefine HAVE_LIBREADLINE 1
/* Define to 1 if you have the `ws2_32' library (-lws2_32). */
#cmakedefine HAVE_LIBWS2_32 1
/* Define to 1 if you have the <netinet/in.h> header file. */
#cmakedefine HAVE_NETINET_IN_H 1

View File

@@ -24,65 +24,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include "avrdude.h"
#include "libavrdude.h"
#include "config.h"
#include "avrintel.h"
#include "config_gram.h"
const char *default_programmer;
const char *default_parallel;
const char *default_serial;
const char *default_spi;
char default_programmer[MAX_STR_CONST];
char default_parallel[PATH_MAX];
char default_serial[PATH_MAX];
double default_bitclock;
int default_safemode;
char string_buf[MAX_STR_CONST];
char *string_buf_ptr;
LISTID string_list;
LISTID number_list;
PROGRAMMER * current_prog;
AVRPART * current_part;
AVRMEM * current_mem;
int current_strct;
LISTID part_list;
LISTID programmers;
bool is_alias;
int cfg_lineno;
char * cfg_infile;
int lineno;
const char * infile;
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
void cleanup_config(void)
@@ -102,44 +73,13 @@ int init_config(void)
current_mem = NULL;
part_list = lcreat(NULL, 0);
programmers = lcreat(NULL, 0);
is_alias = false;
cfg_lineno = 1;
cfg_infile = NULL;
lineno = 1;
infile = NULL;
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()
@@ -157,7 +97,7 @@ int yyerror(char * errmsg, ...)
va_start(args, errmsg);
vsnprintf(message, sizeof(message), errmsg, args);
pmsg_error("%s [%s:%d]\n", message, cfg_infile, cfg_lineno);
avrdude_message(MSG_INFO, "%s: error at %s:%d: %s\n", progname, infile, lineno, message);
va_end(args);
@@ -174,7 +114,7 @@ int yywarning(char * errmsg, ...)
va_start(args, errmsg);
vsnprintf(message, sizeof(message), errmsg, args);
pmsg_warning("%s [%s:%d]\n", message, cfg_infile, cfg_lineno);
avrdude_message(MSG_INFO, "%s: warning at %s:%d: %s\n", progname, infile, lineno, message);
va_end(args);
@@ -182,9 +122,20 @@ int yywarning(char * errmsg, ...)
}
TOKEN * new_token(int primary) {
TOKEN * tkn = (TOKEN *) cfg_malloc("new_token()", sizeof(TOKEN));
TOKEN * new_token(int primary)
{
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;
return tkn;
}
@@ -220,98 +171,100 @@ void free_tokens(int n, ...)
TOKEN *new_number(const char *text) {
struct token_t *tkn = new_token(TKN_NUMBER);
TOKEN * number(char * text)
{
struct token_t * tkn;
tkn = new_token(TKN_NUMBER);
if (tkn == NULL) {
return NULL; /* yyerror already called */
}
tkn->value.type = V_NUM;
tkn->value.number = atoi(text);
#if DEBUG
msg_info("NUMBER(%d)\n", tkn->value.number);
avrdude_message(MSG_INFO, "NUMBER(%d)\n", tkn->value.number);
#endif
return tkn;
}
TOKEN *new_number_real(const char *text) {
struct token_t * tkn = new_token(TKN_NUMBER);
TOKEN * number_real(char * text)
{
struct token_t * tkn;
tkn = new_token(TKN_NUMBER);
tkn->value.type = V_NUM_REAL;
tkn->value.number_real = atof(text);
#if DEBUG
msg_info("NUMBER(%g)\n", tkn->value.number_real);
avrdude_message(MSG_INFO, "NUMBER(%g)\n", tkn->value.number_real);
#endif
return tkn;
}
TOKEN *new_hexnumber(const char *text) {
struct token_t *tkn = new_token(TKN_NUMBER);
TOKEN * hexnumber(char * text)
{
struct token_t * tkn;
char * e;
tkn = new_token(TKN_NUMBER);
if (tkn == NULL) {
return NULL; /* yyerror already called */
}
tkn->value.type = V_NUM;
tkn->value.number = strtoul(text, &e, 16);
if ((e == text) || (*e != 0)) {
yyerror("cannot scan hex number %s", text);
yyerror("can't scan hex number \"%s\"", text);
free_token(tkn);
return NULL;
}
#if DEBUG
msg_info("HEXNUMBER(%d)\n", tkn->value.number);
avrdude_message(MSG_INFO, "HEXNUMBER(%g)\n", tkn->value.number);
#endif
return tkn;
}
TOKEN *new_constant(const char *con) {
struct token_t *tkn = new_token(TKN_NUMBER);
int assigned = 1;
tkn->value.type = V_NUM;
tkn->value.number =
!strcmp("PM_SPM", con)? PM_SPM:
!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);
TOKEN * string(char * text)
{
struct token_t * tkn;
int len;
if(!assigned) {
yyerror("can't identify constant %s", con);
tkn = new_token(TKN_STRING);
if (tkn == NULL) {
return NULL; /* yyerror already called */
}
len = strlen(text);
tkn->value.type = V_STR;
tkn->value.string = (char *) malloc(len+1);
if (tkn->value.string == NULL) {
yyerror("string(): out of memory");
free_token(tkn);
return NULL;
}
strcpy(tkn->value.string, text);
#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.string = cfg_strdup("new_string()", text);
#if DEBUG
msg_info("STRING(%s)\n", tkn->value.string);
avrdude_message(MSG_INFO, "STRING(%s)\n", tkn->value.string);
#endif
return tkn;
}
TOKEN *new_keyword(int primary) {
return new_token(primary);
TOKEN * keyword(int primary)
{
struct token_t * tkn;
tkn = new_token(primary);
return tkn;
}
@@ -320,37 +273,50 @@ void print_token(TOKEN * tkn)
if (!tkn)
return;
msg_info("token = %d = ", tkn->primary);
avrdude_message(MSG_INFO, "token = %d = ", tkn->primary);
switch (tkn->value.type) {
case V_NUM:
msg_info("NUMBER, value=%d", tkn->value.number);
avrdude_message(MSG_INFO, "NUMBER, value=%d", tkn->value.number);
break;
case V_NUM_REAL:
msg_info("NUMBER, value=%g", tkn->value.number_real);
avrdude_message(MSG_INFO, "NUMBER, value=%g", tkn->value.number_real);
break;
case V_STR:
msg_info("STRING, value=%s", tkn->value.string);
avrdude_message(MSG_INFO, "STRING, value=%s", tkn->value.string);
break;
default:
msg_info("<other>");
avrdude_message(MSG_INFO, "<other>");
break;
}
msg_info("\n");
avrdude_message(MSG_INFO, "\n");
}
void pyytext(void)
{
#if DEBUG
msg_info("TOKEN: %s\n", yytext);
avrdude_message(MSG_INFO, "TOKEN: \"%s\"\n", yytext);
#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
/* reset lexer and free any allocated memory */
extern int yylex_destroy(void);
@@ -361,20 +327,15 @@ int read_config(const char * file)
FILE * f;
int r;
if(!(cfg_infile = realpath(file, NULL))) {
pmsg_ext_error("cannot determine realpath() of config file %s: %s\n", file, strerror(errno));
return -1;
}
f = fopen(cfg_infile, "r");
f = fopen(file, "r");
if (f == NULL) {
pmsg_ext_error("cannot open config file %s: %s\n", cfg_infile, strerror(errno));
free(cfg_infile);
cfg_infile = NULL;
avrdude_message(MSG_INFO, "%s: can't open config file \"%s\": %s\n",
progname, file, strerror(errno));
return -1;
}
cfg_lineno = 1;
lineno = 1;
infile = file;
yyin = f;
r = yyparse();
@@ -386,513 +347,5 @@ int read_config(const char * file)
fclose(f);
if(cfg_infile) {
free(cfg_infile);
cfg_infile = NULL;
}
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);
}

View File

@@ -25,61 +25,17 @@
#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
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,
};
enum { V_NONE, V_NUM, V_NUM_REAL, V_STR };
typedef struct value_t {
int type;
union {
/*union { TODO: use an anonymous union here ? */
int number;
double number_real;
char * string;
Component_t *comp;
};
/*};*/
} VALUE;
@@ -94,12 +50,10 @@ extern FILE * yyin;
extern PROGRAMMER * current_prog;
extern AVRPART * current_part;
extern AVRMEM * current_mem;
extern int current_strct;
extern int cfg_lineno;
extern char * cfg_infile;
extern int lineno;
extern const char * infile;
extern LISTID string_list;
extern LISTID number_list;
extern bool is_alias; // current entry is alias
#if !defined(HAS_YYSTYPE)
@@ -107,61 +61,40 @@ extern bool is_alias; // current entry is alias
#endif
extern YYSTYPE yylval;
extern char string_buf[MAX_STR_CONST];
extern char *string_buf_ptr;
#ifdef __cplusplus
extern "C" {
#endif
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, ...);
TOKEN *new_number(const char *text);
TOKEN * number(char * text);
TOKEN *new_number_real(const char *text);
TOKEN * number_real(char * text);
TOKEN *new_hexnumber(const char *text);
TOKEN * hexnumber(char * text);
TOKEN *new_constant(const char *text);
TOKEN * string(char * text);
TOKEN *new_string(const char *text);
TOKEN * keyword(int primary);
TOKEN *new_keyword(int primary);
void print_token(TOKEN *tkn);
void print_token(TOKEN * tkn);
void pyytext(void);
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);
char * dup_string(const char * str);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.60)
AC_INIT(avrdude, 7.1-20230108, avrdude-dev@nongnu.org)
AC_INIT(avrdude, 6.99-20211218, avrdude-dev@nongnu.org)
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
@@ -228,15 +228,23 @@ AC_HEADER_TIME
AC_CHECK_HEADERS([netinet/in.h])
# WinSock2
AC_CHECK_LIB([ws2_32], [puts])
# Checks for library functions.
AC_CHECK_FUNCS([memset select strcasecmp strdup strerror strncasecmp strtol strtoul gettimeofday usleep getaddrinfo])
AC_MSG_CHECKING([for a Win32 HID library])
AC_MSG_CHECKING([for a Win32 HID libray])
SAVED_LIBS="${LIBS}"
case $target in
*-*-mingw32* | *-*-cygwin* | *-*-windows*)
LIBHID="-lhid -lsetupapi"
HIDINCLUDE="#include <hidsdi.h>"
if test $ac_cv_header_ddk_hidsdi_h = yes
then
HIDINCLUDE="#include <ddk/hidsdi.h>"
else
HIDINCLUDE="#include \"my_ddk_hidsdi.h\""
fi
;;
*)
LIBHID=""
@@ -427,7 +435,7 @@ else
fi
# If we are compiling with gcc, enable all warnings and make warnings errors.
# If we are compiling with gcc, enable all warning and make warnings errors.
if test "$GCC" = yes; then
ENABLE_WARNINGS="-Wall"
@@ -511,7 +519,7 @@ AC_CONFIG_FILES([
# The procedure to create avrdude.conf involves two steps. First,
# normal autoconf substitution will be applied, resulting in
# avrdude.conf.tmp. Finally, a sed command will be applied to filter
# avrdude.conf.tmp. Finally, a sed command will be applied to filter
# out unwanted parts (currently the parallel port programmer types)
# based on previous configuration results, thereby producing the final
# avrdude.conf file.
@@ -577,12 +585,6 @@ else
echo "DON'T HAVE libhidapi"
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
echo "DO HAVE pthread"
else

View File

@@ -1,35 +0,0 @@
#
# 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)

View File

@@ -17,33 +17,38 @@
*/
#include "ac_cfg.h"
#include "avrdude.h"
#include "libavrdude.h"
#if defined(WIN32)
#if defined(WIN32NATIVE)
#define WIN32_LEAN_AND_MEAN
#include <limits.h>
#include <windows.h>
static char *filename;
void win_sys_config_set(char sys_config[PATH_MAX])
{
sys_config[0] = 0;
/* Use Windows API call to search for the Windows default system config file.*/
SearchPath(NULL, SYSTEM_CONF_FILE, NULL, PATH_MAX, sys_config, &filename);
SearchPath(NULL, "avrdude.conf", NULL, PATH_MAX, sys_config, &filename);
return;
}
void win_usr_config_set(char usr_config[PATH_MAX])
{
usr_config[0] = 0;
/* Use Windows API call to search for the Windows default user config file. */
SearchPath(NULL, USER_CONF_FILE, NULL, PATH_MAX, usr_config, &filename);
SearchPath(NULL, "avrdude.rc", NULL, PATH_MAX, usr_config, &filename);
return;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +0,0 @@
/*
* 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

View File

@@ -1,140 +0,0 @@
/*
* 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
View File

@@ -38,8 +38,9 @@
#ifndef HAVE_LIBUSB
struct dfu_dev *dfu_open(const char *port_name) {
pmsg_error("no USB support compiled for avrdude\n");
struct dfu_dev *dfu_open(char *port_name) {
avrdude_message(MSG_INFO, "%s: Error: No USB support in this compile of avrdude\n",
progname);
return NULL;
}
@@ -98,7 +99,8 @@ static char * get_usb_string(usb_dev_handle * dev_handle, int index);
/* EXPORTED FUNCTION DEFINITIONS
*/
struct dfu_dev *dfu_open(const char *port_spec) {
struct dfu_dev * dfu_open(char *port_spec)
{
struct dfu_dev *dfu;
char *bus_name = NULL;
char *dev_name = NULL;
@@ -110,14 +112,16 @@ struct dfu_dev *dfu_open(const char *port_spec) {
*/
if (strncmp(port_spec, "usb", 3) != 0) {
pmsg_error("invalid port specification %s for USB device\n", port_spec);
avrdude_message(MSG_INFO, "%s: Error: "
"Invalid port specification \"%s\" for USB device\n",
progname, port_spec);
return NULL;
}
if(':' == port_spec[3]) {
bus_name = strdup(port_spec + 3 + 1);
if (bus_name == NULL) {
pmsg_error("out of memory in strdup\n");
avrdude_message(MSG_INFO, "%s: Out of memory in strdup\n", progname);
return NULL;
}
@@ -134,7 +138,7 @@ struct dfu_dev *dfu_open(const char *port_spec) {
if (dfu == NULL)
{
pmsg_error("out of memory\n");
avrdude_message(MSG_INFO, "%s: out of memory\n", progname);
free(bus_name);
return NULL;
}
@@ -168,7 +172,9 @@ int dfu_init(struct dfu_dev *dfu, unsigned short vid, unsigned short pid)
*/
if (pid == 0 && dfu->dev_name == NULL) {
pmsg_error("no DFU support for part; specify PID in config or USB address (via -P) to override\n");
avrdude_message(MSG_INFO, "%s: Error: No DFU support for part; "
"specify PID in config or USB address (via -P) to override.\n",
progname);
return -1;
}
@@ -203,18 +209,20 @@ 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.
*/
pmsg_error("no matching USB device found\n");
avrdude_message(MSG_INFO, "%s: Error: No matching USB device found\n", progname);
return -1;
}
pmsg_notice("found VID=0x%04x PID=0x%04x at %s:%s\n",
found->descriptor.idVendor, found->descriptor.idProduct,
found->bus->dirname, found->filename);
if(verbose)
avrdude_message(MSG_INFO, "%s: Found VID=0x%04x PID=0x%04x at %s:%s\n",
progname, found->descriptor.idVendor, found->descriptor.idProduct,
found->bus->dirname, found->filename);
dfu->dev_handle = usb_open(found);
if (dfu->dev_handle == NULL) {
pmsg_error("USB device at %s:%s: %s\n", found->bus->dirname, found->filename, usb_strerror());
avrdude_message(MSG_INFO, "%s: Error: USB device at %s:%s: %s\n",
progname, found->bus->dirname, found->filename, usb_strerror());
return -1;
}
@@ -264,32 +272,37 @@ int dfu_getstatus(struct dfu_dev *dfu, struct dfu_status *status)
{
int result;
pmsg_trace("dfu_getstatus(): issuing control IN message\n");
avrdude_message(MSG_TRACE, "%s: dfu_getstatus(): issuing control IN message\n",
progname);
result = usb_control_msg(dfu->dev_handle,
0x80 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_GETSTATUS, 0, 0,
(char*) status, sizeof(struct dfu_status), dfu->timeout);
if (result < 0) {
pmsg_error("unable to get DFU status: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: Error: Failed to get DFU status: %s\n",
progname, usb_strerror());
return -1;
}
if (result < sizeof(struct dfu_status)) {
pmsg_error("unable to get DFU status: %s\n", "short read");
avrdude_message(MSG_INFO, "%s: Error: Failed to get DFU status: %s\n",
progname, "short read");
return -1;
}
if (result > sizeof(struct dfu_status)) {
pmsg_error("oversize read (should not happen); exiting\n");
avrdude_message(MSG_INFO, "%s: Error: Oversize read (should not happen); "
"exiting\n", progname);
exit(1);
}
pmsg_trace("dfu_getstatus(): bStatus 0x%02x, bwPollTimeout %d, bState 0x%02x, iString %d\n",
status->bStatus,
status->bwPollTimeout[0] | (status->bwPollTimeout[1] << 8) | (status->bwPollTimeout[2] << 16),
status->bState,
status->iString);
avrdude_message(MSG_TRACE, "%s: dfu_getstatus(): bStatus 0x%02x, bwPollTimeout %d, bState 0x%02x, iString %d\n",
progname,
status->bStatus,
status->bwPollTimeout[0] | (status->bwPollTimeout[1] << 8) | (status->bwPollTimeout[2] << 16),
status->bState,
status->iString);
return 0;
}
@@ -298,14 +311,16 @@ int dfu_clrstatus(struct dfu_dev *dfu)
{
int result;
pmsg_trace("dfu_clrstatus(): issuing control OUT message\n");
avrdude_message(MSG_TRACE, "%s: dfu_clrstatus(): issuing control OUT message\n",
progname);
result = usb_control_msg(dfu->dev_handle,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_CLRSTATUS, 0, 0,
NULL, 0, dfu->timeout);
if (result < 0) {
pmsg_error("unable to clear DFU status: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: Error: Failed to clear DFU status: %s\n",
progname, usb_strerror());
return -1;
}
@@ -316,14 +331,16 @@ int dfu_abort(struct dfu_dev *dfu)
{
int result;
pmsg_trace("dfu_abort(): issuing control OUT message\n");
avrdude_message(MSG_TRACE, "%s: dfu_abort(): issuing control OUT message\n",
progname);
result = usb_control_msg(dfu->dev_handle,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_ABORT, 0, 0,
NULL, 0, dfu->timeout);
if (result < 0) {
pmsg_error("unable to reset DFU state: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: Error: Failed to reset DFU state: %s\n",
progname, usb_strerror());
return -1;
}
@@ -335,26 +352,29 @@ int dfu_dnload(struct dfu_dev *dfu, void *ptr, int size)
{
int result;
pmsg_trace("dfu_dnload(): issuing control OUT message, wIndex = %d, ptr = %p, size = %d\n",
wIndex, ptr, size);
avrdude_message(MSG_TRACE, "%s: dfu_dnload(): issuing control OUT message, wIndex = %d, ptr = %p, size = %d\n",
progname, wIndex, ptr, size);
result = usb_control_msg(dfu->dev_handle,
USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_DNLOAD, wIndex++, 0,
ptr, size, dfu->timeout);
if (result < 0) {
pmsg_error("DFU_DNLOAD failed: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: Error: DFU_DNLOAD failed: %s\n",
progname, usb_strerror());
return -1;
}
if (result < size) {
pmsg_error("DFU_DNLOAD failed: short write\n");
avrdude_message(MSG_INFO, "%s: Error: DFU_DNLOAD failed: %s\n",
progname, "short write");
return -1;
}
if (result > size) {
pmsg_error("DFU_DNLOAD failed: oversize write (should not happen)\n");
return -1;
avrdude_message(MSG_INFO, "%s: Error: Oversize write (should not happen); " \
"exiting\n", progname);
exit(1);
}
return 0;
@@ -364,25 +384,28 @@ int dfu_upload(struct dfu_dev *dfu, void *ptr, int size)
{
int result;
pmsg_trace("dfu_upload(): issuing control IN message, wIndex = %d, ptr = %p, size = %d\n",
wIndex, ptr, size);
avrdude_message(MSG_TRACE, "%s: dfu_upload(): issuing control IN message, wIndex = %d, ptr = %p, size = %d\n",
progname, wIndex, ptr, size);
result = usb_control_msg(dfu->dev_handle,
0x80 | USB_TYPE_CLASS | USB_RECIP_INTERFACE, DFU_UPLOAD, wIndex++, 0,
ptr, size, dfu->timeout);
if (result < 0) {
pmsg_error("DFU_UPLOAD failed: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: Error: DFU_UPLOAD failed: %s\n",
progname, usb_strerror());
return -1;
}
if (result < size) {
pmsg_error("DFU_UPLOAD failed: %s\n", "short read");
avrdude_message(MSG_INFO, "%s: Error: DFU_UPLOAD failed: %s\n",
progname, "short read");
return -1;
}
if (result > size) {
pmsg_error("oversize read (should not happen); exiting\n");
avrdude_message(MSG_INFO, "%s: Error: Oversize read (should not happen); "
"exiting\n", progname);
exit(1);
}
@@ -392,26 +415,26 @@ int dfu_upload(struct dfu_dev *dfu, void *ptr, int size)
void dfu_show_info(struct dfu_dev *dfu)
{
if (dfu->manf_str != NULL)
msg_info(" USB Vendor : %s (0x%04hX)\n",
avrdude_message(MSG_INFO, " USB Vendor : %s (0x%04hX)\n",
dfu->manf_str, (unsigned short) dfu->dev_desc.idVendor);
else
msg_info(" USB Vendor : 0x%04hX\n",
avrdude_message(MSG_INFO, " USB Vendor : 0x%04hX\n",
(unsigned short) dfu->dev_desc.idVendor);
if (dfu->prod_str != NULL)
msg_info(" USB Product : %s (0x%04hX)\n",
avrdude_message(MSG_INFO, " USB Product : %s (0x%04hX)\n",
dfu->prod_str, (unsigned short) dfu->dev_desc.idProduct);
else
msg_info(" USB Product : 0x%04hX\n",
avrdude_message(MSG_INFO, " USB Product : 0x%04hX\n",
(unsigned short) dfu->dev_desc.idProduct);
msg_info(" USB Release : %hu.%hu.%hu\n",
avrdude_message(MSG_INFO, " USB Release : %hu.%hu.%hu\n",
((unsigned short) dfu->dev_desc.bcdDevice >> 8) & 0xFF,
((unsigned short) dfu->dev_desc.bcdDevice >> 4) & 0xF,
((unsigned short) dfu->dev_desc.bcdDevice >> 0) & 0xF);
if (dfu->serno_str != NULL)
msg_info(" USB Serial No : %s\n", dfu->serno_str);
avrdude_message(MSG_INFO, " USB Serial No : %s\n", dfu->serno_str);
}
/* INTERNAL FUNCTION DEFINITIONS
@@ -428,14 +451,15 @@ char * get_usb_string(usb_dev_handle * dev_handle, int index) {
result = usb_get_string_simple(dev_handle, index, buffer, sizeof(buffer)-1);
if (result < 0) {
pmsg_error("unable to read USB device string %d: %s\n", index, usb_strerror());
avrdude_message(MSG_INFO, "%s: Warning: Failed to read USB device string %d: %s\n",
progname, index, usb_strerror());
return NULL;
}
str = malloc(result+1);
if (str == NULL) {
pmsg_error("out of memory allocating a string\n");
avrdude_message(MSG_INFO, "%s: Out of memory allocating a string\n", progname);
return 0;
}

View File

@@ -61,7 +61,7 @@ struct dfu_dev
#else
struct dfu_dev {
int dummy;
// empty
};
#endif
@@ -114,7 +114,7 @@ struct dfu_status {
// FUNCTIONS
extern struct dfu_dev *dfu_open(const char *port_spec);
extern struct dfu_dev * dfu_open(char *port_spec);
extern int dfu_init(struct dfu_dev *dfu,
unsigned short vid, unsigned short pid);
extern void dfu_close(struct dfu_dev *dfu);

View File

@@ -1,179 +0,0 @@
#
# 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})

View File

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

26
src/doc/TODO Normal file
View File

@@ -0,0 +1,26 @@
- Man page needs updated for avr910 info.
- Website needs to link to docs:
http://savannah.nongnu.org/download/avrdude/doc/avrdude-html/
- Add "skip empty pages" optimization on avr910 paged write. The stk500 has
this optimization already.
- Fix "overfull \hbox" issues in building documentation.
- FIXME: term.c: terminal_get_input(): strip newlines in non-readline input
code.
- FIXME: avr910.c: avr910_cmd(): Insert version check here.
- FIXME: ser_posix.c: serial_close(): Should really restore the terminal to
original state here.
- FIXME: main.c, par.c: exitspecs don't work if RESET-pin is controlled over
PPICTRL.
- transfer ppi-speedtuning to the windows version (CAVEAT: This will make
programming too fast for chips with 500kHz clock)
- make SCK-period configurable for PPI-programmers

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +0,0 @@
#
# 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}")

View File

@@ -1,28 +0,0 @@
#
# 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}")

View File

@@ -1,28 +0,0 @@
#
# 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}")

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,6 @@
#include "ac_cfg.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -31,6 +30,13 @@
#include <limits.h>
#include <unistd.h>
#if HAVE_STDINT_H
#include <stdint.h>
#elif HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include "avrdude.h"
#include "libavrdude.h"
@@ -136,23 +142,23 @@ enum flip1_mem_unit {
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
static int flip1_open(PROGRAMMER *pgm, const char *port_spec);
static int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part);
static int flip1_open(PROGRAMMER *pgm, char *port_spec);
static int flip1_initialize(PROGRAMMER* pgm, AVRPART *part);
static void flip1_close(PROGRAMMER* pgm);
static void flip1_enable(PROGRAMMER *pgm, const AVRPART *p);
static void flip1_disable(const PROGRAMMER *pgm);
static void flip1_display(const PROGRAMMER *pgm, const char *prefix);
static int flip1_program_enable(const PROGRAMMER *pgm, const AVRPART *part);
static int flip1_chip_erase(const PROGRAMMER *pgm, const AVRPART *part);
static int flip1_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
static void flip1_enable(PROGRAMMER* pgm);
static void flip1_disable(PROGRAMMER* pgm);
static void flip1_display(PROGRAMMER* pgm, const char *prefix);
static int flip1_program_enable(PROGRAMMER* pgm, AVRPART *part);
static int flip1_chip_erase(PROGRAMMER* pgm, AVRPART *part);
static int flip1_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char *value);
static int flip1_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
static int flip1_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char value);
static int flip1_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
static int flip1_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
static int flip1_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
static int flip1_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
static int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem);
static int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem);
static void flip1_setup(PROGRAMMER * pgm);
static void flip1_teardown(PROGRAMMER * pgm);
@@ -162,7 +168,7 @@ static void flip1_teardown(PROGRAMMER * pgm);
static void flip1_show_info(struct flip1 *flip1);
static int flip1_read_memory(const PROGRAMMER *pgm,
static int flip1_read_memory(PROGRAMMER * pgm,
enum flip1_mem_unit mem_unit, uint32_t addr, void *ptr, int size);
static int flip1_write_memory(struct dfu_dev *dfu,
enum flip1_mem_unit mem_unit, uint32_t addr, const void *ptr, int size);
@@ -176,7 +182,8 @@ static enum flip1_mem_unit flip1_mem_unit(const char *name);
/* THE INITPGM FUNCTION DEFINITIONS */
void flip1_initpgm(PROGRAMMER *pgm) {
void flip1_initpgm(PROGRAMMER *pgm)
{
strcpy(pgm->type, "flip1");
/* Mandatory Functions */
@@ -200,12 +207,14 @@ void flip1_initpgm(PROGRAMMER *pgm) {
#ifdef HAVE_LIBUSB
/* EXPORTED PROGRAMMER FUNCTION DEFINITIONS */
int flip1_open(PROGRAMMER *pgm, const char *port_spec) {
int flip1_open(PROGRAMMER *pgm, char *port_spec)
{
FLIP1(pgm)->dfu = dfu_open(port_spec);
return (FLIP1(pgm)->dfu != NULL) ? 0 : -1;
}
int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
int flip1_initialize(PROGRAMMER* pgm, AVRPART *part)
{
unsigned short vid, pid;
int result;
struct dfu_dev *dfu = FLIP1(pgm)->dfu;
@@ -234,13 +243,16 @@ int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
if (usbpid) {
pid = *(int *)(ldata(usbpid));
if (lnext(usbpid))
pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid);
avrdude_message(MSG_INFO, "%s: Warning: using PID 0x%04x, ignoring remaining PIDs in list\n",
progname, pid);
} else {
pid = part->usbpid;
}
if (!ovsigck && (part->prog_modes & PM_PDI)) {
pmsg_error("flip1 (FLIP protocol version 1) is for AT90USB* and ATmega*U* devices\n");
imsg_error("for Xmega devices, use flip2 (or use -F to bypass this check)\n");
if (!ovsigck && (part->flags & AVRPART_HAS_PDI)) {
avrdude_message(MSG_INFO, "%s: \"flip1\" (FLIP protocol version 1) is for AT90USB* and ATmega*U* devices.\n"
"%s For Xmega devices, use \"flip2\".\n"
"%s (Use -F to bypass this check.)\n",
progname, progbuf, progbuf);
return -1;
}
@@ -252,25 +264,32 @@ int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
/* Check if descriptor values are what we expect. */
if (dfu->dev_desc.idVendor != vid)
pmsg_warning("USB idVendor = 0x%04X (expected 0x%04X)\n", dfu->dev_desc.idVendor, vid);
avrdude_message(MSG_INFO, "%s: Warning: USB idVendor = 0x%04X (expected 0x%04X)\n",
progname, dfu->dev_desc.idVendor, vid);
if (pid != 0 && dfu->dev_desc.idProduct != pid)
pmsg_warning("USB idProduct = 0x%04X (expected 0x%04X)\n", dfu->dev_desc.idProduct, pid);
avrdude_message(MSG_INFO, "%s: Warning: USB idProduct = 0x%04X (expected 0x%04X)\n",
progname, dfu->dev_desc.idProduct, pid);
if (dfu->dev_desc.bNumConfigurations != 1)
pmsg_warning("USB bNumConfigurations = %d (expected 1)\n", (int) dfu->dev_desc.bNumConfigurations);
avrdude_message(MSG_INFO, "%s: Warning: USB bNumConfigurations = %d (expected 1)\n",
progname, (int) dfu->dev_desc.bNumConfigurations);
if (dfu->conf_desc.bNumInterfaces != 1)
pmsg_warning("USB bNumInterfaces = %d (expected 1)\n", (int) dfu->conf_desc.bNumInterfaces);
avrdude_message(MSG_INFO, "%s: Warning: USB bNumInterfaces = %d (expected 1)\n",
progname, (int) dfu->conf_desc.bNumInterfaces);
if (dfu->dev_desc.bDeviceClass != 254)
pmsg_warning("USB bDeviceClass = %d (expected 254)\n", (int) dfu->dev_desc.bDeviceClass);
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceClass = %d (expected 254)\n",
progname, (int) dfu->dev_desc.bDeviceClass);
if (dfu->dev_desc.bDeviceSubClass != 1)
pmsg_warning("USB bDeviceSubClass = %d (expected 1)\n", (int) dfu->dev_desc.bDeviceSubClass);
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceSubClass = %d (expected 1)\n",
progname, (int) dfu->dev_desc.bDeviceSubClass);
if (dfu->dev_desc.bDeviceProtocol != 0)
pmsg_warning("USB bDeviceProtocol = %d (expected 0)\n", (int) dfu->dev_desc.bDeviceProtocol);
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceProtocol = %d (expected 0)\n",
progname, (int) dfu->dev_desc.bDeviceProtocol);
/*
* doc7618 claims an interface class of FEh and a subclas 01h.
@@ -280,17 +299,21 @@ int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
*/
if (0) {
if (dfu->intf_desc.bInterfaceClass != 254)
pmsg_warning("USB bInterfaceClass = %d (expected 254)\n", (int) dfu->intf_desc.bInterfaceClass);
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceClass = %d (expected 254)\n",
progname, (int) dfu->intf_desc.bInterfaceClass);
if (dfu->intf_desc.bInterfaceSubClass != 1)
pmsg_warning("USB bInterfaceSubClass = %d (expected 1)\n", (int) dfu->intf_desc.bInterfaceSubClass);
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceSubClass = %d (expected 1)\n",
progname, (int) dfu->intf_desc.bInterfaceSubClass);
if (dfu->intf_desc.bInterfaceProtocol != 0)
pmsg_warning("USB bInterfaceSubClass = %d (expected 0)\n", (int) dfu->intf_desc.bInterfaceProtocol);
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceSubClass = %d (expected 0)\n",
progname, (int) dfu->intf_desc.bInterfaceProtocol);
}
if (dfu->dev_desc.bMaxPacketSize0 != 32)
pmsg_warning("bMaxPacketSize0 (%d) != 32, things might go wrong\n", dfu->dev_desc.bMaxPacketSize0);
avrdude_message(MSG_INFO, "%s: Warning: bMaxPacketSize0 (%d) != 32, things might go wrong\n",
progname, dfu->dev_desc.bMaxPacketSize0);
if (verbose)
flip1_show_info(FLIP1(pgm));
@@ -305,26 +328,31 @@ flip1_initialize_fail:
return 0;
}
void flip1_close(PROGRAMMER *pgm) {
void flip1_close(PROGRAMMER* pgm)
{
if (FLIP1(pgm)->dfu != NULL) {
dfu_close(FLIP1(pgm)->dfu);
FLIP1(pgm)->dfu = NULL;
}
}
void flip1_enable(PROGRAMMER *pgm, const AVRPART *p) {
void flip1_enable(PROGRAMMER* pgm)
{
/* Nothing to do. */
}
void flip1_disable(const PROGRAMMER *pgm) {
void flip1_disable(PROGRAMMER* pgm)
{
/* Nothing to do. */
}
void flip1_display(const PROGRAMMER *pgm, const char *prefix) {
void flip1_display(PROGRAMMER* pgm, const char *prefix)
{
/* Nothing to do. */
}
int flip1_program_enable(const PROGRAMMER *pgm, const AVRPART *part) {
int flip1_program_enable(PROGRAMMER* pgm, AVRPART *part)
{
/* 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
* error if we failed to initialize.
@@ -333,13 +361,14 @@ int flip1_program_enable(const PROGRAMMER *pgm, const AVRPART *part) {
return (FLIP1(pgm)->dfu != NULL) ? 0 : -1;
}
int flip1_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
int flip1_chip_erase(PROGRAMMER* pgm, AVRPART *part)
{
struct dfu_status status;
int cmd_result = 0;
int aux_result;
unsigned int default_timeout = FLIP1(pgm)->dfu->timeout;
pmsg_notice2("flip_chip_erase()\n");
avrdude_message(MSG_NOTICE2, "%s: flip_chip_erase()\n", progname);
struct flip1_cmd cmd = {
FLIP1_CMD_WRITE_COMMAND, { 0, 0xff }
@@ -354,7 +383,8 @@ int flip1_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
return -1;
if (status.bStatus != DFU_STATUS_OK) {
pmsg_error("unable to send chip erase command: %s\n", flip1_status_str(&status));
avrdude_message(MSG_INFO, "%s: failed to send chip erase command: %s\n",
progname, flip1_status_str(&status));
if (status.bState == STATE_dfuERROR)
dfu_clrstatus(FLIP1(pgm)->dfu);
return -1;
@@ -363,7 +393,7 @@ int flip1_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
return 0;
}
int flip1_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip1_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char *value)
{
enum flip1_mem_unit mem_unit;
@@ -371,11 +401,12 @@ int flip1_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *me
if (FLIP1(pgm)->dfu == NULL)
return -1;
if (strcmp(mem->desc, "signature") == 0) {
if (strcasecmp(mem->desc, "signature") == 0) {
if (flip1_read_sig_bytes(pgm, part, mem) < 0)
return -1;
if (addr >= mem->size) {
pmsg_error("signature address %lu out of range [0, %d]\n", addr, mem->size-1);
if (addr > mem->size) {
avrdude_message(MSG_INFO, "%s: flip1_read_byte(signature): address %lu out of range\n",
progname, addr);
return -1;
}
*value = mem->buf[addr];
@@ -385,7 +416,10 @@ int flip1_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *me
mem_unit = flip1_mem_unit(mem->desc);
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
pmsg_error("%s memory not accessible using FLIP\n", mem->desc);
avrdude_message(MSG_INFO, "%s: Error: "
"\"%s\" memory not accessible using FLIP",
progname, mem->desc);
avrdude_message(MSG_INFO, "\n");
return -1;
}
@@ -396,7 +430,7 @@ int flip1_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *me
return flip1_read_memory(pgm, mem_unit, addr, value, 1);
}
int flip1_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip1_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char value)
{
enum flip1_mem_unit mem_unit;
@@ -407,14 +441,17 @@ int flip1_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *m
mem_unit = flip1_mem_unit(mem->desc);
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
pmsg_error("%s memory not accessible using FLIP\n", mem->desc);
avrdude_message(MSG_INFO, "%s: Error: "
"\"%s\" memory not accessible using FLIP",
progname, mem->desc);
avrdude_message(MSG_INFO, "\n");
return -1;
}
return flip1_write_memory(FLIP1(pgm)->dfu, mem_unit, addr, &value, 1);
}
int flip1_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip1_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
{
enum flip1_mem_unit mem_unit;
@@ -425,7 +462,10 @@ int flip1_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *m
mem_unit = flip1_mem_unit(mem->desc);
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
pmsg_error("%s memory not accessible using FLIP\n", mem->desc);
avrdude_message(MSG_INFO, "%s: Error: "
"\"%s\" memory not accessible using FLIP",
progname, mem->desc);
avrdude_message(MSG_INFO, "\n");
return -1;
}
@@ -436,7 +476,7 @@ int flip1_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *m
return flip1_read_memory(pgm, mem_unit, addr, mem->buf + addr, n_bytes);
}
int flip1_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip1_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
{
enum flip1_mem_unit mem_unit;
@@ -448,13 +488,17 @@ int flip1_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *
mem_unit = flip1_mem_unit(mem->desc);
if (mem_unit == FLIP1_MEM_UNIT_UNKNOWN) {
pmsg_error("%s memory not accessible using FLIP\n", mem->desc);
avrdude_message(MSG_INFO, "%s: Error: "
"\"%s\" memory not accessible using FLIP",
progname, mem->desc);
avrdude_message(MSG_INFO, "\n");
return -1;
}
if (n_bytes > INT_MAX) {
/* This should never happen, unless the int type is only 16 bits. */
pmsg_error("attempting to read more than %d bytes\n", INT_MAX);
avrdude_message(MSG_INFO, "%s: Error: Attempting to read more than %d bytes\n",
progname, INT_MAX);
exit(1);
}
@@ -464,14 +508,16 @@ int flip1_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *
return (result == 0) ? n_bytes : -1;
}
int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem) {
pmsg_notice2("flip1_read_sig_bytes(): ");
int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
{
avrdude_message(MSG_NOTICE2, "%s: flip1_read_sig_bytes(): ", progname);
if (FLIP1(pgm)->dfu == NULL)
return -1;
if (mem->size < sizeof(FLIP1(pgm)->part_sig)) {
pmsg_error("signature read must be at least %u bytes\n", (unsigned int) sizeof(FLIP1(pgm)->part_sig));
avrdude_message(MSG_INFO, "%s: Error: Signature read must be at least %u bytes\n",
progname, (unsigned int) sizeof(FLIP1(pgm)->part_sig));
return -1;
}
@@ -488,7 +534,7 @@ int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRME
FLIP1_CMD_READ_COMMAND, FLIP1_READ_FAMILY_CODE
};
msg_notice2("from device\n");
avrdude_message(MSG_NOTICE2, "from device\n");
for (i = 0; i < 3; i++)
{
@@ -505,7 +551,8 @@ int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRME
if (status.bStatus != DFU_STATUS_OK)
{
pmsg_error("unable to send cmd for signature byte %d: %s\n", i, flip1_status_str(&status));
avrdude_message(MSG_INFO, "%s: failed to send cmd for signature byte %d: %s\n",
progname, i, flip1_status_str(&status));
if (status.bState == STATE_dfuERROR)
dfu_clrstatus(FLIP1(pgm)->dfu);
return -1;
@@ -519,7 +566,8 @@ int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRME
if (status.bStatus != DFU_STATUS_OK)
{
pmsg_error("unable to read signature byte %d: %s\n", i, flip1_status_str(&status));
avrdude_message(MSG_INFO, "%s: failed to read signature byte %d: %s\n",
progname, i, flip1_status_str(&status));
if (status.bState == STATE_dfuERROR)
dfu_clrstatus(FLIP1(pgm)->dfu);
return -1;
@@ -528,7 +576,7 @@ int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRME
}
else
{
msg_notice2("cached\n");
avrdude_message(MSG_NOTICE2, "cached\n");
}
memcpy(mem->buf, FLIP1(pgm)->part_sig, sizeof(FLIP1(pgm)->part_sig));
@@ -541,7 +589,8 @@ void flip1_setup(PROGRAMMER * pgm)
pgm->cookie = calloc(1, sizeof(struct flip1));
if (pgm->cookie == NULL) {
pmsg_error("out of memory allocating private data structure\n");
avrdude_message(MSG_INFO, "%s: Out of memory allocating private data structure\n",
progname);
exit(1);
}
}
@@ -558,10 +607,11 @@ void flip1_teardown(PROGRAMMER * pgm)
void flip1_show_info(struct flip1 *flip1)
{
dfu_show_info(flip1->dfu);
msg_info(" USB max packet size : %hu\n", (unsigned short) flip1->dfu->dev_desc.bMaxPacketSize0);
avrdude_message(MSG_INFO, " USB max packet size : %hu\n",
(unsigned short) flip1->dfu->dev_desc.bMaxPacketSize0);
}
int flip1_read_memory(const PROGRAMMER *pgm,
int flip1_read_memory(PROGRAMMER * pgm,
enum flip1_mem_unit mem_unit, uint32_t addr, void *ptr, int size)
{
struct dfu_dev *dfu = FLIP1(pgm)->dfu;
@@ -575,7 +625,8 @@ int flip1_read_memory(const PROGRAMMER *pgm,
unsigned int default_timeout = dfu->timeout;
pmsg_notice2("flip_read_memory(%s, 0x%04x, %d)\n", flip1_mem_unit_str(mem_unit), addr, size);
avrdude_message(MSG_NOTICE2, "%s: flip_read_memory(%s, 0x%04x, %d)\n",
progname, flip1_mem_unit_str(mem_unit), addr, size);
/*
* As this function is called once per page, no need to handle 64
@@ -605,8 +656,9 @@ int flip1_read_memory(const PROGRAMMER *pgm,
if (status.bStatus != DFU_STATUS_OK)
{
pmsg_error("unable to read %u bytes of %s memory @%u: %s\n", size,
flip1_mem_unit_str(mem_unit), addr, flip1_status_str(&status));
avrdude_message(MSG_INFO, "%s: failed to read %u bytes of %s memory @%u: %s\n",
progname, size, flip1_mem_unit_str(mem_unit), addr,
flip1_status_str(&status));
if (status.bState == STATE_dfuERROR)
dfu_clrstatus(dfu);
return -1;
@@ -617,14 +669,13 @@ int flip1_read_memory(const PROGRAMMER *pgm,
if (cmd_result < 0 && aux_result == 0 &&
status.bStatus == DFU_STATUS_ERR_WRITE) {
if (FLIP1(pgm)->security_mode_flag == 0) {
msg_error("\n");
pmsg_error("\n");
imsg_error("***********************************************************************\n");
imsg_error("Maybe the device is in ``security mode´´, and needs a chip erase first?\n");
imsg_error("***********************************************************************\n");
msg_error("\n");
}
if (FLIP1(pgm)->security_mode_flag == 0)
avrdude_message(MSG_INFO, "\n%s:\n"
"%s***********************************************************************\n"
"%sMaybe the device is in ``security mode´´, and needs a chip erase first?\n"
"%s***********************************************************************\n"
"\n",
progname, progbuf, progbuf, progbuf);
FLIP1(pgm)->security_mode_flag = 1;
}
@@ -633,8 +684,9 @@ int flip1_read_memory(const PROGRAMMER *pgm,
if (status.bStatus != DFU_STATUS_OK)
{
pmsg_error("unable to read %u bytes of %s memory @%u: %s\n", size,
flip1_mem_unit_str(mem_unit), addr, flip1_status_str(&status));
avrdude_message(MSG_INFO, "%s: failed to read %u bytes of %s memory @%u: %s\n",
progname, size, flip1_mem_unit_str(mem_unit), addr,
flip1_status_str(&status));
if (status.bState == STATE_dfuERROR)
dfu_clrstatus(dfu);
return -1;
@@ -666,14 +718,14 @@ int flip1_write_memory(struct dfu_dev *dfu,
unsigned int default_timeout = dfu->timeout;
unsigned char *buf;
pmsg_notice2("flip_write_memory(%s, 0x%04x, %d)\n",
flip1_mem_unit_str(mem_unit), addr, size);
avrdude_message(MSG_NOTICE2, "%s: flip_write_memory(%s, 0x%04x, %d)\n",
progname, flip1_mem_unit_str(mem_unit), addr, size);
if (size < 32) {
/* presumably single-byte updates; must be padded to USB endpoint size */
if ((addr + size - 1) / 32 != addr / 32) {
pmsg_error("begin 0x%x and end 0x%x not within same 32-byte block\n",
addr, addr + size - 1);
avrdude_message(MSG_INFO, "%s: flip_write_memory(): begin (0x%x) and end (0x%x) not within same 32-byte block\n",
progname, addr, addr + size - 1);
return -1;
}
write_size = 32;
@@ -684,7 +736,7 @@ int flip1_write_memory(struct dfu_dev *dfu,
if ((buf = malloc(sizeof(struct flip1_cmd_header) +
write_size +
sizeof(struct flip1_prog_footer))) == 0) {
pmsg_error("out of memory\n");
avrdude_message(MSG_INFO, "%s: Out of memory\n", progname);
return -1;
}
@@ -733,8 +785,9 @@ int flip1_write_memory(struct dfu_dev *dfu,
if (status.bStatus != DFU_STATUS_OK)
{
pmsg_error("unable to write %u bytes of %s memory @%u: %s\n", size,
flip1_mem_unit_str(mem_unit), addr, flip1_status_str(&status));
avrdude_message(MSG_INFO, "%s: failed to write %u bytes of %s memory @%u: %s\n",
progname, size, flip1_mem_unit_str(mem_unit), addr,
flip1_status_str(&status));
if (status.bState == STATE_dfuERROR)
dfu_clrstatus(dfu);
return -1;
@@ -763,7 +816,8 @@ int flip1_set_mem_page(struct dfu_dev *dfu,
if (status.bStatus != DFU_STATUS_OK)
{
pmsg_error("unable to set memory page: %s\n", flip1_status_str(&status));
avrdude_message(MSG_INFO, "%s: failed to set memory page: %s\n",
progname, flip1_status_str(&status));
if (status.bState == STATE_dfuERROR)
dfu_clrstatus(dfu);
return -1;
@@ -808,20 +862,23 @@ const char * flip1_mem_unit_str(enum flip1_mem_unit mem_unit)
}
enum flip1_mem_unit flip1_mem_unit(const char *name) {
if (strcmp(name, "flash") == 0)
if (strcasecmp(name, "flash") == 0)
return FLIP1_MEM_UNIT_FLASH;
if (strcmp(name, "eeprom") == 0)
if (strcasecmp(name, "eeprom") == 0)
return FLIP1_MEM_UNIT_EEPROM;
return FLIP1_MEM_UNIT_UNKNOWN;
}
#else /* HAVE_LIBUSB */
// Dummy functions
int flip1_open(PROGRAMMER *pgm, const char *port_spec) {
pmsg_error("no USB support compiled for avrdude\n");
int flip1_open(PROGRAMMER *pgm, char *port_spec)
{
fprintf(stderr, "%s: Error: No USB support in this compile of avrdude\n",
progname);
return -1;
}
int flip1_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
int flip1_initialize(PROGRAMMER* pgm, AVRPART *part)
{
return -1;
}
@@ -829,48 +886,54 @@ void flip1_close(PROGRAMMER* pgm)
{
}
void flip1_enable(PROGRAMMER *pgm, const AVRPART *p) {
void flip1_enable(PROGRAMMER* pgm)
{
}
void flip1_disable(const PROGRAMMER *pgm) {
void flip1_disable(PROGRAMMER* pgm)
{
}
void flip1_display(const PROGRAMMER *pgm, const char *prefix) {
void flip1_display(PROGRAMMER* pgm, const char *prefix)
{
}
int flip1_program_enable(const PROGRAMMER *pgm, const AVRPART *part) {
int flip1_program_enable(PROGRAMMER* pgm, AVRPART *part)
{
return -1;
}
int flip1_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
int flip1_chip_erase(PROGRAMMER* pgm, AVRPART *part)
{
return -1;
}
int flip1_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip1_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char *value)
{
return -1;
}
int flip1_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip1_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char value)
{
return -1;
}
int flip1_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip1_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
{
return -1;
}
int flip1_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip1_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
{
return -1;
}
int flip1_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem) {
int flip1_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
{
return -1;
}

View File

@@ -26,7 +26,7 @@ extern "C" {
#endif
extern const char flip1_desc[];
extern void flip1_initpgm(PROGRAMMER *pgm);
extern void flip1_initpgm(PROGRAMMER * pgm);
#ifdef __cplusplus
}

View File

@@ -20,7 +20,6 @@
#include "ac_cfg.h"
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -28,6 +27,12 @@
#include <limits.h>
#include <unistd.h>
#if HAVE_STDINT_H
#include <stdint.h>
#elif HAVE_INTTYPES_H
#include <inttypes.h>
#endif
#include "avrdude.h"
#include "libavrdude.h"
@@ -121,33 +126,31 @@ enum flip2_mem_unit {
FLIP2_MEM_UNIT_EXT_MEM_DF = 0x10
};
#ifdef HAVE_LIBUSB
/* EXPORTED PROGRAMMER FUNCTION PROTOTYPES */
static int flip2_open(PROGRAMMER *pgm, const char *port_spec);
static int flip2_initialize(const PROGRAMMER *pgm, const AVRPART *part);
static int flip2_open(PROGRAMMER *pgm, char *port_spec);
static int flip2_initialize(PROGRAMMER* pgm, AVRPART *part);
static void flip2_close(PROGRAMMER* pgm);
static void flip2_enable(PROGRAMMER *pgm, const AVRPART *p);
static void flip2_disable(const PROGRAMMER *pgm);
static void flip2_display(const PROGRAMMER *pgm, const char *prefix);
static int flip2_program_enable(const PROGRAMMER *pgm, const AVRPART *part);
static int flip2_chip_erase(const PROGRAMMER *pgm, const AVRPART *part);
static int flip2_start_app(const PROGRAMMER *pgm);
static int flip2_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
static void flip2_enable(PROGRAMMER* pgm);
static void flip2_disable(PROGRAMMER* pgm);
static void flip2_display(PROGRAMMER* pgm, const char *prefix);
static int flip2_program_enable(PROGRAMMER* pgm, AVRPART *part);
static int flip2_chip_erase(PROGRAMMER* pgm, AVRPART *part);
static int flip2_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char *value);
static int flip2_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
static int flip2_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char value);
static int flip2_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
static int flip2_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
static int flip2_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
static int flip2_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes);
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 int flip2_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem);
static void flip2_setup(PROGRAMMER * pgm);
static void flip2_teardown(PROGRAMMER * pgm);
/* 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);
@@ -168,7 +171,12 @@ 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 enum flip2_mem_unit flip2_mem_unit(const char *name);
void flip2_initpgm(PROGRAMMER *pgm) {
#endif /* HAVE_LIBUSB */
/* THE INITPGM FUNCTION DEFINITIONS */
void flip2_initpgm(PROGRAMMER *pgm)
{
strcpy(pgm->type, "flip2");
/* Mandatory Functions */
@@ -185,19 +193,21 @@ void flip2_initpgm(PROGRAMMER *pgm) {
pgm->read_byte = flip2_read_byte;
pgm->write_byte = flip2_write_byte;
pgm->read_sig_bytes = flip2_read_sig_bytes;
pgm->parseexitspecs = flip2_parseexitspecs;
pgm->setup = flip2_setup;
pgm->teardown = flip2_teardown;
}
#ifdef HAVE_LIBUSB
/* EXPORTED PROGRAMMER FUNCTION DEFINITIONS */
int flip2_open(PROGRAMMER *pgm, const char *port_spec) {
int flip2_open(PROGRAMMER *pgm, char *port_spec)
{
FLIP2(pgm)->dfu = dfu_open(port_spec);
return (FLIP2(pgm)->dfu != NULL) ? 0 : -1;
}
int flip2_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
int flip2_initialize(PROGRAMMER* pgm, AVRPART *part)
{
unsigned short vid, pid;
int result;
struct dfu_dev *dfu = FLIP2(pgm)->dfu;
@@ -205,7 +215,7 @@ int flip2_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
/* A note about return values. Negative return values from this function are
* interpreted as failure by main(), from where this function is called.
* However such failures are interpreted as a device signature check failure
* and the user is advised to use the -F option to override this check. In
* and the user is adviced to use the -F option to override this check. In
* our case, this is misleading, so we defer reporting an error until another
* function is called. Thus, we always return 0 (success) from initialize().
* I don't like this, but I don't want to mess with main().
@@ -226,15 +236,17 @@ int flip2_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
if (usbpid) {
pid = *(int *)(ldata(usbpid));
if (lnext(usbpid))
pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid);
avrdude_message(MSG_INFO, "%s: Warning: using PID 0x%04x, ignoring remaining PIDs in list\n",
progname, pid);
} else {
pid = part->usbpid;
}
if (!ovsigck && !(part->prog_modes & PM_PDI)) {
pmsg_error("flip2 (FLIP protocol version 2) is for Xmega devices\n");
imsg_error("for AT90USB* or ATmega*U* devices, use flip1\n");
imsg_error("(or use -F to bypass this check)\n");
if (!ovsigck && !(part->flags & AVRPART_HAS_PDI)) {
avrdude_message(MSG_INFO, "%s: \"flip2\" (FLIP protocol version 2) is for Xmega devices.\n"
"%s For AT90USB* or ATmega*U* devices, use \"flip1\".\n"
"%s (Use -F to bypass this check.)\n",
progname, progbuf, progbuf);
return -1;
}
@@ -246,44 +258,44 @@ int flip2_initialize(const PROGRAMMER *pgm, const AVRPART *part) {
/* Check if descriptor values are what we expect. */
if (dfu->dev_desc.idVendor != vid)
pmsg_warning("USB idVendor = 0x%04X (expected 0x%04X)\n",
dfu->dev_desc.idVendor, vid);
avrdude_message(MSG_INFO, "%s: Warning: USB idVendor = 0x%04X (expected 0x%04X)\n",
progname, dfu->dev_desc.idVendor, vid);
if (pid != 0 && dfu->dev_desc.idProduct != pid)
pmsg_warning("USB idProduct = 0x%04X (expected 0x%04X)\n",
dfu->dev_desc.idProduct, pid);
avrdude_message(MSG_INFO, "%s: Warning: USB idProduct = 0x%04X (expected 0x%04X)\n",
progname, dfu->dev_desc.idProduct, pid);
if (dfu->dev_desc.bNumConfigurations != 1)
pmsg_error("USB bNumConfigurations = %d (expected 1)\n",
(int) dfu->dev_desc.bNumConfigurations);
avrdude_message(MSG_INFO, "%s: Warning: USB bNumConfigurations = %d (expected 1)\n",
progname, (int) dfu->dev_desc.bNumConfigurations);
if (dfu->conf_desc.bNumInterfaces != 1)
pmsg_error("USB bNumInterfaces = %d (expected 1)\n",
(int) dfu->conf_desc.bNumInterfaces);
avrdude_message(MSG_INFO, "%s: Warning: USB bNumInterfaces = %d (expected 1)\n",
progname, (int) dfu->conf_desc.bNumInterfaces);
if (dfu->dev_desc.bDeviceClass != 0)
pmsg_error("USB bDeviceClass = %d (expected 0)\n",
(int) dfu->dev_desc.bDeviceClass);
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceClass = %d (expected 0)\n",
progname, (int) dfu->dev_desc.bDeviceClass);
if (dfu->dev_desc.bDeviceSubClass != 0)
pmsg_error("USB bDeviceSubClass = %d (expected 0)\n",
(int) dfu->dev_desc.bDeviceSubClass);
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceSubClass = %d (expected 0)\n",
progname, (int) dfu->dev_desc.bDeviceSubClass);
if (dfu->dev_desc.bDeviceProtocol != 0)
pmsg_error("USB bDeviceProtocol = %d (expected 0)\n",
(int) dfu->dev_desc.bDeviceProtocol);
avrdude_message(MSG_INFO, "%s: Warning: USB bDeviceProtocol = %d (expected 0)\n",
progname, (int) dfu->dev_desc.bDeviceProtocol);
if (dfu->intf_desc.bInterfaceClass != 0xFF)
pmsg_error("USB bInterfaceClass = %d (expected 255)\n",
(int) dfu->intf_desc.bInterfaceClass);
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceClass = %d (expected 255)\n",
progname, (int) dfu->intf_desc.bInterfaceClass);
if (dfu->intf_desc.bInterfaceSubClass != 0)
pmsg_error("USB bInterfaceSubClass = %d (expected 0)\n",
(int) dfu->intf_desc.bInterfaceSubClass);
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceSubClass = %d (expected 0)\n",
progname, (int) dfu->intf_desc.bInterfaceSubClass);
if (dfu->intf_desc.bInterfaceProtocol != 0)
pmsg_error("USB bInterfaceSubClass = %d (expected 0)\n",
(int) dfu->intf_desc.bInterfaceProtocol);
avrdude_message(MSG_INFO, "%s: Warning: USB bInterfaceSubClass = %d (expected 0)\n",
progname, (int) dfu->intf_desc.bInterfaceProtocol);
result = flip2_read_memory(FLIP2(pgm)->dfu,
FLIP2_MEM_UNIT_SIGNATURE, 0, FLIP2(pgm)->part_sig, 4);
@@ -311,27 +323,28 @@ flip2_initialize_fail:
void flip2_close(PROGRAMMER* pgm)
{
if (FLIP2(pgm)->dfu != NULL) {
if (pgm->exit_reset == EXIT_RESET_ENABLED)
flip2_start_app(pgm);
dfu_close(FLIP2(pgm)->dfu);
FLIP2(pgm)->dfu = NULL;
}
}
void flip2_enable(PROGRAMMER *pgm, const AVRPART *p) {
void flip2_enable(PROGRAMMER* pgm)
{
/* Nothing to do. */
}
void flip2_disable(const PROGRAMMER *pgm) {
void flip2_disable(PROGRAMMER* pgm)
{
/* Nothing to do. */
}
void flip2_display(const PROGRAMMER *pgm, const char *prefix) {
void flip2_display(PROGRAMMER* pgm, const char *prefix)
{
/* Nothing to do. */
}
int flip2_program_enable(const PROGRAMMER *pgm, const AVRPART *part) {
int flip2_program_enable(PROGRAMMER* pgm, AVRPART *part)
{
/* 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
* error if we failed to initialize.
@@ -340,12 +353,13 @@ int flip2_program_enable(const PROGRAMMER *pgm, const AVRPART *part) {
return (FLIP2(pgm)->dfu != NULL) ? 0 : -1;
}
int flip2_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
int flip2_chip_erase(PROGRAMMER* pgm, AVRPART *part)
{
struct dfu_status status;
int cmd_result = 0;
int aux_result;
pmsg_notice2("flip_chip_erase()\n");
avrdude_message(MSG_NOTICE2, "%s: flip_chip_erase()\n", progname);
struct flip2_cmd cmd = {
FLIP2_CMD_GROUP_EXEC, FLIP2_CMD_CHIP_ERASE, { 0xFF, 0, 0, 0 }
@@ -363,8 +377,9 @@ int flip2_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
status.bState == ((FLIP2_STATUS_ERASE_ONGOING >> 0) & 0xFF))
{
continue;
}
pmsg_error("DFU status %s\n", flip2_status_str(&status));
} else
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
flip2_status_str(&status));
dfu_clrstatus(FLIP2(pgm)->dfu);
} else
break;
@@ -373,23 +388,7 @@ int flip2_chip_erase(const PROGRAMMER *pgm, const AVRPART *part) {
return cmd_result;
}
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,
int flip2_read_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char *value)
{
enum flip2_mem_unit mem_unit;
@@ -400,17 +399,19 @@ int flip2_read_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *me
mem_unit = flip2_mem_unit(mem->desc);
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
pmsg_error("%s memory not accessible using FLIP", mem->desc);
avrdude_message(MSG_INFO, "%s: Error: "
"\"%s\" memory not accessible using FLIP",
progname, mem->desc);
if (strcmp(mem->desc, "flash") == 0)
msg_error(" (did you mean \"application\"?)");
msg_error("\n");
avrdude_message(MSG_INFO, " (did you mean \"application\"?)");
avrdude_message(MSG_INFO, "\n");
return -1;
}
return flip2_read_memory(FLIP2(pgm)->dfu, mem_unit, addr, value, 1);
}
int flip2_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip2_write_byte(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned long addr, unsigned char value)
{
enum flip2_mem_unit mem_unit;
@@ -421,17 +422,19 @@ int flip2_write_byte(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *m
mem_unit = flip2_mem_unit(mem->desc);
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
pmsg_error("%s memory not accessible using FLIP", mem->desc);
avrdude_message(MSG_INFO, "%s: Error: "
"\"%s\" memory not accessible using FLIP",
progname, mem->desc);
if (strcmp(mem->desc, "flash") == 0)
msg_error(" (did you mean \"application\"?)");
msg_error("\n");
avrdude_message(MSG_INFO, " (did you mean \"application\"?)");
avrdude_message(MSG_INFO, "\n");
return -1;
}
return flip2_write_memory(FLIP2(pgm)->dfu, mem_unit, addr, &value, 1);
}
int flip2_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip2_paged_load(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
{
enum flip2_mem_unit mem_unit;
@@ -443,16 +446,19 @@ int flip2_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *m
mem_unit = flip2_mem_unit(mem->desc);
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
pmsg_error("%s memory not accessible using FLIP", mem->desc);
avrdude_message(MSG_INFO, "%s: Error: "
"\"%s\" memory not accessible using FLIP",
progname, mem->desc);
if (strcmp(mem->desc, "flash") == 0)
msg_error(" (did you mean \"application\"?)");
msg_error("\n");
avrdude_message(MSG_INFO, " (did you mean \"application\"?)");
avrdude_message(MSG_INFO, "\n");
return -1;
}
if (n_bytes > INT_MAX) {
/* This should never happen, unless the int type is only 16 bits. */
pmsg_error("attempting to read more than %d bytes\n", INT_MAX);
avrdude_message(MSG_INFO, "%s: Error: Attempting to read more than %d bytes\n",
progname, INT_MAX);
exit(1);
}
@@ -462,7 +468,7 @@ int flip2_paged_load(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *m
return (result == 0) ? n_bytes : -1;
}
int flip2_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *mem,
int flip2_paged_write(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem,
unsigned int page_size, unsigned int addr, unsigned int n_bytes)
{
enum flip2_mem_unit mem_unit;
@@ -474,16 +480,19 @@ int flip2_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *
mem_unit = flip2_mem_unit(mem->desc);
if (mem_unit == FLIP2_MEM_UNIT_UNKNOWN) {
pmsg_error("%s memory not accessible using FLIP", mem->desc);
avrdude_message(MSG_INFO, "%s: Error: "
"\"%s\" memory not accessible using FLIP",
progname, mem->desc);
if (strcmp(mem->desc, "flash") == 0)
msg_error(" (did you mean \"application\"?)");
msg_error("\n");
avrdude_message(MSG_INFO, " (did you mean \"application\"?)");
avrdude_message(MSG_INFO, "\n");
return -1;
}
if (n_bytes > INT_MAX) {
/* This should never happen, unless the int type is only 16 bits. */
pmsg_error("attempting to read more than %d bytes\n", INT_MAX);
avrdude_message(MSG_INFO, "%s: Error: Attempting to read more than %d bytes\n",
progname, INT_MAX);
exit(1);
}
@@ -493,35 +502,14 @@ int flip2_paged_write(const PROGRAMMER *pgm, const AVRPART *part, const AVRMEM *
return (result == 0) ? n_bytes : -1;
}
// 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) {
int flip2_read_sig_bytes(PROGRAMMER* pgm, AVRPART *part, AVRMEM *mem)
{
if (FLIP2(pgm)->dfu == NULL)
return -1;
if (mem->size < sizeof(FLIP2(pgm)->part_sig)) {
pmsg_error("signature read must be at least %u bytes\n", (unsigned int) sizeof(FLIP2(pgm)->part_sig));
avrdude_message(MSG_INFO, "%s: Error: Signature read must be at least %u bytes\n",
progname, (unsigned int) sizeof(FLIP2(pgm)->part_sig));
return -1;
}
@@ -534,7 +522,8 @@ void flip2_setup(PROGRAMMER * pgm)
pgm->cookie = calloc(1, sizeof(struct flip2));
if (pgm->cookie == NULL) {
pmsg_error("out of memory allocating private data structure\n");
avrdude_message(MSG_INFO, "%s: Out of memory allocating private data structure\n",
progname);
exit(1);
}
}
@@ -552,24 +541,24 @@ void flip2_show_info(struct flip2 *flip2)
{
dfu_show_info(flip2->dfu);
msg_info(" Part signature : 0x%02X%02X%02X\n",
avrdude_message(MSG_INFO, " Part signature : 0x%02X%02X%02X\n",
(int) flip2->part_sig[0],
(int) flip2->part_sig[1],
(int) flip2->part_sig[2]);
if (flip2->part_rev < 26)
msg_info(" Part revision : %c\n",
avrdude_message(MSG_INFO, " Part revision : %c\n",
(char) (flip2->part_rev + 'A'));
else
msg_info(" Part revision : %c%c\n",
avrdude_message(MSG_INFO, " Part revision : %c%c\n",
(char) (flip2->part_rev / 26 - 1 + 'A'),
(char) (flip2->part_rev % 26 + 'A'));
msg_info(" Bootloader version : 2.%hu.%hu\n",
avrdude_message(MSG_INFO, " Bootloader version : 2.%hu.%hu\n",
((unsigned short) flip2->boot_ver >> 4) & 0xF,
((unsigned short) flip2->boot_ver >> 0) & 0xF);
msg_info(" USB max packet size : %hu\n",
avrdude_message(MSG_INFO, " USB max packet size : %hu\n",
(unsigned short) flip2->dfu->dev_desc.bMaxPacketSize0);
}
@@ -582,15 +571,18 @@ int flip2_read_memory(struct dfu_dev *dfu,
int read_size;
int result;
pmsg_notice2("flip_read_memory(%s, 0x%04x, %d)\n", flip2_mem_unit_str(mem_unit), addr, size);
avrdude_message(MSG_NOTICE2, "%s: flip_read_memory(%s, 0x%04x, %d)\n",
progname, flip2_mem_unit_str(mem_unit), addr, size);
result = flip2_set_mem_unit(dfu, mem_unit);
if (result != 0) {
if ((mem_name = flip2_mem_unit_str(mem_unit)) != NULL)
pmsg_error("unable to set memory unit 0x%02X (%s)\n", (int) mem_unit, mem_name);
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory unit 0x%02X (%s)\n",
progname, (int) mem_unit, mem_name);
else
pmsg_error("unable to set memory unit 0x%02X\n", (int) mem_unit);
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory unit 0x%02X\n",
progname, (int) mem_unit);
return -1;
}
@@ -598,7 +590,8 @@ int flip2_read_memory(struct dfu_dev *dfu,
result = flip2_set_mem_page(dfu, page_addr);
if (result != 0) {
pmsg_error("unable to set memory page 0x%04hX\n", page_addr);
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory page 0x%04hX\n",
progname, page_addr);
return -1;
}
@@ -609,7 +602,8 @@ int flip2_read_memory(struct dfu_dev *dfu,
if (page_addr != prev_page_addr) {
result = flip2_set_mem_page(dfu, page_addr);
if (result != 0) {
pmsg_error("unable to set memory page 0x%04hX\n", page_addr);
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory page 0x%04hX\n",
progname, page_addr);
return -1;
}
}
@@ -618,11 +612,12 @@ int flip2_read_memory(struct dfu_dev *dfu,
result = flip2_read_max1k(dfu, addr & 0xFFFF, ptr, read_size);
if (result != 0) {
pmsg_error("unable to read 0x%04X bytes at 0x%04lX\n", read_size, (unsigned long) addr);
avrdude_message(MSG_INFO, "%s: Error: Failed to read 0x%04X bytes at 0x%04lX\n",
progname, read_size, (unsigned long) addr);
return -1;
}
ptr = (char*)ptr + read_size;
ptr += read_size;
addr += read_size;
size -= read_size;
}
@@ -639,15 +634,18 @@ int flip2_write_memory(struct dfu_dev *dfu,
int write_size;
int result;
pmsg_notice2("flip_write_memory(%s, 0x%04x, %d)\n", flip2_mem_unit_str(mem_unit), addr, size);
avrdude_message(MSG_NOTICE2, "%s: flip_write_memory(%s, 0x%04x, %d)\n",
progname, flip2_mem_unit_str(mem_unit), addr, size);
result = flip2_set_mem_unit(dfu, mem_unit);
if (result != 0) {
if ((mem_name = flip2_mem_unit_str(mem_unit)) != NULL)
pmsg_error("unable to set memory unit 0x%02X (%s)\n", (int) mem_unit, mem_name);
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory unit 0x%02X (%s)\n",
progname, (int) mem_unit, mem_name);
else
pmsg_error("unable to set memory unit 0x%02X\n", (int) mem_unit);
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory unit 0x%02X\n",
progname, (int) mem_unit);
return -1;
}
@@ -655,7 +653,8 @@ int flip2_write_memory(struct dfu_dev *dfu,
result = flip2_set_mem_page(dfu, page_addr);
if (result != 0) {
pmsg_error("unable to set memory page 0x%04hX\n", page_addr);
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory page 0x%04hX\n",
progname, page_addr);
return -1;
}
@@ -666,7 +665,8 @@ int flip2_write_memory(struct dfu_dev *dfu,
if (page_addr != prev_page_addr) {
result = flip2_set_mem_page(dfu, page_addr);
if (result != 0) {
pmsg_error("unable to set memory page 0x%04hX\n", page_addr);
avrdude_message(MSG_INFO, "%s: Error: Failed to set memory page 0x%04hX\n",
progname, page_addr);
return -1;
}
}
@@ -675,11 +675,12 @@ int flip2_write_memory(struct dfu_dev *dfu,
result = flip2_write_max1k(dfu, addr & 0xFFFF, ptr, write_size);
if (result != 0) {
pmsg_error("unable to write 0x%04X bytes at 0x%04lX\n", write_size, (unsigned long) addr);
avrdude_message(MSG_INFO, "%s: Error: Failed to write 0x%04X bytes at 0x%04lX\n",
progname, write_size, (unsigned long) addr);
return -1;
}
ptr = (const char*)ptr + write_size;
ptr += write_size;
addr += write_size;
size -= write_size;
}
@@ -711,9 +712,11 @@ int flip2_set_mem_unit(struct dfu_dev *dfu, enum flip2_mem_unit mem_unit)
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
{
pmsg_error("unknown memory unit (0x%02x)\n", (unsigned int) mem_unit);
avrdude_message(MSG_INFO, "%s: Error: Unknown memory unit (0x%02x)\n",
progname, (unsigned int) mem_unit);
} else
pmsg_error("DFU status %s\n", flip2_status_str(&status));
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
flip2_status_str(&status));
dfu_clrstatus(dfu);
}
@@ -746,9 +749,11 @@ int flip2_set_mem_page(struct dfu_dev *dfu,
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
{
pmsg_error("page address out of range (0x%04hx)\n", page_addr);
avrdude_message(MSG_INFO, "%s: Error: Page address out of range (0x%04hx)\n",
progname, page_addr);
} else
pmsg_error("DFU status %s\n", flip2_status_str(&status));
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
flip2_status_str(&status));
dfu_clrstatus(dfu);
}
@@ -789,9 +794,11 @@ flip2_read_max1k_status:
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
{
pmsg_error("address out of range [0x%04hX,0x%04hX]\n", offset, offset+size-1);
avrdude_message(MSG_INFO, "%s: Error: Address out of range [0x%04hX,0x%04hX]\n",
progname, offset, offset+size-1);
} else
pmsg_error("DFU status %s\n", flip2_status_str(&status));
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
flip2_status_str(&status));
dfu_clrstatus(dfu);
}
@@ -817,7 +824,8 @@ int flip2_write_max1k(struct dfu_dev *dfu,
cmd.args[3] = ((offset+size-1) >> 0) & 0xFF;
if (size > 0x400) {
pmsg_error("erite block too large (%hu > 1024)\n", size);
avrdude_message(MSG_INFO, "%s: Error: Write block too large (%hu > 1024)\n",
progname, size);
return -1;
}
@@ -847,9 +855,11 @@ int flip2_write_max1k(struct dfu_dev *dfu,
if (status.bStatus == ((FLIP2_STATUS_OUTOFRANGE >> 8) & 0xFF) &&
status.bState == ((FLIP2_STATUS_OUTOFRANGE >> 0) & 0xFF))
{
pmsg_error("address out of range [0x%04hX,0x%04hX]\n", offset, offset+size-1);
avrdude_message(MSG_INFO, "%s: Error: Address out of range [0x%04hX,0x%04hX]\n",
progname, offset, offset+size-1);
} else
pmsg_error("DFU status %s\n", flip2_status_str(&status));
avrdude_message(MSG_INFO, "%s: Error: DFU status %s\n", progname,
flip2_status_str(&status));
dfu_clrstatus(dfu);
}
@@ -900,26 +910,93 @@ const char * flip2_mem_unit_str(enum flip2_mem_unit mem_unit)
}
enum flip2_mem_unit flip2_mem_unit(const char *name) {
if (strcmp(name, "application") == 0)
if (strcasecmp(name, "application") == 0)
return FLIP2_MEM_UNIT_FLASH;
if (strcmp(name, "eeprom") == 0)
if (strcasecmp(name, "eeprom") == 0)
return FLIP2_MEM_UNIT_EEPROM;
if (strcmp(name, "signature") == 0)
if (strcasecmp(name, "signature") == 0)
return FLIP2_MEM_UNIT_SIGNATURE;
return FLIP2_MEM_UNIT_UNKNOWN;
}
#else /* !HAVE_LIBUSB */
#else /* HAVE_LIBUSB */
// Give a proper error if we were not compiled with libusb
static int flip2_nousb_open(PROGRAMMER* pgm, const char* name) {
pmsg_error("no USB support; please compile with libusb installed\n");
return -1;
/* EXPORTED PROGRAMMER FUNCTION DEFINITIONS */
int flip2_open(PROGRAMMER *pgm, char *port_spec)
{
fprintf(stderr, "%s: Error: No USB support in this compile of avrdude\n",
progname);
return -1;
}
void flip2_initpgm(PROGRAMMER *pgm) {
strcpy(pgm->type, "flip2");
pgm->open = flip2_nousb_open;
int flip2_initialize(PROGRAMMER* pgm, AVRPART *part)
{
return -1;
}
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 */

View File

@@ -26,7 +26,7 @@ extern "C" {
#endif
extern const char flip2_desc[];
extern void flip2_initpgm(PROGRAMMER *pgm);
extern void flip2_initpgm(PROGRAMMER * pgm);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
#define ft245r_h
extern const char ft245r_desc[];
void ft245r_initpgm(PROGRAMMER *pgm);
void ft245r_initpgm (PROGRAMMER * pgm);
#endif /* ft245r_h */

File diff suppressed because it is too large Load Diff

View File

@@ -25,32 +25,27 @@
extern "C" {
#endif
int jtag3_open_common(PROGRAMMER *pgm, const char *port);
int jtag3_send(const PROGRAMMER *pgm, unsigned char *data, size_t len);
int jtag3_recv(const PROGRAMMER *pgm, unsigned char **msg);
int jtag3_open_common(PROGRAMMER * pgm, char * port);
int jtag3_send(PROGRAMMER * pgm, unsigned char * data, size_t len);
int jtag3_recv(PROGRAMMER * pgm, unsigned char **msg);
void jtag3_close(PROGRAMMER * pgm);
int jtag3_getsync(const PROGRAMMER *pgm, int mode);
int jtag3_getparm(const PROGRAMMER *pgm, unsigned char scope,
unsigned char section, unsigned char parm,
unsigned char *value, unsigned char length);
int jtag3_setparm(const PROGRAMMER *pgm, unsigned char scope,
unsigned char section, unsigned char parm,
unsigned char *value, unsigned char length);
int jtag3_command(const PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
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);
int jtag3_getsync(PROGRAMMER * pgm, int mode);
int jtag3_getparm(PROGRAMMER * pgm, unsigned char scope,
unsigned char section, unsigned char parm,
unsigned char *value, unsigned char length);
int jtag3_setparm(PROGRAMMER * pgm, unsigned char scope,
unsigned char section, unsigned char parm,
unsigned char *value, unsigned char length);
int jtag3_command(PROGRAMMER *pgm, unsigned char *cmd, unsigned int cmdlen,
unsigned char **resp, const char *descr);
extern const char jtag3_desc[];
extern const char jtag3_dw_desc[];
extern const char jtag3_pdi_desc[];
extern const char jtag3_updi_desc[];
extern const char jtag3_tpi_desc[];
void jtag3_initpgm(PROGRAMMER *pgm);
void jtag3_dw_initpgm(PROGRAMMER *pgm);
void jtag3_pdi_initpgm(PROGRAMMER *pgm);
void jtag3_updi_initpgm(PROGRAMMER *pgm);
void jtag3_tpi_initpgm(PROGRAMMER *pgm);
void jtag3_initpgm (PROGRAMMER * pgm);
void jtag3_dw_initpgm (PROGRAMMER * pgm);
void jtag3_pdi_initpgm (PROGRAMMER * pgm);
void jtag3_updi_initpgm (PROGRAMMER * pgm);
/*
* These functions are referenced from stk500v2.c for JTAGICE3 in

View File

@@ -96,7 +96,6 @@
#define SCOPE_GENERAL 0x01
#define SCOPE_AVR_ISP 0x11
#define SCOPE_AVR 0x12
#define SCOPE_AVR_TPI 0x14
/* Info scope */
#define CMD3_GET_INFO 0x00
@@ -145,7 +144,6 @@
# define RSP3_FAIL_WRONG_MODE 0x32 /* progmode vs. non-prog */
# define RSP3_FAIL_UNSUPP_MEMORY 0x34 /* unsupported memory type */
# define RSP3_FAIL_WRONG_LENGTH 0x35 /* wrong lenth for mem access */
# define RSP3_FAIL_CRC_FAILURE 0x43 /* CRC failure in device */
# define RSP3_FAIL_OCD_LOCKED 0x44 /* device is locked */
# define RSP3_FAIL_NOT_UNDERSTOOD 0x91
@@ -185,24 +183,16 @@
* precedes each parameter address. There are distinct parameter
* sets for generic and AVR scope.
*/
#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_MINOR 0x02 /* section 0, generic scope, 1 byte */
#define PARM3_FW_RELEASE 0x03 /* section 0, generic scope, 1 byte;
* always asked for by Atmel Studio,
* 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_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_HW_VER 0x00 /* 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_RELEASE 0x03 /* section 0, generic scope, 1 byte;
* always asked for by Atmel Studio,
* 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_VUSB 0x02 /* section 1, generic scope, 2 bytes, USB voltage */
#define PARM3_VADJUST 0x20 /* section 1, generic scope, 2 bytes, set voltage */
#define PARM3_DEVICEDESC 0x00 /* section 2, memory etc. configuration,
* 31 bytes for tiny/mega AVR, 47 bytes
@@ -246,14 +236,6 @@
#define PARM3_OPT_12V_UPDI_ENABLE 0x06
#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 */
#define XMEGA_ERASE_CHIP 0x00
#define XMEGA_ERASE_APP 0x01
@@ -315,60 +297,6 @@
#define UPDI_ADDRESS_MODE_24BIT 1
#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)
struct mega_device_desc {
@@ -464,7 +392,5 @@ struct updi_device_desc {
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 hvupdi_variant; // Indicates the target UPDI HV implementation
};
#endif /* JTAG3_PRIVATE_EXPORTED */

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,7 @@ extern "C" {
#endif
extern const char jtagmkI_desc[];
void jtagmkI_initpgm(PROGRAMMER *pgm);
void jtagmkI_initpgm (PROGRAMMER * pgm);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@@ -25,29 +25,27 @@
extern "C" {
#endif
int jtagmkII_send(const PROGRAMMER *pgm, unsigned char *data, size_t len);
int jtagmkII_recv(const PROGRAMMER *pgm, unsigned char **msg);
int jtagmkII_send(PROGRAMMER * pgm, unsigned char * data, size_t len);
int jtagmkII_recv(PROGRAMMER * pgm, unsigned char **msg);
void jtagmkII_close(PROGRAMMER * pgm);
int jtagmkII_getsync(const PROGRAMMER *pgm, int mode);
int jtagmkII_getparm(const PROGRAMMER *pgm, unsigned char parm,
int jtagmkII_getsync(PROGRAMMER * pgm, int mode);
int jtagmkII_getparm(PROGRAMMER * pgm, unsigned char parm,
unsigned char * value);
extern const char jtagmkII_desc[];
extern const char jtagmkII_avr32_desc[];
extern const char jtagmkII_dw_desc[];
extern const char jtagmkII_pdi_desc[];
extern const char jtagmkII_updi_desc[];
extern const char jtagmkII_dragon_desc[];
extern const char jtagmkII_dragon_dw_desc[];
extern const char jtagmkII_dragon_pdi_desc[];
void jtagmkII_initpgm(PROGRAMMER *pgm);
void jtagmkII_avr32_initpgm(PROGRAMMER *pgm);
void jtagmkII_dw_initpgm(PROGRAMMER *pgm);
void jtagmkII_pdi_initpgm(PROGRAMMER *pgm);
void jtagmkII_updi_initpgm(PROGRAMMER *pgm);
void jtagmkII_dragon_initpgm(PROGRAMMER *pgm);
void jtagmkII_dragon_dw_initpgm(PROGRAMMER *pgm);
void jtagmkII_dragon_pdi_initpgm(PROGRAMMER *pgm);
void jtagmkII_initpgm (PROGRAMMER * pgm);
void jtagmkII_avr32_initpgm (PROGRAMMER * pgm);
void jtagmkII_dw_initpgm (PROGRAMMER * pgm);
void jtagmkII_pdi_initpgm (PROGRAMMER * pgm);
void jtagmkII_dragon_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

View File

@@ -28,7 +28,6 @@
#include <sys/types.h>
#include <sys/stat.h>
#include "ac_cfg.h"
#include "avrdude.h"
#include "libavrdude.h"
#include "config.h"
@@ -39,21 +38,15 @@
#define YYERRCODE 256
#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]
HEXDIGIT [0-9a-fA-F]
SIGN [+-]
%x strng
%x incl
%x comment
%option nounput
/* Bump resources for classic lex. */
@@ -63,47 +56,35 @@ SIGN [+-]
%%
{DIGIT}+ { yylval = new_number(yytext); return TKN_NUMBER; /* sign is treated in grammar */ }
{SIGN}?{DIGIT}+"."{DIGIT}* { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; }
{SIGN}?"."{DIGIT}+ { yylval = new_number_real(yytext); return TKN_NUMBER_REAL; }
#{SIGN}*{DIGIT}+ { yylval = number(yytext); return TKN_NUMBER; }
#{SIGN}*{DIGIT}+"."{DIGIT}* { yylval = number_real(yytext); return TKN_NUMBER_REAL; }
#{SIGN}*"."{DIGIT}* { yylval = 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; }
["]([^"\\\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;
}
"\"" { string_buf_ptr = string_buf; BEGIN(strng); }
0x{HEXDIGIT}+ { yylval = new_hexnumber(yytext); return TKN_NUMBER; }
0x{HEXDIGIT}+ { yylval = 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);
}
[ \t]*#[^\n]*\n+ { /* Record and skip # comments including preceding white space */
capture_comment_str(yytext, cfg_lineno);
adjust_cfg_lineno(yytext);
}
# { /* The following eats '#' style comments to end of line */
BEGIN(comment); }
<comment>[^\n] { /* eat comments */ }
<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 comment_start;
comment_start = cfg_lineno;
comment_start = lineno;
while (1) {
while (((c = input()) != '*') && (c != EOF)) {
/* eat up text of comment, but keep counting lines */
if (c == '\n')
cfg_lineno++;
lineno++;
}
if (c == '*') {
@@ -121,175 +102,156 @@ SIGN [+-]
}
(?x: prog_modes | mcuid | n_interrupts | n_page_erase | n_word_writes | n_boot_sections |
boot_section_size | autobaud_sync | idr | rampz | spmcr | eecr | eind ) { /* struct components */
<strng>\" { *string_buf_ptr = 0; string_buf_ptr = string_buf;
yylval = string(string_buf_ptr); BEGIN(INITIAL); return TKN_STRING; }
<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++); }
Component_t *cp = cfg_comp_search(yytext, current_strct);
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;
}
<strng>\n { yyerror("unterminated character constant");
return YYERRCODE; }
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; }
allowfullpagebitstream { yylval=NULL; ccap(); return K_ALLOWFULLPAGEBITSTREAM; }
avr910_devcode { yylval=NULL; ccap(); return K_AVR910_DEVCODE; }
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
bank_size { yylval=NULL; return K_PAGE_SIZE; }
banked { yylval=NULL; return K_PAGED; }
baudrate { yylval=NULL; ccap(); return K_BAUDRATE; }
blocksize { yylval=NULL; ccap(); return K_BLOCKSIZE; }
bs2 { yylval=NULL; ccap(); return K_BS2; }
buff { yylval=NULL; ccap(); return K_BUFF; }
bytedelay { yylval=NULL; ccap(); return K_BYTEDELAY; }
chip_erase { yylval=new_token(K_CHIP_ERASE); ccap(); return K_CHIP_ERASE; }
chip_erase_delay { yylval=NULL; ccap(); return K_CHIP_ERASE_DELAY; }
chiperasepolltimeout { yylval=NULL; ccap(); return K_CHIPERASEPOLLTIMEOUT; }
chiperasepulsewidth { yylval=NULL; ccap(); return K_CHIPERASEPULSEWIDTH; }
chiperasetime { yylval=NULL; ccap(); return K_CHIPERASETIME; }
cmdexedelay { yylval=NULL; ccap(); return K_CMDEXEDELAY; }
connection_type { yylval=NULL; ccap(); return K_CONNTYPE; }
baudrate { yylval=NULL; return K_BAUDRATE; }
blocksize { yylval=NULL; return K_BLOCKSIZE; }
bs2 { yylval=NULL; return K_BS2; }
buff { yylval=NULL; return K_BUFF; }
bytedelay { yylval=NULL; return K_BYTEDELAY; }
chip_erase { yylval=new_token(K_CHIP_ERASE); return K_CHIP_ERASE; }
chip_erase_delay { yylval=NULL; return K_CHIP_ERASE_DELAY; }
chiperasepolltimeout { yylval=NULL; return K_CHIPERASEPOLLTIMEOUT; }
chiperasepulsewidth { yylval=NULL; return K_CHIPERASEPULSEWIDTH; }
chiperasetime { yylval=NULL; return K_CHIPERASETIME; }
cmdexedelay { yylval=NULL; return K_CMDEXEDELAY; }
connection_type { yylval=NULL; return K_CONNTYPE; }
dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; }
default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
default_safemode { yylval=NULL; return K_DEFAULT_SAFEMODE; }
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
default_spi { yylval=NULL; return K_DEFAULT_SPI; }
delay { yylval=NULL; ccap(); return K_DELAY; }
desc { yylval=NULL; ccap(); return K_DESC; }
devicecode { yylval=NULL; ccap(); return K_DEVICECODE; }
delay { yylval=NULL; return K_DELAY; }
desc { yylval=NULL; return K_DESC; }
family_id { yylval=NULL; return K_FAMILY_ID; }
devicecode { yylval=NULL; return K_DEVICECODE; }
eecr { yylval=NULL; return K_EECR; }
eeprom { yylval=NULL; return K_EEPROM; }
eeprom_instr { yylval=NULL; ccap(); return K_EEPROM_INSTR; }
enablepageprogramming { yylval=NULL; ccap(); return K_ENABLEPAGEPROGRAMMING; }
errled { yylval=NULL; ccap(); return K_ERRLED; }
family_id { yylval=NULL; ccap(); return K_FAMILY_ID; }
eeprom_instr { yylval=NULL; return K_EEPROM_INSTR; }
enablepageprogramming { yylval=NULL; return K_ENABLEPAGEPROGRAMMING; }
errled { yylval=NULL; return K_ERRLED; }
flash { yylval=NULL; return K_FLASH; }
flash_instr { yylval=NULL; ccap(); return K_FLASH_INSTR; }
has_debugwire { yylval=NULL; ccap(); return K_HAS_DW; }
has_jtag { yylval=NULL; ccap(); return K_HAS_JTAG; }
has_pdi { yylval=NULL; ccap(); return K_HAS_PDI; }
has_tpi { yylval=NULL; ccap(); return K_HAS_TPI; }
has_updi { yylval=NULL; ccap(); return K_HAS_UPDI; }
hventerstabdelay { yylval=NULL; ccap(); return K_HVENTERSTABDELAY; }
hvleavestabdelay { yylval=NULL; ccap(); return K_HVLEAVESTABDELAY; }
hvsp_controlstack { yylval=NULL; ccap(); return K_HVSP_CONTROLSTACK; }
hvspcmdexedelay { yylval=NULL; ccap(); return K_HVSPCMDEXEDELAY; }
hvupdi_support { yylval=NULL; ccap(); return K_HVUPDI_SUPPORT; }
hvupdi_variant { yylval=NULL; ccap(); return K_HVUPDI_VARIANT; }
id { yylval=NULL; ccap(); return K_ID; }
flash_instr { yylval=NULL; return K_FLASH_INSTR; }
has_debugwire { yylval=NULL; return K_HAS_DW; }
has_jtag { yylval=NULL; return K_HAS_JTAG; }
has_pdi { yylval=NULL; return K_HAS_PDI; }
has_tpi { yylval=NULL; return K_HAS_TPI; }
has_updi { yylval=NULL; return K_HAS_UPDI; }
hventerstabdelay { yylval=NULL; return K_HVENTERSTABDELAY; }
hvleavestabdelay { yylval=NULL; return K_HVLEAVESTABDELAY; }
hvsp_controlstack { yylval=NULL; return K_HVSP_CONTROLSTACK; }
hvspcmdexedelay { yylval=NULL; return K_HVSPCMDEXEDELAY; }
id { yylval=NULL; return K_ID; }
idr { yylval=NULL; return K_IDR; }
io { yylval=new_token(K_IO); return K_IO; }
is_at90s1200 { yylval=NULL; ccap(); return K_IS_AT90S1200; }
is_avr32 { yylval=NULL; ccap(); return K_IS_AVR32; }
latchcycles { yylval=NULL; ccap(); return K_LATCHCYCLES; }
load_ext_addr { yylval=new_token(K_LOAD_EXT_ADDR); ccap(); return K_LOAD_EXT_ADDR; }
loadpage_hi { yylval=new_token(K_LOADPAGE_HI); ccap(); return K_LOADPAGE_HI; }
loadpage_lo { yylval=new_token(K_LOADPAGE_LO); ccap(); return K_LOADPAGE_LO; }
max_write_delay { yylval=NULL; ccap(); return K_MAX_WRITE_DELAY; }
mcu_base { yylval=NULL; ccap(); return K_MCU_BASE; }
memory { yylval=NULL; ccap(); current_strct = COMP_AVRMEM; return K_MEMORY; }
min_write_delay { yylval=NULL; ccap(); return K_MIN_WRITE_DELAY; }
miso { yylval=NULL; ccap(); return K_SDI; } // Deprecated
mode { yylval=NULL; ccap(); return K_MODE; }
mosi { yylval=NULL; ccap(); return K_SDO; } // Deprecated
is_at90s1200 { yylval=NULL; return K_IS_AT90S1200; }
is_avr32 { yylval=NULL; return K_IS_AVR32; }
latchcycles { yylval=NULL; return K_LATCHCYCLES; }
load_ext_addr { yylval=new_token(K_LOAD_EXT_ADDR); return K_LOAD_EXT_ADDR; }
loadpage_hi { yylval=new_token(K_LOADPAGE_HI); return K_LOADPAGE_HI; }
loadpage_lo { yylval=new_token(K_LOADPAGE_LO); return K_LOADPAGE_LO; }
max_write_delay { yylval=NULL; return K_MAX_WRITE_DELAY; }
mcu_base { yylval=NULL; return K_MCU_BASE; }
memory { yylval=NULL; return K_MEMORY; }
min_write_delay { yylval=NULL; return K_MIN_WRITE_DELAY; }
miso { yylval=NULL; return K_MISO; }
mode { yylval=NULL; return K_MODE; }
mosi { yylval=NULL; return K_MOSI; }
no { yylval=new_token(K_NO); return K_NO; }
NULL { yylval=NULL; return K_NULL; }
num_banks { yylval=NULL; return K_NUM_PAGES; }
num_pages { yylval=NULL; ccap(); return K_NUM_PAGES; }
nvm_base { yylval=NULL; ccap(); return K_NVM_BASE; }
ocd_base { yylval=NULL; ccap(); return K_OCD_BASE; }
ocdrev { yylval=NULL; ccap(); return K_OCDREV; }
offset { yylval=NULL; ccap(); return K_OFFSET; }
paged { yylval=NULL; ccap(); return K_PAGED; }
pagel { yylval=NULL; ccap(); return K_PAGEL; }
page_size { yylval=NULL; ccap(); return K_PAGE_SIZE; }
parallel { yylval=NULL; ccap(); return K_PARALLEL; }
num_pages { yylval=NULL; return K_NUM_PAGES; }
nvm_base { yylval=NULL; return K_NVM_BASE; }
ocd_base { yylval=NULL; return K_OCD_BASE; }
ocdrev { yylval=NULL; return K_OCDREV; }
offset { yylval=NULL; return K_OFFSET; }
page_size { yylval=NULL; return K_PAGE_SIZE; }
paged { yylval=NULL; return K_PAGED; }
pagel { yylval=NULL; return K_PAGEL; }
parallel { yylval=NULL; return K_PARALLEL; }
parent { yylval=NULL; return K_PARENT; }
part { yylval=NULL; ccap(); current_strct = COMP_AVRPART; return K_PART; }
pgm_enable { yylval=new_token(K_PGM_ENABLE); ccap(); return K_PGM_ENABLE; }
pgmled { yylval=NULL; ccap(); return K_PGMLED; }
pollindex { yylval=NULL; ccap(); return K_POLLINDEX; }
pollmethod { yylval=NULL; ccap(); return K_POLLMETHOD; }
pollvalue { yylval=NULL; ccap(); return K_POLLVALUE; }
postdelay { yylval=NULL; ccap(); return K_POSTDELAY; }
poweroffdelay { yylval=NULL; ccap(); return K_POWEROFFDELAY; }
pp_controlstack { yylval=NULL; ccap(); return K_PP_CONTROLSTACK; }
predelay { yylval=NULL; ccap(); return K_PREDELAY; }
progmodedelay { yylval=NULL; ccap(); return K_PROGMODEDELAY; }
programfusepolltimeout { yylval=NULL; ccap(); return K_PROGRAMFUSEPOLLTIMEOUT; }
programfusepulsewidth { yylval=NULL; ccap(); return K_PROGRAMFUSEPULSEWIDTH; }
programlockpolltimeout { yylval=NULL; ccap(); return K_PROGRAMLOCKPOLLTIMEOUT; }
programlockpulsewidth { yylval=NULL; ccap(); return K_PROGRAMLOCKPULSEWIDTH; }
programmer { yylval=NULL; ccap(); current_strct = COMP_PROGRAMMER; return K_PROGRAMMER; }
part { yylval=NULL; return K_PART; }
pgm_enable { yylval=new_token(K_PGM_ENABLE); return K_PGM_ENABLE; }
pgmled { yylval=NULL; return K_PGMLED; }
pollindex { yylval=NULL; return K_POLLINDEX; }
pollmethod { yylval=NULL; return K_POLLMETHOD; }
pollvalue { yylval=NULL; return K_POLLVALUE; }
postdelay { yylval=NULL; return K_POSTDELAY; }
poweroffdelay { yylval=NULL; return K_POWEROFFDELAY; }
pp_controlstack { yylval=NULL; return K_PP_CONTROLSTACK; }
predelay { yylval=NULL; return K_PREDELAY; }
progmodedelay { yylval=NULL; return K_PROGMODEDELAY; }
programfusepolltimeout { yylval=NULL; return K_PROGRAMFUSEPOLLTIMEOUT; }
programfusepulsewidth { yylval=NULL; return K_PROGRAMFUSEPULSEWIDTH; }
programlockpolltimeout { yylval=NULL; return K_PROGRAMLOCKPOLLTIMEOUT; }
programlockpulsewidth { yylval=NULL; return K_PROGRAMLOCKPULSEWIDTH; }
programmer { yylval=NULL; return K_PROGRAMMER; }
pseudo { yylval=new_token(K_PSEUDO); return K_PSEUDO; }
pwroff_after_write { yylval=NULL; ccap(); return K_PWROFF_AFTER_WRITE; }
rdyled { yylval=NULL; ccap(); return K_RDYLED; }
read { yylval=new_token(K_READ); ccap(); return K_READ; }
read_hi { yylval=new_token(K_READ_HI); ccap(); return K_READ_HI; }
read_lo { yylval=new_token(K_READ_LO); ccap(); return K_READ_LO; }
readback { yylval=NULL; ccap(); return K_READBACK; }
readback_p1 { yylval=NULL; ccap(); return K_READBACK_P1; }
readback_p2 { yylval=NULL; ccap(); return K_READBACK_P2; }
readsize { yylval=NULL; ccap(); return K_READSIZE; }
reset { yylval=new_token(K_RESET); ccap(); return K_RESET; }
resetdelay { yylval=NULL; ccap(); return K_RESETDELAY; }
resetdelayms { yylval=NULL; ccap(); return K_RESETDELAYMS; }
resetdelayus { yylval=NULL; ccap(); return K_RESETDELAYUS; }
retry_pulse { yylval=NULL; ccap(); return K_RETRY_PULSE; }
sck { yylval=new_token(K_SCK); ccap(); return K_SCK; }
sdi { yylval=NULL; ccap(); return K_SDI; }
sdo { yylval=NULL; ccap(); return K_SDO; }
serial { yylval=NULL; ccap(); return K_SERIAL; }
signature { yylval=NULL; ccap(); return K_SIGNATURE; }
size { yylval=NULL; ccap(); return K_SIZE; }
spi { yylval=NULL; return K_SPI; }
stabdelay { yylval=NULL; ccap(); return K_STABDELAY; }
stk500_devcode { yylval=NULL; ccap(); return K_STK500_DEVCODE; }
synchcycles { yylval=NULL; ccap(); return K_SYNCHCYCLES; }
synchloops { yylval=NULL; ccap(); return K_SYNCHLOOPS; }
timeout { yylval=NULL; ccap(); return K_TIMEOUT; }
togglevtg { yylval=NULL; ccap(); return K_TOGGLEVTG; }
type { yylval=NULL; ccap(); return K_TYPE; }
pwroff_after_write { yylval=NULL; return K_PWROFF_AFTER_WRITE; }
rampz { yylval=NULL; return K_RAMPZ; }
rdyled { yylval=NULL; return K_RDYLED; }
read { yylval=new_token(K_READ); return K_READ; }
read_hi { yylval=new_token(K_READ_HI); return K_READ_HI; }
read_lo { yylval=new_token(K_READ_LO); return K_READ_LO; }
readback_p1 { yylval=NULL; return K_READBACK_P1; }
readback_p2 { yylval=NULL; return K_READBACK_P2; }
readsize { yylval=NULL; return K_READSIZE; }
reset { yylval=new_token(K_RESET); return K_RESET; }
resetdelay { yylval=NULL; return K_RESETDELAY; }
resetdelayms { yylval=NULL; return K_RESETDELAYMS; }
resetdelayus { yylval=NULL; return K_RESETDELAYUS; }
retry_pulse { yylval=NULL; return K_RETRY_PULSE; }
sck { yylval=new_token(K_SCK); return K_SCK; }
serial { yylval=NULL; return K_SERIAL; }
signature { yylval=NULL; return K_SIGNATURE; }
size { yylval=NULL; return K_SIZE; }
spmcr { yylval=NULL; return K_SPMCR; }
stabdelay { yylval=NULL; return K_STABDELAY; }
stk500_devcode { yylval=NULL; return K_STK500_DEVCODE; }
synchcycles { yylval=NULL; return K_SYNCHCYCLES; }
synchloops { yylval=NULL; return K_SYNCHLOOPS; }
timeout { yylval=NULL; return K_TIMEOUT; }
togglevtg { yylval=NULL; return K_TOGGLEVTG; }
type { yylval=NULL; return K_TYPE; }
usb { yylval=NULL; return K_USB; }
usbdev { yylval=NULL; ccap(); return K_USBDEV; }
usbpid { yylval=NULL; ccap(); return K_USBPID; }
usbproduct { yylval=NULL; ccap(); return K_USBPRODUCT; }
usbsn { yylval=NULL; ccap(); return K_USBSN; }
usbvendor { yylval=NULL; ccap(); return K_USBVENDOR; }
usbvid { yylval=NULL; ccap(); return K_USBVID; }
vcc { yylval=NULL; ccap(); return K_VCC; }
vfyled { yylval=NULL; ccap(); return K_VFYLED; }
write { yylval=new_token(K_WRITE); ccap(); return K_WRITE; }
write_hi { yylval=new_token(K_WRITE_HI); ccap(); return K_WRITE_HI; }
write_lo { yylval=new_token(K_WRITE_LO); ccap(); return K_WRITE_LO; }
writepage { yylval=new_token(K_WRITEPAGE); ccap(); return K_WRITEPAGE; }
usbdev { yylval=NULL; return K_USBDEV; }
usbpid { yylval=NULL; return K_USBPID; }
usbproduct { yylval=NULL; return K_USBPRODUCT; }
usbsn { yylval=NULL; return K_USBSN; }
usbvendor { yylval=NULL; return K_USBVENDOR; }
usbvid { yylval=NULL; return K_USBVID; }
vcc { yylval=NULL; return K_VCC; }
vfyled { yylval=NULL; return K_VFYLED; }
write { yylval=new_token(K_WRITE); return K_WRITE; }
write_hi { yylval=new_token(K_WRITE_HI); return K_WRITE_HI; }
write_lo { yylval=new_token(K_WRITE_LO); return K_WRITE_LO; }
writepage { yylval=new_token(K_WRITEPAGE); return K_WRITEPAGE; }
yes { yylval=new_token(K_YES); return K_YES; }
"," { yylval = NULL; pyytext(); return TKN_COMMA; }
"=" { yylval = NULL; pyytext(); return TKN_EQUAL; }
";" { yylval = NULL; pyytext(); return TKN_SEMI; }
"|" { 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_TILDE; }
"(" { yylval = NULL; pyytext(); return TKN_LEFT_PAREN; }
")" { yylval = NULL; pyytext(); return TKN_RIGHT_PAREN; }
"\n" { cfg_lineno++; }
"\n" { lineno++; }
[ \r\t]+ { /* ignore whitespace */ }
c: { yyerror("possible old-style config file entry\n"

View File

@@ -21,22 +21,21 @@
#ifndef libavrdude_h
#define libavrdude_h
/* XXX should go away */
#include "ac_cfg.h"
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
/* lets try to select at least 32 bits */
#ifdef HAVE_STDINT_H
#include <stdint.h>
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
#else
#error Need a C99 capable compiler
#endif
/* formerly lists.h */
@@ -169,7 +168,6 @@ enum ctl_stack_t {
CTL_STACK_HVSP /* high voltage serial programming control stack */
};
/*
* serial programming instruction bit specifications
*/
@@ -184,33 +182,23 @@ typedef struct opcode {
} OPCODE;
// Any changes here, please also reflect in dev_part_strct() of developer_opts.c
#define AVRPART_SERIALOK 1 // Part supports serial programming
#define AVRPART_PARALLELOK 2 // Part supports parallel programming
#define AVRPART_PSEUDOPARALLEL 4 // Part has pseudo parallel support
#define AVRPART_ALLOWFULLPAGEBITSTREAM 8 // JTAG ICE mkII param
#define AVRPART_ENABLEPAGEPROGRAMMING 16 // JTAG ICE mkII param
#define AVRPART_IS_AT90S1200 32 // Part is an AT90S1200, needs special treatment
// Programming modes for parts and programmers: reflect changes in lexer.l, developer_opts.c and config.c
#define PM_SPM 1 // Bootloaders, self-programming with SPM opcodes or NVM Controllers
#define PM_TPI 2 // Tiny Programming Interface (t4, t5, t9, t10, t20, t40, t102, t104)
#define PM_ISP 4 // SPI programming for In-System Programming (almost all classic parts)
#define PM_PDI 8 // Program and Debug Interface (xmega parts)
#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 AVRPART_SERIALOK 0x0001 /* part supports serial programming */
#define AVRPART_PARALLELOK 0x0002 /* part supports parallel programming */
#define AVRPART_PSEUDOPARALLEL 0x0004 /* part has pseudo parallel support */
#define AVRPART_HAS_JTAG 0x0008 /* part has a JTAG i/f */
#define AVRPART_ALLOWFULLPAGEBITSTREAM 0x0010 /* JTAG ICE mkII param. */
#define AVRPART_ENABLEPAGEPROGRAMMING 0x0020 /* JTAG ICE mkII param. */
#define AVRPART_HAS_DW 0x0040 /* part has a debugWire i/f */
#define AVRPART_HAS_PDI 0x0080 /* part has PDI i/f rather than ISP (ATxmega) */
#define AVRPART_AVR32 0x0100 /* part is in AVR32 family */
#define AVRPART_INIT_SMC 0x0200 /* part will undergo chip erase */
#define AVRPART_WRITE 0x0400 /* at least one write operation specified */
#define AVRPART_HAS_TPI 0x0800 /* part has TPI i/f rather than ISP (ATtiny4/5/9/10) */
#define AVRPART_IS_AT90S1200 0x1000 /* part is an AT90S1200 (needs special treatment) */
#define AVRPART_HAS_UPDI 0x2000 /* part has UPDI i/f (AVR8X) */
#define AVR_DESCLEN 64
#define AVR_IDLEN 32
#define AVR_FAMILYIDLEN 7
#define AVR_SIBLEN 16
#define CTL_STACK_SIZE 32
@@ -219,27 +207,10 @@ typedef struct opcode {
#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 {
const char * desc; /* long part name */
const char * id; /* short part name */
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 */
char desc[AVR_DESCLEN]; /* long part name */
char id[AVR_IDLEN]; /* short part name */
char family_id[AVR_FAMILYIDLEN+1]; /* family id in the SIB (avr8x) */
int stk500_devcode; /* stk500 device code */
int avr910_devcode; /* avr910 device code */
int chip_erase_delay; /* microseconds */
@@ -252,74 +223,64 @@ typedef struct avrpart {
this pin (PIN_AVR_*) */
unsigned flags; /* see AVRPART_ masks */
/* STK500 v2 parameters from ATDF files */
int timeout;
int stabdelay;
int cmdexedelay;
int synchloops;
int bytedelay;
int pollindex;
unsigned char pollvalue;
int predelay;
int postdelay;
int pollmethod;
int timeout; /* stk500 v2 xml file parameter */
int stabdelay; /* stk500 v2 xml file parameter */
int cmdexedelay; /* stk500 v2 xml file parameter */
int synchloops; /* stk500 v2 xml file parameter */
int bytedelay; /* stk500 v2 xml file parameter */
int pollindex; /* stk500 v2 xml file parameter */
unsigned char pollvalue; /* stk500 v2 xml file parameter */
int predelay; /* stk500 v2 xml file parameter */
int postdelay; /* stk500 v2 xml file parameter */
int pollmethod; /* stk500 v2 xml file parameter */
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 flash_instr[FLASH_INSTR_SIZE]; /* flash instructions (debugWire, JTAG) */
unsigned char eeprom_instr[EEPROM_INSTR_SIZE]; /* EEPROM instructions (debugWire, JTAG) */
/* STK500 v2 hv mode parameters */
int hventerstabdelay;
int progmodedelay;
int latchcycles;
int togglevtg;
int poweroffdelay;
int resetdelayms;
int resetdelayus;
int hvleavestabdelay;
int resetdelay;
int chiperasepulsewidth;
int chiperasepolltimeout;
int chiperasetime;
int programfusepulsewidth;
int programfusepolltimeout;
int programlockpulsewidth;
int programlockpolltimeout;
int synchcycles;
int hvspcmdexedelay;
int hventerstabdelay; /* stk500 v2 hv mode parameter */
int progmodedelay; /* stk500 v2 hv mode parameter */
int latchcycles; /* stk500 v2 hv mode parameter */
int togglevtg; /* stk500 v2 hv mode parameter */
int poweroffdelay; /* stk500 v2 hv mode parameter */
int resetdelayms; /* stk500 v2 hv mode parameter */
int resetdelayus; /* stk500 v2 hv mode parameter */
int hvleavestabdelay; /* stk500 v2 hv mode parameter */
int resetdelay; /* stk500 v2 hv mode parameter */
int chiperasepulsewidth; /* stk500 v2 hv mode parameter */
int chiperasepolltimeout; /* stk500 v2 hv mode parameter */
int chiperasetime; /* stk500 v2 hv mode parameter */
int programfusepulsewidth; /* stk500 v2 hv mode parameter */
int programfusepolltimeout; /* stk500 v2 hv mode parameter */
int programlockpulsewidth; /* stk500 v2 hv mode parameter */
int programlockpolltimeout; /* stk500 v2 hv mode parameter */
int synchcycles; /* stk500 v2 hv mode parameter */
int hvspcmdexedelay; /* stk500 v2 xml file parameter */
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) */
/* 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) */
OPCODE * op[AVR_OP_MAX]; /* opcodes */
/* Bootloader paramater */
unsigned char autobaud_sync; /* Sync byte for bootloader autobaud, must be <= 0x30 */
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 */
LISTID mem; /* avr memory definitions */
char config_file[PATH_MAX]; /* config file where defined */
int lineno; /* config file line number */
} AVRPART;
#define AVR_MEMDESCLEN 64
typedef struct avrmem {
const char *desc; /* memory description ("flash", "eeprom", etc) */
LISTID comments; // Used by developer options -p*/[ASsr...]
char desc[AVR_MEMDESCLEN]; /* memory description ("flash", "eeprom", etc) */
int paged; /* page addressed (e.g. ATmega flash) */
int size; /* total memory size in bytes */
int page_size; /* size of memory page (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) */
int min_write_delay; /* microseconds */
int max_write_delay; /* microseconds */
@@ -340,55 +301,37 @@ typedef struct avrmem {
OPCODE * op[AVR_OP_MAX]; /* opcodes */
} AVRMEM;
typedef struct avrmem_alias {
const char *desc; /* alias name ("syscfg0" etc.) */
AVRMEM *aliased_mem;
} AVRMEM_ALIAS;
#ifdef __cplusplus
extern "C" {
#endif
int intlog2(unsigned int n);
/* Functions for OPCODE structures */
OPCODE * avr_new_opcode(void);
void avr_free_opcode(OPCODE * op);
int avr_set_bits(const OPCODE *op, unsigned char *cmd);
int avr_set_addr(const OPCODE *op, unsigned char *cmd, unsigned long addr);
int avr_set_addr_mem(const AVRMEM *mem, int opnum, unsigned char *cmd, unsigned long addr);
int avr_set_input(const OPCODE *op, unsigned char *cmd, unsigned char data);
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);
int avr_set_bits(OPCODE * op, unsigned char * cmd);
int avr_set_addr(OPCODE * op, unsigned char * cmd, unsigned long addr);
int avr_set_input(OPCODE * op, unsigned char * cmd, unsigned char data);
int avr_get_output(OPCODE * op, unsigned char * res, unsigned char * data);
int avr_get_output_index(OPCODE * op);
/* Functions for AVRMEM structures */
AVRMEM * avr_new_memtype(void);
AVRMEM_ALIAS * avr_new_memalias(void);
int avr_initmem(const AVRPART *p);
AVRMEM * avr_dup_mem(const AVRMEM *m);
int avr_initmem(AVRPART * p);
AVRMEM * avr_dup_mem(AVRMEM * m);
void avr_free_mem(AVRMEM * m);
void avr_free_memalias(AVRMEM_ALIAS * m);
AVRMEM * avr_locate_mem(const AVRPART *p, const char *desc);
AVRMEM * avr_locate_mem_noalias(const AVRPART *p, const char *desc);
AVRMEM_ALIAS * avr_locate_memalias(const AVRPART *p, const char *desc);
AVRMEM_ALIAS * avr_find_memalias(const AVRPART *p, const AVRMEM *m_orig);
void avr_mem_display(const char *prefix, FILE *f, const AVRMEM *m,
const AVRPART *p, int verbose);
AVRMEM * avr_locate_mem(AVRPART * p, char * desc);
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type,
int verbose);
/* Functions for AVRPART structures */
AVRPART * avr_new_part(void);
AVRPART * avr_dup_part(const AVRPART *d);
AVRPART * avr_dup_part(AVRPART * d);
void avr_free_part(AVRPART * d);
AVRPART * locate_part(const LISTID parts, const char *partdesc);
AVRPART * locate_part_by_avr910_devcode(const LISTID parts, int devcode);
AVRPART * locate_part_by_signature(const LISTID parts, unsigned char *sig,
AVRPART * locate_part(LISTID parts, char * partdesc);
AVRPART * locate_part_by_avr910_devcode(LISTID parts, int devcode);
AVRPART * locate_part_by_signature(LISTID parts, unsigned char * sig,
int sigsize);
void avr_display(FILE *f, const AVRPART *p, const char *prefix, int verbose);
void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose);
typedef void (*walk_avrparts_cb)(const char *name, const char *desc,
const char *cfgname, int cfglineno,
@@ -396,8 +339,6 @@ typedef void (*walk_avrparts_cb)(const char *name, const char *desc,
void walk_avrparts(LISTID avrparts, walk_avrparts_cb cb, void *cookie);
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);
#ifdef __cplusplus
@@ -411,8 +352,8 @@ enum {
PPI_AVR_BUFF,
PIN_AVR_RESET,
PIN_AVR_SCK,
PIN_AVR_SDO,
PIN_AVR_SDI,
PIN_AVR_MOSI,
PIN_AVR_MISO,
PIN_LED_ERR,
PIN_LED_RDY,
PIN_LED_PGM,
@@ -434,7 +375,7 @@ enum {
/** Number of pins in each element of the bitfield */
#define PIN_FIELD_ELEMENT_SIZE (sizeof(pinmask_t) * 8)
/** Numer of elements to store the complete bitfield of all pins */
#define PIN_FIELD_SIZE ((PIN_MAX+1 + PIN_FIELD_ELEMENT_SIZE-1)/PIN_FIELD_ELEMENT_SIZE)
#define PIN_FIELD_SIZE ((PIN_MAX + PIN_FIELD_ELEMENT_SIZE)/PIN_FIELD_ELEMENT_SIZE)
/**
* This sets the corresponding bits to 1 or 0, the inverse mask is used to invert the value in necessary.
@@ -545,15 +486,7 @@ int pins_check(const struct programmer_t * const pgm, const struct pin_checklist
const char * avr_pin_name(int pinname);
/**
* 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)"
* This function returns a string representation of defined pins eg. ~1,2,~4,~5,7
* 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
@@ -562,17 +495,9 @@ const char * avr_pin_lcname(int pinname);
const char * pins_to_str(const struct pindef_t * const pindef);
/**
* 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
* 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.
* Consecutive pin number are represented as start-end.
* Consecutive pin number are representated as start-end.
*
* @param[in] pinmask the pin mask for which we want the string representation
* @returns pointer to a static string.
@@ -589,9 +514,7 @@ const char * pinmask_to_str(const pinmask_t * const pinmask);
The target file will be selected at configure time. */
extern long serial_recv_timeout; /* ms */
extern long serial_drain_timeout; /* ms */
extern long serial_recv_timeout;
union filedescriptor
{
int ifd;
@@ -646,19 +569,19 @@ union pinfo
};
struct serial_device {
struct serial_device
{
// open should return -1 on error, other values on success
int (*open)(const char *port, union pinfo pinfo, union filedescriptor *fd);
int (*setparams)(const union filedescriptor *fd, long baud, unsigned long cflags);
int (*open)(char * port, union pinfo pinfo, union filedescriptor *fd);
int (*setparams)(union filedescriptor *fd, long baud, unsigned long cflags);
void (*close)(union filedescriptor *fd);
int (*send)(const union filedescriptor *fd, const unsigned char * buf, size_t buflen);
int (*recv)(const union filedescriptor *fd, unsigned char * buf, size_t buflen);
int (*drain)(const union filedescriptor *fd, int display);
int (*send)(union filedescriptor *fd, const unsigned char * buf, size_t buflen);
int (*recv)(union filedescriptor *fd, unsigned char * buf, size_t buflen);
int (*drain)(union filedescriptor *fd, int display);
int (*set_dtr_rts)(const union filedescriptor *fd, int is_on);
int (*set_dtr_rts)(union filedescriptor *fd, int is_on);
const char *usbsn;
int flags;
#define SERDEV_FL_NONE 0x0000 /* no flags */
#define SERDEV_FL_CANSETSPEED 0x0001 /* device can change speed */
@@ -679,21 +602,15 @@ extern struct serial_device usbhid_serdev;
#define serial_drain (serdev->drain)
#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 */
#define ON 1
#define OFF 0
#define PGM_DESCLEN 80
#define PGM_PORTLEN PATH_MAX
#define PGM_TYPELEN 32
#define PGM_USBSTRINGLEN 256
typedef enum {
EXIT_VCC_UNSPEC,
@@ -716,142 +633,106 @@ typedef enum {
typedef enum {
CONNTYPE_PARALLEL,
CONNTYPE_SERIAL,
CONNTYPE_USB,
CONNTYPE_SPI
CONNTYPE_USB
} 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 {
LISTID id;
const char *desc;
void (*initpgm)(struct programmer_t *pgm); // Sets up the AVRDUDE programmer
LISTID comments; // Used by developer options -c*/[ASsr...]
const char *parent_id; // Used by developer options
int prog_modes; // Programming interfaces, see #define PM_...
char desc[PGM_DESCLEN];
char type[PGM_TYPELEN];
char port[PGM_PORTLEN];
void (*initpgm)(struct programmer_t * pgm);
unsigned int pinno[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;
int ppidata;
int ppictrl;
int baudrate;
int usbvid;
LISTID usbpid;
const char *usbdev;
const char *usbsn;
const char *usbvendor;
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()
char usbdev[PGM_USBSTRINGLEN], usbsn[PGM_USBSTRINGLEN];
char usbvendor[PGM_USBSTRINGLEN], usbproduct[PGM_USBSTRINGLEN];
double bitclock; /* JTAG ICE clock period in microseconds */
int ispdelay; /* ISP clock delay */
union filedescriptor fd;
char type[PGM_TYPELEN];
char port[PGM_PORTLEN];
unsigned int pinno[N_PINS]; // TODO to be removed if old pin data no longer needed
exit_vcc_t exit_vcc; // Should these be set in avrdude.conf?
exit_reset_t exit_reset;
exit_datahigh_t exit_datahigh;
int ppidata;
int ppictrl;
int ispdelay; // ISP clock delay
int page_size; // Page size if the programmer supports paged write/load
double bitclock; // JTAG ICE clock period in microseconds
int (*rdy_led) (const struct programmer_t *pgm, int value);
int (*err_led) (const struct programmer_t *pgm, int value);
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,
int page_size; /* page size if the programmer supports paged write/load */
int (*rdy_led) (struct programmer_t * pgm, int value);
int (*err_led) (struct programmer_t * pgm, int value);
int (*pgm_led) (struct programmer_t * pgm, int value);
int (*vfy_led) (struct programmer_t * pgm, int value);
int (*initialize) (struct programmer_t * pgm, AVRPART * p);
void (*display) (struct programmer_t * pgm, const char * p);
void (*enable) (struct programmer_t * pgm);
void (*disable) (struct programmer_t * pgm);
void (*powerup) (struct programmer_t * pgm);
void (*powerdown) (struct programmer_t * pgm);
int (*program_enable) (struct programmer_t * pgm, AVRPART * p);
int (*chip_erase) (struct programmer_t * pgm, AVRPART * p);
int (*unlock) (struct programmer_t * pgm, AVRPART * p);
int (*cmd) (struct programmer_t * pgm, const unsigned char *cmd,
unsigned char *res);
int (*cmd_tpi) (const struct programmer_t *pgm, const unsigned char *cmd,
int (*cmd_tpi) (struct programmer_t * pgm, const unsigned char *cmd,
int cmd_len, unsigned char res[], int res_len);
int (*spi) (const struct programmer_t *pgm, const unsigned char *cmd,
int (*spi) (struct programmer_t * pgm, const unsigned char *cmd,
unsigned char *res, int count);
int (*open) (struct programmer_t *pgm, const char *port);
void (*close) (struct programmer_t *pgm);
int (*paged_write) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
int (*open) (struct programmer_t * pgm, char * port);
void (*close) (struct programmer_t * pgm);
int (*paged_write) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int baseaddr,
unsigned int n_bytes);
int (*paged_load) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
int (*paged_load) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
unsigned int page_size, unsigned int baseaddr,
unsigned int n_bytes);
int (*page_erase) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
int (*page_erase) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
unsigned int baseaddr);
void (*write_setup) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m);
int (*write_byte) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
void (*write_setup) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m);
int (*write_byte) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char value);
int (*read_byte) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m,
unsigned long addr, unsigned char *value);
int (*read_sig_bytes) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *m);
int (*read_sib) (const struct programmer_t *pgm, const AVRPART *p, char *sib);
int (*term_keep_alive)(const struct programmer_t *pgm, const AVRPART *p);
void (*print_parms) (const struct programmer_t *pgm, FILE *fp);
int (*set_vtarget) (const struct programmer_t *pgm, double v);
int (*set_varef) (const struct programmer_t *pgm, unsigned int chan, double v);
int (*set_fosc) (const struct programmer_t *pgm, double v);
int (*set_sck_period) (const struct programmer_t *pgm, double v);
int (*setpin) (const struct programmer_t *pgm, int pinfunc, int value);
int (*getpin) (const struct programmer_t *pgm, int pinfunc);
int (*highpulsepin) (const struct programmer_t *pgm, int pinfunc);
int (*parseexitspecs) (struct programmer_t *pgm, const char *s);
int (*perform_osccal) (const struct programmer_t *pgm);
int (*parseextparams) (const struct programmer_t *pgm, const LISTID xparams);
void (*setup) (struct programmer_t *pgm);
void (*teardown) (struct programmer_t *pgm);
int (*flash_readhook) (const struct programmer_t *pgm, const AVRPART *p, const AVRMEM *flm, const char *fname, int size);
// Cached r/w API for terminal reads/writes
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()
int (*read_byte) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m,
unsigned long addr, unsigned char * value);
int (*read_sig_bytes) (struct programmer_t * pgm, AVRPART * p, AVRMEM * m);
int (*read_sib) (struct programmer_t * pgm, AVRPART * p, char *sib);
void (*print_parms) (struct programmer_t * pgm);
int (*set_vtarget) (struct programmer_t * pgm, double v);
int (*set_varef) (struct programmer_t * pgm, unsigned int chan, double v);
int (*set_fosc) (struct programmer_t * pgm, double v);
int (*set_sck_period) (struct programmer_t * pgm, double v);
int (*setpin) (struct programmer_t * pgm, int pinfunc, int value);
int (*getpin) (struct programmer_t * pgm, int pinfunc);
int (*highpulsepin) (struct programmer_t * pgm, int pinfunc);
int (*parseexitspecs) (struct programmer_t * pgm, char *s);
int (*perform_osccal) (struct programmer_t * pgm);
int (*parseextparams) (struct programmer_t * pgm, LISTID xparams);
void (*setup) (struct programmer_t * pgm);
void (*teardown) (struct programmer_t * pgm);
char config_file[PATH_MAX]; /* config file where defined */
int lineno; /* config file line number */
void *cookie; /* for private use by the programmer */
char flag; /* for private use of the programmer */
} PROGRAMMER;
#define NO_PIN (PIN_MAX + 1U) // Magic pinno[] value for unused pins
#ifdef __cplusplus
extern "C" {
#endif
PROGRAMMER * pgm_new(void);
PROGRAMMER * pgm_dup(const PROGRAMMER *src);
void pgm_free(PROGRAMMER *p);
PROGRAMMER * pgm_dup(const PROGRAMMER * const src);
void pgm_free(PROGRAMMER * const p);
void programmer_display(PROGRAMMER * pgm, const char * p);
/* show is a mask like this (1<<PIN_AVR_SCK)|(1<<PIN_AVR_SDO)| ... */
/* show is a mask like this (1<<PIN_AVR_SCK)|(1<<PIN_AVR_MOSI)| ... */
#define SHOW_ALL_PINS (~0u)
#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_SDO)|(1<<PIN_AVR_SDI))
#define SHOW_AVR_PINS ((1<<PIN_AVR_RESET)|(1<<PIN_AVR_SCK)|(1<<PIN_AVR_MOSI)|(1<<PIN_AVR_MISO))
#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(const PROGRAMMER *pgm, const char *p, unsigned int show);
void pgm_display_generic(const PROGRAMMER *pgm, const char *p);
void pgm_display_generic_mask(PROGRAMMER * pgm, const char * p, unsigned int show);
void pgm_display_generic(PROGRAMMER * pgm, const char * p);
PROGRAMMER *locate_programmer(const LISTID programmers, const char *configid);
PROGRAMMER * locate_programmer(LISTID programmers, const char * configid);
typedef void (*walk_programmers_cb)(const char *name, const char *desc,
const char *cfgname, int cfglineno,
@@ -866,10 +747,9 @@ void sort_programmers(LISTID programmers);
/* formerly avr.h */
typedef void (*FP_UpdateProgress)(int percent, double etime, const char *hdr, int finish);
typedef void (*FP_UpdateProgress)(int percent, double etime, char *hdr);
extern struct avrpart parts[];
extern const char *avr_mem_order[100];
extern FP_UpdateProgress update_progress;
@@ -877,81 +757,41 @@ extern FP_UpdateProgress update_progress;
extern "C" {
#endif
int avr_tpi_poll_nvmbsy(const PROGRAMMER *pgm);
int avr_tpi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p);
int avr_tpi_program_enable(const PROGRAMMER *pgm, const AVRPART *p, unsigned char guard_time);
int avr_read_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
int avr_tpi_poll_nvmbsy(PROGRAMMER *pgm);
int avr_tpi_chip_erase(PROGRAMMER * pgm, AVRPART * p);
int avr_tpi_program_enable(PROGRAMMER * pgm, AVRPART * p, unsigned char guard_time);
int avr_read_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char * value);
int avr_read_mem(const PROGRAMMER * pgm, const AVRPART *p, const AVRMEM *mem, const AVRPART *v);
int avr_read(PROGRAMMER * pgm, AVRPART * p, char * memtype, AVRPART * v);
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,
int avr_write_page(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr);
unsigned long avr_ustimestamp();
unsigned long avr_mstimestamp();
double avr_timestamp();
int avr_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char data);
int avr_write_byte_default(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
unsigned long addr, unsigned char data);
int avr_write_mem(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem, int size, int auto_erase);
int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
int auto_erase);
int avr_write(const PROGRAMMER *pgm, const AVRPART *p, const char *memtype, int size, int auto_erase);
int avr_signature(PROGRAMMER * pgm, AVRPART * p);
int avr_signature(const PROGRAMMER *pgm, const AVRPART *p);
int avr_verify(AVRPART * p, AVRPART * v, char * memtype, int size);
int avr_verify(const PROGRAMMER *pgm, const AVRPART *p, const AVRPART *v, const char *m, int size);
int avr_get_cycle_count(PROGRAMMER * pgm, AVRPART * p, int * cycles);
int avr_get_cycle_count(const PROGRAMMER *pgm, const AVRPART *p, int *cycles);
int avr_put_cycle_count(PROGRAMMER * pgm, AVRPART * p, int cycles);
int avr_put_cycle_count(const PROGRAMMER *pgm, const AVRPART *p, int cycles);
int avr_mem_hiaddr(AVRMEM * mem);
void avr_add_mem_order(const char *str);
int avr_chip_erase(PROGRAMMER * pgm, AVRPART * p);
int avr_memtype_is_flash_type(const char *mem);
int avr_unlock(PROGRAMMER * pgm, AVRPART * p);
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);
void report_progress (int completed, int total, char *hdr);
#ifdef __cplusplus
}
@@ -969,8 +809,7 @@ typedef enum {
FMT_DEC,
FMT_OCT,
FMT_BIN,
FMT_ELF,
FMT_IHXC,
FMT_ELF
} FILEFMT;
struct fioparms {
@@ -984,20 +823,41 @@ struct fioparms {
enum {
FIO_READ,
FIO_WRITE,
FIO_READ_FOR_VERIFY,
FIO_WRITE
};
#ifdef __cplusplus
extern "C" {
#endif
char * fileio_fmtstr(FILEFMT format);
char * fmtstr(FILEFMT format);
int fileio_fmt_autodetect(const char * fname);
int fileio(int op, char * filename, FILEFMT format,
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
}
#endif
/* formerly safemode.h */
#ifdef __cplusplus
extern "C" {
#endif
/* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or "efuse") and verifies it. Will try up to tries
amount of times before giving up */
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries);
/* Reads the fuses three times, checking that all readings are the same. This will ensure that the before values aren't in error! */
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse, PROGRAMMER * pgm, AVRPART * p);
/* This routine will store the current values pointed to by lfuse, hfuse, and efuse into an internal buffer in this routine
when save is set to 1. When save is 0 (or not 1 really) it will copy the values from the internal buffer into the locations
pointed to be lfuse, hfuse, and efuse. This allows you to change the fuse bits if needed from another routine (ie: have it so
if user requests fuse bits are changed, the requested value is now verified */
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse);
#ifdef __cplusplus
}
@@ -1016,7 +876,6 @@ enum updateflags {
UF_NONE = 0,
UF_NOWRITE = 1,
UF_AUTO_ERASE = 2,
UF_VERIFY = 4,
};
@@ -1027,17 +886,6 @@ typedef struct update_t {
int format;
} 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
extern "C" {
#endif
@@ -1047,24 +895,8 @@ extern UPDATE * dup_update(UPDATE * upd);
extern UPDATE * new_update(int op, char * memtype, int filefmt,
char * filename);
extern void free_update(UPDATE * upd);
extern int do_op(const PROGRAMMER *pgm, const AVRPART *p, UPDATE *upd,
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);
extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
enum updateflags flags);
#ifdef __cplusplus
}
@@ -1077,7 +909,7 @@ int update_dryrun(const AVRPART *p, UPDATE *upd);
typedef struct programmer_type_t {
const char * const id;
void (*initpgm)(struct programmer_t *pgm);
void (*initpgm)(struct programmer_t * pgm);
const char * const desc;
} PROGRAMMER_TYPE;
@@ -1085,9 +917,7 @@ typedef struct programmer_type_t {
extern "C" {
#endif
const PROGRAMMER_TYPE *locate_programmer_type(const char *id);
const char *locate_programmer_type_id(void (*initpgm)(struct programmer_t *pgm));
const PROGRAMMER_TYPE * locate_programmer_type(/*LISTID programmer_types, */const char * id);
typedef void (*walk_programmer_types_cb)(const char *id, const char *desc,
void *cookie);
@@ -1101,11 +931,11 @@ void walk_programmer_types(/*LISTID programmer_types,*/ walk_programmer_types_cb
extern LISTID part_list;
extern LISTID programmers;
extern const char *default_programmer;
extern const char *default_parallel;
extern const char *default_serial;
extern const char *default_spi;
extern char default_programmer[];
extern char default_parallel[];
extern char default_serial[];
extern double default_bitclock;
extern int default_safemode;
/* This name is fixed, it's only here for symmetry with
* default_parallel and default_serial. */
@@ -1115,24 +945,12 @@ extern double default_bitclock;
extern "C" {
#endif
void *cfg_malloc(const char *funcname, size_t n);
char *cfg_strdup(const char *funcname, const char *s);
int init_config(void);
void cleanup_config(void);
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
}
#endif
@@ -1140,7 +958,7 @@ char *cfg_escape(const char *s);
/* formerly confwin.h */
#if defined(WIN32)
#if defined(WIN32NATIVE)
#ifdef __cplusplus
extern "C" {
@@ -1153,7 +971,7 @@ void win_usr_config_set(char usr_config[PATH_MAX]);
}
#endif
#endif /* WIN32 */
#endif /* WIN32NATIVE */
#endif /* libavrdude_h */

View File

@@ -31,18 +31,18 @@
#include <stdlib.h>
#define ppi_claim(fd) \
if (ioctl(fd, PPCLAIM)) { \
pmsg_ext_error("cannot claim port %s: %s\n\n", \
port, strerror(errno)); \
close(fd); \
return; \
#define ppi_claim(fd) \
if (ioctl(fd, PPCLAIM)) { \
avrdude_message(MSG_INFO, "%s: can't claim device \"%s\": %s\n\n", \
progname, port, strerror(errno)); \
close(fd); \
return; \
}
#define ppi_release(fd) \
if (ioctl(fd, PPRELEASE)) { \
pmsg_ext_error("cannot release device: %s\n\n", \
strerror(errno)); \
#define ppi_release(fd) \
if (ioctl(fd, PPRELEASE)) { \
avrdude_message(MSG_INFO, "%s: can't release device: %s\n\n", \
progname, strerror(errno)); \
}
#define DO_PPI_READ(fd, reg, valp) \

View File

@@ -27,7 +27,6 @@
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include "avrdude.h"
#include "libavrdude.h"
@@ -47,8 +46,10 @@
/*
* GPIO user space helpers
* The following functions are acting on an "unsigned gpio" argument, which corresponds to the
* gpio numbering scheme in the kernel (starting from 0).
* The following functions are acting on an "unsigned gpio" argument, which corresponds to the
* 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
@@ -61,7 +62,7 @@ static int linuxgpio_export(unsigned int gpio)
fd = open("/sys/class/gpio/export", O_WRONLY);
if (fd < 0) {
pmsg_ext_error("cannot open /sys/class/gpio/export: %s\n", strerror(errno));
perror("Can't open /sys/class/gpio/export");
return fd;
}
@@ -79,7 +80,7 @@ static int linuxgpio_unexport(unsigned int gpio)
fd = open("/sys/class/gpio/unexport", O_WRONLY);
if (fd < 0) {
pmsg_ext_error("cannot open /sys/class/gpio/unexport: %s\n", strerror(errno));
perror("Can't open /sys/class/gpio/unexport");
return fd;
}
@@ -107,7 +108,7 @@ static int linuxgpio_dir(unsigned int gpio, unsigned int dir)
fd = open(buf, O_WRONLY);
if (fd < 0) {
pmsg_ext_error("cannot open %s: %s\n", buf, strerror(errno));
perror("Can't open gpioX/direction");
return fd;
}
@@ -137,31 +138,32 @@ static int linuxgpio_dir_in(unsigned int gpio)
#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
*/
static int linuxgpio_fds[N_GPIO] ;
static int linuxgpio_setpin(const PROGRAMMER *pgm, int pinfunc, int value) {
if(pinfunc < 0 || pinfunc >= N_PINS)
return -1;
static int linuxgpio_setpin(PROGRAMMER * pgm, int pinfunc, int value)
{
int r;
int pin = pgm->pinno[pinfunc]; // TODO
unsigned pin = pgm->pinno[pinfunc];
if (pin & PIN_INVERSE)
value = !value;
pin &= PIN_MASK;
{
value = !value;
pin &= PIN_MASK;
}
if (pin > PIN_MAX || linuxgpio_fds[pin] < 0)
if ( linuxgpio_fds[pin] < 0 )
return -1;
if (write(linuxgpio_fds[pin], value? "1": "0", 1) != 1)
return -1;
if (value)
r = write(linuxgpio_fds[pin], "1", 1);
else
r = write(linuxgpio_fds[pin], "0", 1);
if (r!=1) return -1;
if (pgm->ispdelay > 1)
bitbang_delay(pgm->ispdelay);
@@ -169,34 +171,41 @@ static int linuxgpio_setpin(const PROGRAMMER *pgm, int pinfunc, int value) {
return 0;
}
static int linuxgpio_getpin(const PROGRAMMER *pgm, int pinfunc) {
if(pinfunc < 0 || pinfunc >= N_PINS)
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;
static int linuxgpio_getpin(PROGRAMMER * pgm, int pinfunc)
{
unsigned char invert=0;
char c;
if(read(linuxgpio_fds[pin], &c, 1) != 1)
int pin = pgm->pinno[pinfunc]; // TODO
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 c=='0'? 0+invert: c=='1'? 1-invert: -1;
}
static int linuxgpio_highpulsepin(const PROGRAMMER *pgm, int pinfunc) {
if(pinfunc < 0 || pinfunc >= N_PINS)
return -1;
unsigned int pin = pgm->pinno[pinfunc] & PIN_MASK;
if (pin > PIN_MAX || linuxgpio_fds[pin] < 0 )
static int linuxgpio_highpulsepin(PROGRAMMER * pgm, int pinfunc)
{
int pin = pgm->pinno[pinfunc]; // TODO
if ( linuxgpio_fds[pin & PIN_MASK] < 0 )
return -1;
linuxgpio_setpin(pgm, pinfunc, 1);
@@ -207,31 +216,35 @@ static int linuxgpio_highpulsepin(const PROGRAMMER *pgm, int pinfunc) {
static void linuxgpio_display(const PROGRAMMER *pgm, const char *p) {
msg_info("%sPin assignment : /sys/class/gpio/gpio{n}\n",p);
static void linuxgpio_display(PROGRAMMER *pgm, const char *p)
{
avrdude_message(MSG_INFO, "%sPin assignment : /sys/class/gpio/gpio{n}\n",p);
pgm_display_generic_mask(pgm, p, SHOW_AVR_PINS);
}
static void linuxgpio_enable(PROGRAMMER *pgm, const AVRPART *p) {
static void linuxgpio_enable(PROGRAMMER *pgm)
{
/* nothing */
}
static void linuxgpio_disable(const PROGRAMMER *pgm) {
static void linuxgpio_disable(PROGRAMMER *pgm)
{
/* nothing */
}
static void linuxgpio_powerup(const PROGRAMMER *pgm) {
static void linuxgpio_powerup(PROGRAMMER *pgm)
{
/* nothing */
}
static void linuxgpio_powerdown(const PROGRAMMER *pgm) {
static void linuxgpio_powerdown(PROGRAMMER *pgm)
{
/* nothing */
}
static int linuxgpio_open(PROGRAMMER *pgm, const char *port) {
static int linuxgpio_open(PROGRAMMER *pgm, char *port)
{
int r, i, pin;
char gpio_path[60];
struct stat stat_buf;
if (bitbang_check_prerequisites(pgm) < 0)
return -1;
@@ -239,58 +252,33 @@ static int linuxgpio_open(PROGRAMMER *pgm, const char *port) {
for (i=0; i<N_GPIO; i++)
linuxgpio_fds[i] = -1;
// Avrdude assumes that if a pin number is invalid it means not used/available
for (i = 1; i < N_PINS; i++) { // The pin enumeration in libavrdude.h starts with PPI_AVR_VCC = 1
if ((pgm->pinno[i] & PIN_MASK) <= PIN_MAX) {
//Avrdude assumes that if a pin number is 0 it means not used/available
//this causes a problem because 0 is a valid GPIO number in Linux sysfs.
//To avoid annoying off by one pin numbering we assume SCK, MOSI, MISO
//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;
if ((r=linuxgpio_export(pin)) < 0) {
pmsg_ext_error("cannot export GPIO %d, already exported/busy?: %s",
avrdude_message(MSG_INFO, "Can't export GPIO %d, already exported/busy?: %s",
pin, strerror(errno));
return r;
}
if (i == PIN_AVR_MISO)
r=linuxgpio_dir_in(pin);
else
r=linuxgpio_dir_out(pin);
/* 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);
if (r < 0)
return r;
}
if ((linuxgpio_fds[pin]=linuxgpio_openfd(pin)) < 0)
return linuxgpio_fds[pin];
@@ -311,21 +299,20 @@ static void linuxgpio_close(PROGRAMMER *pgm)
for (i=0; i<N_GPIO; i++) {
if (linuxgpio_fds[i] >= 0 && i != reset_pin) {
close(linuxgpio_fds[i]);
linuxgpio_fds[i] = -1;
linuxgpio_dir_in(i);
linuxgpio_unexport(i);
}
}
//configure RESET as input, if there's external pull up it will go high
if(reset_pin <= PIN_MAX && linuxgpio_fds[reset_pin] >= 0) {
if (linuxgpio_fds[reset_pin] >= 0) {
close(linuxgpio_fds[reset_pin]);
linuxgpio_fds[reset_pin] = -1;
linuxgpio_dir_in(reset_pin);
linuxgpio_unexport(reset_pin);
}
}
void linuxgpio_initpgm(PROGRAMMER *pgm) {
void linuxgpio_initpgm(PROGRAMMER *pgm)
{
strcpy(pgm->type, "linuxgpio");
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
@@ -357,8 +344,10 @@ const char linuxgpio_desc[] = "GPIO bitbanging using the Linux sysfs interface";
#else /* !HAVE_LINUXGPIO */
void linuxgpio_initpgm(PROGRAMMER *pgm) {
pmsg_error("Linux sysfs GPIO support not available in this configuration\n");
void linuxgpio_initpgm(PROGRAMMER * pgm)
{
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)";

View File

@@ -27,7 +27,7 @@ extern "C" {
#endif
extern const char linuxgpio_desc[];
void linuxgpio_initpgm(PROGRAMMER *pgm);
void linuxgpio_initpgm (PROGRAMMER * pgm);
#ifdef __cplusplus
}

View File

@@ -62,22 +62,14 @@
#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;
/**
* @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/recieved
*/
static int linuxspi_spi_duplex(const PROGRAMMER *pgm, const unsigned char *tx, unsigned char *rx, int len) {
static int linuxspi_spi_duplex(PROGRAMMER *pgm, const unsigned char *tx, unsigned char *rx, int len)
{
struct spi_ioc_transfer tr;
int ret;
@@ -86,33 +78,27 @@ static int linuxspi_spi_duplex(const PROGRAMMER *pgm, const unsigned char *tx, u
.rx_buf = (unsigned long)rx,
.len = len,
.delay_usecs = 1,
.speed_hz = 1.0 / pgm->bitclock,
.speed_hz = 1.0 / pgm->bitclock, // seconds to Hz
.bits_per_word = 8,
};
errno = 0;
ret = ioctl(fd_spidev, SPI_IOC_MESSAGE(1), &tr);
if (ret != len) {
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");
}
if (ret != len)
avrdude_message(MSG_INFO, "\n%s: error: Unable to send SPI message\n", progname);
return ret == -1? -1: 0;
return (ret == -1) ? -1 : 0;
}
static void linuxspi_setup(PROGRAMMER *pgm) {
pgm->cookie = cfg_malloc("linuxspi_setup()", sizeof(struct pdata));
static void linuxspi_setup(PROGRAMMER *pgm)
{
}
static void linuxspi_teardown(PROGRAMMER* pgm) {
free(pgm->cookie);
static void linuxspi_teardown(PROGRAMMER* pgm)
{
}
static int linuxspi_reset_mcu(const PROGRAMMER *pgm, bool active) {
static int linuxspi_reset_mcu(PROGRAMMER *pgm, bool active)
{
struct gpiohandle_data data;
int ret;
@@ -134,20 +120,21 @@ static int linuxspi_reset_mcu(const PROGRAMMER *pgm, bool active) {
#endif
if (ret == -1) {
ret = -errno;
pmsg_ext_error("unable to set GPIO line %d value: %s\n", pgm->pinno[PIN_AVR_RESET] & PIN_MASK, strerror(errno));
avrdude_message(MSG_INFO, "%s error: Unable to set GPIO line %d value\n",
progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE);
return ret;
}
return 0;
}
static int linuxspi_open(PROGRAMMER *pgm, const char *pt) {
static int linuxspi_open(PROGRAMMER *pgm, char *port)
{
const char *port_error =
"unknown port specification, "
"please use the format /dev/spidev:/dev/gpiochip[:resetno]\n";
"%s: error: Unknown port specification. "
"Please use the format /dev/spidev:/dev/gpiochip[:resetno]\n";
char port_default[] = "/dev/spidev0.0:/dev/gpiochip0";
char *spidev, *gpiochip, *reset_pin;
char *port = cfg_strdup("linuxspi_open()", pt);
struct gpiohandle_request req;
int ret;
@@ -157,13 +144,13 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) {
spidev = strtok(port, ":");
if (!spidev) {
pmsg_error("%s", port_error);
avrdude_message(MSG_INFO, port_error, progname);
return -1;
}
gpiochip = strtok(NULL, ":");
if (!gpiochip) {
pmsg_error("%s", port_error);
avrdude_message(MSG_INFO, port_error, progname);
return -1;
}
@@ -175,32 +162,27 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) {
strcpy(pgm->port, port);
fd_spidev = open(pgm->port, O_RDWR);
if (fd_spidev < 0) {
pmsg_ext_error("unable to open the spidev device %s: %s\n", pgm->port, strerror(errno));
avrdude_message(MSG_INFO, "\n%s: error: Unable to open the spidev device %s", progname, pgm->port);
return -1;
}
uint32_t mode = SPI_MODE_0;
if (!PDATA(pgm)->disable_no_cs)
mode |= SPI_NO_CS;
uint32_t mode = SPI_MODE_0 | SPI_NO_CS;
ret = ioctl(fd_spidev, SPI_IOC_WR_MODE32, &mode);
if (ret == -1) {
int ioctl_errno = errno;
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");
avrdude_message(MSG_INFO, "%s: error: Unable to set SPI mode %0X on %s\n",
progname, mode, spidev);
goto close_spidev;
}
fd_gpiochip = open(gpiochip, 0);
if (fd_gpiochip < 0) {
pmsg_ext_error("unable to open the gpiochip %s: %s\n", gpiochip, strerror(errno));
avrdude_message(MSG_INFO, "\n%s error: Unable to open the gpiochip %s", progname, gpiochip);
ret = -1;
goto close_spidev;
}
strcpy(req.consumer_label, progname);
req.lines = 1;
req.lineoffsets[0] = pgm->pinno[PIN_AVR_RESET] & PIN_MASK;
req.lineoffsets[0] = pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE;
req.default_values[0] = !!(pgm->pinno[PIN_AVR_RESET] & PIN_INVERSE);
req.flags = GPIOHANDLE_REQUEST_OUTPUT;
@@ -212,7 +194,7 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) {
struct gpio_v2_line_request reqv2;
memset(&reqv2, 0, sizeof(reqv2));
reqv2.offsets[0] = pgm->pinno[PIN_AVR_RESET] & PIN_MASK;
reqv2.offsets[0] = pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE;
strncpy(reqv2.consumer, progname, sizeof(reqv2.consumer) - 1);
reqv2.config.flags = GPIO_V2_LINE_FLAG_OUTPUT;
reqv2.config.num_attrs = 1;
@@ -228,7 +210,8 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) {
#endif
if (ret == -1) {
ret = -errno;
pmsg_ext_error("unable to get GPIO line %d. %s\n", pgm->pinno[PIN_AVR_RESET] & PIN_MASK, strerror(errno));
avrdude_message(MSG_INFO, "%s error: Unable to get GPIO line %d\n",
progname, pgm->pinno[PIN_AVR_RESET] & ~PIN_INVERSE);
goto close_gpiochip;
}
@@ -237,12 +220,16 @@ static int linuxspi_open(PROGRAMMER *pgm, const char *pt) {
goto close_out;
if (pgm->baudrate != 0) {
pmsg_warning("obsolete use of -b <clock> option for bit clock; use -B <clock>\n");
pgm->bitclock = 1.0 / pgm->baudrate;
avrdude_message(MSG_INFO,
"%s: obsolete use of -b <clock> option for bit clock; use -B <clock>\n",
progname);
pgm->bitclock = 1E6 / pgm->baudrate;
}
if (pgm->bitclock == 0) {
pmsg_notice("defaulting bit clock to 200 kHz\n");
pgm->bitclock = 5E-6; // 200 kHz - 5 µs
avrdude_message(MSG_NOTICE,
"%s: defaulting bit clock to 200 kHz\n",
progname);
pgm->bitclock = 5E-6; // 200 kHz - 5 µs
}
return 0;
@@ -256,7 +243,8 @@ close_spidev:
return ret;
}
static void linuxspi_close(PROGRAMMER *pgm) {
static void linuxspi_close(PROGRAMMER *pgm)
{
switch (pgm->exit_reset) {
case EXIT_RESET_ENABLED:
linuxspi_reset_mcu(pgm, true);
@@ -275,21 +263,25 @@ static void linuxspi_close(PROGRAMMER *pgm) {
close(fd_gpiochip);
}
static void linuxspi_disable(const PROGRAMMER* pgm) {
static void linuxspi_disable(PROGRAMMER* pgm)
{
}
static void linuxspi_enable(PROGRAMMER *pgm, const AVRPART *p) {
static void linuxspi_enable(PROGRAMMER* pgm)
{
}
static void linuxspi_display(const PROGRAMMER* pgm, const char* p) {
static void linuxspi_display(PROGRAMMER* pgm, const char* p)
{
}
static int linuxspi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
static int linuxspi_initialize(PROGRAMMER *pgm, AVRPART *p)
{
int tries, ret;
if (p->prog_modes & PM_TPI) {
/* We do not support TPI. This is a dedicated SPI thing */
pmsg_error("programmer " LINUXSPI " does not support TPI\n");
if (p->flags & AVRPART_HAS_TPI) {
/* We do not support tpi. This is a dedicated SPI thing */
avrdude_message(MSG_INFO, "%s: error: Programmer " LINUXSPI " does not support TPI\n", progname);
return -1;
}
@@ -303,21 +295,22 @@ static int linuxspi_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
} while(tries++ < 65);
if (ret)
pmsg_error("AVR device not responding\n");
avrdude_message(MSG_INFO, "%s: error: AVR device not responding\n", progname);
return ret;
}
static int linuxspi_cmd(const PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res)
static int linuxspi_cmd(PROGRAMMER *pgm, const unsigned char *cmd, unsigned char *res)
{
return linuxspi_spi_duplex(pgm, cmd, res, 4);
}
static int linuxspi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
static int linuxspi_program_enable(PROGRAMMER *pgm, AVRPART *p)
{
unsigned char cmd[4], res[4];
if (!p->op[AVR_OP_PGM_ENABLE]) {
pmsg_error("program enable instruction not defined for part %s\n", p->desc);
avrdude_message(MSG_INFO, "%s: error: program enable instruction not defined for part \"%s\"\n", progname, p->desc);
return -1;
}
@@ -335,7 +328,7 @@ static int linuxspi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
* plus two CPU clock cycles. See Table 25-5 on page 240 for definition of
* minimum pulse width on RESET pin, t RST
* 2. Wait for at least 20 ms and then enable serial programming by sending
* the Programming Enable serial instruction to the SDO pin
* the Programming Enable serial instruction to the MOSI pin
* 3. The serial programming instructions will not work if the communication
* is out of synchronization. When in sync, the second byte (0x53) will echo
* back when issuing the third byte of the Programming Enable instruction
@@ -356,11 +349,12 @@ static int linuxspi_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
return 0;
}
static int linuxspi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
static int linuxspi_chip_erase(PROGRAMMER *pgm, AVRPART *p)
{
unsigned char cmd[4], res[4];
if (!p->op[AVR_OP_CHIP_ERASE]) {
pmsg_error("chip erase instruction not defined for part %s\n", p->desc);
avrdude_message(MSG_INFO, "%s: error: chip erase instruction not defined for part \"%s\"\n", progname, p->desc);
return -1;
}
@@ -373,12 +367,12 @@ static int linuxspi_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
return 0;
}
static int linuxspi_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
char *cp, *s, *str = cfg_strdup("linuxspi_parseextitspecs()", sp);
static int linuxspi_parseexitspecs(PROGRAMMER *pgm, char *s)
{
char *cp;
s = str;
while ((cp = strtok(s, ","))) {
s = NULL;
s = 0;
if (!strcmp(cp, "reset")) {
pgm->exit_reset = EXIT_RESET_ENABLED;
continue;
@@ -387,35 +381,14 @@ static int linuxspi_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
pgm->exit_reset = EXIT_RESET_DISABLED;
continue;
}
free(str);
return -1;
}
free(str);
return 0;
}
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) {
void linuxspi_initpgm(PROGRAMMER *pgm)
{
strcpy(pgm->type, LINUXSPI);
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
@@ -437,15 +410,16 @@ void linuxspi_initpgm(PROGRAMMER *pgm) {
pgm->setup = linuxspi_setup;
pgm->teardown = linuxspi_teardown;
pgm->parseexitspecs = linuxspi_parseexitspecs;
pgm->parseextparams = linuxspi_parseextparams;
}
const char linuxspi_desc[] = "SPI using Linux spidev driver";
#else /* !HAVE_LINUXSPI */
void linuxspi_initpgm(PROGRAMMER *pgm) {
pmsg_error("Linux SPI driver not available in this configuration\n");
void linuxspi_initpgm(PROGRAMMER * pgm)
{
avrdude_message(MSG_INFO, "%s: Linux SPI driver not available in this configuration\n",
progname);
}
const char linuxspi_desc[] = "SPI using Linux spidev driver (not available)";

View File

@@ -25,7 +25,7 @@ extern "C" {
#endif
extern const char linuxspi_desc[];
void linuxspi_initpgm(PROGRAMMER *pgm);
void linuxspi_initpgm (PROGRAMMER * pgm);
#ifdef __cplusplus
}

1534
src/main.c

File diff suppressed because it is too large Load Diff

View File

@@ -119,10 +119,7 @@ static int micronucleus_check_connection(pdata_t* pdata)
int result = usb_control_msg(
pdata->usb_handle,
USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
MICRONUCLEUS_CMD_INFO,
0, 0,
(char*)buffer, sizeof(buffer),
MICRONUCLEUS_DEFAULT_TIMEOUT);
MICRONUCLEUS_CMD_INFO, 0, 0, (char*)buffer, sizeof(buffer), MICRONUCLEUS_DEFAULT_TIMEOUT);
return result == sizeof(buffer) ? 0 : -1;
}
else
@@ -131,30 +128,11 @@ static int micronucleus_check_connection(pdata_t* pdata)
int result = usb_control_msg(
pdata->usb_handle,
USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
MICRONUCLEUS_CMD_INFO,
0, 0,
(char*)buffer, sizeof(buffer),
MICRONUCLEUS_DEFAULT_TIMEOUT);
MICRONUCLEUS_CMD_INFO, 0, 0, (char*)buffer, sizeof(buffer), MICRONUCLEUS_DEFAULT_TIMEOUT);
return result == sizeof(buffer) ? 0 : -1;
}
}
static bool micronucleus_is_device_responsive(pdata_t* pdata, struct usb_device* device)
{
pdata->usb_handle = usb_open(device);
if (pdata->usb_handle == NULL)
{
return false;
}
int result = micronucleus_check_connection(pdata);
usb_close(pdata->usb_handle);
pdata->usb_handle = NULL;
return result >= 0;
}
static int micronucleus_reconnect(pdata_t* pdata)
{
struct usb_device* device = usb_device(pdata->usb_handle);
@@ -164,7 +142,7 @@ static int micronucleus_reconnect(pdata_t* pdata)
for (int i = 0; i < 25; i++)
{
pmsg_notice("trying to reconnect ...\n");
avrdude_message(MSG_NOTICE, "%s: Trying to reconnect...\n", progname);
pdata->usb_handle = usb_open(device);
if (pdata->usb_handle != NULL)
@@ -182,18 +160,17 @@ static int micronucleus_get_bootloader_info_v1(pdata_t* pdata)
int result = usb_control_msg(
pdata->usb_handle,
USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
MICRONUCLEUS_CMD_INFO,
0, 0,
(char*)buffer, sizeof(buffer),
MICRONUCLEUS_DEFAULT_TIMEOUT);
MICRONUCLEUS_CMD_INFO, 0, 0, (char*)buffer, sizeof(buffer), MICRONUCLEUS_DEFAULT_TIMEOUT);
if (result < 0)
{
pmsg_warning("unable to get bootloader info block: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: WARNING: Failed to get bootloader info block: %s\n",
progname, usb_strerror());
return result;
}
else if (result < sizeof(buffer))
{
pmsg_warning("received invalid bootloader info block size: %d\n", result);
avrdude_message(MSG_INFO, "%s: WARNING: Received invalid bootloader info block size: %d\n",
progname, result);
return -1;
}
@@ -249,18 +226,17 @@ static int micronucleus_get_bootloader_info_v2(pdata_t* pdata)
int result = usb_control_msg(
pdata->usb_handle,
USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
MICRONUCLEUS_CMD_INFO,
0, 0,
(char*)buffer, sizeof(buffer),
MICRONUCLEUS_DEFAULT_TIMEOUT);
MICRONUCLEUS_CMD_INFO, 0, 0, (char*)buffer, sizeof(buffer), MICRONUCLEUS_DEFAULT_TIMEOUT);
if (result < 0)
{
pmsg_warning("unable to get bootloader info block: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: WARNING: Failed to get bootloader info block: %s\n",
progname, usb_strerror());
return result;
}
else if (result < sizeof(buffer))
{
pmsg_warning("received invalid bootloader info block size: %d\n", result);
avrdude_message(MSG_INFO, "%s: WARNING: Received invalid bootloader info block size: %d\n",
progname, result);
return -1;
}
@@ -298,37 +274,34 @@ static int micronucleus_get_bootloader_info(pdata_t* pdata)
static void micronucleus_dump_device_info(pdata_t* pdata)
{
pmsg_notice("Bootloader version: %d.%d\n", pdata->major_version, pdata->minor_version);
imsg_notice("Available flash size: %u\n", pdata->flash_size);
imsg_notice("Page size: %u\n", pdata->page_size);
imsg_notice("Bootloader start: 0x%04X\n", pdata->bootloader_start);
imsg_notice("Write sleep: %ums\n", pdata->write_sleep);
imsg_notice("Erase sleep: %ums\n", pdata->erase_sleep);
imsg_notice("Signature1: 0x%02X\n", pdata->signature1);
imsg_notice("Signature2: 0x%02X\n", pdata->signature2);
avrdude_message(MSG_NOTICE, "%s: Bootloader version: %d.%d\n", progname, pdata->major_version, pdata->minor_version);
avrdude_message(MSG_NOTICE, "%s: Available flash size: %u\n", progname, pdata->flash_size);
avrdude_message(MSG_NOTICE, "%s: Page size: %u\n", progname, pdata->page_size);
avrdude_message(MSG_NOTICE, "%s: Bootloader start: 0x%04X\n", progname, pdata->bootloader_start);
avrdude_message(MSG_NOTICE, "%s: Write sleep: %ums\n", progname, pdata->write_sleep);
avrdude_message(MSG_NOTICE, "%s: Erase sleep: %ums\n", progname, pdata->erase_sleep);
avrdude_message(MSG_NOTICE, "%s: Signature1: 0x%02X\n", progname, pdata->signature1);
avrdude_message(MSG_NOTICE, "%s: Signature2: 0x%02X\n", progname, pdata->signature2);
}
static int micronucleus_erase_device(pdata_t* pdata)
{
pmsg_debug("micronucleus_erase_device()\n");
avrdude_message(MSG_DEBUG, "%s: micronucleus_erase_device()\n", progname);
int result = usb_control_msg(
pdata->usb_handle,
USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
MICRONUCLEUS_CMD_ERASE,
0, 0,
NULL, 0,
MICRONUCLEUS_DEFAULT_TIMEOUT);
MICRONUCLEUS_CMD_ERASE, 0, 0, NULL, 0, MICRONUCLEUS_DEFAULT_TIMEOUT);
if (result < 0)
{
switch (result)
{
case -EIO:
case -EPIPE:
pmsg_notice("ignoring last error of erase command: %s\n", usb_strerror());
avrdude_message(MSG_NOTICE, "%s: Ignoring last error of erase command: %s\n", progname, usb_strerror());
break;
default:
pmsg_warning("erase command failed, code %d: %s\n", result, usb_strerror());
avrdude_message(MSG_INFO, "%s: WARNING: Failed is issue erase command, code %d: %s\n", progname, result, usb_strerror());
return result;
}
}
@@ -338,12 +311,12 @@ static int micronucleus_erase_device(pdata_t* pdata)
result = micronucleus_check_connection(pdata);
if (result < 0)
{
pmsg_notice("connection dropped, trying to reconnect ...\n");
avrdude_message(MSG_NOTICE, "%s: Connection dropped, trying to reconnect...\n", progname);
result = micronucleus_reconnect(pdata);
if (result < 0)
{
pmsg_warning("unable to reconnect USB device: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: WARNING: Failed to reconnect USB device: %s\n", progname, usb_strerror());
return result;
}
}
@@ -369,7 +342,7 @@ static int micronucleus_patch_reset_vector(pdata_t* pdata, uint8_t* buffer)
}
else
{
pmsg_error("the reset vector of the user program does not contain a branch instruction\n");
avrdude_message(MSG_INFO, "%s: The reset vector of the user program does not contain a branch instruction.\n", progname);
return -1;
}
@@ -418,16 +391,15 @@ static void micronucleus_patch_user_vector(pdata_t* pdata, uint8_t* buffer)
static int micronucleus_write_page_v1(pdata_t* pdata, uint32_t address, uint8_t* buffer, uint32_t size)
{
int result = usb_control_msg(
pdata->usb_handle,
int result = usb_control_msg(pdata->usb_handle,
USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
MICRONUCLEUS_CMD_TRANSFER,
size, address,
(char*)buffer, size,
buffer, size,
MICRONUCLEUS_DEFAULT_TIMEOUT);
if (result < 0)
{
pmsg_error("unable to transfer page: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: Failed to transfer page: %s\n", progname, usb_strerror());
return result;
}
@@ -445,7 +417,7 @@ static int micronucleus_write_page_v2(pdata_t* pdata, uint32_t address, uint8_t*
MICRONUCLEUS_DEFAULT_TIMEOUT);
if (result < 0)
{
pmsg_error("unable to transfer page: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: Failed to transfer page: %s\n", progname, usb_strerror());
return result;
}
@@ -462,7 +434,7 @@ static int micronucleus_write_page_v2(pdata_t* pdata, uint32_t address, uint8_t*
MICRONUCLEUS_DEFAULT_TIMEOUT);
if (result < 0)
{
pmsg_error("unable to transfer page: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: Failed to transfer page: %s\n", progname, usb_strerror());
return result;
}
}
@@ -472,7 +444,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)
{
pmsg_debug("micronucleus_write_page(address=0x%04X, size=%d)\n", address, size);
avrdude_message(MSG_DEBUG, "%s: micronucleus_write_page(address=0x%04X, size=%d)\n", progname, address, size);
if (address == 0)
{
@@ -524,18 +496,15 @@ static int micronucleus_write_page(pdata_t* pdata, uint32_t address, uint8_t* bu
static int micronucleus_start(pdata_t* pdata)
{
pmsg_debug("micronucleus_start()\n");
avrdude_message(MSG_DEBUG, "%s: micronucleus_start()\n", progname);
int result = usb_control_msg(
pdata->usb_handle,
USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
MICRONUCLEUS_CMD_START,
0, 0,
NULL, 0,
MICRONUCLEUS_DEFAULT_TIMEOUT);
MICRONUCLEUS_CMD_START, 0, 0, NULL, 0, MICRONUCLEUS_DEFAULT_TIMEOUT);
if (result < 0)
{
pmsg_warning("start command failed: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: WARNING: Failed is issue start command: %s\n", progname, usb_strerror());
return result;
}
@@ -546,11 +515,11 @@ static int micronucleus_start(pdata_t* pdata)
static void micronucleus_setup(PROGRAMMER* pgm)
{
pmsg_debug("micronucleus_setup()\n");
avrdude_message(MSG_DEBUG, "%s: micronucleus_setup()\n", progname);
if ((pgm->cookie = malloc(sizeof(pdata_t))) == 0)
{
pmsg_error("out of memory allocating private data\n");
avrdude_message(MSG_INFO, "%s: micronucleus_setup(): Out of memory allocating private data\n", progname);
exit(1);
}
@@ -559,12 +528,13 @@ static void micronucleus_setup(PROGRAMMER* pgm)
static void micronucleus_teardown(PROGRAMMER* pgm)
{
pmsg_debug("micronucleus_teardown()\n");
avrdude_message(MSG_DEBUG, "%s: micronucleus_teardown()\n", progname);
free(pgm->cookie);
}
static int micronucleus_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
pmsg_debug("micronucleus_initialize()\n");
static int micronucleus_initialize(PROGRAMMER* pgm, AVRPART* p)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_initialize()\n", progname);
pdata_t* pdata = PDATA(pgm);
@@ -577,16 +547,19 @@ static int micronucleus_initialize(const PROGRAMMER *pgm, const AVRPART *p) {
return 0;
}
static void micronucleus_display(const PROGRAMMER *pgm, const char *prefix) {
pmsg_debug("micronucleus_display()\n");
static void micronucleus_display(PROGRAMMER* pgm, const char* prefix)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_display()\n", progname);
}
static void micronucleus_powerup(const PROGRAMMER *pgm) {
pmsg_debug("micronucleus_powerup()\n");
static void micronucleus_powerup(PROGRAMMER* pgm)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_powerup()\n", progname);
}
static void micronucleus_powerdown(const PROGRAMMER *pgm) {
pmsg_debug("micronucleus_powerdown()\n");
static void micronucleus_powerdown(PROGRAMMER* pgm)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_powerdown()\n", progname);
pdata_t* pdata = PDATA(pgm);
if (pdata->write_last_page)
@@ -610,25 +583,29 @@ static void micronucleus_powerdown(const PROGRAMMER *pgm) {
}
}
static void micronucleus_enable(PROGRAMMER *pgm, const AVRPART *p) {
pmsg_debug("micronucleus_enable()\n");
static void micronucleus_enable(PROGRAMMER* pgm)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_enable()\n", progname);
}
static void micronucleus_disable(const PROGRAMMER *pgm) {
pmsg_debug("micronucleus_disable()\n");
static void micronucleus_disable(PROGRAMMER* pgm)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_disable()\n", progname);
}
static int micronucleus_program_enable(const PROGRAMMER *pgm, const AVRPART *p) {
pmsg_debug("micronucleus_program_enable()\n");
static int micronucleus_program_enable(PROGRAMMER* pgm, AVRPART* p)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_program_enable()\n", progname);
return 0;
}
static int micronucleus_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem) {
pmsg_debug("micronucleus_read_sig_bytes()\n");
static int micronucleus_read_sig_bytes(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_read_sig_bytes()\n", progname);
if (mem->size < 3)
{
pmsg_error("memory size %d < 3 too small for read_sig_bytes", mem->size);
avrdude_message(MSG_INFO, "%s: memory size too small for read_sig_bytes", progname);
return -1;
}
@@ -639,18 +616,20 @@ static int micronucleus_read_sig_bytes(const PROGRAMMER *pgm, const AVRPART *p,
return 0;
}
static int micronucleus_chip_erase(const PROGRAMMER *pgm, const AVRPART *p) {
pmsg_debug("micronucleus_chip_erase()\n");
static int micronucleus_chip_erase(PROGRAMMER* pgm, AVRPART* p)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_chip_erase()\n", progname);
pdata_t* pdata = PDATA(pgm);
return micronucleus_erase_device(pdata);
}
static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
pmsg_debug("micronucleus_open(\"%s\")\n", port);
static int micronucleus_open(PROGRAMMER* pgm, char* port)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_open(\"%s\")\n", progname, port);
pdata_t* pdata = PDATA(pgm);
const char *bus_name = NULL;
char* bus_name = NULL;
char* dev_name = NULL;
// if no -P was given or '-P usb' was given
@@ -675,8 +654,8 @@ static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
if (port != NULL && dev_name == NULL)
{
pmsg_error("invalid -P value %s\n", port);
imsg_error("use -P usb:bus:device\n");
avrdude_message(MSG_INFO, "%s: ERROR: Invalid -P value: '%s'\n", progname, port);
avrdude_message(MSG_INFO, "%sUse -P usb:bus:device\n", progbuf);
return -1;
}
@@ -690,14 +669,14 @@ static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
pid = *(int*)(ldata(usbpid));
if (lnext(usbpid))
{
pmsg_warning("using PID 0x%04x, ignoring remaining PIDs in list\n", pid);
avrdude_message(MSG_INFO, "%s: WARNING: using PID 0x%04x, ignoring remaining PIDs in list\n",
progname, pid);
}
}
usb_init();
bool show_retry_message = true;
bool show_unresponsive_device_message = true;
time_t start_time = time(NULL);
for (;;)
@@ -719,19 +698,8 @@ static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
pdata->major_version = (uint8_t)(device->descriptor.bcdDevice >> 8);
pdata->minor_version = (uint8_t)(device->descriptor.bcdDevice >> 0);
if (!micronucleus_is_device_responsive(pdata, device))
{
if (show_unresponsive_device_message)
{
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",
avrdude_message(MSG_NOTICE, "%s: Found device with Micronucleus V%d.%d, bus:device: %s:%s\n",
progname,
pdata->major_version, pdata->minor_version,
bus->dirname, device->filename);
@@ -746,7 +714,8 @@ static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
if (pdata->major_version > MICRONUCLEUS_MAX_MAJOR_VERSION)
{
pmsg_warning("device with unsupported Micronucleus version V%d.%d\n",
avrdude_message(MSG_INFO, "%s: WARNING: device with unsupported version (V%d.%d) of Micronucleus detected.\n",
progname,
pdata->major_version, pdata->minor_version);
continue;
}
@@ -754,7 +723,7 @@ static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
pdata->usb_handle = usb_open(device);
if (pdata->usb_handle == NULL)
{
pmsg_error("unable to open USB device: %s\n", usb_strerror());
avrdude_message(MSG_INFO, "%s: ERROR: Failed to open USB device: %s\n", progname, usb_strerror());
}
}
}
@@ -766,15 +735,16 @@ static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
{
if (pdata->wait_timout < 0)
{
pmsg_error("no device found, waiting for device to be plugged in ...\n");
avrdude_message(MSG_INFO, "%s: No device found, waiting for device to be plugged in...\n", progname);
}
else
{
pmsg_error("no device found, waiting %d seconds for device to be plugged in ...\n",
avrdude_message(MSG_INFO, "%s: No device found, waiting %d seconds for device to be plugged in...\n",
progname,
pdata->wait_timout);
}
pmsg_error("press CTRL-C to terminate\n");
avrdude_message(MSG_INFO, "%s: Press CTRL-C to terminate.\n", progname);
show_retry_message = false;
}
@@ -790,7 +760,8 @@ static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
if (!pdata->usb_handle)
{
pmsg_error("cannot find device with Micronucleus bootloader (%04X:%04X)\n", vid, pid);
avrdude_message(MSG_INFO, "%s: ERROR: Could not find device with Micronucleus bootloader (%04X:%04X)\n",
progname, vid, pid);
return -1;
}
@@ -799,7 +770,7 @@ static int micronucleus_open(PROGRAMMER* pgm, const char *port) {
static void micronucleus_close(PROGRAMMER* pgm)
{
pmsg_debug("micronucleus_close()\n");
avrdude_message(MSG_DEBUG, "%s: micronucleus_close()\n", progname);
pdata_t* pdata = PDATA(pgm);
if (pdata->usb_handle != NULL)
@@ -809,10 +780,11 @@ static void micronucleus_close(PROGRAMMER* pgm)
}
}
static int micronucleus_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
static int micronucleus_read_byte(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
unsigned long addr, unsigned char* value)
{
pmsg_debug("micronucleus_read_byte(desc=%s, addr=0x%04lX)\n", mem->desc, addr);
avrdude_message(MSG_DEBUG, "%s: micronucleus_read_byte(desc=%s, addr=0x%0X)\n",
progname, mem->desc, addr);
if (strcmp(mem->desc, "lfuse") == 0 ||
strcmp(mem->desc, "hfuse") == 0 ||
@@ -824,31 +796,34 @@ static int micronucleus_read_byte(const PROGRAMMER *pgm, const AVRPART *p, const
}
else
{
pmsg_notice("reading not supported for %s memory\n", mem->desc);
avrdude_message(MSG_INFO, "%s: Unsupported memory type: %s\n", progname, mem->desc);
return -1;
}
}
static int micronucleus_write_byte(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
static int micronucleus_write_byte(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
unsigned long addr, unsigned char value)
{
pmsg_debug("micronucleus_write_byte(desc=%s, addr=0x%04lX)\n", mem->desc, addr);
avrdude_message(MSG_DEBUG, "%s: micronucleus_write_byte(desc=%s, addr=0x%0X)\n",
progname, mem->desc, addr);
return -1;
}
static int micronucleus_paged_load(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
static int micronucleus_paged_load(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
unsigned int page_size,
unsigned int addr, unsigned int n_bytes)
{
pmsg_debug("micronucleus_paged_load(page_size=0x%X, addr=0x%X, n_bytes=0x%X)\n", page_size, addr, n_bytes);
avrdude_message(MSG_DEBUG, "%s: micronucleus_paged_load(page_size=0x%X, addr=0x%X, n_bytes=0x%X)\n",
progname, page_size, addr, n_bytes);
return -1;
}
static int micronucleus_paged_write(const PROGRAMMER *pgm, const AVRPART *p, const AVRMEM *mem,
static int micronucleus_paged_write(PROGRAMMER* pgm, AVRPART* p, AVRMEM* mem,
unsigned int page_size,
unsigned int addr, unsigned int n_bytes)
{
pmsg_debug("micronucleus_paged_write(page_size=0x%X, addr=0x%X, n_bytes=0x%X)\n", page_size, addr, n_bytes);
avrdude_message(MSG_DEBUG, "%s: micronucleus_paged_write(page_size=0x%X, addr=0x%X, n_bytes=0x%X)\n",
progname, page_size, addr, n_bytes);
if (strcmp(mem->desc, "flash") == 0)
{
@@ -856,20 +831,20 @@ static int micronucleus_paged_write(const PROGRAMMER *pgm, const AVRPART *p, con
if (n_bytes > page_size)
{
pmsg_error("buffer size %u exceeds page size %u\n", n_bytes, page_size);
avrdude_message(MSG_INFO, "%s: Buffer size (%u) exceeds page size (%u)\n", progname, n_bytes, page_size);
return -1;
}
if (addr + n_bytes > pdata->flash_size)
{
pmsg_error("program size %u exceeds flash size %u\n", 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);
return -1;
}
uint8_t* page_buffer = (uint8_t*)malloc(pdata->page_size);
if (page_buffer == NULL)
{
pmsg_error("unable to allocate memory\n");
avrdude_message(MSG_INFO, "%s: Failed to allocate memory\n", progname);
return -1;
}
@@ -897,13 +872,14 @@ static int micronucleus_paged_write(const PROGRAMMER *pgm, const AVRPART *p, con
}
else
{
pmsg_error("unsupported memory type: %s\n", mem->desc);
avrdude_message(MSG_INFO, "%s: Unsupported memory type: %s\n", progname, mem->desc);
return -1;
}
}
static int micronucleus_parseextparams(const PROGRAMMER *pgm, const LISTID xparams) {
pmsg_debug("micronucleus_parseextparams()\n");
static int micronucleus_parseextparams(PROGRAMMER* pgm, LISTID xparams)
{
avrdude_message(MSG_DEBUG, "%s: micronucleus_parseextparams()\n", progname);
pdata_t* pdata = PDATA(pgm);
for (LNODEID node = lfirst(xparams); node != NULL; node = lnext(node))
@@ -922,7 +898,7 @@ static int micronucleus_parseextparams(const PROGRAMMER *pgm, const LISTID xpara
}
else
{
pmsg_error("invalid extended parameter '%s'\n", param);
avrdude_message(MSG_INFO, "%s: Invalid extended parameter '%s'\n", progname, param);
return -1;
}
}
@@ -930,7 +906,8 @@ static int micronucleus_parseextparams(const PROGRAMMER *pgm, const LISTID xpara
return 0;
}
void micronucleus_initpgm(PROGRAMMER *pgm) {
void micronucleus_initpgm(PROGRAMMER* pgm)
{
strcpy(pgm->type, "Micronucleus V2.0");
pgm->setup = micronucleus_setup;
@@ -957,12 +934,14 @@ void micronucleus_initpgm(PROGRAMMER *pgm) {
#else /* !HAVE_LIBUSB */
// Give a proper error if we were not compiled with libusb
static int micronucleus_nousb_open(PROGRAMMER* pgm, const char* name) {
pmsg_error("no usb support; please compile again with libusb installed\n");
static int micronucleus_nousb_open(struct programmer_t* pgm, char* name)
{
avrdude_message(MSG_INFO, "%s: error: No usb support. Please compile again with libusb installed.\n", progname);
return -1;
}
void micronucleus_initpgm(PROGRAMMER *pgm) {
void micronucleus_initpgm(PROGRAMMER* pgm)
{
strcpy(pgm->type, "micronucleus");
pgm->open = micronucleus_nousb_open;
}

View File

@@ -26,7 +26,7 @@ extern "C" {
#endif
extern const char micronucleus_desc[];
void micronucleus_initpgm(PROGRAMMER *pgm);
void micronucleus_initpgm(PROGRAMMER* pgm);
#ifdef __cplusplus
}

View File

@@ -1,563 +0,0 @@
/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */
/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
/*
* Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Dieter Baron and Thomas Klausner.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#define WIN32_LEAN_AND_MEAN
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <stdarg.h>
#include <stdio.h>
#include <windows.h>
#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
#ifdef REPLACE_GETOPT
int opterr = 1; /* if error message should be printed */
int optind = 1; /* index into parent argv vector */
int optopt = '?'; /* character checked for validity */
#undef optreset /* see getopt.h */
#define optreset __mingw_optreset
int optreset; /* reset getopt */
char *optarg; /* argument associated with option */
#endif
#define PRINT_ERROR ((opterr) && (*options != ':'))
#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
/* return values */
#define BADCH (int)'?'
#define BADARG ((*options == ':') ? (int)':' : (int)'?')
#define INORDER (int)1
#ifndef __CYGWIN__
#define __progname __argv[0]
#else
extern char __declspec(dllimport) *__progname;
#endif
#ifdef __CYGWIN__
static char EMSG[] = "";
#else
#define EMSG ""
#endif
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
const struct option *, int *, int);
static int gcd(int, int);
static void permute_args(int, int, int, char * const *);
static char *place = EMSG; /* option letter processing */
/* XXX: set optreset to 1 rather than these two */
static int nonopt_start = -1; /* first non option argument (for permute) */
static int nonopt_end = -1; /* first option after non options (for permute) */
/* Error messages */
static const char recargchar[] = "option requires an argument -- %c";
static const char recargstring[] = "option requires an argument -- %s";
static const char ambig[] = "ambiguous option -- %.*s";
static const char noarg[] = "option doesn't take an argument -- %.*s";
static const char illoptchar[] = "unknown option -- %c";
static const char illoptstring[] = "unknown option -- %s";
static void
_vwarnx(const char *fmt,va_list ap)
{
(void)fprintf(stderr,"%s: ",__progname);
if (fmt != NULL)
(void)vfprintf(stderr,fmt,ap);
(void)fprintf(stderr,"\n");
}
static void
warnx(const char *fmt,...)
{
va_list ap;
va_start(ap,fmt);
_vwarnx(fmt,ap);
va_end(ap);
}
/*
* Compute the greatest common divisor of a and b.
*/
static int
gcd(int a, int b)
{
int c;
c = a % b;
while (c != 0) {
a = b;
b = c;
c = a % b;
}
return (b);
}
/*
* Exchange the block from nonopt_start to nonopt_end with the block
* from nonopt_end to opt_end (keeping the same order of arguments
* in each block).
*/
static void
permute_args(int panonopt_start, int panonopt_end, int opt_end,
char * const *nargv)
{
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
char *swap;
/*
* compute lengths of blocks and number and size of cycles
*/
nnonopts = panonopt_end - panonopt_start;
nopts = opt_end - panonopt_end;
ncycle = gcd(nnonopts, nopts);
cyclelen = (opt_end - panonopt_start) / ncycle;
for (i = 0; i < ncycle; i++) {
cstart = panonopt_end+i;
pos = cstart;
for (j = 0; j < cyclelen; j++) {
if (pos >= panonopt_end)
pos -= nnonopts;
else
pos += nopts;
swap = nargv[pos];
/* LINTED const cast */
((char **) nargv)[pos] = nargv[cstart];
/* LINTED const cast */
((char **)nargv)[cstart] = swap;
}
}
}
/*
* parse_long_options --
* Parse long options in argc/argv argument vector.
* Returns -1 if short_too is set and the option does not match long_options.
*/
static int
parse_long_options(char * const *nargv, const char *options,
const struct option *long_options, int *idx, int short_too)
{
char *current_argv, *has_equal;
size_t current_argv_len;
int i, ambiguous, match;
#define IDENTICAL_INTERPRETATION(_x, _y) \
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
long_options[(_x)].flag == long_options[(_y)].flag && \
long_options[(_x)].val == long_options[(_y)].val)
current_argv = place;
match = -1;
ambiguous = 0;
optind++;
if ((has_equal = strchr(current_argv, '=')) != NULL) {
/* argument found (--option=arg) */
current_argv_len = has_equal - current_argv;
has_equal++;
} else
current_argv_len = strlen(current_argv);
for (i = 0; long_options[i].name; i++) {
/* find matching long option */
if (strncmp(current_argv, long_options[i].name,
current_argv_len))
continue;
if (strlen(long_options[i].name) == current_argv_len) {
/* exact match */
match = i;
ambiguous = 0;
break;
}
/*
* If this is a known short option, don't allow
* a partial match of a single character.
*/
if (short_too && current_argv_len == 1)
continue;
if (match == -1) /* partial match */
match = i;
else if (!IDENTICAL_INTERPRETATION(i, match))
ambiguous = 1;
}
if (ambiguous) {
/* ambiguous abbreviation */
if (PRINT_ERROR)
warnx(ambig, (int)current_argv_len,
current_argv);
optopt = 0;
return (BADCH);
}
if (match != -1) { /* option found */
if (long_options[match].has_arg == no_argument
&& has_equal) {
if (PRINT_ERROR)
warnx(noarg, (int)current_argv_len,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
return (BADARG);
}
if (long_options[match].has_arg == required_argument ||
long_options[match].has_arg == optional_argument) {
if (has_equal)
optarg = has_equal;
else if (long_options[match].has_arg ==
required_argument) {
/*
* optional argument doesn't use next nargv
*/
optarg = nargv[optind++];
}
}
if ((long_options[match].has_arg == required_argument)
&& (optarg == NULL)) {
/*
* Missing argument; leading ':' indicates no error
* should be generated.
*/
if (PRINT_ERROR)
warnx(recargstring,
current_argv);
/*
* XXX: GNU sets optopt to val regardless of flag
*/
if (long_options[match].flag == NULL)
optopt = long_options[match].val;
else
optopt = 0;
--optind;
return (BADARG);
}
} else { /* unknown option */
if (short_too) {
--optind;
return (-1);
}
if (PRINT_ERROR)
warnx(illoptstring, current_argv);
optopt = 0;
return (BADCH);
}
if (idx)
*idx = match;
if (long_options[match].flag) {
*long_options[match].flag = long_options[match].val;
return (0);
} else
return (long_options[match].val);
#undef IDENTICAL_INTERPRETATION
}
/*
* getopt_internal --
* Parse argc/argv argument vector. Called by user level routines.
*/
static int
getopt_internal(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx, int flags)
{
char *oli; /* option letter list index */
int optchar, short_too;
static int posixly_correct = -1;
if (options == NULL)
return (-1);
/*
* XXX Some GNU programs (like cvs) set optind to 0 instead of
* XXX using optreset. Work around this braindamage.
*/
if (optind == 0)
optind = optreset = 1;
/*
* Disable GNU extensions if POSIXLY_CORRECT is set or options
* string begins with a '+'.
*
* CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or
* optreset != 0 for GNU compatibility.
*/
if (posixly_correct == -1 || optreset != 0)
posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
if (*options == '-')
flags |= FLAG_ALLARGS;
else if (posixly_correct || *options == '+')
flags &= ~FLAG_PERMUTE;
if (*options == '+' || *options == '-')
options++;
optarg = NULL;
if (optreset)
nonopt_start = nonopt_end = -1;
start:
if (optreset || !*place) { /* update scanning pointer */
optreset = 0;
if (optind >= nargc) { /* end of argument vector */
place = EMSG;
if (nonopt_end != -1) {
/* do permutation, if we have to */
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
else if (nonopt_start != -1) {
/*
* If we skipped non-options, set optind
* to the first of them.
*/
optind = nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
if (*(place = nargv[optind]) != '-' ||
(place[1] == '\0' && strchr(options, '-') == NULL)) {
place = EMSG; /* found non-option */
if (flags & FLAG_ALLARGS) {
/*
* GNU extension:
* return non-option as argument to option 1
*/
optarg = nargv[optind++];
return (INORDER);
}
if (!(flags & FLAG_PERMUTE)) {
/*
* If no permutation wanted, stop parsing
* at first non-option.
*/
return (-1);
}
/* do permutation */
if (nonopt_start == -1)
nonopt_start = optind;
else if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
nonopt_start = optind -
(nonopt_end - nonopt_start);
nonopt_end = -1;
}
optind++;
/* process next argument */
goto start;
}
if (nonopt_start != -1 && nonopt_end == -1)
nonopt_end = optind;
/*
* If we have "-" do nothing, if "--" we are done.
*/
if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
optind++;
place = EMSG;
/*
* We found an option (--), so if we skipped
* non-options, we have to permute.
*/
if (nonopt_end != -1) {
permute_args(nonopt_start, nonopt_end,
optind, nargv);
optind -= nonopt_end - nonopt_start;
}
nonopt_start = nonopt_end = -1;
return (-1);
}
}
/*
* Check long options if:
* 1) we were passed some
* 2) the arg is not just "-"
* 3) either the arg starts with -- we are getopt_long_only()
*/
if (long_options != NULL && place != nargv[optind] &&
(*place == '-' || (flags & FLAG_LONGONLY))) {
short_too = 0;
if (*place == '-')
place++; /* --foo long option */
else if (*place != ':' && strchr(options, *place) != NULL)
short_too = 1; /* could be short option too */
optchar = parse_long_options(nargv, options, long_options,
idx, short_too);
if (optchar != -1) {
place = EMSG;
return (optchar);
}
}
if ((optchar = (int)*place++) == (int)':' ||
(optchar == (int)'-' && *place != '\0') ||
(oli = strchr(options, optchar)) == NULL) {
/*
* If the user specified "-" and '-' isn't listed in
* options, return -1 (non-option) as per POSIX.
* Otherwise, it is an unknown option character (or ':').
*/
if (optchar == (int)'-' && *place == '\0')
return (-1);
if (!*place)
++optind;
if (PRINT_ERROR)
warnx(illoptchar, optchar);
optopt = optchar;
return (BADCH);
}
if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
/* -W long-option */
if (*place) /* no space */
/* NOTHING */;
else if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else /* white space */
place = nargv[optind];
optchar = parse_long_options(nargv, options, long_options,
idx, 0);
place = EMSG;
return (optchar);
}
if (*++oli != ':') { /* doesn't take argument */
if (!*place)
++optind;
} else { /* takes (optional) argument */
optarg = NULL;
if (*place) /* no white space */
optarg = place;
else if (oli[1] != ':') { /* arg not optional */
if (++optind >= nargc) { /* no arg */
place = EMSG;
if (PRINT_ERROR)
warnx(recargchar, optchar);
optopt = optchar;
return (BADARG);
} else
optarg = nargv[optind];
}
place = EMSG;
++optind;
}
/* dump back option letter */
return (optchar);
}
#ifdef REPLACE_GETOPT
/*
* getopt --
* Parse argc/argv argument vector.
*
* [eventually this will replace the BSD getopt]
*/
int
getopt(int nargc, char * const *nargv, const char *options)
{
/*
* We don't pass FLAG_PERMUTE to getopt_internal() since
* the BSD getopt(3) (unlike GNU) has never done this.
*
* Furthermore, since many privileged programs call getopt()
* before dropping privileges it makes sense to keep things
* as simple (and bug-free) as possible.
*/
return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
}
#endif /* REPLACE_GETOPT */
/*
* getopt_long --
* Parse argc/argv argument vector.
*/
int
getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE));
}
/*
* getopt_long_only --
* Parse argc/argv argument vector.
*/
int
getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx)
{
return (getopt_internal(nargc, nargv, options, long_options, idx,
FLAG_PERMUTE|FLAG_LONGONLY));
}

View File

@@ -1,95 +0,0 @@
#ifndef __GETOPT_H__
/**
* DISCLAIMER
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
*
* The mingw-w64 runtime package and its code is distributed in the hope that it
* will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR
* IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to
* warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#define __GETOPT_H__
/* All the headers include this file. */
#include <crtdefs.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int optind; /* index of first non-option in argv */
extern int optopt; /* single option character, as parsed */
extern int opterr; /* flag to enable built-in diagnostics... */
/* (user may set to zero, to suppress) */
extern char *optarg; /* pointer to argument of current option */
extern int getopt(int nargc, char * const *nargv, const char *options);
#ifdef _BSD_SOURCE
/*
* BSD adds the non-standard `optreset' feature, for reinitialisation
* of `getopt' parsing. We support this feature, for applications which
* proclaim their BSD heritage, before including this header; however,
* to maintain portability, developers are advised to avoid it.
*/
# define optreset __mingw_optreset
extern int optreset;
#endif
#ifdef __cplusplus
}
#endif
/*
* POSIX requires the `getopt' API to be specified in `unistd.h';
* thus, `unistd.h' includes this header. However, we do not want
* to expose the `getopt_long' or `getopt_long_only' APIs, when
* included in this manner. Thus, close the standard __GETOPT_H__
* declarations block, and open an additional __GETOPT_LONG_H__
* specific block, only when *not* __UNISTD_H_SOURCED__, in which
* to declare the extended API.
*/
#endif /* !defined(__GETOPT_H__) */
#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__)
#define __GETOPT_LONG_H__
#ifdef __cplusplus
extern "C" {
#endif
struct option /* specification for a long form option... */
{
const char *name; /* option name, without leading hyphens */
int has_arg; /* does it take an argument? */
int *flag; /* where to save its status, or NULL */
int val; /* its associated status value */
};
enum /* permitted values for its `has_arg' field... */
{
no_argument = 0, /* option never takes an argument */
required_argument, /* option always requires an argument */
optional_argument /* option may take an argument */
};
extern int getopt_long(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx);
extern int getopt_long_only(int nargc, char * const *nargv, const char *options,
const struct option *long_options, int *idx);
/*
* Previous MinGW implementation had...
*/
#ifndef HAVE_DECL_GETOPT
/*
* ...for the long form API only; keep this for compatibility.
*/
# define HAVE_DECL_GETOPT 1
#endif
#ifdef __cplusplus
}
#endif
#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */

View File

@@ -1,77 +0,0 @@
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the mingw-w64 runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#define WIN32_LEAN_AND_MEAN
#include <time.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <errno.h>
#include <windows.h>
#define FILETIME_1970 116444736000000000ull /* seconds between 1/1/1601 and 1/1/1970 */
#define HECTONANOSEC_PER_SEC 10000000ull
int getntptimeofday(struct timespec *, struct timezone *);
int getntptimeofday(struct timespec *tp, struct timezone *z)
{
int res = 0;
union
{
unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */
FILETIME ft;
} _now;
TIME_ZONE_INFORMATION TimeZoneInformation;
DWORD tzi;
if (z != NULL)
{
if ((tzi = GetTimeZoneInformation(&TimeZoneInformation)) != TIME_ZONE_ID_INVALID)
{
z->tz_minuteswest = TimeZoneInformation.Bias;
if (tzi == TIME_ZONE_ID_DAYLIGHT)
z->tz_dsttime = 1;
else
z->tz_dsttime = 0;
}
else
{
z->tz_minuteswest = 0;
z->tz_dsttime = 0;
}
}
if (tp != NULL)
{
GetSystemTimeAsFileTime(&_now.ft); /* 100-nanoseconds since 1-1-1601 */
/* The actual accuracy on XP seems to be 125,000 nanoseconds = 125 microseconds = 0.125 milliseconds */
_now.ns100 -= FILETIME_1970; /* 100 nano-seconds since 1-1-1970 */
tp->tv_sec = _now.ns100 / HECTONANOSEC_PER_SEC; /* seconds since 1-1-1970 */
tp->tv_nsec = (long)(_now.ns100 % HECTONANOSEC_PER_SEC) * 100; /* nanoseconds */
}
return res;
}
int __cdecl gettimeofday(struct timeval *p, void *z)
{
struct timespec tp;
if (getntptimeofday(&tp, (struct timezone *) z))
return -1;
p->tv_sec = (long)tp.tv_sec;
p->tv_usec = (tp.tv_nsec / 1000);
return 0;
}
int __cdecl mingw_gettimeofday(struct timeval *p, struct timezone *z)
{
struct timespec tp;
if (getntptimeofday(&tp, z))
return -1;
p->tv_sec = (long)tp.tv_sec;
p->tv_usec = (tp.tv_nsec / 1000);
return 0;
}

View File

@@ -1,63 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2018 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/>.
*/
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <io.h>
#include <malloc.h>
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "hid.lib")
#pragma comment(lib, "ws2_32.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 PATH_MAX _MAX_PATH
#define setvbuf msvc_setvbuf
static inline int msvc_setvbuf(
FILE* const public_stream,
char* const buffer,
int const type,
size_t const buffer_size_in_bytes
)
{
// Just ignore calls to setvbuf with invalid buffer size.
// Purpose of setvbuf calls unknown, probably in an attempt to fix broken
// programs that capture stdout and stderr using separate stream handles?
return 0;
}
static inline int strcasecmp(const char* s1, const char* s2)
{
return _stricmp(s1, s2);
}
static inline int strncasecmp(const char* s1, const char* s2, size_t n)
{
return _strnicmp(s1, s2, n);
}

View File

@@ -1,95 +0,0 @@
//
// 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*)
{
}

View File

@@ -1,17 +0,0 @@
//
// 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

View File

@@ -1,24 +0,0 @@
//
// 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

View File

@@ -1,43 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2018 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/>.
*/
#ifndef _TIME_H_
#define _TIME_H_
// If you need both <windows.h> and <sys/time.h>,
// make sure you include <windows.h> first.
#ifndef _WINSOCKAPI_
#ifndef _TIMEVAL_DEFINED
#define _TIMEVAL_DEFINED
struct timeval
{
long tv_sec;
long tv_usec;
};
#endif /* _TIMEVAL_DEFINED */
#endif /* _WINSOCKAPI_ */
struct timezone
{
int tz_minuteswest;
int tz_dsttime;
};
int __cdecl gettimeofday(struct timeval* p, void* z);
#endif

View File

@@ -1,38 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2018 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/>.
*/
#ifndef _UNISTD_H
#define _UNISTD_H
#define STDIN_FILENO _fileno(stdin)
#define STDERR_FILENO _fileno(stderr)
#include <getopt.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned int useconds_t;
int usleep(unsigned int us);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -1,93 +0,0 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2018 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/>.
*/
#include "unistd.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
class MicroSleep
{
public:
MicroSleep()
{
if (::timeBeginPeriod(timerPeriod) == TIMERR_NOERROR)
{
m_resetTimerPeriod = true;
}
}
~MicroSleep()
{
if (m_resetTimerPeriod)
{
::timeEndPeriod(timerPeriod);
}
}
int Sleep(DWORD us)
{
if (us == 0)
{
return 0;
}
LARGE_INTEGER frequency{};
if (QueryPerformanceFrequency(&frequency))
{
LARGE_INTEGER start{};
QueryPerformanceCounter(&start);
if (us > 10000)
{
::Sleep((us - 5000) / 1000);
}
LARGE_INTEGER end{};
end.QuadPart = start.QuadPart + (frequency.QuadPart * us / 1000000);
while (true)
{
LARGE_INTEGER current;
QueryPerformanceCounter(&current);
if (current.QuadPart >= end.QuadPart)
{
break;
}
}
}
else
{
::Sleep((us / 1000) + 1);
}
return 0;
}
private:
static const UINT timerPeriod = 1; // 1ms
bool m_resetTimerPeriod = false;
};
int usleep(unsigned int us)
{
static MicroSleep microSleep;
return microSleep.Sleep(us);
}

48
src/my_ddk_hidsdi.h Normal file
View File

@@ -0,0 +1,48 @@
/*
* avrdude - A Downloader/Uploader for AVR device programmers
* Copyright (C) 2006 Christian Starkjohann
*
* 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$ */
/*
The following is a replacement for hidsdi.h from the Windows DDK. It defines some
of the types and function prototypes of this header for our project. If you
have the Windows DDK version of this file or a version shipped with MinGW, use
that instead.
*/
#ifndef MY_DDK_HIDSDI_H
#define MY_DDK_HIDSDI_H
#include <pshpack4.h>
#include <ddk/hidusage.h>
#include <ddk/hidpi.h>
typedef struct{
ULONG Size;
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
}HIDD_ATTRIBUTES;
void __stdcall HidD_GetHidGuid(OUT LPGUID hidGuid);
BOOLEAN __stdcall HidD_GetAttributes(IN HANDLE device, OUT HIDD_ATTRIBUTES *attributes);
BOOLEAN __stdcall HidD_GetManufacturerString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
BOOLEAN __stdcall HidD_GetProductString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
BOOLEAN __stdcall HidD_GetSerialNumberString(IN HANDLE device, OUT void *buffer, IN ULONG bufferLen);
BOOLEAN __stdcall HidD_GetFeature(IN HANDLE device, OUT void *reportBuffer, IN ULONG bufferLen);
BOOLEAN __stdcall HidD_SetFeature(IN HANDLE device, IN void *reportBuffer, IN ULONG bufferLen);
BOOLEAN __stdcall HidD_GetNumInputBuffers(IN HANDLE device, OUT ULONG *numBuffers);
BOOLEAN __stdcall HidD_SetNumInputBuffers(IN HANDLE device, OUT ULONG numBuffers);
#include <poppack.h>
#endif /* MY_DDK_HIDSDI_H */

113
src/par.c
View File

@@ -73,7 +73,8 @@ static struct ppipins_t ppipins[] = {
#define NPINS (sizeof(ppipins)/sizeof(struct ppipins_t))
static int par_setpin_internal(const PROGRAMMER *pgm, int pin, int value) {
static int par_setpin_internal(PROGRAMMER * pgm, int pin, int value)
{
int inverted;
inverted = pin & PIN_INVERSE;
@@ -101,20 +102,15 @@ static int par_setpin_internal(const PROGRAMMER *pgm, int pin, int value) {
return 0;
}
static int par_setpin(const PROGRAMMER * pgm, int pinfunc, int value) {
if(pinfunc < 0 || pinfunc >= N_PINS)
return -1;
static int par_setpin(PROGRAMMER * pgm, int pinfunc, int value)
{
return par_setpin_internal(pgm, pgm->pinno[pinfunc], value);
}
static void par_setmany(const PROGRAMMER *pgm, int pinfunc, int value) {
int pin, mask, pinset;
if(pinfunc < 0 || pinfunc >= N_PINS)
return;
pinset = pgm->pinno[pinfunc];
static void par_setmany(PROGRAMMER * pgm, int pinfunc, int value)
{
int pin, mask;
int pinset = pgm->pinno[pinfunc];
/* mask is anything non-pin - needs to be applied to each par_setpin to preserve inversion */
mask = pinset & (~PIN_MASK);
@@ -125,13 +121,11 @@ static void par_setmany(const PROGRAMMER *pgm, int pinfunc, int value) {
}
}
static int par_getpin(const PROGRAMMER * pgm, int pinfunc) {
int value, inverted, pin;
if(pinfunc < 0 || pinfunc >= N_PINS)
return -1;
pin = pgm->pinno[pinfunc];
static int par_getpin(PROGRAMMER * pgm, int pinfunc)
{
int value;
int inverted;
int pin = pgm->pinno[pinfunc];
inverted = pin & PIN_INVERSE;
pin &= PIN_MASK;
@@ -156,13 +150,10 @@ static int par_getpin(const PROGRAMMER * pgm, int pinfunc) {
}
static int par_highpulsepin(const PROGRAMMER *pgm, int pinfunc) {
int inverted, pin;
if(pinfunc < 0 || pinfunc >= N_PINS)
return -1;
pin = pgm->pinno[pinfunc];
static int par_highpulsepin(PROGRAMMER * pgm, int pinfunc)
{
int inverted;
int pin = pgm->pinno[pinfunc];
inverted = pin & PIN_INVERSE;
pin &= PIN_MASK;
@@ -199,7 +190,8 @@ static int par_highpulsepin(const PROGRAMMER *pgm, int pinfunc) {
/*
* apply power to the AVR processor
*/
static void par_powerup(const PROGRAMMER *pgm) {
static void par_powerup(PROGRAMMER * pgm)
{
par_setmany(pgm, PPI_AVR_VCC, 1); /* power up */
usleep(100000);
}
@@ -208,15 +200,18 @@ static void par_powerup(const PROGRAMMER *pgm) {
/*
* remove power from the AVR processor
*/
static void par_powerdown(const PROGRAMMER *pgm) {
static void par_powerdown(PROGRAMMER * pgm)
{
par_setmany(pgm, PPI_AVR_VCC, 0); /* power down */
}
static void par_disable(const PROGRAMMER *pgm) {
static void par_disable(PROGRAMMER * pgm)
{
par_setmany(pgm, PPI_AVR_BUFF, 1); /* turn off */
}
static void par_enable(PROGRAMMER *pgm, const AVRPART *p) {
static void par_enable(PROGRAMMER * pgm)
{
/*
* Prepare to start talking to the connected device - pull reset low
* first, delay a few milliseconds, then enable the buffer. This
@@ -237,7 +232,8 @@ static void par_enable(PROGRAMMER *pgm, const AVRPART *p) {
par_setmany(pgm, PPI_AVR_BUFF, 0);
}
static int par_open(PROGRAMMER *pgm, const char *port) {
static int par_open(PROGRAMMER * pgm, char * port)
{
int rc;
if (bitbang_check_prerequisites(pgm) < 0)
@@ -245,7 +241,8 @@ static int par_open(PROGRAMMER *pgm, const char *port) {
ppi_open(port, &pgm->fd);
if (pgm->fd.ifd < 0) {
pmsg_error("unable to open parallel port %s\n\n", port);
avrdude_message(MSG_INFO, "%s: failed to open parallel port \"%s\"\n\n",
progname, port);
return -1;
}
@@ -254,14 +251,14 @@ static int par_open(PROGRAMMER *pgm, const char *port) {
*/
rc = ppi_getall(&pgm->fd, PPIDATA);
if (rc < 0) {
pmsg_error("unable to read status of ppi data port\n");
avrdude_message(MSG_INFO, "%s: error reading status of ppi data port\n", progname);
return -1;
}
pgm->ppidata = rc;
rc = ppi_getall(&pgm->fd, PPICTRL);
if (rc < 0) {
pmsg_error("unable to read status of ppi ctrl port\n");
avrdude_message(MSG_INFO, "%s: error reading status of ppi ctrl port\n", progname);
return -1;
}
pgm->ppictrl = rc;
@@ -270,7 +267,8 @@ static int par_open(PROGRAMMER *pgm, const char *port) {
}
static void par_close(PROGRAMMER *pgm) {
static void par_close(PROGRAMMER * pgm)
{
/*
* Restore pin values before closing,
@@ -333,41 +331,40 @@ static void par_close(PROGRAMMER *pgm) {
/*
* parse the -E string
*/
static int par_parseexitspecs(PROGRAMMER *pgm, const char *sp) {
char *cp, *s, *str = cfg_strdup("par_parseexitspecs()", sp);
static int par_parseexitspecs(PROGRAMMER * pgm, char *s)
{
char *cp;
s = str;
while((cp = strtok(s, ","))) {
if(strcmp(cp, "reset") == 0)
while ((cp = strtok(s, ","))) {
if (strcmp(cp, "reset") == 0) {
pgm->exit_reset = EXIT_RESET_ENABLED;
else if(strcmp(cp, "noreset") == 0)
}
else if (strcmp(cp, "noreset") == 0) {
pgm->exit_reset = EXIT_RESET_DISABLED;
else if(strcmp(cp, "vcc") == 0)
}
else if (strcmp(cp, "vcc") == 0) {
pgm->exit_vcc = EXIT_VCC_ENABLED;
else if(strcmp(cp, "novcc") == 0)
}
else if (strcmp(cp, "novcc") == 0) {
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;
else if(strcmp(cp, "d_low") == 0)
}
else if (strcmp(cp, "d_low") == 0) {
pgm->exit_datahigh = EXIT_DATAHIGH_DISABLED;
}
else {
free(str);
return -1;
}
s = NULL; // Only call strtok() once with the actual string
s = 0; /* strtok() should be called with the actual string only once */
}
free(str);
return 0;
}
void par_initpgm(PROGRAMMER *pgm) {
void par_initpgm(PROGRAMMER * pgm)
{
strcpy(pgm->type, "PPI");
pgm_fill_old_pins(pgm); // TODO to be removed if old pin data no longer needed
@@ -403,8 +400,10 @@ void par_initpgm(PROGRAMMER *pgm) {
#else /* !HAVE_PARPORT */
void par_initpgm(PROGRAMMER *pgm) {
pmsg_error("parallel port access not available in this configuration\n");
void par_initpgm(PROGRAMMER * pgm)
{
avrdude_message(MSG_INFO, "%s: parallel port access not available in this configuration\n",
progname);
}
#endif /* HAVE_PARPORT */

View File

@@ -26,7 +26,7 @@ extern "C" {
#endif
extern const char par_desc[];
void par_initpgm(PROGRAMMER *pgm);
void par_initpgm (PROGRAMMER * pgm);
#ifdef __cplusplus
}

Some files were not shown because too many files have changed in this diff Show More