Compare commits
33 Commits
284068430f
...
55e90161da
Author | SHA1 | Date |
---|---|---|
Marius Greuel | 55e90161da | |
Marius Greuel | 9a575ec456 | |
Marius Greuel | f8895abb1b | |
Marius Greuel | 9706426d8f | |
Marius Greuel | b08dd59ce2 | |
Marius Greuel | 14d88fb921 | |
Marius Greuel | 2a709447e7 | |
Marius Greuel | 32d155e43d | |
Marius Greuel | de1e8c75cc | |
Marius Greuel | dedc0e87d0 | |
Marius Greuel | 76b6b67883 | |
Joerg Wunsch | 7b79b72794 | |
Jörg Wunsch | 76a17be4d0 | |
MCUdude | 80f1d96e07 | |
Joerg Wunsch | 09fe08e51c | |
Jörg Wunsch | f2c73c2bb8 | |
MCUdude | b581d14823 | |
Joerg Wunsch | 354a1c4f1f | |
Jörg Wunsch | 23a09a6197 | |
MCUdude | 3fc39c47ad | |
MCUdude | d6ccf7a3ff | |
Joerg Wunsch | 452f673f38 | |
Joerg Wunsch | 38a3af37e2 | |
Jörg Wunsch | d134dc8fff | |
Jörg Wunsch | ba314f23e9 | |
MCUdude | a43f220ef9 | |
Joerg Wunsch | 1c0b70da89 | |
Jörg Wunsch | b6a6c681df | |
Joerg Wunsch | 3eda1d15f9 | |
Marius Greuel | c6438532f0 | |
Joerg Wunsch | 8c6c6a14ec | |
Yegor Yefremov | 7ed3632902 | |
MCUdude | f6bbaadfa6 |
|
@ -0,0 +1,51 @@
|
|||
#
|
||||
# build_extra.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 Extra
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
BUILD_TYPE: RelWithDebInfo
|
||||
|
||||
jobs:
|
||||
freebsd-x86_64:
|
||||
runs-on: macos-10.15
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
id: build
|
||||
uses: vmactions/freebsd-vm@v0.1.5
|
||||
with:
|
||||
prepare: pkg install -y git cmake flex bison libftdi1 hidapi
|
||||
run: |
|
||||
cd src
|
||||
cmake -D DEBUG_CMAKE=1 -D CMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -D CMAKE_C_FLAGS=-I/usr/local/include -D CMAKE_EXE_LINKER_FLAGS=-L/usr/local/lib -B ../build
|
||||
cmake --build ../build
|
||||
- name: Archive build artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: freebsd-x86_64
|
||||
path: |
|
||||
build/
|
||||
!**/*.d
|
||||
!**/*.o
|
|
@ -25,7 +25,7 @@ on:
|
|||
|
||||
jobs:
|
||||
build:
|
||||
uses: avrdudes/avrdude/.github/workflows/build.yml@main
|
||||
uses: mariusgreuel/avrdude/.github/workflows/build.yml@windows
|
||||
|
||||
release:
|
||||
needs: build
|
||||
|
|
|
@ -182,6 +182,9 @@ endif()
|
|||
# Find libhidapi
|
||||
|
||||
find_library(HAVE_LIBHID NAMES hid)
|
||||
if(HAVE_LIBHID)
|
||||
set(LIB_LIBHID ${HAVE_LIBHID})
|
||||
endif()
|
||||
|
||||
find_library(HAVE_LIBHIDAPI NAMES ${PREFERRED_LIBHIDAPI})
|
||||
if(HAVE_LIBHIDAPI)
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x86-Debug",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"configurationType": "Debug",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x86" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "DEBUG_CMAKE",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "USE_EXTERNAL",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x86-Release",
|
||||
"generator": "Visual Studio 17 2022",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x86" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "DEBUG_CMAKE",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "USE_EXTERNAL",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_FLAGS_RELWITHDEBINFO",
|
||||
"value": "/MT /GL /Zi /O2 /Ob1 /DNDEBUG",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
|
||||
"value": "/MT /GL /Zi /O2 /Ob1 /DNDEBUG",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO",
|
||||
"value": "/debug /INCREMENTAL:NO /LTCG /OPT:REF /OPT:ICF",
|
||||
"type": "STRING"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Visual Studio 17 2022 Win64",
|
||||
"configurationType": "Debug",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "DEBUG_CMAKE",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "USE_EXTERNAL",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "x64-Release",
|
||||
"generator": "Visual Studio 17 2022 Win64",
|
||||
"configurationType": "RelWithDebInfo",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"variables": [
|
||||
{
|
||||
"name": "DEBUG_CMAKE",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "USE_EXTERNAL",
|
||||
"value": "True",
|
||||
"type": "BOOL"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_C_FLAGS_RELWITHDEBINFO",
|
||||
"value": "/MT /GL /Zi /O2 /Ob1 /DNDEBUG",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
|
||||
"value": "/MT /GL /Zi /O2 /Ob1 /DNDEBUG",
|
||||
"type": "STRING"
|
||||
},
|
||||
{
|
||||
"name": "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO",
|
||||
"value": "/debug /INCREMENTAL:NO /LTCG /OPT:REF /OPT:ICF",
|
||||
"type": "STRING"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
14
NEWS
14
NEWS
|
@ -13,6 +13,11 @@ Changes since version 6.4:
|
|||
- Started to add CMake (by now, parallel with autoconf/automake)
|
||||
- New-architecture devices (AVR8X mega and tiny) can access all
|
||||
fuses, and memory display shows meaningful alias names
|
||||
- The "safemode" feature has been removed. The major class of
|
||||
programmers it has been designed for (lowlevel bitbang
|
||||
programmers on parallel or serial ports) virtually doesn't exist
|
||||
anymore, and the fuse combination that was covered by it do not
|
||||
match the fuses of modern AVR devices anyway.
|
||||
|
||||
* New devices supported:
|
||||
|
||||
|
@ -119,10 +124,19 @@ Changes since version 6.4:
|
|||
- Fix libusb-1.0 error strings #850
|
||||
- Assign proper type to msg[] in errstr() #857
|
||||
- Fix Arduino retry attempts #855
|
||||
- CMake: use CMAKE_CURRENT_BINARY_DIR to locate avrdude.conf #858
|
||||
- Remove the "safemode" feature. #859
|
||||
- Add support for reading from more memory sections #863
|
||||
- Alias keyword #868
|
||||
- Add fuse name aliases to avrdude.conf + tweak update.c #869
|
||||
- Print JTAG3 clocks after configuration + string formatting #853
|
||||
- Tweak programmer info formatting strings #872
|
||||
|
||||
* Internals:
|
||||
|
||||
- Development moved to Github
|
||||
- Addition of "alias" keyword to avrdude.conf.in syntax; used
|
||||
for fuse name aliases right now
|
||||
|
||||
|
||||
Version 6.4:
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
# AVRDUDE
|
||||
|
||||
[![Build Status](https://github.com/avrdudes/avrdude/actions/workflows/build.yml/badge.svg)](https://github.com/avrdudes/avrdude/actions/workflows/build.yml)
|
||||
|
||||
AVRDUDE - AVR Downloader Uploader - is a program for downloading and uploading
|
||||
the on-chip memories of Microchip’s [AVR microcontrollers](https://en.wikipedia.org/wiki/AVR_microcontrollers).
|
||||
It can program the Flash and EEPROM, and where supported by the 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 was originally written in 2003 by Brian S. Dean. Since 2006, AVRDUDE has been maintained by Jörg Wunsch,
|
||||
with the help of [various contributors](./AUTHORS).
|
||||
|
||||
The latest version of AVRDUDE is always available here:\
|
||||
<https://github.com/avrdudes/avrdude>
|
||||
|
||||
## Getting AVRDUDE for Windows
|
||||
|
||||
To get AVRDUDE for Windows, install the latest version from the [Releases](http://download.savannah.gnu.org/releases/avrdude/) page.
|
||||
|
||||
Alternatively, you may [build AVRDUDE](https://github.com/avrdudes/avrdude/wiki) yourself from source.
|
||||
|
||||
## Getting AVRDUDE for Linux
|
||||
|
||||
To install AVRDUDE for Linux, install the package `avrdude` by running the following commands:
|
||||
|
||||
```console
|
||||
sudo apt-get install avrdude
|
||||
```
|
||||
|
||||
Alternatively, you may [build AVRDUDE](https://github.com/avrdudes/avrdude/wiki) 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.
|
||||
|
||||
## Using AVRDUDE
|
||||
|
||||
AVRDUDE is a command-line application. Run the command `avrdude` without any arguments for a list of options.
|
||||
|
||||
A typical command to program your HEX file into your AVR microcontroller looks like this:
|
||||
|
||||
```console
|
||||
avrdude -c <programmer> -p <part> -U flash:w:<file>:i
|
||||
```
|
||||
|
||||
For instance, to program an **Arduino Uno** connected to the serial port **COM1** with a HEX file called `blink.hex`,
|
||||
you would run the following command:
|
||||
|
||||
```console
|
||||
avrdude -c arduino -P COM1 -b 115200 -p atmega328p -D -U flash:w:objs/blink.hex:i
|
||||
```
|
||||
|
||||
There are many different programmers and options that may be required for the programming to succeed.
|
||||
|
||||
For more information, refer to the [AVRDUDE documentation](http://download.savannah.gnu.org/releases/avrdude/avrdude-doc-6.4.pdf).
|
226
README.md
226
README.md
|
@ -1,60 +1,220 @@
|
|||
# AVRDUDE
|
||||
# AVRDUDE for Windows
|
||||
|
||||
[![Build Status](https://github.com/avrdudes/avrdude/actions/workflows/build.yml/badge.svg)](https://github.com/avrdudes/avrdude/actions/workflows/build.yml)
|
||||
[![Build Status](https://github.com/mariusgreuel/avrdude/actions/workflows/build.yml/badge.svg?branch=windows)](https://github.com/mariusgreuel/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
|
||||
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.
|
||||
This is a fork of AVRDUDE 6.4 from <https://github.com/avrdudes/avrdude>.
|
||||
|
||||
AVRDUDE was originally written in 2003 by Brian S. Dean. Since 2006, AVRDUDE has been maintained by Jörg Wunsch,
|
||||
with the help of [various contributors](./AUTHORS).
|
||||
The purpose of this fork is to add better support for Windows to bring it on par with the Linux version of AVRDUDE.
|
||||
|
||||
The latest version of AVRDUDE is always available here:\
|
||||
<https://github.com/avrdudes/avrdude>
|
||||
Noteable changes include:
|
||||
|
||||
## Getting AVRDUDE for Windows
|
||||
- [Support Atmel AVR programmers out of the box](#support-atmel-avr-programmers-out-of-the-box)
|
||||
- [Support Micronucleus bootloader](#support-micronucleus-bootloader)
|
||||
- [Support Teensy HalfKay bootloader](#support-teensy-halfkay-bootloader)
|
||||
- [Support COM port discovery via USB VID/PID](#support-com-port-discovery-via-usb-vidpid)
|
||||
- [Support Arduino Leonardo bootloader auto-reset](#support-arduino-leonardo-bootloader-auto-reset)
|
||||
- [Support WinUSB devices via custom libusb](#support-winusb-devices-via-custom-libusb)
|
||||
- [Support FTDI devices via custom libftdi](#support-ftdi-devices-via-custom-libftdi)
|
||||
- [Support HID devices via libhidapi](#support-hid-devices-via-libhidapi)
|
||||
- [Support Visual Studio](#support-visual-studio)
|
||||
- [Miscellaneous bug-fixes and patches](#miscellaneous-bug-fixes-and-patches)
|
||||
|
||||
To get AVRDUDE for Windows, install the latest version from the [Releases](http://download.savannah.gnu.org/releases/avrdude/) page.
|
||||
The original AVRDUDE project homepage can be found here <https://savannah.nongnu.org/projects/avrdude>.
|
||||
|
||||
Alternatively, you may [build AVRDUDE](https://github.com/avrdudes/avrdude/wiki) yourself from source.
|
||||
## Download
|
||||
|
||||
## Getting AVRDUDE for Linux
|
||||
To get the latest version of **AVRDUDE for Windows**, go to the [releases folder](https://github.com/mariusgreuel/avrdude/releases):
|
||||
|
||||
To install AVRDUDE for Linux, install the package `avrdude` by running the following commands:
|
||||
<https://github.com/mariusgreuel/avrdude/releases>
|
||||
|
||||
## Feature Details
|
||||
|
||||
### Support Atmel AVR programmers out of the box
|
||||
|
||||
This build contains support for Atmel AVR programmers, such as
|
||||
|
||||
- [Atmel-ICE](https://www.microchip.com/DevelopmentTools/ProductDetails/ATATMEL-ICE) (Part Number: ATATMEL-ICE)
|
||||
- [Atmel AVRISP mkII](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNO/ATAVRISP2) (Part Number: ATAVRISP2)
|
||||
|
||||
This build does not rely on **libusb** drivers. Instead the default Atmel drivers can be used, allowing you to use AVRDUDE and Atmel Studio 7 side-by-side, without switching drivers.
|
||||
|
||||
If you previously changed the driver of your programmer to libusb, you should use **Windows Device Manager** to uninstall the device, and then reinstall using the default Windows drivers.
|
||||
|
||||
### Support Micronucleus bootloader
|
||||
|
||||
This build adds support for the [Micronucleus bootloader](https://github.com/micronucleus/micronucleus), so you do no longer need a separate command-line utility when working with devices that use the Micronucleus bootloader.
|
||||
|
||||
The Micronucleus bootloader is typically used on small ATtiny boards, such as **Digispark** (ATtiny85), **Digispark Pro** (ATtiny167), and the respective clones.
|
||||
By default, it uses the USB VID/PID **16D0:0753** (MCS Digistump).
|
||||
|
||||
Since this bootloader is optimized for size, it implements writing to flash memory only.
|
||||
As it does not support reading, you need to use the **-V** option to prevent AVRDUDE from verifing the flash memory. To have AVRDUDE wait for the device to be connected, use the extended option '-x wait'.
|
||||
|
||||
#### Example: Flashing a Micronucleus bootloader device
|
||||
|
||||
```console
|
||||
sudo apt-get install avrdude
|
||||
avrdude -c micronucleus -p t85 -x wait -V -U flash:w:main.hex:i
|
||||
```
|
||||
|
||||
Alternatively, you may [build AVRDUDE](https://github.com/avrdudes/avrdude/wiki) yourself from source.
|
||||
### Support Teensy HalfKay bootloader
|
||||
|
||||
## Getting AVRDUDE for MacOS
|
||||
This build adds support for the [Teensy HalfKay bootloader](https://www.pjrc.com/teensy/halfkay_protocol.html), so you do no longer need a the Teensy Loader tool when working with Teensy devices.
|
||||
|
||||
On MacOS, AVRDUDE can be installed through Mac Ports.
|
||||
Since this bootloader is optimized for size, it implements writing to flash memory only.
|
||||
As it does not support reading, you need to use the **-V** option to prevent AVRDUDE from verifing the flash memory. To have AVRDUDE wait for the device to be connected, use the extended option '-x wait'.
|
||||
|
||||
Alternatively, you may [build AVRDUDE](https://github.com/avrdudes/avrdude/wiki) yourself from source.
|
||||
Supported devices are:
|
||||
|
||||
## Using AVRDUDE
|
||||
- Teensy 1.0 (AT90USB162)
|
||||
- Teensy 2.0 (ATmega32U4)
|
||||
- Teensy++ 1.0 (AT90USB646)
|
||||
- Teensy++ 2.0 (AT90USB1286)
|
||||
|
||||
AVRDUDE is a command-line application. Run the command `avrdude` without any arguments for a list of options.
|
||||
|
||||
A typical command to program your HEX file into your AVR microcontroller looks like this:
|
||||
#### Example: Flashing a Teensy 2.0 device
|
||||
|
||||
```console
|
||||
avrdude -c <programmer> -p <part> -U flash:w:<file>:i
|
||||
avrdude -c teensy -p m32u4 -x wait -V -U flash:w:main.hex:i
|
||||
```
|
||||
|
||||
For instance, to program an **Arduino Uno** connected to the serial port **COM1** with a HEX file called `blink.hex`,
|
||||
you would run the following command:
|
||||
### Support COM port discovery via USB VID/PID
|
||||
|
||||
Most Arduino boards use a USB-based virtual COM port, which is connected to some sort of bootloader. Since COM port numbers (COM1, COM2, ...) are determined by Windows, you first need to use Windows device manager to figure out the COM port before you can use AVRDUDE to flash the board. Alternatively, you may use Windows device manager to assign a COM port of your choice to the USB device. Additionally, the COM port of your Arduino board may change over time, for instance if you plug the device in a different USB port.
|
||||
|
||||
To simplify the discovery of your Arduino board, I provided the possibility to specify the USB vendor and product ID instead of the COM port.
|
||||
|
||||
For instance, to connect to an Arduino Leonardo, use the following command:
|
||||
|
||||
```console
|
||||
avrdude -c arduino -P COM1 -b 115200 -p atmega328p -D -U flash:w:objs/blink.hex:i
|
||||
avrdude -c avr109 -P usb:2341:0036 -p m32u4
|
||||
```
|
||||
|
||||
There are many different programmers and options that may be required for the programming to succeed.
|
||||
Since the USB vendor and device ID **2341:0036** is the identical for all Leonardo boards, the command above will work regardless of which COM port was actually assigned to your board.
|
||||
|
||||
Note that can cannot use this method if you have more than one device of the same type (i.e. that share the same USB VID/PID) plugged into your computer. Also, some devices ship various versions of firmwares using different VID/PID.
|
||||
|
||||
To figure out the USB VID and PID, you may use **Windows devices manager** (see the **Hardware IDs** of the **Details tab** of the USB device), or look it up in the official list of Arduino devices:
|
||||
<https://github.com/arduino/ArduinoCore-avr/blob/master/boards.txt>
|
||||
|
||||
USB VID/PID pairs for some popular boards and the respective commands are:
|
||||
|
||||
- Arduino Uno Rev 3: **2A03:0043** -> `avrdude -c arduino -P usb:2A03:0043 -p m328p`
|
||||
- Arduino Micro: **2341:0037** -> `avrdude -c avr109 -P usb:2341:0037 -p m32u4`
|
||||
- Arduino Leonardo: **2341:0036** -> `avrdude -c avr109 -P usb:2341:0036 -p m32u4`
|
||||
- Sparkfun Pro Micro (5V): **1B4F:9205** -> `avrdude -c avr109 -P usb:1B4F:9205 -p m32u4`
|
||||
- Sparkfun Pro Micro (3.3V): **1B4F:9203** -> `avrdude -c avr109 -P usb:1B4F:9203 -p m32u4`
|
||||
- Adafruit Circuit Playground: **239A:0011** -> `avrdude -c avr109 -P usb:239A:0011 -p m32u4`
|
||||
|
||||
### Support Arduino Leonardo bootloader auto-reset
|
||||
|
||||
Before any Arduino board may be flashed via the bootloader, you need to kick it into bootloader mode first. This can done manually by pressing the reset button, or automatically via an special auto-reset mechanism: For boards with a USB to serial converter chip (such as Arduino Uno or Nano), the tool needs to pull the DTR signal to low, which will briefly pull the RESET pin of the microcontroller to low. For boards with a direct USB connection (such as Arduino Leonardo or Micro), the sketch typically implements a serial port via a USB composite device with a virtual COM port. To perform the auto-reset, the sketch implements a hack that resets the device into bootloader mode when the COM port is opened with a baudrate of 1200bps. To make matters even more complicated, the bootloader COM port has a different USB VID:PID pair than the sketch COM port, which causes the COM port to change while performing the reset.
|
||||
|
||||
To simplify the process of auto-resetting the board, this version will auto-reset the device when AVRDUDE detects that the device is running in sketch mode. Note that the sketch is required to implement a USB composite device with a virtual COM port with a matching USB VID:PID, which is implemented in the Arduino core software.
|
||||
|
||||
### Support WinUSB devices via custom libusb
|
||||
|
||||
Since AVRDUDE originated from Unix, the USB support in AVRDUDE is built upon the Unix-based USB library [libusb](https://sourceforge.net/projects/libusb/). In order to support Windows, libusb has been ported to Windows [libusb-win32](https://sourceforge.net/projects/libusb-win32/).
|
||||
|
||||
The downside of using libusb-win32 is that it requires the user to manually install a kernel-mode driver (libusb0.sys or libusbk.sys) instead of the manufacturer supplied Windows driver. There are several hacks to accomplish this, such as the [Zadig driver installation utility](https://zadig.akeo.ie/), which installs a self-signed root certificate in the Windows driver store due to the lack of proper driver installation packages.
|
||||
|
||||
This build contains a custom library called **libwinusb**, which implements a sub-set of the libusb-win32 API. The libwinusb implementation supports both the **winusb.sys** driver, and the **libusb0.sys** driver as well. This patch has a number of advantages, such as
|
||||
|
||||
- Many USB devices that ship with WinUSB drivers, such as Atmel programmer, will run out of the box.
|
||||
- Works with both WinUSB and libusb: You can use either Windows built-in WinUSB driver to access your USB devices, or keep using the libusb drivers if you have them installed already.
|
||||
- No static dependency to libusb0.dll: You cannot run the original version AVRDUDE, unless you previously installed libusb. On systems where libusb is not installed, this build eliminates the error "The code execution cannot proceed because libusb0.dll was not found. Reinstalling the program may fix this problem".
|
||||
|
||||
#### Microsoft OS descriptors and firmware examples
|
||||
|
||||
Windows provides a mechanism to automatically load the built-in WinUSB driver without providing a driver installation package (INF file). The automatic WinUSB driver installation is triggered via a special [Microsoft OS descriptor](https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors) that must be present in the firmware of the USB device.
|
||||
|
||||
To demonstrate how this works, I added Microsoft OS descriptors to the following projects:
|
||||
|
||||
- **USBasp** - USB programmer for Atmel AVR controllers: <https://github.com/mariusgreuel/USBasp>
|
||||
|
||||
- **FabISP** a.k.a **USBtinyISP** - A fab-able in-system programmer: <https://github.com/mariusgreuel/FabISP>
|
||||
|
||||
- **Micronucleus** - ATtiny USB bootloader with a strong emphasis on bootloader compactness: <https://github.com/mariusgreuel/micronucleus>
|
||||
|
||||
### Support FTDI devices via custom libftdi
|
||||
|
||||
In order to support FTDI devices, AVRDUDE uses the Unix-based library [libftdi1](https://www.intra2net.com/en/developer/libftdi/). Similar to libusb, the libftdi1 library does not play nice on Windows: On Windows, FTDI devices load the manufacturer supplied driver via plug-and-play. The FTDI drivers implement an API via the FTDI D2XX DLLs. However, libftdi1 cannot use the D2XX interface, so it will not work with the plug-and-play drivers.
|
||||
|
||||
This build contains a patches library of **libftdi**. The patches load the D2XX DLLs to support FTDI devices, so FTDI devices will just work.
|
||||
|
||||
### Support HID devices via libhidapi
|
||||
|
||||
This build include the WIN32 version of libhidapi, and some patches, to allow HID devices to work out of the box.
|
||||
|
||||
### Support Visual Studio
|
||||
|
||||
This build adds support for **Microsoft Visual Studio**. Building AVRDUDE with Microsoft Visual C/C++ will give you the best user and debugging experience while working on Windows.
|
||||
|
||||
### Miscellaneous bug-fixes and patches
|
||||
|
||||
- This build fixes [bug #54159: Buffer overflow in usbtiny.c](http://savannah.nongnu.org/bugs/?54159), which causes AVRDUDE to crash when using the USBtiny programmer.
|
||||
|
||||
- Support new microcontroller: ATtiny167
|
||||
|
||||
## Releases
|
||||
|
||||
You can find the latest releases of **AVRDUDE for Windows** here:
|
||||
|
||||
<https://github.com/mariusgreuel/avrdude/releases>
|
||||
|
||||
## Users manual
|
||||
|
||||
You can find the original users manual (does not contain AVRDUDE for Windows extras) of AVRDUDE here:
|
||||
|
||||
<https://www.nongnu.org/avrdude/user-manual/avrdude.html>
|
||||
|
||||
## Build
|
||||
|
||||
The build instructions have been moved here:\
|
||||
<https://github.com/avrdudes/avrdude/wiki>
|
||||
|
||||
### Building AVRDUDE for Windows using MSVC
|
||||
|
||||
#### Windows Prerequisites
|
||||
|
||||
In order to build AVRDUDE on Windows, you need:
|
||||
|
||||
- Flex and Bison installed, for instance via [Chocolatey](https://chocolatey.org/)
|
||||
- Microsoft Visual Studio 2019 with **Desktop development with C++** and **CMake** enabled
|
||||
|
||||
#### Windows Build Instructions
|
||||
|
||||
To build AVRDUDE on Windows, do the following:
|
||||
|
||||
- `git clone --branch windows https://github.com/mariusgreuel/avrdude`
|
||||
- Open the folder **avrdude** using the menu item **File->Open->Folder**
|
||||
- Build the project using the menu item **Build->Build All**
|
||||
|
||||
### Linux udev rules
|
||||
|
||||
If you intent to use either the Micronucleus or Teensy bootloader, you should edit the udev rules so that you can run AVRDUDE without root.
|
||||
|
||||
For instance, if you are on Ubuntu and you installed the avrdude package, you would edit `/lib/udev/rules.d/60-avrdude.rules` and add the following rules:
|
||||
|
||||
```console
|
||||
# Micronucleus Bootloader
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="16d0", ATTR{idProduct}=="0753", TAG+="uaccess"
|
||||
# Teensy Bootloader
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="16c0", ATTR{idProduct}=="0478", TAG+="uaccess"
|
||||
```
|
||||
|
||||
## Troubleshooting Tips & Tricks
|
||||
|
||||
### Atmel DFU Device driver broken
|
||||
|
||||
The current version of the Atmel DFU drivers that are distributed via the Windows Update are goofed up (@Atmel: It might have something to do with the fact that you commented out the CopyFiles sections!).
|
||||
Symptoms are:
|
||||
|
||||
- You cannot use AVRDUDE to connect to an Atmel DFU device, and you get the error message "No matching USB device found".
|
||||
- When installing the drivers via Windows Update, you get the error message "Windows encountered a problem installing the drivers for your device" and "A service installation section in this INF is invalid."
|
||||
- In Windows Device Manager, the Atmel DFU device shows up as an unknown device.
|
||||
|
||||
You should use an older driver package that does not contain this bug.
|
||||
|
||||
### Outdated libusb0 driver
|
||||
|
||||
The most current version of libusb0.sys is 1.2.6.0, signed on 12/17/2012 by Travis Lee Robinson. If you are using an older version (check with Windows Device Manager), you may not be able to connect to your USB devices using the libusb0 driver.
|
||||
|
||||
For more information, refer to the [AVRDUDE documentation](http://download.savannah.gnu.org/releases/avrdude/avrdude-doc-6.4.pdf).
|
||||
|
|
|
@ -75,6 +75,7 @@ if(MSVC)
|
|||
"msvc/getopt.c"
|
||||
"msvc/gettimeofday.c"
|
||||
"msvc/usleep.cpp"
|
||||
"msvc/usb_com_helper.cpp"
|
||||
)
|
||||
set(EXTRA_WINDOWS_INCLUDES ${EXTRA_WINDOWS_INCLUDES}
|
||||
"msvc"
|
||||
|
@ -173,7 +174,6 @@ add_library(libavrdude
|
|||
ppi.c
|
||||
ppi.h
|
||||
ppiwin.c
|
||||
safemode.c
|
||||
serbb.h
|
||||
serbb_posix.c
|
||||
serbb_win32.c
|
||||
|
@ -240,6 +240,7 @@ target_link_libraries(libavrdude
|
|||
${LIB_LIBELF}
|
||||
${LIB_LIBUSB}
|
||||
${LIB_LIBUSB_1_0}
|
||||
${LIB_LIBHID}
|
||||
${LIB_LIBHIDAPI}
|
||||
${LIB_LIBFTDI}
|
||||
${LIB_LIBFTDI1}
|
||||
|
@ -268,5 +269,5 @@ install(TARGETS libavrdude
|
|||
ARCHIVE DESTINATION lib
|
||||
PUBLIC_HEADER DESTINATION include COMPONENT dev
|
||||
)
|
||||
install(FILES "${PROJECT_BINARY_DIR}/avrdude.conf" TYPE SYSCONF)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/avrdude.conf" TYPE SYSCONF)
|
||||
install(FILES avrdude.1 TYPE MAN)
|
||||
|
|
|
@ -148,7 +148,6 @@ libavrdude_a_SOURCES = \
|
|||
ppi.c \
|
||||
ppi.h \
|
||||
ppiwin.c \
|
||||
safemode.c \
|
||||
serbb.h \
|
||||
serbb_posix.c \
|
||||
serbb_win32.c \
|
||||
|
|
41
src/avr.c
41
src/avr.c
|
@ -791,30 +791,6 @@ int avr_write_byte_default(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
|||
int avr_write_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
||||
unsigned long addr, unsigned char data)
|
||||
{
|
||||
|
||||
unsigned char safemode_lfuse;
|
||||
unsigned char safemode_hfuse;
|
||||
unsigned char safemode_efuse;
|
||||
unsigned char safemode_fuse;
|
||||
|
||||
/* If we write the fuses, then we need to tell safemode that they *should* change */
|
||||
safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||
|
||||
if (strcmp(mem->desc, "fuse")==0) {
|
||||
safemode_fuse = data;
|
||||
}
|
||||
if (strcmp(mem->desc, "lfuse")==0) {
|
||||
safemode_lfuse = data;
|
||||
}
|
||||
if (strcmp(mem->desc, "hfuse")==0) {
|
||||
safemode_hfuse = data;
|
||||
}
|
||||
if (strcmp(mem->desc, "efuse")==0) {
|
||||
safemode_efuse = data;
|
||||
}
|
||||
|
||||
safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||
|
||||
return pgm->write_byte(pgm, p, mem, addr, data);
|
||||
}
|
||||
|
||||
|
@ -877,15 +853,11 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
|||
/* setup for WORD_WRITE */
|
||||
avr_tpi_setup_rw(pgm, m, 0, TPI_NVMCMD_WORD_WRITE);
|
||||
|
||||
/* make sure it's aligned to a word boundary */
|
||||
if (wsize & 0x1) {
|
||||
wsize++;
|
||||
}
|
||||
|
||||
/* write words, low byte first */
|
||||
for (lastaddr = i = 0; i < wsize; i += 2) {
|
||||
bool have_two_bytes = i + 1 < wsize;
|
||||
if ((m->tags[i] & TAG_ALLOCATED) != 0 ||
|
||||
(m->tags[i + 1] & TAG_ALLOCATED) != 0) {
|
||||
(have_two_bytes && m->tags[i + 1] & TAG_ALLOCATED) != 0) {
|
||||
|
||||
if (lastaddr != i) {
|
||||
/* need to setup new address */
|
||||
|
@ -897,8 +869,11 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
|||
cmd[1] = m->buf[i];
|
||||
rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0);
|
||||
|
||||
cmd[1] = m->buf[i + 1];
|
||||
rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0);
|
||||
if (have_two_bytes)
|
||||
{
|
||||
cmd[1] = m->buf[i + 1];
|
||||
rc = pgm->cmd_tpi(pgm, cmd, 2, NULL, 0);
|
||||
}
|
||||
|
||||
lastaddr += 2;
|
||||
|
||||
|
@ -906,7 +881,7 @@ int avr_write(PROGRAMMER * pgm, AVRPART * p, char * memtype, int size,
|
|||
}
|
||||
report_progress(i, wsize, NULL);
|
||||
}
|
||||
return i;
|
||||
return wsize;
|
||||
}
|
||||
|
||||
if (pgm->paged_write != NULL && m->page_size > 1) {
|
||||
|
|
|
@ -607,40 +607,11 @@ Posix systems (by now).
|
|||
.It Fl q
|
||||
Disable (or quell) output of the progress bar while reading or writing
|
||||
to the device. Specify it a second time for even quieter operation.
|
||||
.It Fl s
|
||||
Disable safemode prompting. When safemode discovers that one or more
|
||||
fuse bits have unintentionally changed, it will prompt for
|
||||
confirmation regarding whether or not it should attempt to recover the
|
||||
fuse bit(s). Specifying this flag disables the prompt and assumes
|
||||
that the fuse bit(s) should be recovered without asking for
|
||||
confirmation first.
|
||||
.It Fl t
|
||||
Tells
|
||||
.Nm
|
||||
to enter the interactive ``terminal'' mode instead of up- or downloading
|
||||
files. See below for a detailed description of the terminal mode.
|
||||
.It Fl u
|
||||
Disable the safemode fuse bit checks. Safemode is enabled by default
|
||||
and is intended to prevent unintentional fuse bit changes. When
|
||||
enabled, safemode will issue a warning if the any fuse bits are found
|
||||
to be different at program exit than they were when
|
||||
.Nm
|
||||
was invoked. Safemode won't alter fuse bits itself, but rather will
|
||||
prompt for instructions, unless the terminal is non-interactive, in
|
||||
which case safemode is disabled. See the
|
||||
.Fl s
|
||||
option to disable safemode prompting.
|
||||
.Pp
|
||||
If one of the configuration files has a line
|
||||
.Dl "default_safemode = no;"
|
||||
safemode is disabled by default.
|
||||
The
|
||||
.Fl u
|
||||
option's effect is negated in that case, i. e. it
|
||||
.Em enables
|
||||
safemode.
|
||||
.Pp
|
||||
Safemode is always disabled for AVR32, Xmega and TPI devices.
|
||||
.It Xo Fl U Ar memtype Ns
|
||||
.Ar \&: Ns Ar op Ns
|
||||
.Ar \&: Ns Ar filename Ns
|
||||
|
|
|
@ -339,10 +339,6 @@ default_parallel = "@DEFAULT_PAR_PORT@";
|
|||
default_serial = "@DEFAULT_SER_PORT@";
|
||||
# default_bitclock = 2.5;
|
||||
|
||||
# Turn off safemode by default
|
||||
#default_safemode = no;
|
||||
|
||||
|
||||
#
|
||||
# PROGRAMMER DEFINITIONS
|
||||
#
|
||||
|
@ -16632,9 +16628,7 @@ part
|
|||
;
|
||||
|
||||
memory "wdtcfg"
|
||||
size = 1;
|
||||
offset = 0x1280;
|
||||
readsize = 1;
|
||||
alias "fuse0";
|
||||
;
|
||||
|
||||
memory "fuse1"
|
||||
|
@ -16644,9 +16638,7 @@ part
|
|||
;
|
||||
|
||||
memory "bodcfg"
|
||||
size = 1;
|
||||
offset = 0x1281;
|
||||
readsize = 1;
|
||||
alias "fuse1";
|
||||
;
|
||||
|
||||
memory "fuse2"
|
||||
|
@ -16656,9 +16648,7 @@ part
|
|||
;
|
||||
|
||||
memory "osccfg"
|
||||
size = 1;
|
||||
offset = 0x1282;
|
||||
readsize = 1;
|
||||
alias "fuse2";
|
||||
;
|
||||
|
||||
memory "fuse4"
|
||||
|
@ -16668,9 +16658,7 @@ part
|
|||
;
|
||||
|
||||
memory "tcd0cfg"
|
||||
size = 1;
|
||||
offset = 0x1284;
|
||||
readsize = 1;
|
||||
alias "fuse4";
|
||||
;
|
||||
|
||||
memory "fuse5"
|
||||
|
@ -16680,9 +16668,7 @@ part
|
|||
;
|
||||
|
||||
memory "syscfg0"
|
||||
size = 1;
|
||||
offset = 0x1285;
|
||||
readsize = 1;
|
||||
alias "fuse5";
|
||||
;
|
||||
|
||||
memory "fuse6"
|
||||
|
@ -16692,9 +16678,7 @@ part
|
|||
;
|
||||
|
||||
memory "syscfg1"
|
||||
size = 1;
|
||||
offset = 0x1286;
|
||||
readsize = 1;
|
||||
alias "fuse6";
|
||||
;
|
||||
|
||||
memory "fuse7"
|
||||
|
@ -16704,9 +16688,11 @@ part
|
|||
;
|
||||
|
||||
memory "append"
|
||||
size = 1;
|
||||
offset = 0x1287;
|
||||
readsize = 1;
|
||||
alias "fuse7";
|
||||
;
|
||||
|
||||
memory "codesize"
|
||||
alias "fuse7";
|
||||
;
|
||||
|
||||
memory "fuse8"
|
||||
|
@ -16716,9 +16702,11 @@ part
|
|||
;
|
||||
|
||||
memory "bootend"
|
||||
size = 1;
|
||||
offset = 0x1288;
|
||||
readsize = 1;
|
||||
alias "fuse8";
|
||||
;
|
||||
|
||||
memory "bootsize"
|
||||
alias "fuse8";
|
||||
;
|
||||
|
||||
memory "lock"
|
||||
|
@ -17900,9 +17888,7 @@ part
|
|||
;
|
||||
|
||||
memory "wdtcfg"
|
||||
size = 1;
|
||||
offset = 0x1050;
|
||||
readsize = 1;
|
||||
alias "fuse0";
|
||||
;
|
||||
|
||||
memory "fuse1"
|
||||
|
@ -17912,9 +17898,7 @@ part
|
|||
;
|
||||
|
||||
memory "bodcfg"
|
||||
size = 1;
|
||||
offset = 0x1051;
|
||||
readsize = 1;
|
||||
alias "fuse1";
|
||||
;
|
||||
|
||||
memory "fuse2"
|
||||
|
@ -17924,9 +17908,7 @@ part
|
|||
;
|
||||
|
||||
memory "osccfg"
|
||||
size = 1;
|
||||
offset = 0x1052;
|
||||
readsize = 1;
|
||||
alias "fuse2";
|
||||
;
|
||||
|
||||
memory "fuse4"
|
||||
|
@ -17936,9 +17918,7 @@ part
|
|||
;
|
||||
|
||||
memory "tcd0cfg"
|
||||
size = 1;
|
||||
offset = 0x1054;
|
||||
readsize = 1;
|
||||
alias "fuse4";
|
||||
;
|
||||
|
||||
memory "fuse5"
|
||||
|
@ -17948,9 +17928,7 @@ part
|
|||
;
|
||||
|
||||
memory "syscfg0"
|
||||
size = 1;
|
||||
offset = 0x1055;
|
||||
readsize = 1;
|
||||
alias "fuse5";
|
||||
;
|
||||
|
||||
memory "fuse6"
|
||||
|
@ -17960,9 +17938,7 @@ part
|
|||
;
|
||||
|
||||
memory "syscfg1"
|
||||
size = 1;
|
||||
offset = 0x1056;
|
||||
readsize = 1;
|
||||
alias "fuse6";
|
||||
;
|
||||
|
||||
memory "fuse7"
|
||||
|
@ -17972,15 +17948,11 @@ part
|
|||
;
|
||||
|
||||
memory "codesize"
|
||||
size = 1;
|
||||
offset = 0x1057;
|
||||
readsize = 1;
|
||||
alias "fuse7";
|
||||
;
|
||||
|
||||
memory "append"
|
||||
size = 1;
|
||||
offset = 0x1057;
|
||||
readsize = 1;
|
||||
alias "fuse7";
|
||||
;
|
||||
|
||||
memory "fuse8"
|
||||
|
@ -17990,15 +17962,11 @@ part
|
|||
;
|
||||
|
||||
memory "bootsize"
|
||||
size = 1;
|
||||
offset = 0x1058;
|
||||
readsize = 1;
|
||||
alias "fuse8";
|
||||
;
|
||||
|
||||
memory "bootend"
|
||||
size = 1;
|
||||
offset = 0x1058;
|
||||
readsize = 1;
|
||||
alias "fuse8";
|
||||
;
|
||||
|
||||
memory "lock"
|
||||
|
|
144
src/avrpart.c
144
src/avrpart.c
|
@ -260,6 +260,21 @@ AVRMEM * avr_new_memtype(void)
|
|||
return m;
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * avr_new_memalias(void)
|
||||
{
|
||||
AVRMEM_ALIAS * m;
|
||||
|
||||
m = (AVRMEM_ALIAS *)malloc(sizeof(*m));
|
||||
if (m == NULL) {
|
||||
avrdude_message(MSG_INFO, "avr_new_memalias(): out of memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(m, 0, sizeof(*m));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocate and initialize memory buffers for each of the device's
|
||||
|
@ -326,6 +341,17 @@ AVRMEM * avr_dup_mem(AVRMEM * m)
|
|||
return n;
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * avr_dup_memalias(AVRMEM_ALIAS * m)
|
||||
{
|
||||
AVRMEM_ALIAS * n;
|
||||
|
||||
n = avr_new_memalias();
|
||||
|
||||
*n = *m;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void avr_free_mem(AVRMEM * m)
|
||||
{
|
||||
int i;
|
||||
|
@ -348,7 +374,36 @@ void avr_free_mem(AVRMEM * m)
|
|||
free(m);
|
||||
}
|
||||
|
||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
|
||||
void avr_free_memalias(AVRMEM_ALIAS * m)
|
||||
{
|
||||
free(m);
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, char * desc)
|
||||
{
|
||||
AVRMEM_ALIAS * m, * match;
|
||||
LNODEID ln;
|
||||
int matches;
|
||||
int l;
|
||||
|
||||
l = strlen(desc);
|
||||
matches = 0;
|
||||
match = NULL;
|
||||
for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
if (strncmp(desc, m->desc, l) == 0) {
|
||||
match = m;
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
|
||||
if (matches == 1)
|
||||
return match;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AVRMEM * avr_locate_mem_noalias(AVRPART * p, char * desc)
|
||||
{
|
||||
AVRMEM * m, * match;
|
||||
LNODEID ln;
|
||||
|
@ -373,11 +428,54 @@ AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
|
|||
}
|
||||
|
||||
|
||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc)
|
||||
{
|
||||
AVRMEM * m, * match;
|
||||
AVRMEM_ALIAS * alias;
|
||||
LNODEID ln;
|
||||
int matches;
|
||||
int l;
|
||||
|
||||
l = strlen(desc);
|
||||
matches = 0;
|
||||
match = NULL;
|
||||
for (ln=lfirst(p->mem); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
if (strncmp(desc, m->desc, l) == 0) {
|
||||
match = m;
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
|
||||
if (matches == 1)
|
||||
return match;
|
||||
|
||||
/* not yet found: look for matching alias name */
|
||||
alias = avr_locate_memalias(p, desc);
|
||||
if (alias != NULL)
|
||||
return alias->aliased_mem;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig)
|
||||
{
|
||||
AVRMEM_ALIAS * m;
|
||||
LNODEID ln;
|
||||
|
||||
for (ln=lfirst(p->mem_alias); ln; ln=lnext(ln)) {
|
||||
m = ldata(ln);
|
||||
if (m->aliased_mem == m_orig)
|
||||
return m;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
||||
int type, int verbose)
|
||||
{
|
||||
static LNODEID ln;
|
||||
static AVRMEM * n;
|
||||
static unsigned int prev_mem_offset, prev_mem_size;
|
||||
int i, j;
|
||||
char * optr;
|
||||
|
@ -398,25 +496,14 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
|||
prefix, prefix, prefix);
|
||||
}
|
||||
|
||||
// Get the next memory section, and stop before going out of band
|
||||
if (ln == NULL)
|
||||
ln = lnext(lfirst(p->mem));
|
||||
else
|
||||
ln = lnext(ln);
|
||||
if (ln != NULL)
|
||||
n = ldata(ln);
|
||||
|
||||
// Only print memory section if the previous section printed isn't identical
|
||||
if(prev_mem_offset != m->offset || prev_mem_size != m->size || (strcmp(p->family_id, "") == 0)) {
|
||||
prev_mem_offset = m->offset;
|
||||
prev_mem_size = m->size;
|
||||
AVRMEM_ALIAS *ap = avr_find_memalias(p, m);
|
||||
/* Show alias if the current and the next memory section has the same offset
|
||||
and size, we're not out of band and a family_id is present */
|
||||
char * mem_desc_alias = m->offset == n->offset && \
|
||||
m->size == n->size && \
|
||||
ln != NULL && \
|
||||
strcmp(p->family_id, "") != 0 ?
|
||||
n->desc : "";
|
||||
char * mem_desc_alias = ap? ap->desc: "";
|
||||
fprintf(f,
|
||||
"%s%-11s %-8s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
|
||||
prefix,
|
||||
|
@ -488,6 +575,7 @@ AVRPART * avr_new_part(void)
|
|||
p->ocdrev = -1;
|
||||
|
||||
p->mem = lcreat(NULL, 0);
|
||||
p->mem_alias = lcreat(NULL, 0);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
@ -496,19 +584,35 @@ AVRPART * avr_new_part(void)
|
|||
AVRPART * avr_dup_part(AVRPART * d)
|
||||
{
|
||||
AVRPART * p;
|
||||
LISTID save;
|
||||
LNODEID ln;
|
||||
LISTID save, save2;
|
||||
LNODEID ln, ln2;
|
||||
int i;
|
||||
|
||||
p = avr_new_part();
|
||||
save = p->mem;
|
||||
save2 = p->mem_alias;
|
||||
|
||||
*p = *d;
|
||||
|
||||
p->mem = save;
|
||||
p->mem_alias = save2;
|
||||
|
||||
for (ln=lfirst(d->mem); ln; ln=lnext(ln)) {
|
||||
ladd(p->mem, avr_dup_mem(ldata(ln)));
|
||||
AVRMEM *m = ldata(ln);
|
||||
AVRMEM *m2 = avr_dup_mem(m);
|
||||
ladd(p->mem, m2);
|
||||
// see if there is any alias for it
|
||||
for (ln2=lfirst(d->mem_alias); ln2; ln2=lnext(ln2)) {
|
||||
AVRMEM_ALIAS *a = ldata(ln2);
|
||||
if (a->aliased_mem == m) {
|
||||
// yes, duplicate it
|
||||
AVRMEM_ALIAS *a2 = avr_dup_memalias(a);
|
||||
// ... adjust the pointer ...
|
||||
a2->aliased_mem = m2;
|
||||
// ... and add to new list
|
||||
ladd(p->mem_alias, a2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < AVR_OP_MAX; i++) {
|
||||
|
@ -523,6 +627,8 @@ void avr_free_part(AVRPART * d)
|
|||
int i;
|
||||
ldestroy_cb(d->mem, (void(*)(void *))avr_free_mem);
|
||||
d->mem = NULL;
|
||||
ldestroy_cb(d->mem_alias, (void(*)(void *))avr_free_memalias);
|
||||
d->mem_alias = NULL;
|
||||
for(i=0;i<sizeof(d->op)/sizeof(d->op[0]);i++)
|
||||
{
|
||||
if (d->op[i] != NULL)
|
||||
|
|
|
@ -36,7 +36,6 @@ char default_programmer[MAX_STR_CONST];
|
|||
char default_parallel[PATH_MAX];
|
||||
char default_serial[PATH_MAX];
|
||||
double default_bitclock;
|
||||
int default_safemode;
|
||||
|
||||
char string_buf[MAX_STR_CONST];
|
||||
char *string_buf_ptr;
|
||||
|
@ -48,6 +47,7 @@ AVRPART * current_part;
|
|||
AVRMEM * current_mem;
|
||||
LISTID part_list;
|
||||
LISTID programmers;
|
||||
bool is_alias;
|
||||
|
||||
int lineno;
|
||||
const char * infile;
|
||||
|
@ -73,6 +73,7 @@ int init_config(void)
|
|||
current_mem = NULL;
|
||||
part_list = lcreat(NULL, 0);
|
||||
programmers = lcreat(NULL, 0);
|
||||
is_alias = false;
|
||||
|
||||
lineno = 1;
|
||||
infile = NULL;
|
||||
|
|
|
@ -54,6 +54,7 @@ extern int lineno;
|
|||
extern const char * infile;
|
||||
extern LISTID string_list;
|
||||
extern LISTID number_list;
|
||||
extern bool is_alias; // current entry is alias
|
||||
|
||||
|
||||
#if !defined(HAS_YYSTYPE)
|
||||
|
|
|
@ -68,6 +68,7 @@ static int pin_name;
|
|||
%token K_PAGE_SIZE
|
||||
%token K_PAGED
|
||||
|
||||
%token K_ALIAS
|
||||
%token K_BAUDRATE
|
||||
%token K_BS2
|
||||
%token K_BUFF
|
||||
|
@ -77,7 +78,6 @@ static int pin_name;
|
|||
%token K_DEFAULT_BITCLOCK
|
||||
%token K_DEFAULT_PARALLEL
|
||||
%token K_DEFAULT_PROGRAMMER
|
||||
%token K_DEFAULT_SAFEMODE
|
||||
%token K_DEFAULT_SERIAL
|
||||
%token K_DESC
|
||||
%token K_FAMILY_ID
|
||||
|
@ -257,14 +257,6 @@ def :
|
|||
K_DEFAULT_BITCLOCK TKN_EQUAL number_real TKN_SEMI {
|
||||
default_bitclock = $3->value.number_real;
|
||||
free_token($3);
|
||||
} |
|
||||
|
||||
K_DEFAULT_SAFEMODE TKN_EQUAL yesno TKN_SEMI {
|
||||
if ($3->primary == K_YES)
|
||||
default_safemode = 1;
|
||||
else if ($3->primary == K_NO)
|
||||
default_safemode = 0;
|
||||
free_token($3);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1248,12 +1240,17 @@ part_parm :
|
|||
{
|
||||
AVRMEM * existing_mem;
|
||||
|
||||
existing_mem = avr_locate_mem(current_part, current_mem->desc);
|
||||
existing_mem = avr_locate_mem_noalias(current_part, current_mem->desc);
|
||||
if (existing_mem != NULL) {
|
||||
lrmv_d(current_part->mem, existing_mem);
|
||||
avr_free_mem(existing_mem);
|
||||
}
|
||||
ladd(current_part->mem, current_mem);
|
||||
if (is_alias) {
|
||||
avr_free_mem(current_mem); // alias mem has been already entered below
|
||||
is_alias = false;
|
||||
} else {
|
||||
ladd(current_part->mem, current_mem);
|
||||
}
|
||||
current_mem = NULL;
|
||||
} |
|
||||
|
||||
|
@ -1290,6 +1287,7 @@ yesno :
|
|||
|
||||
mem_specs :
|
||||
mem_spec TKN_SEMI |
|
||||
mem_alias TKN_SEMI |
|
||||
mem_specs mem_spec TKN_SEMI
|
||||
;
|
||||
|
||||
|
@ -1419,6 +1417,38 @@ mem_spec :
|
|||
}
|
||||
;
|
||||
|
||||
mem_alias :
|
||||
K_ALIAS TKN_STRING
|
||||
{
|
||||
AVRMEM * existing_mem;
|
||||
|
||||
existing_mem = avr_locate_mem(current_part, $2->value.string);
|
||||
if (existing_mem == NULL) {
|
||||
yyerror("%s alias to non-existent memory %s",
|
||||
current_mem->desc, $2->value.string);
|
||||
free_token($2);
|
||||
YYABORT;
|
||||
}
|
||||
|
||||
// if this alias does already exist, drop the old one
|
||||
AVRMEM_ALIAS * alias = avr_locate_memalias(current_part, current_mem->desc);
|
||||
if (alias) {
|
||||
lrmv_d(current_part->mem_alias, alias);
|
||||
avr_free_memalias(alias);
|
||||
}
|
||||
|
||||
is_alias = true;
|
||||
alias = avr_new_memalias();
|
||||
|
||||
// alias->desc and current_mem->desc have the same length
|
||||
// definition, thus no need to check for length here
|
||||
strcpy(alias->desc, current_mem->desc);
|
||||
alias->aliased_mem = existing_mem;
|
||||
ladd(current_part->mem_alias, alias);
|
||||
|
||||
free_token($2);
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
|
|
|
@ -681,32 +681,6 @@ Posix systems (by now).
|
|||
Disable (or quell) output of the progress bar while reading or writing
|
||||
to the device. Specify it a second time for even quieter operation.
|
||||
|
||||
@item -u
|
||||
Disables the default behaviour of reading out the fuses three times before
|
||||
programming, then verifying at the end of programming that the fuses have not
|
||||
changed. If you want to change fuses you will need to specify this option,
|
||||
as avrdude will see the fuses have changed (even though you wanted to) and
|
||||
will change them back for your "safety". This option was designed to
|
||||
prevent cases of fuse bits magically changing (usually called @emph{safemode}).
|
||||
|
||||
If one of the configuration files contains a line
|
||||
|
||||
@code{default_safemode = no;}
|
||||
|
||||
safemode is disabled by default.
|
||||
The @option{-u} option's effect is negated in that case, i. e. it
|
||||
@emph{enables} safemode.
|
||||
|
||||
Safemode is always disabled for AVR32, Xmega and TPI devices.
|
||||
|
||||
@item -s
|
||||
Disable safemode prompting. When safemode discovers that one or more
|
||||
fuse bits have unintentionally changed, it will prompt for
|
||||
confirmation regarding whether or not it should attempt to recover the
|
||||
fuse bit(s). Specifying this flag disables the prompt and assumes
|
||||
that the fuse bit(s) should be recovered without asking for
|
||||
confirmation first.
|
||||
|
||||
@item -t
|
||||
Tells AVRDUDE to enter the interactive ``terminal'' mode instead of up-
|
||||
or downloading files. See below for a detailed description of the
|
||||
|
@ -1133,8 +1107,6 @@ Reading | ################################################## | 100% 6.83s
|
|||
avrdude: verifying ...
|
||||
avrdude: 19278 bytes of flash verified
|
||||
|
||||
avrdude: safemode: Fuses OK
|
||||
|
||||
avrdude done. Thank you.
|
||||
|
||||
%
|
||||
|
@ -1162,8 +1134,6 @@ Reading | ################################################## | 100% 46.10s
|
|||
|
||||
avrdude: writing output file "c:/diag flash.bin"
|
||||
|
||||
avrdude: safemode: Fuses OK
|
||||
|
||||
avrdude done. Thank you.
|
||||
|
||||
%
|
||||
|
@ -1845,9 +1815,6 @@ flash pages of the application section.
|
|||
|
||||
Reading fuse and lock bits is fully supported.
|
||||
|
||||
Note that due to the inability to write the fuse bits, the safemode
|
||||
functionality does not make sense for these boot loaders.
|
||||
|
||||
@end itemize
|
||||
|
||||
@c
|
||||
|
@ -2021,9 +1988,6 @@ fuse, extended fuse) have no meaning whatsoever, as they have been
|
|||
simply replaced by array of fuses: fuse0..9. Therefore you can simply
|
||||
ignore this particular line of AVRDUDE output.
|
||||
|
||||
In connection to the above, @emph{safemode} has no meaning in context
|
||||
of UPDI devices and should be ignored.
|
||||
|
||||
Currently available devices support only UPDI NVM programming model 0
|
||||
and 2, but there is also experimental implementation of model 3 - not
|
||||
yet tested.
|
||||
|
|
|
@ -1159,7 +1159,7 @@ static int fileio_ihex(struct fioparms * fio,
|
|||
|
||||
switch (fio->op) {
|
||||
case FIO_WRITE:
|
||||
rc = b2ihex(mem->buf, size, 32, fio->fileoffset, filename, f);
|
||||
rc = b2ihex(mem->buf, size, 16, fio->fileoffset, filename, f);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
|
63
src/jtag3.c
63
src/jtag3.c
|
@ -1129,7 +1129,7 @@ static int jtag3_initialize(PROGRAMMER * pgm, AVRPART * p)
|
|||
if (PDATA(pgm)->set_sck(pgm, parm) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
jtag3_print_parms1(pgm, progbuf);
|
||||
if (conn == PARM3_CONN_JTAG)
|
||||
{
|
||||
avrdude_message(MSG_NOTICE2, "%s: jtag3_initialize(): "
|
||||
|
@ -1968,6 +1968,18 @@ static int jtag3_read_byte(PROGRAMMER * pgm, AVRPART * p, AVRMEM * mem,
|
|||
cmd[3] = MTYPE_USERSIG;
|
||||
} else if (strcmp(mem->desc, "prodsig") == 0) {
|
||||
cmd[3] = MTYPE_PRODSIG;
|
||||
} else if (strcmp(mem->desc, "sernum") == 0) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (strcmp(mem->desc, "osccal16") == 0) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (strcmp(mem->desc, "osccal20") == 0) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (strcmp(mem->desc, "tempsense") == 0) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (strcmp(mem->desc, "osc16err") == 0) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (strcmp(mem->desc, "osc20err") == 0) {
|
||||
cmd[3] = MTYPE_SIGN_JTAG;
|
||||
} else if (strcmp(mem->desc, "calibration") == 0) {
|
||||
cmd[3] = MTYPE_OSCCAL_BYTE;
|
||||
if (pgm->flag & PGM_FL_IS_DW)
|
||||
|
@ -2364,14 +2376,12 @@ static void jtag3_display(PROGRAMMER * pgm, const char * p)
|
|||
memmove(resp, resp + 3, status - 3);
|
||||
resp[status - 3] = 0;
|
||||
|
||||
avrdude_message(MSG_INFO, "%sICE hardware version: %d\n", p, parms[0]);
|
||||
avrdude_message(MSG_INFO, "%sICE firmware version: %d.%02d (rel. %d)\n", p,
|
||||
avrdude_message(MSG_INFO, "%sICE HW version : %d\n", p, parms[0]);
|
||||
avrdude_message(MSG_INFO, "%sICE FW version : %d.%02d (rel. %d)\n", p,
|
||||
parms[1], parms[2],
|
||||
(parms[3] | (parms[4] << 8)));
|
||||
avrdude_message(MSG_INFO, "%sSerial number : %s\n", p, resp);
|
||||
avrdude_message(MSG_INFO, "%sSerial number : %s", p, resp);
|
||||
free(resp);
|
||||
|
||||
jtag3_print_parms1(pgm, p);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2383,27 +2393,39 @@ static void jtag3_print_parms1(PROGRAMMER * pgm, const char * p)
|
|||
return;
|
||||
|
||||
avrdude_message(MSG_INFO, "%sVtarget : %.2f V\n", p,
|
||||
b2_to_u16(buf) / 1000.0);
|
||||
b2_to_u16(buf) / 1000.0);
|
||||
|
||||
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_PROG, buf, 2) < 0)
|
||||
return;
|
||||
avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/program: %u kHz\n", p,
|
||||
b2_to_u16(buf));
|
||||
|
||||
if (b2_to_u16(buf) > 0) {
|
||||
avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/program : %u kHz\n", p,
|
||||
b2_to_u16(buf));
|
||||
}
|
||||
|
||||
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_MEGA_DEBUG, buf, 2) < 0)
|
||||
return;
|
||||
avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/debug: %u kHz\n", p,
|
||||
b2_to_u16(buf));
|
||||
|
||||
if (b2_to_u16(buf) > 0) {
|
||||
avrdude_message(MSG_INFO, "%sJTAG clock megaAVR/debug : %u kHz\n", p,
|
||||
b2_to_u16(buf));
|
||||
}
|
||||
|
||||
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_JTAG, buf, 2) < 0)
|
||||
return;
|
||||
avrdude_message(MSG_INFO, "%sJTAG clock Xmega: %u kHz\n", p,
|
||||
b2_to_u16(buf));
|
||||
|
||||
if (b2_to_u16(buf) > 0) {
|
||||
avrdude_message(MSG_INFO, "%sJTAG clock Xmega : %u kHz\n", p,
|
||||
b2_to_u16(buf));
|
||||
}
|
||||
|
||||
if (jtag3_getparm(pgm, SCOPE_AVR, 1, PARM3_CLK_XMEGA_PDI, buf, 2) < 0)
|
||||
return;
|
||||
avrdude_message(MSG_INFO, "%sPDI clock Xmega : %u kHz\n", p,
|
||||
b2_to_u16(buf));
|
||||
|
||||
if (b2_to_u16(buf) > 0) {
|
||||
avrdude_message(MSG_INFO, "%sPDI/UPDI clock Xmega/megaAVR : %u kHz\n\n", p,
|
||||
b2_to_u16(buf));
|
||||
}
|
||||
}
|
||||
|
||||
static void jtag3_print_parms(PROGRAMMER * pgm)
|
||||
|
@ -2440,14 +2462,11 @@ static unsigned int jtag3_memaddr(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, uns
|
|||
* Non-Xmega device.
|
||||
*/
|
||||
if (p->flags & AVRPART_HAS_UPDI) {
|
||||
if (strcmp(m->desc, "fuses") == 0) {
|
||||
addr += m->offset;
|
||||
if (m->size == 1) {
|
||||
addr = m->offset;
|
||||
}
|
||||
else if (matches(m->desc, "fuse")) {
|
||||
addr = m->offset;
|
||||
}
|
||||
else if (strcmp(m->desc, "flash") != 0) {
|
||||
addr += m->offset;
|
||||
else if (m->size > 1) {
|
||||
addr += m->offset;
|
||||
}
|
||||
}
|
||||
return addr;
|
||||
|
|
|
@ -1275,8 +1275,8 @@ static void jtagmkI_display(PROGRAMMER * pgm, const char * p)
|
|||
jtagmkI_getparm(pgm, PARM_SW_VERSION, &fw) < 0)
|
||||
return;
|
||||
|
||||
avrdude_message(MSG_INFO, "%sICE hardware version: 0x%02x\n", p, hw);
|
||||
avrdude_message(MSG_INFO, "%sICE firmware version: 0x%02x\n", p, fw);
|
||||
avrdude_message(MSG_INFO, "%sICE HW version: 0x%02x\n", p, hw);
|
||||
avrdude_message(MSG_INFO, "%sICE FW version: 0x%02x\n", p, fw);
|
||||
|
||||
jtagmkI_print_parms1(pgm, p);
|
||||
|
||||
|
@ -1320,9 +1320,9 @@ static void jtagmkI_print_parms1(PROGRAMMER * pgm, const char * p)
|
|||
clk = 1e6;
|
||||
}
|
||||
|
||||
avrdude_message(MSG_INFO, "%sVtarget : %.1f V\n", p,
|
||||
avrdude_message(MSG_INFO, "%sVtarget : %.1f V\n", p,
|
||||
6.25 * (unsigned)vtarget / 255.0);
|
||||
avrdude_message(MSG_INFO, "%sJTAG clock : %s (%.1f us)\n", p, clkstr,
|
||||
avrdude_message(MSG_INFO, "%sJTAG clock : %s (%.1f us)\n", p, clkstr,
|
||||
1.0e6 / clk);
|
||||
|
||||
return;
|
||||
|
|
|
@ -2688,11 +2688,11 @@ static void jtagmkII_display(PROGRAMMER * pgm, const char * p)
|
|||
jtagmkII_getparm(pgm, PAR_FW_VERSION, fw) < 0)
|
||||
return;
|
||||
|
||||
avrdude_message(MSG_INFO, "%sM_MCU hardware version: %d\n", p, hw[0]);
|
||||
avrdude_message(MSG_INFO, "%sM_MCU firmware version: %d.%02d\n", p, fw[1], fw[0]);
|
||||
avrdude_message(MSG_INFO, "%sS_MCU hardware version: %d\n", p, hw[1]);
|
||||
avrdude_message(MSG_INFO, "%sS_MCU firmware version: %d.%02d\n", p, fw[3], fw[2]);
|
||||
avrdude_message(MSG_INFO, "%sSerial number: %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
avrdude_message(MSG_INFO, "%sM_MCU HW version: %d\n", p, hw[0]);
|
||||
avrdude_message(MSG_INFO, "%sM_MCU FW version: %d.%02d\n", p, fw[1], fw[0]);
|
||||
avrdude_message(MSG_INFO, "%sS_MCU HW version: %d\n", p, hw[1]);
|
||||
avrdude_message(MSG_INFO, "%sS_MCU FW version: %d.%02d\n", p, fw[3], fw[2]);
|
||||
avrdude_message(MSG_INFO, "%sSerial number : %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
p, PDATA(pgm)->serno[0], PDATA(pgm)->serno[1], PDATA(pgm)->serno[2], PDATA(pgm)->serno[3], PDATA(pgm)->serno[4], PDATA(pgm)->serno[5]);
|
||||
|
||||
jtagmkII_print_parms1(pgm, p);
|
||||
|
|
|
@ -117,6 +117,7 @@ SIGN [+-]
|
|||
<strng>\n { yyerror("unterminated character constant");
|
||||
return YYERRCODE; }
|
||||
|
||||
alias { yylval=NULL; return K_ALIAS; }
|
||||
allowfullpagebitstream { yylval=NULL; return K_ALLOWFULLPAGEBITSTREAM; }
|
||||
avr910_devcode { yylval=NULL; return K_AVR910_DEVCODE; }
|
||||
bank_size { yylval=NULL; return K_PAGE_SIZE; }
|
||||
|
@ -137,7 +138,6 @@ dedicated { yylval=new_token(K_DEDICATED); return K_DEDICATED; }
|
|||
default_bitclock { yylval=NULL; return K_DEFAULT_BITCLOCK; }
|
||||
default_parallel { yylval=NULL; return K_DEFAULT_PARALLEL; }
|
||||
default_programmer { yylval=NULL; return K_DEFAULT_PROGRAMMER; }
|
||||
default_safemode { yylval=NULL; return K_DEFAULT_SAFEMODE; }
|
||||
default_serial { yylval=NULL; return K_DEFAULT_SERIAL; }
|
||||
delay { yylval=NULL; return K_DELAY; }
|
||||
desc { yylval=NULL; return K_DESC; }
|
||||
|
|
|
@ -261,6 +261,7 @@ typedef struct avrpart {
|
|||
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
||||
|
||||
LISTID mem; /* avr memory definitions */
|
||||
LISTID mem_alias; /* memory alias definitions */
|
||||
char config_file[PATH_MAX]; /* config file where defined */
|
||||
int lineno; /* config file line number */
|
||||
} AVRPART;
|
||||
|
@ -292,6 +293,11 @@ typedef struct avrmem {
|
|||
OPCODE * op[AVR_OP_MAX]; /* opcodes */
|
||||
} AVRMEM;
|
||||
|
||||
typedef struct avrmem_alias {
|
||||
char desc[AVR_MEMDESCLEN]; /* alias name ("syscfg0" etc.) */
|
||||
AVRMEM *aliased_mem;
|
||||
} AVRMEM_ALIAS;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -307,10 +313,15 @@ int avr_get_output_index(OPCODE * op);
|
|||
|
||||
/* Functions for AVRMEM structures */
|
||||
AVRMEM * avr_new_memtype(void);
|
||||
AVRMEM_ALIAS * avr_new_memalias(void);
|
||||
int avr_initmem(AVRPART * p);
|
||||
AVRMEM * avr_dup_mem(AVRMEM * m);
|
||||
void avr_free_mem(AVRMEM * m);
|
||||
void avr_free_memalias(AVRMEM_ALIAS * m);
|
||||
AVRMEM * avr_locate_mem(AVRPART * p, char * desc);
|
||||
AVRMEM * avr_locate_mem_noalias(AVRPART * p, char * desc);
|
||||
AVRMEM_ALIAS * avr_locate_memalias(AVRPART * p, char * desc);
|
||||
AVRMEM_ALIAS * avr_find_memalias(AVRPART * p, AVRMEM * m_orig);
|
||||
void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, AVRPART * p,
|
||||
int type, int verbose);
|
||||
|
||||
|
@ -831,30 +842,6 @@ int fileio(int op, char * filename, FILEFMT format,
|
|||
#endif
|
||||
|
||||
|
||||
/* formerly safemode.h */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or "efuse") and verifies it. Will try up to tries
|
||||
amount of times before giving up */
|
||||
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm, AVRPART * p, int tries);
|
||||
|
||||
/* Reads the fuses three times, checking that all readings are the same. This will ensure that the before values aren't in error! */
|
||||
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse, PROGRAMMER * pgm, AVRPART * p);
|
||||
|
||||
/* This routine will store the current values pointed to by lfuse, hfuse, and efuse into an internal buffer in this routine
|
||||
when save is set to 1. When save is 0 (or not 1 really) it will copy the values from the internal buffer into the locations
|
||||
pointed to be lfuse, hfuse, and efuse. This allows you to change the fuse bits if needed from another routine (ie: have it so
|
||||
if user requests fuse bits are changed, the requested value is now verified */
|
||||
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse, unsigned char * efuse, unsigned char * fuse);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* formerly update.h */
|
||||
|
||||
enum {
|
||||
|
@ -926,7 +913,6 @@ extern char default_programmer[];
|
|||
extern char default_parallel[];
|
||||
extern char default_serial[];
|
||||
extern double default_bitclock;
|
||||
extern int default_safemode;
|
||||
|
||||
/* This name is fixed, it's only here for symmetry with
|
||||
* default_parallel and default_serial. */
|
||||
|
|
241
src/main.c
241
src/main.c
|
@ -122,9 +122,6 @@ static void usage(void)
|
|||
" is performed in the order specified.\n"
|
||||
" -n Do not write anything to the device.\n"
|
||||
" -V Do not verify.\n"
|
||||
" -u Disable safemode, default when running from a script.\n"
|
||||
" -s Silent safemode operation, will not ask you if\n"
|
||||
" fuses should be changed back.\n"
|
||||
" -t Enter terminal mode.\n"
|
||||
" -E <exitspec>[,<exitspec>] List programmer exit specifications.\n"
|
||||
" -x <extended_param> Pass <extended_param> to programmer.\n"
|
||||
|
@ -132,7 +129,7 @@ static void usage(void)
|
|||
" -q Quell progress output. -q -q for less.\n"
|
||||
" -l logfile Use logfile rather than stderr for diagnostics.\n"
|
||||
" -? Display this usage.\n"
|
||||
"\navrdude version %s, URL: <https://github.com/avrdudes/avrdude>\n"
|
||||
"\navrdude version %s, URL: <https://github.com/mariusgreuel/avrdude>\n"
|
||||
,progname, version);
|
||||
}
|
||||
|
||||
|
@ -349,19 +346,11 @@ int main(int argc, char * argv [])
|
|||
int baudrate; /* override default programmer baud rate */
|
||||
double bitclock; /* Specify programmer bit clock (JTAG ICE) */
|
||||
int ispdelay; /* Specify the delay for ISP clock */
|
||||
int safemode; /* Enable safemode, 1=safemode on, 0=normal */
|
||||
int silentsafe; /* Don't ask about fuses, 1=silent, 0=normal */
|
||||
int init_ok; /* Device initialization worked well */
|
||||
int is_open; /* Device open succeeded */
|
||||
char * logfile; /* Use logfile rather than stderr for diagnostics */
|
||||
enum updateflags uflags = UF_AUTO_ERASE; /* Flags for do_op() */
|
||||
unsigned char safemode_lfuse = 0xff;
|
||||
unsigned char safemode_hfuse = 0xff;
|
||||
unsigned char safemode_efuse = 0xff;
|
||||
unsigned char safemode_fuse = 0xff;
|
||||
|
||||
char * safemode_response;
|
||||
int fuses_updated = 0;
|
||||
#if !defined(WIN32)
|
||||
char * homedir;
|
||||
#endif
|
||||
|
@ -394,7 +383,6 @@ int main(int argc, char * argv [])
|
|||
default_parallel[0] = 0;
|
||||
default_serial[0] = 0;
|
||||
default_bitclock = 0.0;
|
||||
default_safemode = -1;
|
||||
|
||||
init_config();
|
||||
|
||||
|
@ -434,8 +422,6 @@ int main(int argc, char * argv [])
|
|||
baudrate = 0;
|
||||
bitclock = 0.0;
|
||||
ispdelay = 0;
|
||||
safemode = 1; /* Safemode on by default */
|
||||
silentsafe = 0; /* Ask by default */
|
||||
is_open = 0;
|
||||
logfile = NULL;
|
||||
|
||||
|
@ -581,19 +567,10 @@ int main(int argc, char * argv [])
|
|||
quell_progress++ ;
|
||||
break;
|
||||
|
||||
case 's' : /* Silent safemode */
|
||||
silentsafe = 1;
|
||||
safemode = 1;
|
||||
break;
|
||||
|
||||
case 't': /* enter terminal mode */
|
||||
terminal = 1;
|
||||
break;
|
||||
|
||||
case 'u' : /* Disable safemode */
|
||||
safemode = 0;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
upd = parse_op(optarg);
|
||||
if (upd == NULL) {
|
||||
|
@ -975,29 +952,6 @@ int main(int argc, char * argv [])
|
|||
}
|
||||
}
|
||||
|
||||
if (default_safemode == 0) {
|
||||
/* configuration disables safemode: revert meaning of -u */
|
||||
if (safemode == 0)
|
||||
/* -u was given: enable safemode */
|
||||
safemode = 1;
|
||||
else
|
||||
/* -u not given: turn off */
|
||||
safemode = 0;
|
||||
}
|
||||
|
||||
if (isatty(STDIN_FILENO) == 0 && silentsafe == 0)
|
||||
safemode = 0; /* Turn off safemode if this isn't a terminal */
|
||||
|
||||
|
||||
if(p->flags & AVRPART_AVR32) {
|
||||
safemode = 0;
|
||||
}
|
||||
|
||||
if(p->flags & (AVRPART_HAS_PDI | AVRPART_HAS_TPI)) {
|
||||
safemode = 0;
|
||||
}
|
||||
|
||||
|
||||
if (avr_initmem(p) != 0)
|
||||
{
|
||||
avrdude_message(MSG_INFO, "\n%s: failed to initialize memories\n",
|
||||
|
@ -1281,36 +1235,6 @@ int main(int argc, char * argv [])
|
|||
}
|
||||
}
|
||||
|
||||
if (init_ok && safemode == 1) {
|
||||
/* If safemode is enabled, go ahead and read the current low, high,
|
||||
and extended fuse bytes as needed */
|
||||
|
||||
rc = safemode_readfuses(&safemode_lfuse, &safemode_hfuse,
|
||||
&safemode_efuse, &safemode_fuse, pgm, p);
|
||||
|
||||
if (rc != 0) {
|
||||
|
||||
//Check if the programmer just doesn't support reading
|
||||
if (rc == -5)
|
||||
{
|
||||
avrdude_message(MSG_NOTICE, "%s: safemode: Fuse reading not supported by programmer.\n"
|
||||
" Safemode disabled.\n", progname);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
avrdude_message(MSG_INFO, "%s: safemode: To protect your AVR the programming "
|
||||
"will be aborted\n",
|
||||
progname);
|
||||
exitrc = 1;
|
||||
goto main_exit;
|
||||
}
|
||||
} else {
|
||||
//Save the fuses as default
|
||||
safemode_memfuses(1, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||
}
|
||||
}
|
||||
|
||||
if (uflags & UF_AUTO_ERASE) {
|
||||
if ((p->flags & AVRPART_HAS_PDI) && pgm->page_erase != NULL &&
|
||||
lsize(updates) > 0) {
|
||||
|
@ -1386,169 +1310,6 @@ int main(int argc, char * argv [])
|
|||
}
|
||||
}
|
||||
|
||||
/* Right before we exit programming mode, which will make the fuse
|
||||
bits active, check to make sure they are still correct */
|
||||
if (safemode == 1) {
|
||||
/* If safemode is enabled, go ahead and read the current low,
|
||||
* high, and extended fuse bytes as needed */
|
||||
unsigned char safemodeafter_lfuse = 0xff;
|
||||
unsigned char safemodeafter_hfuse = 0xff;
|
||||
unsigned char safemodeafter_efuse = 0xff;
|
||||
unsigned char safemodeafter_fuse = 0xff;
|
||||
unsigned char failures = 0;
|
||||
char yes[1] = {'y'};
|
||||
|
||||
if (quell_progress < 2) {
|
||||
avrdude_message(MSG_INFO, "\n");
|
||||
}
|
||||
|
||||
//Restore the default fuse values
|
||||
safemode_memfuses(0, &safemode_lfuse, &safemode_hfuse, &safemode_efuse, &safemode_fuse);
|
||||
|
||||
/* Try reading back fuses, make sure they are reliable to read back */
|
||||
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
||||
&safemodeafter_efuse, &safemodeafter_fuse, pgm, p) != 0) {
|
||||
/* Uh-oh.. try once more to read back fuses */
|
||||
if (safemode_readfuses(&safemodeafter_lfuse, &safemodeafter_hfuse,
|
||||
&safemodeafter_efuse, &safemodeafter_fuse, pgm, p) != 0) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: Sorry, reading back fuses was unreliable. "
|
||||
"I have given up and exited programming mode\n",
|
||||
progname);
|
||||
exitrc = 1;
|
||||
goto main_exit;
|
||||
}
|
||||
}
|
||||
|
||||
AVRMEM * m;
|
||||
|
||||
/* Now check what fuses are against what they should be */
|
||||
m = avr_locate_mem(p, "fuse");
|
||||
if (compare_memory_masked(m, safemodeafter_fuse, safemode_fuse)) {
|
||||
fuses_updated = 1;
|
||||
avrdude_message(MSG_INFO, "%s: safemode: fuse changed! Was %x, and is now %x\n",
|
||||
progname, safemode_fuse, safemodeafter_fuse);
|
||||
|
||||
|
||||
/* Ask user - should we change them */
|
||||
|
||||
if (silentsafe == 0)
|
||||
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
|
||||
else
|
||||
safemode_response = yes;
|
||||
|
||||
if (tolower((int)(safemode_response[0])) == 'y') {
|
||||
|
||||
/* Enough chit-chat, time to program some fuses and check them */
|
||||
if (safemode_writefuse (safemode_fuse, "fuse", pgm, p,
|
||||
10) == 0) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
|
||||
}
|
||||
else {
|
||||
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now check what fuses are against what they should be */
|
||||
m = avr_locate_mem(p, "lfuse");
|
||||
if (compare_memory_masked(m, safemodeafter_lfuse, safemode_lfuse)) {
|
||||
fuses_updated = 1;
|
||||
avrdude_message(MSG_INFO, "%s: safemode: lfuse changed! Was %x, and is now %x\n",
|
||||
progname, safemode_lfuse, safemodeafter_lfuse);
|
||||
|
||||
|
||||
/* Ask user - should we change them */
|
||||
|
||||
if (silentsafe == 0)
|
||||
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
|
||||
else
|
||||
safemode_response = yes;
|
||||
|
||||
if (tolower((int)(safemode_response[0])) == 'y') {
|
||||
|
||||
/* Enough chit-chat, time to program some fuses and check them */
|
||||
if (safemode_writefuse (safemode_lfuse, "lfuse", pgm, p,
|
||||
10) == 0) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
|
||||
}
|
||||
else {
|
||||
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now check what fuses are against what they should be */
|
||||
m = avr_locate_mem(p, "hfuse");
|
||||
if (compare_memory_masked(m, safemodeafter_hfuse, safemode_hfuse)) {
|
||||
fuses_updated = 1;
|
||||
avrdude_message(MSG_INFO, "%s: safemode: hfuse changed! Was %x, and is now %x\n",
|
||||
progname, safemode_hfuse, safemodeafter_hfuse);
|
||||
|
||||
/* Ask user - should we change them */
|
||||
if (silentsafe == 0)
|
||||
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
|
||||
else
|
||||
safemode_response = yes;
|
||||
if (tolower((int)(safemode_response[0])) == 'y') {
|
||||
|
||||
/* Enough chit-chat, time to program some fuses and check them */
|
||||
if (safemode_writefuse(safemode_hfuse, "hfuse", pgm, p,
|
||||
10) == 0) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
|
||||
}
|
||||
else {
|
||||
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now check what fuses are against what they should be */
|
||||
m = avr_locate_mem(p, "efuse");
|
||||
if (compare_memory_masked(m, safemodeafter_efuse, safemode_efuse)) {
|
||||
fuses_updated = 1;
|
||||
avrdude_message(MSG_INFO, "%s: safemode: efuse changed! Was %x, and is now %x\n",
|
||||
progname, safemode_efuse, safemodeafter_efuse);
|
||||
|
||||
/* Ask user - should we change them */
|
||||
if (silentsafe == 0)
|
||||
safemode_response = terminal_get_input("Would you like this fuse to be changed back? [y/n] ");
|
||||
else
|
||||
safemode_response = yes;
|
||||
if (tolower((int)(safemode_response[0])) == 'y') {
|
||||
|
||||
/* Enough chit-chat, time to program some fuses and check them */
|
||||
if (safemode_writefuse (safemode_efuse, "efuse", pgm, p,
|
||||
10) == 0) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: and is now rescued\n", progname);
|
||||
}
|
||||
else {
|
||||
avrdude_message(MSG_INFO, "%s: and COULD NOT be changed\n", progname);
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (quell_progress < 2) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: ", progname);
|
||||
if (failures == 0) {
|
||||
avrdude_message(MSG_INFO, "Fuses OK (E:%02X, H:%02X, L:%02X)\n",
|
||||
safemodeafter_efuse, safemodeafter_hfuse, safemodeafter_lfuse);
|
||||
}
|
||||
else {
|
||||
avrdude_message(MSG_INFO, "Fuses not recovered, sorry\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (fuses_updated) {
|
||||
exitrc = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
main_exit:
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2019 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/>.
|
||||
*/
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "avrdude.h"
|
||||
}
|
||||
|
||||
#include "usb_com_helper.h"
|
||||
#include "usb_com_locator.h"
|
||||
|
||||
class AvrdudeConsole : public UsbComLocator::IConsole
|
||||
{
|
||||
public:
|
||||
void WriteLine(UsbComLocator::MessageLevel level, const std::string& message) override
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case UsbComLocator::MessageLevel::Verbose:
|
||||
avrdude_message(MSG_NOTICE, "%s: %s\n", progname, message.c_str());
|
||||
break;
|
||||
case UsbComLocator::MessageLevel::Debug:
|
||||
avrdude_message(MSG_DEBUG, "%s: %s\n", progname, message.c_str());
|
||||
break;
|
||||
default:
|
||||
avrdude_message(MSG_INFO, "%s: %s\n", progname, message.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int win32_find_usb_com_port(const char* deviceId, char** port, bool wait_for_device, bool find_related_devices, bool auto_reset)
|
||||
{
|
||||
try
|
||||
{
|
||||
UsbComLocator::Locator::Options options;
|
||||
options.WaitForDevice = wait_for_device;
|
||||
options.FindRelatedDevices = find_related_devices;
|
||||
options.AutoReset = auto_reset;
|
||||
|
||||
AvrdudeConsole console;
|
||||
UsbComLocator::Locator locator(&console);
|
||||
std::string filename = locator.FindPortForDevice(deviceId, &options);
|
||||
if (filename.empty())
|
||||
{
|
||||
*port = nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
filename = "\\\\.\\" + filename;
|
||||
|
||||
size_t bufferSize = filename.size() + 1;
|
||||
*port = static_cast<char*>(malloc(bufferSize));
|
||||
if (*port == nullptr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
strncpy(*port, filename.c_str(), bufferSize);
|
||||
return 0;
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
*port = nullptr;
|
||||
return -1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* Copyright (C) 2019 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 USB_COM_HELPER_H
|
||||
#define USB_COM_HELPER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int win32_find_usb_com_port(const char* deviceId, char** port, bool wait_for_device, bool find_related_devices, bool auto_reset);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // USB_COM_HELPER_H
|
File diff suppressed because it is too large
Load Diff
318
src/safemode.c
318
src/safemode.c
|
@ -1,318 +0,0 @@
|
|||
/*
|
||||
* avrdude - A Downloader/Uploader for AVR device programmers
|
||||
* avrdude is Copyright (C) 2000-2004 Brian S. Dean <bsd@bsdhome.com>
|
||||
*
|
||||
* This file: Copyright (C) 2005-2007 Colin O'Flynn <coflynn@newae.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/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ac_cfg.h"
|
||||
|
||||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
|
||||
/* This value from ac_cfg.h */
|
||||
/*
|
||||
* Writes the specified fuse in fusename (can be "lfuse", "hfuse", or
|
||||
* "efuse") and verifies it. Will try up to tries amount of times
|
||||
* before giving up
|
||||
*/
|
||||
int safemode_writefuse (unsigned char fuse, char * fusename, PROGRAMMER * pgm,
|
||||
AVRPART * p, int tries)
|
||||
{
|
||||
AVRMEM * m;
|
||||
unsigned char fuseread;
|
||||
int returnvalue = -1;
|
||||
|
||||
m = avr_locate_mem(p, fusename);
|
||||
if (m == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Keep trying to write then read back the fuse values */
|
||||
while (tries > 0) {
|
||||
if (avr_write_byte(pgm, p, m, 0, fuse) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pgm->read_byte(pgm, p, m, 0, &fuseread) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Report information to user if needed */
|
||||
avrdude_message(MSG_NOTICE, "%s: safemode: Wrote %s to %x, read as %x. %d attempts left\n",
|
||||
progname, fusename, fuse, fuseread, tries-1);
|
||||
|
||||
/* If fuse wrote OK, no need to keep going */
|
||||
if (fuse == fuseread) {
|
||||
tries = 0;
|
||||
returnvalue = 0;
|
||||
}
|
||||
tries--;
|
||||
}
|
||||
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads the fuses three times, checking that all readings are the
|
||||
* same. This will ensure that the before values aren't in error!
|
||||
*/
|
||||
int safemode_readfuses (unsigned char * lfuse, unsigned char * hfuse,
|
||||
unsigned char * efuse, unsigned char * fuse,
|
||||
PROGRAMMER * pgm, AVRPART * p)
|
||||
{
|
||||
|
||||
unsigned char value;
|
||||
unsigned char fusegood = 0;
|
||||
unsigned char allowfuseread = 1;
|
||||
unsigned char safemode_lfuse;
|
||||
unsigned char safemode_hfuse;
|
||||
unsigned char safemode_efuse;
|
||||
unsigned char safemode_fuse;
|
||||
AVRMEM * m;
|
||||
|
||||
safemode_lfuse = *lfuse;
|
||||
safemode_hfuse = *hfuse;
|
||||
safemode_efuse = *efuse;
|
||||
safemode_fuse = *fuse;
|
||||
|
||||
|
||||
/* Read fuse three times */
|
||||
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||
to generate a verify error */
|
||||
m = avr_locate_mem(p, "fuse");
|
||||
if (m != NULL) {
|
||||
fusegood = 0; /* By default fuse is a failure */
|
||||
if(pgm->read_byte(pgm, p, m, 0, &safemode_fuse) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 1, fuse value: %x\n",progname, safemode_fuse);
|
||||
if(pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 2, fuse value: %x\n",progname, value);
|
||||
if (value == safemode_fuse) {
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 3, fuse value: %x\n",progname, value);
|
||||
if (value == safemode_fuse)
|
||||
{
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Programmer does not allow fuse reading.... no point trying anymore
|
||||
if (allowfuseread == 0)
|
||||
{
|
||||
return -5;
|
||||
}
|
||||
|
||||
if (fusegood == 0) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read fuse properly. "
|
||||
"Programmer may not be reliable.\n", progname);
|
||||
return -1;
|
||||
}
|
||||
else if (fusegood == 1) {
|
||||
avrdude_message(MSG_NOTICE, "%s: safemode: fuse reads as %X\n", progname, safemode_fuse);
|
||||
}
|
||||
|
||||
|
||||
/* Read lfuse three times */
|
||||
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||
to generate a verify error */
|
||||
m = avr_locate_mem(p, "lfuse");
|
||||
if (m != NULL) {
|
||||
fusegood = 0; /* By default fuse is a failure */
|
||||
if (pgm->read_byte(pgm, p, m, 0, &safemode_lfuse) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 1, lfuse value: %x\n",progname, safemode_lfuse);
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 2, lfuse value: %x\n",progname, value);
|
||||
if (value == safemode_lfuse) {
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 3, lfuse value: %x\n",progname, value);
|
||||
if (value == safemode_lfuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Programmer does not allow fuse reading.... no point trying anymore
|
||||
if (allowfuseread == 0)
|
||||
{
|
||||
return -5;
|
||||
}
|
||||
|
||||
|
||||
if (fusegood == 0) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read lfuse properly. "
|
||||
"Programmer may not be reliable.\n", progname);
|
||||
return -1;
|
||||
}
|
||||
else if (fusegood == 1) {
|
||||
avrdude_message(MSG_NOTICE, "%s: safemode: lfuse reads as %X\n", progname, safemode_lfuse);
|
||||
}
|
||||
|
||||
/* Read hfuse three times */
|
||||
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||
to generate a verify error */
|
||||
m = avr_locate_mem(p, "hfuse");
|
||||
if (m != NULL) {
|
||||
fusegood = 0; /* By default fuse is a failure */
|
||||
if (pgm->read_byte(pgm, p, m, 0, &safemode_hfuse) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 1, hfuse value: %x\n",progname, safemode_hfuse);
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 2, hfuse value: %x\n",progname, value);
|
||||
if (value == safemode_hfuse) {
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 3, hfuse value: %x\n",progname, value);
|
||||
if (value == safemode_hfuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Programmer does not allow fuse reading.... no point trying anymore
|
||||
if (allowfuseread == 0)
|
||||
{
|
||||
return -5;
|
||||
}
|
||||
|
||||
if (fusegood == 0) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read hfuse properly. "
|
||||
"Programmer may not be reliable.\n", progname);
|
||||
return -2;
|
||||
}
|
||||
else if (fusegood == 1){
|
||||
avrdude_message(MSG_NOTICE, "%s: safemode: hfuse reads as %X\n", progname, safemode_hfuse);
|
||||
}
|
||||
|
||||
/* Read efuse three times */
|
||||
fusegood = 2; /* If AVR device doesn't support this fuse, don't want
|
||||
to generate a verify error */
|
||||
m = avr_locate_mem(p, "efuse");
|
||||
if (m != NULL) {
|
||||
fusegood = 0; /* By default fuse is a failure */
|
||||
if (pgm->read_byte(pgm, p, m, 0, &safemode_efuse) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 1, efuse value: %x\n",progname, safemode_efuse);
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 2, efuse value: %x\n",progname, value);
|
||||
if (value == safemode_efuse) {
|
||||
if (pgm->read_byte(pgm, p, m, 0, &value) != 0)
|
||||
{
|
||||
allowfuseread = 0;
|
||||
}
|
||||
avrdude_message(MSG_DEBUG, "%s: safemode read 3, efuse value: %x\n",progname, value);
|
||||
if (value == safemode_efuse){
|
||||
fusegood = 1; /* Fuse read OK three times */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Programmer does not allow fuse reading.... no point trying anymore
|
||||
if (allowfuseread == 0)
|
||||
{
|
||||
return -5;
|
||||
}
|
||||
|
||||
if (fusegood == 0) {
|
||||
avrdude_message(MSG_INFO, "%s: safemode: Verify error - unable to read efuse properly. "
|
||||
"Programmer may not be reliable.\n", progname);
|
||||
return -3;
|
||||
}
|
||||
else if (fusegood == 1) {
|
||||
avrdude_message(MSG_NOTICE, "%s: safemode: efuse reads as %X\n", progname, safemode_efuse);
|
||||
}
|
||||
|
||||
*lfuse = safemode_lfuse;
|
||||
*hfuse = safemode_hfuse;
|
||||
*efuse = safemode_efuse;
|
||||
*fuse = safemode_fuse;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This routine will store the current values pointed to by lfuse,
|
||||
* hfuse, and efuse into an internal buffer in this routine when save
|
||||
* is set to 1. When save is 0 (or not 1 really) it will copy the
|
||||
* values from the internal buffer into the locations pointed to be
|
||||
* lfuse, hfuse, and efuse. This allows you to change the fuse bits if
|
||||
* needed from another routine (ie: have it so if user requests fuse
|
||||
* bits are changed, the requested value is now verified
|
||||
*/
|
||||
int safemode_memfuses (int save, unsigned char * lfuse, unsigned char * hfuse,
|
||||
unsigned char * efuse, unsigned char * fuse)
|
||||
{
|
||||
static unsigned char safemode_lfuse = 0xff;
|
||||
static unsigned char safemode_hfuse = 0xff;
|
||||
static unsigned char safemode_efuse = 0xff;
|
||||
static unsigned char safemode_fuse = 0xff;
|
||||
|
||||
switch (save) {
|
||||
|
||||
/* Save the fuses as safemode setting */
|
||||
case 1:
|
||||
safemode_lfuse = *lfuse;
|
||||
safemode_hfuse = *hfuse;
|
||||
safemode_efuse = *efuse;
|
||||
safemode_fuse = *fuse;
|
||||
|
||||
break;
|
||||
/* Read back the fuses */
|
||||
default:
|
||||
*lfuse = safemode_lfuse;
|
||||
*hfuse = safemode_hfuse;
|
||||
*efuse = safemode_efuse;
|
||||
*fuse = safemode_fuse;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -36,6 +36,10 @@
|
|||
#include "avrdude.h"
|
||||
#include "libavrdude.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "msvc/usb_com_helper.h"
|
||||
#endif
|
||||
|
||||
long serial_recv_timeout = 5000; /* ms */
|
||||
|
||||
#define W32SERBUFSIZE 1024
|
||||
|
@ -257,6 +261,13 @@ static int ser_open(char * port, union pinfo pinfo, union filedescriptor *fdp)
|
|||
return net_open(port + strlen("net:"), fdp);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
if (win32_find_usb_com_port(port, &newname, true, true, true) >= 0)
|
||||
{
|
||||
port = newname;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strncasecmp(port, "com", strlen("com")) == 0) {
|
||||
|
||||
// prepend "\\\\.\\" to name, required for port # >= 10
|
||||
|
|
47
src/update.c
47
src/update.c
|
@ -227,6 +227,13 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
return -1;
|
||||
}
|
||||
|
||||
AVRMEM_ALIAS * alias_mem = avr_find_memalias(p, mem);
|
||||
char alias_mem_desc[AVR_DESCLEN + 1] = "";
|
||||
if(alias_mem) {
|
||||
strcat(alias_mem_desc, "/");
|
||||
strcat(alias_mem_desc, alias_mem->desc);
|
||||
}
|
||||
|
||||
if (upd->op == DEVICE_READ) {
|
||||
/*
|
||||
* read out the specified device memory and write it to a file
|
||||
|
@ -238,14 +245,14 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
return -1;
|
||||
}
|
||||
if (quell_progress < 2) {
|
||||
avrdude_message(MSG_INFO, "%s: reading %s memory:\n",
|
||||
progname, mem->desc);
|
||||
avrdude_message(MSG_INFO, "%s: reading %s%s memory:\n",
|
||||
progname, mem->desc, alias_mem_desc);
|
||||
}
|
||||
report_progress(0,1,"Reading");
|
||||
rc = avr_read(pgm, p, upd->memtype, 0);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n",
|
||||
progname, mem->desc, rc);
|
||||
avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n",
|
||||
progname, mem->desc, alias_mem_desc, rc);
|
||||
return -1;
|
||||
}
|
||||
report_progress(1,1,NULL);
|
||||
|
@ -288,8 +295,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
* write the buffer contents to the selected memory type
|
||||
*/
|
||||
if (quell_progress < 2) {
|
||||
avrdude_message(MSG_INFO, "%s: writing %s (%d bytes):\n",
|
||||
progname, mem->desc, size);
|
||||
avrdude_message(MSG_INFO, "%s: writing %s%s (%d bytes):\n",
|
||||
progname, mem->desc, alias_mem_desc, size);
|
||||
}
|
||||
|
||||
if (!(flags & UF_NOWRITE)) {
|
||||
|
@ -306,16 +313,16 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
}
|
||||
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: failed to write %s memory, rc=%d\n",
|
||||
progname, mem->desc, rc);
|
||||
avrdude_message(MSG_INFO, "%s: failed to write %s%s memory, rc=%d\n",
|
||||
progname, mem->desc, alias_mem_desc, rc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vsize = rc;
|
||||
|
||||
if (quell_progress < 2) {
|
||||
avrdude_message(MSG_INFO, "%s: %d bytes of %s written\n", progname,
|
||||
vsize, mem->desc);
|
||||
avrdude_message(MSG_INFO, "%s: %d bytes of %s%s written\n", progname,
|
||||
vsize, mem->desc, alias_mem_desc);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -327,11 +334,11 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
pgm->vfy_led(pgm, ON);
|
||||
|
||||
if (quell_progress < 2) {
|
||||
avrdude_message(MSG_INFO, "%s: verifying %s memory against %s:\n",
|
||||
progname, mem->desc, upd->filename);
|
||||
avrdude_message(MSG_INFO, "%s: verifying %s%s memory against %s:\n",
|
||||
progname, mem->desc, alias_mem_desc, upd->filename);
|
||||
|
||||
avrdude_message(MSG_NOTICE2, "%s: load data %s data from input file %s:\n",
|
||||
progname, mem->desc, upd->filename);
|
||||
avrdude_message(MSG_NOTICE2, "%s: load data %s%s data from input file %s:\n",
|
||||
progname, mem->desc, alias_mem_desc, upd->filename);
|
||||
}
|
||||
|
||||
rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1);
|
||||
|
@ -345,15 +352,15 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
if (quell_progress < 2) {
|
||||
avrdude_message(MSG_NOTICE2, "%s: input file %s contains %d bytes\n",
|
||||
progname, upd->filename, size);
|
||||
avrdude_message(MSG_NOTICE2, "%s: reading on-chip %s data:\n",
|
||||
progname, mem->desc);
|
||||
avrdude_message(MSG_NOTICE2, "%s: reading on-chip %s%s data:\n",
|
||||
progname, mem->desc, alias_mem_desc);
|
||||
}
|
||||
|
||||
report_progress (0,1,"Reading");
|
||||
rc = avr_read(pgm, p, upd->memtype, v);
|
||||
if (rc < 0) {
|
||||
avrdude_message(MSG_INFO, "%s: failed to read all of %s memory, rc=%d\n",
|
||||
progname, mem->desc, rc);
|
||||
avrdude_message(MSG_INFO, "%s: failed to read all of %s%s memory, rc=%d\n",
|
||||
progname, mem->desc, alias_mem_desc, rc);
|
||||
pgm->err_led(pgm, ON);
|
||||
avr_free_part(v);
|
||||
return -1;
|
||||
|
@ -375,8 +382,8 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
|
|||
}
|
||||
|
||||
if (quell_progress < 2) {
|
||||
avrdude_message(MSG_INFO, "%s: %d bytes of %s verified\n",
|
||||
progname, rc, mem->desc);
|
||||
avrdude_message(MSG_INFO, "%s: %d bytes of %s%s verified\n",
|
||||
progname, rc, mem->desc, alias_mem_desc);
|
||||
}
|
||||
|
||||
pgm->vfy_led(pgm, OFF);
|
||||
|
|
|
@ -100,7 +100,7 @@ static int usb_control (PROGRAMMER * pgm,
|
|||
{
|
||||
int nbytes;
|
||||
nbytes = usb_control_msg( PDATA(pgm)->usb_handle,
|
||||
USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||
requestid,
|
||||
val, index, // 2 bytes each of data
|
||||
NULL, 0, // no data buffer in control message
|
||||
|
|
Loading…
Reference in New Issue