Skip to content

Commit 722e7a1

Browse files
committed
faster verify, full signature, and UNO example
1 parent 86276dd commit 722e7a1

File tree

4 files changed

+117
-20
lines changed

4 files changed

+117
-20
lines changed

adafruit_avrprog.py

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,32 +68,34 @@ def init(self, sck_pin, mosi_pin, miso_pin, rst_pin):
6868
self._rst.value = True
6969

7070

71-
def verify_sig(self, chip):
71+
def verify_sig(self, chip, verbose=False):
7272
"""
7373
Verify that the chip is connected properly, responds to commands,
7474
and has the correct signature. Returns True/False based on success
7575
"""
7676
self.begin()
7777
sig = self.read_signature()
7878
self.end()
79-
#print("Signature: ", [hex(i) for i in sig])
79+
if verbose:
80+
print("Found signature: %s" % [hex(i) for i in sig])
8081
if sig != chip['sig']:
8182
return False
8283
return True
8384

84-
def program_file(self, chip, file_name, verbose=False):
85+
def program_file(self, chip, file_name, verbose=False, verify=True):
8586
"""
8687
Perform a chip erase and program from a file that
87-
contains Intel HEX data. Does not verify the memory post-write!
88+
contains Intel HEX data. Returns true on verify-success, False on
89+
verify-failure. If 'verify' is False, return will always be True
8890
"""
8991
if not self.verify_sig(chip):
9092
raise RuntimeError("Signature read failure")
9193

92-
self.begin()
9394
if verbose:
9495
print("Erasing chip....")
9596
self.erase_chip()
9697

98+
self.begin()
9799
hexfile = open(file_name, 'r')
98100

99101
page_size = chip['page_size']
@@ -114,8 +116,27 @@ def program_file(self, chip, file_name, verbose=False):
114116
print("Programming page @ $%04X" % (page_addr))
115117
#print("From HEX file: ", page_buffer)
116118
self._flash_page(bytearray(page_buffer), page_addr, page_size)
119+
120+
if not verify:
121+
continue
122+
123+
if verbose:
124+
print("Verifying page @ $%04X" % page_addr)
125+
read_buffer = bytearray(page_size)
126+
self.read(page_addr, read_buffer)
127+
#print("From memory: ", read_buffer)
128+
129+
if page_buffer != read_buffer:
130+
if verbose:
131+
# pylint: disable=line-too-long
132+
print("Verify fail at address %04X\nPage should be: %s\nBut contains: %s" % (page_addr, page_buffer, read_buffer))
133+
# pylint: enable=line-too-long
134+
self.end()
135+
return False
136+
117137
hexfile.close()
118138
self.end()
139+
return True
119140

120141
def verify_file(self, chip, file_name, verbose=False):
121142
"""
@@ -195,6 +216,16 @@ def verify_fuses(self, chip, low=None, high=None, ext=None, lock=None):
195216
return False
196217
return True
197218

219+
220+
def erase_chip(self):
221+
"""
222+
Fully erases the chip.
223+
"""
224+
self.begin()
225+
self._transaction((0xAC, 0x80, 0, 0))
226+
self._busy_wait()
227+
self.end()
228+
198229
#################### Mid level
199230

200231
def begin(self):
@@ -223,8 +254,9 @@ def read_signature(self):
223254
Requires calling begin() beforehand to put in programming mode.
224255
"""
225256
# signature is last byte of two transactions:
226-
sig = [self._transaction((0x30, 0, 0x01, 0))[2]]
227-
sig.append(self._transaction((0x30, 0, 0x02, 0))[2])
257+
sig = []
258+
for i in range(3):
259+
sig.append(self._transaction((0x30, 0, i, 0))[2])
228260
return sig
229261

230262
def read(self, addr, read_buffer):
@@ -242,14 +274,6 @@ def read(self, addr, read_buffer):
242274
read_buffer[i*2] = low
243275
read_buffer[i*2+1] = high
244276

245-
def erase_chip(self):
246-
"""
247-
Fully erases the chip.
248-
Requires calling begin() beforehand to put in programming mode.
249-
"""
250-
self._transaction((0xAC, 0x80, 0, 0))
251-
self._busy_wait()
252-
253277
#################### Low level
254278
def _flash_word(self, addr, low, high):
255279
self._transaction((0x40, addr >> 8, addr, low))

examples/trinket_programmer/trinket_prog.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
# Each chip has to have a definition so the script knows how to find it
1010
attiny85 = {'name': "ATtiny85"}
11-
attiny85['sig'] = [0x93, 0x0b]
11+
attiny85['sig'] = [0x1E, 0x93, 0x0B]
1212
attiny85['flash_size'] = 8192
1313
attiny85['page_size'] = 64
1414
attiny85['fuse_mask'] = (0xFF, 0xFF, 0x07, 0x3F)
@@ -29,9 +29,6 @@ def error(err):
2929
error("Failure verifying fuses!")
3030

