2 import sys, time, pyftdi
4 # serial device to communicate with
7 # baudrate used for initialization
9 # baudrate used for communication with the internal bootloader after init
10 BOOTLOADER_BAUDRATE=38400
11 # baudrate used for communication with the pkernel program that does the flashing eventually
12 KERNEL_BAUDRATE=1000000
14 # contains the last received checksum from a READ, WRITE or CHECKSUM command
17 class FlashSequence(object):
18 def __init__(self, address, data):
19 self.address = address
23 tty.write_data(chr(byte))
27 sendByte((word >> 8) & 0xFF)
30 sendByte(dword & 0xFF)
31 sendByte((dword >> 8) & 0xFF)
32 sendByte((dword >> 16) & 0xFF)
33 sendByte((dword >> 24) & 0xFF)
36 bla = tty.read_data(1)
38 bla = tty.read_data(1)
43 last_checksum = recvByte()
44 last_checksum |= (recvByte() << 8)
46 def bootromREAD(address, size):
49 if (recvByte() != 0xF1):
52 if (recvByte() != 0x82):
54 # tell desired address and size
57 # get binary stream of data
59 for i in range(0, size):
60 data.append(recvByte())
65 def bootromWRITE(address, size, data):
68 if (recvByte() != 0xF1):
71 if (recvByte() != 0x83):
73 # tell desired address and size
76 # write binary stream of data
77 for i in range(0, size):
82 # TODO: test this function!
83 def bootromCALL(address):
86 if (recvByte() != 0xF1):
89 if (recvByte() != 0x84):
91 # tell desired address
93 # wait for return parameter - not needed here!
96 # TODO: test this function!
97 def bootromCHECKSUM():
98 # call CHECKSUM command
100 if (recvByte() != 0xF1):
103 if (recvByte() != 0x84):
108 def bootromBAUDRATE(baudrate):
109 # send BAUDRATE command
111 if (recvByte() != 0xF1):
114 if (recvByte() != 0x86):
116 # send desired baudrate
119 def pkernCHIPERASE():
121 if (recvByte() != 0x45):
123 # wait till completion...
124 if (recvByte() != 0x23):
127 def pkernERASE(address, size):
129 if (recvByte() != 0x11):
133 if (recvByte() != 0x18):
136 def pkernWRITE(address, size, data):
139 if (recvByte() != 0x37):
141 # tell desired address and size
145 # write binary stream of data
146 for i in range(0, size):
149 if (recvByte() != 0x28):
152 def readMHXFile(filename): # desired mhx filename
153 fp = open(filename, "r")
154 retval = [] # returns a list of FlashSequence objects
158 # get rid of newline characters
161 # we're only interested in S2 (data sequence with 3 address bytes) records by now
162 if line[0:2] == "S2":
163 byte_count = int(line[2:4], 16)
164 # just to get sure, check if byte count field is valid
165 if (len(line)-4) != (byte_count*2):
166 print sys.argv[0] + ": Warning - inavlid byte count field in " + \
167 sys.argv[1] + ":" + str(linecount) + ", skipping line!"
170 # address and checksum bytes are not needed
172 address = int(line[4:10], 16)
173 datastr = line[10:10+byte_count*2]
175 # convert data hex-byte-string to real byte data list
177 for i in range(0, len(datastr)/2):
178 data.append(int(datastr[2*i:2*i+2], 16))
180 # add flash sequence to our list
181 retval.append(FlashSequence(address, data))
186 # check command line arguments
190 print "Usage: " + argv[0] + " [target mhx-file]"
193 # read in data from mhx-files before starting
196 bootloaderseqs = readMHXFile("pkernel/pkernel.mhx")
197 except IOError as error1:
198 bootloaderseqs = readMHXFile("%PREFIX%/share/frprog/pkernel.mhx")
199 pkernelseqs = readMHXFile(argv[1])
200 except IOError as error:
201 print argv[0] + ": Error - couldn't open file " + error.filename + "!"
204 print "Initializing serial port..."
207 tty.usb_open(DEVICE1, DEVICE2)
208 tty.set_baudrate(INIT_BAUDRATE)
209 #tty.set_latency_timer(100)
210 #print "latency:", tty.get_latency_timer()
212 print "Please press RESET on your board..."
217 if tty.read_data(1) == 'F':
219 except Exception: # hm... thats not true atm :/ no timeout here i think
220 # timeout happened, who cares ;-)
223 starttime = time.time() # save time at this point for evaluating the duration at the end
225 print "OK, trying to set baudrate..."
227 bootromBAUDRATE(BOOTLOADER_BAUDRATE)
228 time.sleep(0.1) # just to get sure that the bootloader is really running in new baudrate mode!
231 tty.usb_open(DEVICE1, DEVICE2)
232 tty.set_baudrate(BOOTLOADER_BAUDRATE)
234 print "Transfering pkernel program to IRAM",
236 for seq in bootloaderseqs:
237 if(seq.address <= 0x40000):
241 #print "RAMing", len(seq.data), "bytes at address", hex(addr)
242 bootromWRITE(addr, len(seq.data), seq.data)
243 sys.stdout.write(".")
247 # execute our pkernel finally and set pkernel conform baudrate
249 time.sleep(0.1) # just to get sure that the pkernel is really running!
252 tty.usb_open(DEVICE1, DEVICE2)
253 tty.set_baudrate(KERNEL_BAUDRATE)
255 print "Performing ChipErase..."
259 for seq in pkernelseqs:
260 # skip seqs only consisting of 0xffs
261 seqset = list(set(seq.data))
262 if len(seqset) == 1 and seqset[0] == 0xff:
264 #print "Flashing", len(seq.data), "bytes at address", hex(seq.address)
265 pkernWRITE(seq.address, len(seq.data), seq.data)
266 sys.stdout.write(".")
270 duration = time.time() - starttime
271 print "Procedure complete, took", round(duration, 2), "seconds."
273 sendByte(0x97) # exit and restart
274 print "Program was started. Have fun!"
277 if __name__ == '__main__':