3 This file realize a simple programmer, which communicates with our "pkernel"
7 from SerialPort_linux import SerialPort, SerialPortException
9 # baudrate used for initialization
11 # baudrate used for communication with the internal bootloader after init
12 BOOTLOADER_BAUDRATE = 38400
13 # baudrate used for communication with the pkernel program that does the
15 KERNEL_BAUDRATE = 115200
19 # contains the last received checksum from a READ, WRITE or CHECKSUM command
22 class FlashSequence(object):
23 def __init__(self, address, data):
24 self.address = address
29 send a byte to the TTY-device
35 send a word to the TTY-device
38 sendbyte((word >> 8) & 0xFF)
42 send a dword to the TTY-device
44 sendbyte(dword & 0xFF)
45 sendbyte((dword >> 8) & 0xFF)
46 sendbyte((dword >> 16) & 0xFF)
47 sendbyte((dword >> 24) & 0xFF)
51 receive a byte from the TTY-device
53 return ord(tty.read())
57 receive checksum from the bootROM firmware
60 lastchecksum = recvbyte()
61 lastchecksum |= (recvbyte() << 8)
63 def bootromread(address, size):
65 send a READ-command to the bootROM-firmware
69 if (recvbyte() != 0xF1):
72 if (recvbyte() != 0x82):
74 # tell desired address and size
77 # get binary stream of data
79 for _ in range(0, size):
80 data.append(recvbyte())
85 def bootromwrite(address, size, data):
87 send a WRITE-command to the bootROM-firmware
91 if (recvbyte() != 0xF1):
94 if (recvbyte() != 0x83):
96 # tell desired address and size
99 # write binary stream of data
100 for i in range(0, size):
105 def bootromcall(address):
107 send a CALL-command to the bootROM-firmware
111 if (recvbyte() != 0xF1):
114 if (recvbyte() != 0x84):
116 # tell desired address
118 # wait for return parameter - not needed here!
121 # TODO: test this function!
122 def bootromchecksum():
124 send a CHECKSUM-command to the bootROM-firmware
126 # call CHECKSUM command
128 if (recvbyte() != 0xF1):
131 if (recvbyte() != 0x84):
136 def bootrombaudrate(baudrate):
138 send a BAUDRAME-command to the bootROM-firmware
140 # send BAUDRATE command
142 if (recvbyte() != 0xF1):
145 if (recvbyte() != 0x86):
147 # send desired baudrate
150 def pkernchiperase():
152 send a CHIPERASE-command to the pkernel-firmware
155 if (recvbyte() != 0x45):
157 # wait till completion...
158 if (recvbyte() != 0x23):
161 def pkernerase(address, size):
163 send a ERASE-command to the pkernel-firmware
166 if (recvbyte() != 0x11):
170 if (recvbyte() != 0x18):
173 def pkernwrite(address, size, data):
175 send a WRITE-command to the pkernel-firmware
179 if (recvbyte() != 0x37):
181 # tell desired address and size
185 # write binary stream of data
186 for i in range(0, size):
189 if (recvbyte() != 0x28):
192 def readmhxfile(filename): # desired mhx filename
196 filep = open(filename, "r")
197 retval = [] # returns a list of FlashSequence objects
201 # get rid of newline characters
204 # we're only interested in S2 (data sequence with 3 address bytes)
206 if line[0:2] == "S2":
207 byte_count = int(line[2:4], 16)
208 # just to get sure, check if byte count field is valid
209 if (len(line)-4) != (byte_count*2):
210 print sys.argv[0] + ": Warning - inavlid byte count field in " + \
211 sys.argv[1] + ":" + str(linecount) + ", skipping line!"
214 # address and checksum bytes are not needed
216 address = int(line[4:10], 16)
217 datastr = line[10:10+byte_count*2]
219 # convert data hex-byte-string to real byte data list
221 for i in range(0, len(datastr)/2):
222 data.append(int(datastr[2*i:2*i+2], 16))
224 # add flash sequence to our list
225 retval.append(FlashSequence(address, data))
231 print usage of frprog
233 print "Usage: " + execf + " <target mhx-file> [-d DEVICE]"
237 main function of frprog
239 # check command line arguments
243 if len(argv) == 2 and (argv[1] == "-v" or argv[1] == "--version"):
244 print "Version: %VERSION%"
247 if len(argv) != 2 and len(argv) != 4:
251 # standard serial device to communicate with
252 device = "/dev/ttyUSB0"
254 # overrule standard device if provided with -d
262 # read in data from mhx-files before starting
265 bootloaderseqs = readmhxfile("pkernel/pkernel.mhx")
267 bootloaderseqs = readmhxfile("%PREFIX%/share/frprog/pkernel.mhx")
268 pkernelseqs = readmhxfile(argv[1])
269 except IOError as error:
270 print argv[0] + ": Error - couldn't open file " + error.filename + "!"
273 print "Initializing serial port..."
275 tty = SerialPort(device, 100, INIT_BAUDRATE)
277 print "Please press RESET on your board..."
283 if tty.read() == 'F':
285 except SerialPortException:
286 # timeout happened, who cares ;-)
289 # save time at this point for evaluating the duration at the end
290 starttime = time.time()
292 print "OK, trying to set baudrate..."
295 bootrombaudrate(BOOTLOADER_BAUDRATE)
296 except SerialPortException:
297 print "timeout exception: try again ->"
298 bootrombaudrate(BOOTLOADER_BAUDRATE)
299 # just to get sure that the bootloader is really running in new baudrate mode!
302 tty = SerialPort(device, 100, BOOTLOADER_BAUDRATE)
305 print "Transfering pkernel program to IRAM",
307 for seq in bootloaderseqs:
308 if(seq.address <= 0x40000):
312 #print "RAMing", len(seq.data), "bytes at address", hex(addr)
313 bootromwrite(addr, len(seq.data), seq.data)
318 sys.stdout.write(".")
323 # execute our pkernel finally and set pkernel conform baudrate
325 time.sleep(0.1) # just to get sure that the pkernel is really running!
327 tty = SerialPort(device, None, KERNEL_BAUDRATE)
329 print "Performing ChipErase..."
334 for seq in pkernelseqs:
335 # skip seqs only consisting of 0xffs
336 seqset = list(set(seq.data))
337 if len(seqset) == 1 and seqset[0] == 0xff:
339 #print "Flashing", len(seq.data), "bytes at address", hex(seq.address)
340 pkernwrite(seq.address, len(seq.data), seq.data)
345 sys.stdout.write(".")
350 duration = time.time() - starttime
351 print "Procedure complete, took", round(duration, 2), "seconds."
353 sendbyte(0x97) # exit and restart
354 print "Program was started. Have fun!"
357 if __name__ == '__main__':