-
Notifications
You must be signed in to change notification settings - Fork 0
/
loader.py
154 lines (118 loc) · 4.14 KB
/
loader.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
151
152
153
154
import os
import sys
import time
import serial
import wave
from crc16 import crc16
from firmware import FLASH_PAGE_SIZE, FLASH_PAGES
class LoaderError(Exception):
pass
class LoaderSignatureError(LoaderError):
pass
class LoaderCRCError(LoaderError):
pass
class Loader(object):
def __init__(self, device):
self.fp = serial.Serial(device,
57600,
bytesize=8,
parity=serial.PARITY_NONE,
stopbits=2,
timeout=2)
def version(self):
self.fp.write('hi\r\n')
self.fp.flush()
reply = self.fp.readline()
reply = reply.rstrip().split(None, 1)
if not reply or reply[0] != 'disconnect':
raise LoaderSignatureError, "No DISCONNECT device found"
return reply[1]
def read_page(self, page):
self.fp.write('read %x\r\n' % page)
self.wait()
reply = self.fp.read(FLASH_PAGE_SIZE + 6)
if len(reply) != FLASH_PAGE_SIZE + 6:
raise LoaderError, \
"Reply to short for read command, length = %d" % len(reply)
data = reply[:FLASH_PAGE_SIZE]
crc = int(reply[FLASH_PAGE_SIZE:], 16)
if crc16(data) != crc:
raise LoaderCRCError, "CRC16 error"
return data
def write_page(self, page, data):
if len(data) > FLASH_PAGE_SIZE:
raise LoaderError, "data is larger than page size"
crc = crc16(data)
self.fp.write('write %x %x %x\r\n' % (page, len(data), crc))
self.fp.write(data)
self.fp.flush()
self.wait()
def custom(self, cmd):
self.fp.write("%s\r\n" % cmd)
self.fp.flush()
def wait(self, timeout=2):
"""Wait for okay reply"""
self.fp.setTimeout(timeout)
reply = self.fp.readline()
if reply != 'ok\r\n':
raise LoaderError, "got %r instead of OK" % reply
def test_hardware(loader):
print 'Writing to flash'
data = os.urandom(FLASH_PAGE_SIZE)
loader.write_page(FLASH_PAGES - 1, data)
print 'Reading from flash'
rdata = loader.read_page(FLASH_PAGES - 1)
if data != rdata:
raise LoaderError, "data mismatch"
print 'Testing speaker with "saw"'
loader.custom('saw')
loader.wait(5)
print 'Testing beeper'
loader.custom('zoom')
loader.wait(5)
print 'Testing busy beeper'
loader.custom('busy')
loader.wait(5)
print 'Testing ring'
loader.custom('ring')
loader.wait(8)
def flash_data(loader, data, page_no=0):
while data:
page = data[:FLASH_PAGE_SIZE]
data = data[FLASH_PAGE_SIZE:]
loader.write_page(page_no, page)
page_no += 1
sys.stdout.write('.')
sys.stdout.flush()
sys.stdout.write('\n')
if __name__ == "__main__":
from optparse import OptionParser
parser = OptionParser()
parser.add_option("-d", "--device",
dest="device", default="/dev/ttyUSB0",
help="Specify serial device (default %default)")
parser.add_option("--hwtest", dest="hwtest", default=False,
action="store_true", help="Run hardware test")
parser.add_option("--go", dest="go", default=False,
action="store_true", help="Enter normal operation mode")
parser.add_option("--monitor", dest="monitor", default=False,
action="store_true", help="Enter monitor mode")
parser.add_option("-l", "--load", dest="firmware",
help="Flash firmware file")
(options, args) = parser.parse_args()
loader = Loader(options.device)
version = loader.version()
print 'DISCONNECT device version %r found' % version
if options.hwtest:
test_hardware(loader)
elif options.go:
loader.custom('go')
elif options.firmware:
with open(options.firmware, 'rb') as fp:
data = fp.read()
flash_data(loader, data)
if options.monitor:
loader.fp.setTimeout(None)
while True:
reply = loader.fp.readline()
sys.stdout.write(reply)