3131
print("Programming flash from file")
32-
avrprog.program_file(attiny85, "trinket.hex", verbose=True)
33-
34-
print("Verifying flash vs file")
35-
avrprog.verify_file(attiny85, "trinket.hex", verbose=True)
32+
avrprog.program_file(attiny85, "trinket.hex", verbose=True, verify=True)
3633

3734
print("Done!")
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
:107E0000112484B714BE81FFF0D085E080938100F7
2+
:107E100082E08093C00088E18093C10086E0809377
3+
:107E2000C20080E18093C4008EE0C9D0259A86E02C
4+
:107E300020E33CEF91E0309385002093840096BBD3
5+
:107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4
6+
:107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7
7+
:107E6000A2D0813461F49FD0082FAFD0023811F036
8+
:107E7000013811F484E001C083E08DD089C08234E0
9+
:107E800011F484E103C0853419F485E0A6D080C0E4
10+
:107E9000853579F488D0E82EFF2485D0082F10E0AE
11+
:107EA000102F00270E291F29000F111F8ED06801E7
12+
:107EB0006FC0863521F484E090D080E0DECF843638
13+
:107EC00009F040C070D06FD0082F6DD080E0C81688
14+
:107ED00080E7D80618F4F601B7BEE895C0E0D1E017
15+
:107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8
16+
:107EF00018F0F601B7BEE89568D007B600FCFDCFD4
17+
:107F0000A601A0E0B1E02C9130E011968C91119780
18+
:107F100090E0982F8827822B932B1296FA010C0160
19+
:107F200087BEE89511244E5F5F4FF1E0A038BF0790
20+
:107F300051F7F601A7BEE89507B600FCFDCF97BE46
21+
:107F4000E89526C08437B1F42ED02DD0F82E2BD052
22+
:107F50003CD0F601EF2C8F010F5F1F4F84911BD097
23+
:107F6000EA94F801C1F70894C11CD11CFA94CF0C13
24+
:107F7000D11C0EC0853739F428D08EE10CD085E9AC
25+
:107F80000AD08FE07ACF813511F488E018D01DD067
26+
:107F900080E101D065CF982F8091C00085FFFCCF94
27+
:107FA0009093C60008958091C00087FFFCCF809118
28+
:107FB000C00084FD01C0A8958091C6000895E0E648
29+
:107FC000F0E098E1908380830895EDDF803219F02E
30+
:107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA
31+
:107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6
32+
:047FF000FF270994CA
33+
:027FFE00040479
34+
:0400000300007E007B
35+
:00000001FF

examples/uno_optiboot/program_uno.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# UNO Optiboot programming example
2+
3+
import board
4+
import adafruit_avrprog
5+
6+
avrprog = adafruit_avrprog.AVRprog()
7+
avrprog.init(board.SCK, board.MOSI, board.MISO, board.D5)
8+
9+
# Each chip has to have a definition so the script knows how to find it
10+
atmega328p = {'name': "ATmega328P"}
11+
atmega328p['sig'] = [0x1E, 0x95, 0x0F]
12+
atmega328p['flash_size'] = 32768
13+
atmega328p['page_size'] = 128
14+
atmega328p['fuse_mask'] = (0xFF, 0xFF, 0x07, 0x3F)
15+
16+
# Helper to print out errors for us
17+
def error(err):
18+
print("ERROR: "+err)
19+
avrprog.end()
20+
while True:
21+
pass
22+
23+
if not avrprog.verify_sig(atmega328p, verbose=True):
24+
error("Signature read failure")
25+
print("Found", atmega328p['name'])
26+
27+
# Since we are unsetting the lock fuse, an erase is required!
28+
avrprog.erase_chip()
29+
30+
avrprog.write_fuses(atmega328p, low=0xFF, high=0xDE, ext=0x05, lock=0x3F)
31+
if not avrprog.verify_fuses(atmega328p, low=0xFF, high=0xDE, ext=0x05, lock=0x3F):
32+
error("Failure programming fuses: "+str([hex(i) for i in avrprog.read_fuses(atmega328p)]))
33+
34+
print("Programming flash from file")
35+
avrprog.program_file(atmega328p, "optiboot_atmega328.hex", verbose=True, verify=True)
36+
37+
avrprog.write_fuses(atmega328p, lock=0x0F)
38+
if not avrprog.verify_fuses(atmega328p,lock=0x0F):
39+
error("Failure verifying fuses!")
40+
41+
print("Done!")

0 commit comments

Comments
 (0)