forked from mraardvark/pyupdi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pyupdi.py
executable file
·150 lines (122 loc) · 5.44 KB
/
pyupdi.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#!/usr/bin/env python
from device.device import Device
from updi.nvm import UpdiNvmProgrammer
import sys
import argparse
import re
import logging
"""
Copyright (c) 2016 Atmel Corporation, a wholly owned subsidiary of Microchip Technology Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
"""
pyupdi is a Python utility for programming AVR devices with UPDI interface
using a standard TTL serial port.
Connect RX and TX together with a suitable resistor and connect this node
to the UPDI pin of the AVR device.
Be sure to connect a common ground, and use a TTL serial adapter running at
the same voltage as the AVR device.
Vcc Vcc
+-+ +-+
| |
+---------------------+ | | +--------------------+
| Serial port +-+ +-+ AVR device |
| | +----------+ | |
| TX +------+ 4k7 +---------+ UPDI |
| | +----------+ | | |
| | | | |
| RX +----------------------+ | |
| | | |
| +--+ +--+ |
+---------------------+ | | +--------------------+
+-+ +-+
GND GND
"""
def _main():
parser = argparse.ArgumentParser(description="Simple command line"
" interface for UPDI programming")
parser.add_argument("-d", "--device", choices=Device.get_supported_devices(),
required=True, help="Target device")
parser.add_argument("-c", "--comport", required=True,
help="Com port to use (Windows: COMx | *nix: /dev/ttyX)")
parser.add_argument("-e", "--erase", action="store_true",
help="Perform a chip erase (implied with --flash)")
parser.add_argument("-b", "--baudrate", type=int, default=115200)
parser.add_argument("-f", "--flash", help="Intel HEX file to flash.")
parser.add_argument("-fs", "--fuses", action="append", nargs="*",
help="Fuse to set (syntax: fuse_nr:0xvalue)")
parser.add_argument("-v", "--verbose", action="store_true",
help="Set verbose mode")
args = parser.parse_args(sys.argv[1:])
if args.fuses is None and args.flash is None and not args.erase:
print("No action (erase, flash or fuses)")
sys.exit(0)
if args.verbose:
logging.basicConfig(format="%(levelname)s:%(name)s %(message)s",
level=logging.INFO)
else:
logging.basicConfig(format="%(levelname)s:%(name)s %(message)s",
level=logging.WARNING)
nvm = UpdiNvmProgrammer(comport=args.comport,
baud=args.baudrate,
device=Device(args.device))
try:
nvm.enter_progmode()
except:
print("Device is locked. Performing unlock with chip erase.")
nvm.unlock_device()
nvm.get_device_info()
if not _process(nvm, args):
print("Error during processing")
nvm.leave_progmode()
def _process(nvm, args):
if args.erase:
try:
nvm.chip_erase()
except:
return False
if args.fuses is not None:
for fslist in args.fuses:
for fsarg in fslist:
if not re.match("^[0-9]+:0x[0-9a-fA-F]+$", fsarg):
print("Bad fuses format {}. Expected fuse_nr:0xvalue".format(fsarg))
continue
lst = fsarg.split(":0x")
fusenum = int(lst[0])
value = int(lst[1], 16)
if not _set_fuse(nvm, fusenum, value):
return False
if args.flash is not None:
return _flash_file(nvm, args.flash)
return True
def _flash_file(nvm, filename):
data, start_address = nvm.load_ihex(filename)
fail=False
nvm.chip_erase()
nvm.write_flash(start_address, data)
# Read out again
readback = nvm.read_flash(nvm.device.flash_start, len(data))
for i, _ in enumerate(data):
if data[i] != readback[i]:
print("Verify error at location 0x{0:04X}: expected 0x{1:02X} read 0x{2:02X} ".format(i, data[i], readback[i]))
fail=True
if not fail:
print("Programming successful")
return not fail
def _set_fuse(nvm, fusenum, value):
nvm.write_fuse(fusenum, value)
actual_val = nvm.read_fuse(fusenum)
ret = actual_val == value
if not ret:
print("Verify error for fuse {0}, expected 0x{1:02X} read 0x{2:02X}".format(fusenum, value, actual_val))
return ret
if __name__ == "__main__":
_main()