Merge branch 'master' of wien.tomnetworks.com:pyfrprog
[pyfrprog.git] / frprog.py
1 #!/usr/bin/env python
2 import sys, time
3 from SerialPort_linux import *
4
5 # serial device to communicate with
6 DEVICE="/dev/ttyUSB0"
7 # baudrate used for initialization
8 INIT_BAUDRATE=9600
9 # baudrate used for communication after init
10 REAL_BAUDRATE=38400
11
12 # contains the last received checksum from a READ, WRITE or CHECKSUM command
13 last_checksum = 0
14
15 def sendByte(byte):
16         time.sleep(0.001) # just to get sure, wait 1ms
17         tty.write(chr(byte))
18
19 def sendWord(word):
20         sendByte(word & 0xFF)
21         sendByte((word >> 8) & 0xFF)
22
23 def sendDWord(dword):
24         sendByte(dword & 0xFF)
25         sendByte((dword >> 8) & 0xFF)
26         sendByte((dword >> 16) & 0xFF)
27         sendByte((dword >> 24) & 0xFF)
28
29 def recvByte():
30         return ord(tty.read())
31
32 def recvChecksum():
33         global last_checksum
34         last_checksum = recvByte()
35         last_checksum |= (recvByte() << 8)
36
37 def cmdREAD(address, size):
38         # send READ command
39         sendByte(0x01)
40         if (recvByte() != 0xF1):
41                 raise Exception
42         sendByte(0x02)
43         if (recvByte() != 0x82):
44                 raise Exception
45         # tell desired address and size
46         sendDWord(address)
47         sendWord(size)
48         # get binary stream of data
49         data = []
50         for i in range(0, size):
51                 data.append(recvByte())
52         # get checksum
53         recvChecksum()
54         return data
55
56 def cmdWRITE(address, size, data):
57         # send WRITE command
58         sendByte(0x01)
59         if (recvByte() != 0xF1):
60                 raise Exception
61         sendByte(0x03)
62         if (recvByte() != 0x83):
63                 raise Exception
64         # tell desired address and size
65         sendDWord(address)
66         sendWord(size)
67         # write binary stream of data
68         for i in range(0, size):
69                 sendByte(data[i])
70         # get checksum
71         recvChecksum()
72
73 # TODO: test this function!
74 def cmdCALL(address):
75         # send CALL command
76         sendByte(0x01)
77         if (recvByte() != 0xF1):
78                 raise Exception
79         sendByte(0x04)
80         if (recvByte() != 0x84):
81                 raise Exception
82         # tell desired address
83         sendDWord(address)
84         # wait for return parameter - not needed here!
85         #return recvByte()
86
87 # TODO: test this function!
88 def cmdCHECKSUM():
89         # call CHECKSUM command
90         sendByte(0x01)
91         if (recvByte() != 0xF1):
92                 raise Exception
93         sendByte(0x05)
94         if (recvByte() != 0x84):
95                 raise Exception
96         # get checksum
97         recvChecksum()
98
99 def cmdBAUDRATE(baudrate):
100         # send BAUDRATE command
101         sendByte(0x01)
102         if (recvByte() != 0xF1):
103                 raise Exception
104         sendByte(0x06)
105         if (recvByte() != 0x86):
106                 raise Exception
107         # send desired baudrate
108         sendDWord(baudrate)
109
110
111 class FlashSequence(object):
112         def __init__(self, address, data):
113                 self.address = address
114                 self.data = data
115
116 def read_mhx_file(fp): # needs a file handle to the desired mhx file
117         retval = [] # returns a list of FlashSequence objects
118         linecount = 0
119         for line in fp:
120                 linecount += 1
121                 # get rid of newline characters
122                 line = line.strip()
123
124                 # we're only interested in S2 (data sequence with 3 address bytes) records by now
125                 if line[0:2] == "S2":
126                         byte_count = int(line[2:4], 16)
127                         # just to get sure, check if byte count field is valid
128                         if (len(line)-4) != (byte_count*2):
129                                 print sys.argv[0] + ": Warning - inavlid byte count field in " + \
130                                         sys.argv[1] + ":" + str(linecount) + ", skipping line!"
131                                 continue
132
133                         # address and checksum bytes are not needed
134                         byte_count -= 4
135                         address = int(line[4:10], 16)
136                         datastr = line[10:10+byte_count*2]
137
138                         # convert data hex-byte-string to real byte data list
139                         data = []
140                         for i in range(0, len(datastr)/2):
141                                 data.append(int(datastr[2*i:2*i+2], 16))
142
143                         # add flash sequence to our list
144                         retval.append(FlashSequence(address, data))
145         return retval
146
147
148 # check command line arguments
149 if len(sys.argv) != 2:
150         print "Usage: " + sys.argv[0] + " [mhx-file]"
151         sys.exit(1)
152
153 # read in data from mhx-file before starting
154 try:
155         fp = open(sys.argv[1], "r")
156 except IOError:
157         print sys.argv[0] + ": Error - couldn't open file " + sys.argv[1] + "!"
158         sys.exit(1)
159
160 # get list of all our address/data pairs to flash
161 flashseqs = read_mhx_file(fp)
162 fp.close()
163
164 print "The following flash sequences have been read in:"
165 for seq in flashseqs:
166         print hex(seq.address) + ":", seq.data
167
168 print "Initializing serial port..."
169 tty = SerialPort(DEVICE, 100, INIT_BAUDRATE)
170
171 print "Please press RESET on your 1337 board..."
172
173 while 1:
174         tty.write('V')
175         tty.flush()
176         try: 
177                 if tty.read() == 'F':
178                         break
179         except SerialPortException: 
180                 # timeout happened, who cares ;-)
181                 pass
182
183 print "OK, trying to set baudrate..."
184 # set baudrate
185 cmdBAUDRATE(REAL_BAUDRATE)
186 tty = SerialPort(DEVICE, 100, REAL_BAUDRATE)
187
188 # let the fun begin!
189 for seq in flashseqs:
190         if(seq.address <= 0x40000):
191                 addr = seq.address
192         else:
193                 continue
194         print "RAMing", len(seq.data), "bytes at address", hex(addr)
195         cmdWRITE(addr, len(seq.data), seq.data)
196         tty.flush()
197
198 cmdCALL(0x30000);
199 sys.exit(0)
200
201
202 # some tests here.......
203 """
204 # execute (existing) program in ram
205 cmdCALL(0x00033ffc)
206 sys.exit(0)
207 """
208
209 # read something from the IRAM
210 #print cmdREAD(0x00030000, 32)
211
212 #data = []
213 #for i in range(0, 32):
214 #       data.append(i)
215 #cmdWRITE(0x00030000, 32, data)
216
217
218 """
219 # write something to the begin of the IRAM
220 data_wr = []
221 checksum = 0
222 for i in range(0, 0x400):
223         value = i%256
224         data_wr.append(value)
225         checksum = (checksum + value) % (2**16)
226
227 print "Calculated checksum:", checksum
228 print "Writing", data_wr, "to the IRAM..."
229 cmdWRITE(0x00030000, len(data_wr), data_wr)
230 print "Received Checksum:", last_checksum
231 print
232
233 print "Reading from the IRAM again..."
234 data_re = cmdREAD(0x00030000, len(data_wr))
235 print "Received data:", data_re, "Checksum:", last_checksum
236 """
237
238 """
239 # see whats in the iram at the moment
240 data_wr = []
241 print "Reading from the IRAM..."
242 data_re = cmdREAD(0x00030000, 0x10000-4)
243 print "Received data:", data_re, "Checksum:", last_checksum
244 """
245
246 """
247 # see whats in the dram at the moment
248 data_wr = []
249 print "Reading from the DRAM..."
250 data_re = cmdREAD(0x0002C000, 0x10000-0xC000-4)
251 print "Received data:", data_re, "Checksum:", last_checksum
252 """
253
254 """
255 # blank the iram
256 data_wr = []
257 for i in range(0, 0x10000-4):
258         value = 0
259         data_wr.append(value)
260
261 print "Writing", data_wr, "to the IRAM..."
262 cmdWRITE(0x00030000, len(data_wr), data_wr)
263 print "Received Checksum:", last_checksum
264 print
265 """
266
267 """
268 # blank the dram
269 data_wr = []
270 for i in range(0, 0x10000-0xC000-4):
271         value = 0
272         data_wr.append(value)
273
274 print "Writing", data_wr, "to the DRAM..."
275 cmdWRITE(0x0002C000, len(data_wr), data_wr)
276 print "Received Checksum:", last_checksum
277 print
278 """
279
280 """
281 # write some data in the iram and try to execute it
282 data_wr =[
283                 0x9B,0x00,
284                 0x0D,0x4e,
285                 0xcf,0xf1,
286                 0x16,0x01,
287                 0x9b,0x05,
288                 0x04,0xc7,
289                 0xc1,0x06,
290                 0x16,0x56,
291                 0xe0,0xfb, #branch
292                 0x9f,0xa0,0x9f,0xa0,0x9f,0xa0, #nop
293                 0x9f,0xa0,0x9f,0xa0,0x9f,0xa0,
294                 0x9f,0xa0,0x9f,0xa0,0x9f,0xa0,
295                 0x9f,0xa0,0x9f,0xa0,0x9f,0xa0,
296                 0x9f,0xa0,0x9f,0xa0,0x9f,0xa0,
297                 0x9f,0xa0,0x9f,0xa0,0x9f,0xa0,
298                 0x9f,0xa0,0x9f,0xa0,0x9f,0xa0]
299 print "Writing", data_wr, "to the IRAM..."
300 cmdWRITE(0x00030000, len(data_wr), data_wr)
301 print "Received Checksum:", last_checksum
302 print
303 cmdCALL(0x00030000)
304 """