mirror of
https://github.com/mariusgreuel/avrdude.git
synced 2025-12-15 10:11:07 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21dd63c82f | ||
|
|
b4a980e659 |
293
.github/workflows/build.yml
vendored
293
.github/workflows/build.yml
vendored
@@ -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
139
.github/workflows/build_cmake.yml
vendored
Normal 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/*
|
||||
78
.github/workflows/deploy.yml
vendored
78
.github/workflows/deploy.yml
vendored
@@ -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
2
.gitignore
vendored
@@ -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
15
AUTHORS
@@ -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.
|
||||
|
||||
|
||||
396
CMakeLists.txt
396
CMakeLists.txt
@@ -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 "----------------------")
|
||||
@@ -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
449
NEWS
@@ -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
144
README.md
@@ -1,7 +1,5 @@
|
||||
# AVRDUDE
|
||||
|
||||
[](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 Microchip’s [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/).
|
||||
|
||||
92
build.sh
92
build.sh
@@ -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
2
docs/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
build/
|
||||
_build/
|
||||
231
docs/1-Introduction.rst
Normal file
231
docs/1-Introduction.rst
Normal 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.
|
||||
|
||||
1386
docs/2-Command_Line_Options.rst
Normal file
1386
docs/2-Command_Line_Options.rst
Normal file
File diff suppressed because it is too large
Load Diff
241
docs/3-Terminal_Mode_Operation.rst
Normal file
241
docs/3-Terminal_Mode_Operation.rst
Normal 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
|
||||
|
||||
|
||||
382
docs/4-Configuration_File.rst
Normal file
382
docs/4-Configuration_File.rst
Normal 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.
|
||||
|
||||
|
||||
843
docs/5-Programmer_Specific_Information.rst
Normal file
843
docs/5-Programmer_Specific_Information.rst
Normal 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
35
docs/conf.py
Normal 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
27
docs/index.rst
Normal 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#define arduino_h__
|
||||
|
||||
extern const char arduino_desc[];
|
||||
void arduino_initpgm(PROGRAMMER *pgm);
|
||||
void arduino_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
123
src/avr910.c
123
src/avr910.c
@@ -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");
|
||||
|
||||
/*
|
||||
|
||||
@@ -26,7 +26,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char avr910_desc[];
|
||||
void avr910_initpgm(PROGRAMMER *pgm);
|
||||
void avr910_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
774
src/avrcache.c
774
src/avrcache.c
@@ -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;
|
||||
}
|
||||
562
src/avrdude.1
562
src/avrdude.1
@@ -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
|
||||
|
||||
26232
src/avrdude.conf.in
26232
src/avrdude.conf.in
File diff suppressed because it is too large
Load Diff
102
src/avrdude.h
102
src/avrdude.h
@@ -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
|
||||
|
||||
283
src/avrftdi.c
283
src/avrftdi.c
@@ -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");
|
||||
|
||||
/*
|
||||
|
||||
@@ -29,7 +29,7 @@ extern "C" {
|
||||
|
||||
|
||||
extern const char avrftdi_desc[];
|
||||
void avrftdi_initpgm(PROGRAMMER *pgm);
|
||||
void avrftdi_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -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, ...);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
5458
src/avrintel.c
5458
src/avrintel.c
File diff suppressed because it is too large
Load Diff
1477
src/avrintel.h
1477
src/avrintel.h
File diff suppressed because it is too large
Load Diff
902
src/avrpart.c
902
src/avrpart.c
File diff suppressed because it is too large
Load Diff
204
src/bitbang.c
204
src/bitbang.c
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
409
src/buspirate.c
409
src/buspirate.c
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@
|
||||
|
||||
extern const char buspirate_desc[];
|
||||
extern const char buspirate_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
|
||||
|
||||
195
src/butterfly.c
195
src/butterfly.c
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
745
src/config.c
745
src/config.c
@@ -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);
|
||||
}
|
||||
|
||||
107
src/config.h
107
src/config.h
@@ -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
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
1432
src/developer_opts.c
1432
src/developer_opts.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
112
src/dfu.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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})
|
||||
@@ -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
26
src/doc/TODO
Normal 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
|
||||
@@ -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
@@ -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}")
|
||||
@@ -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}")
|
||||
@@ -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}")
|
||||
640
src/fileio.c
640
src/fileio.c
File diff suppressed because it is too large
Load Diff
259
src/flip1.c
259
src/flip1.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
391
src/flip2.c
391
src/flip2.c
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
690
src/ft245r.c
690
src/ft245r.c
File diff suppressed because it is too large
Load Diff
@@ -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 */
|
||||
|
||||
1988
src/jtag3.c
1988
src/jtag3.c
File diff suppressed because it is too large
Load Diff
37
src/jtag3.h
37
src/jtag3.h
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
479
src/jtagmkI.c
479
src/jtagmkI.c
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char jtagmkI_desc[];
|
||||
void jtagmkI_initpgm(PROGRAMMER *pgm);
|
||||
void jtagmkI_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
1411
src/jtagmkII.c
1411
src/jtagmkII.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
326
src/lexer.l
326
src/lexer.l
@@ -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"
|
||||
|
||||
636
src/libavrdude.h
636
src/libavrdude.h
@@ -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 */
|
||||
|
||||
@@ -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) \
|
||||
|
||||
195
src/linuxgpio.c
195
src/linuxgpio.c
@@ -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)";
|
||||
|
||||
@@ -27,7 +27,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char linuxgpio_desc[];
|
||||
void linuxgpio_initpgm(PROGRAMMER *pgm);
|
||||
void linuxgpio_initpgm (PROGRAMMER * pgm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
166
src/linuxspi.c
166
src/linuxspi.c
@@ -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)";
|
||||
|
||||
@@ -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
1534
src/main.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
extern const char micronucleus_desc[];
|
||||
void micronucleus_initpgm(PROGRAMMER *pgm);
|
||||
void micronucleus_initpgm(PROGRAMMER* pgm);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
@@ -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__) */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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*)
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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(¤t);
|
||||
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
48
src/my_ddk_hidsdi.h
Normal 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
113
src/par.c
@@ -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 */
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user