red-bsl.py

00001 #!/usr/bin/python
00002 
00003 # This file was written by Andrew Pullin
00004 # This file obtained from: http://bmi.berkeley.edu/~pullin/red-bsl.py
00005 # No copyright or licensing is claimed
00006 # Permission to use this file was granted via correspondence
00007 
00008 
00009 import serial
00010 from struct import pack,unpack
00011 import os
00012 import sys
00013 import time
00014 from optparse import OptionParser
00015 
00016 parser = OptionParser()
00017 parser.add_option("-f", "--file", dest="filename",
00018                   help="binary file to program", metavar="FILE")
00019 parser.add_option("-t", "--target", dest="target",
00020                   help="serial device to send to, default /dev/tty.usbserial-000030FDB",
00021                   default="/dev/tty.usbserial-000030FDB'",
00022                   metavar="TARGET")
00023 parser.add_option("-s", "--flash", dest="flashprog", action="store_true",
00024                   help="write program to flash using libmc1322x flasher", 
00025                   default=False,
00026                   metavar="FLASHPROG")
00027 parser.add_option("-S", "--SSL", dest="SSL_flashprog", action="store_true",
00028                   help="write program to flash using SSL flasher", default=False,
00029                   metavar="SSLFLASHPROG")
00030 parser.add_option("-b", "--baudrate", dest="baudrate",
00031                   help="baudrate for serial device, default 115200", default=115200,
00032                   metavar="BAUDRATE")
00033 
00034 (options, args) = parser.parse_args()
00035 
00036 ZEROCHAR = chr(0)
00037 SOF = chr(0x55)
00038 
00039 engReadReq      = 0x01
00040 engReadResp     = 0x02
00041 engWriteReq     = 0x03
00042 engCommitReq    = 0x04
00043 engEraseReq     = 0x05
00044 engCmdCnf       = 0xF0
00045 
00046 gEngValidReq    = 0x0
00047 gEngInvalidReq  = 0x1
00048 gEngSuccessOp   = 0x2
00049 gEngWriteError  = 0x3
00050 gEngReadError   = 0x4
00051 gEngCRCError    = 0x5
00052 gEngCommError   = 0x6
00053 gEngExecError   = 0x7
00054 gEngNoConfirm   = 0x8
00055 
00056 engSecured    = 0xC3
00057 engUnsecured  = 0x3C
00058 
00059 ENG_BUFFER_SIZE = 0x200
00060 FLASH_IMAGE_HEADER = 0x8;
00061 
00062 ### Helper functions, should be moved to a different class or module later:
00063 def simpleCRC(bytes):
00064         crc = 0;
00065         return sum([ord(b) for b in bytes]) & 255;
00066 
00067 def SendCommand(command):
00068         ser.write(SOF)
00069         ser.write((Int16AsBytes(len(command))))
00070         ser.write(command)
00071         ser.write(chr(simpleCRC(command)))
00072         #print "SOF: ",SOF.encode("hex")
00073         #print "LEN: ",len(command)
00074         #print "PAY: ",command.encode("hex")
00075         #print "CRC: %x" % simpleCRC(command)
00076 
00077 
00078 def ENG_Erase(address):
00079         print "Erasing address 0x%08x" % address
00080         command = chr(engEraseReq) + Int32AsBytes(address)
00081         SendCommand(command)
00082         return WaitForConfirm()
00083 
00084 def ENG_Write(address, data):
00085         if len(data) > ENG_BUFFER_SIZE:
00086           return gEngInvalidReq
00087 
00088         #print "Writing ",len(data),"B to 0x%08x" % address
00089         #data is a list, so list->str is required for concat
00090         command = chr(engWriteReq) + Int32AsBytes(address) + Int16AsBytes(len(data)) + ''.join(data)
00091         SendCommand(command)
00092         return WaitForConfirm()
00093 
00094 def ENG_Commit(length, secure):
00095         command = chr(engCommitReq) + Int32AsBytes(length)
00096         if secure:
00097                 command += chr(engSecured)
00098         else:
00099                 command += chr(engUnsecured)
00100         SendCommand(command)
00101         return WaitForConfirm()
00102 
00103 
00104 def WaitForConfirm():
00105         recvd = ser.read(1)
00106         while(recvd != SOF):
00107           recvd = ser.read(1)
00108         lenStr = ser.read(2)
00109         len = unpack("H",lenStr)[0]
00110         command = ser.read(len)
00111         crcIn = ord(ser.read(1))
00112         if crcIn != simpleCRC(command):
00113           print "CRC error"
00114           return gEngCRCError
00115         if ord(command[0]) != engCmdCnf:
00116           print "Confirm error"
00117           return gEngNoConfirm
00118         else:
00119           return ord(command[1])
00120 
00121 def Int32AsBytes(val):
00122         #For sanity, value is wrapped to unsigned 32-bit
00123         val &= 0xffffffff
00124         return pack('I',val)
00125 
00126 def Int16AsBytes(val):
00127         #For sanity, value is wrapped to unsigned 16-bit
00128         val &= 0xffff
00129         return pack('H',val)
00130 
00131 def EraseFlash():
00132         status = ENG_Erase(0xffffffff)
00133         if status != gEngSuccessOp:
00134           print "Error erasing flash: ",status
00135         else:
00136           print "Flash erased..."
00137 
00138 def DownloadBinary():
00139         flashFile = open(options.filename)
00140         filesize = os.path.getsize(options.filename)
00141         print "Writing ",options.filename," to flash... (%dB)" % filesize
00142         #load entire BIN into an array. Images are < 128KB, so this isn't too terrible
00143         flashBytes = [i for i in flashFile.read()]
00144         flashIndex = 0
00145         currentWriteAddress = FLASH_IMAGE_HEADER
00146         binRemainder = filesize
00147 
00148         starttime = time.time()
00149 
00150         #Write
00151         while binRemainder != 0:
00152                 if binRemainder > ENG_BUFFER_SIZE:
00153                     sendSize = ENG_BUFFER_SIZE
00154                 else:
00155                     sendSize = binRemainder
00156                 binRemainder -= sendSize
00157                 status = ENG_Write(currentWriteAddress, flashBytes[flashIndex:(flashIndex+sendSize)])
00158                 if status != gEngSuccessOp:
00159                     print "Error trying to write to Flash: ",status
00160                     sys.exit(-1)
00161                 currentWriteAddress += sendSize;
00162                 flashIndex += sendSize;
00163                 #print ".",
00164 
00165         #Commit
00166         status = ENG_Commit(filesize, False)
00167         if status != gEngSuccessOp:
00168                 print "Error executing commit: ",status
00169                 sys.exit(-1)
00170 
00171         endtime = time.time()
00172         print "Speed: %.2f KBps" % (filesize/(endtime-starttime)/1000)
00173 
00174 #######################################
00175 
00176 
00177 if options.filename == None:
00178         print "No binary file specified."
00179         parser.print_help()
00180         sys.exit(-1)
00181 
00182 if options.SSL_flashprog and options.flashprog:
00183         print "You can only use one flasher binary! -s and -S are mutually exclusive."
00184         sys.exit(-1)
00185 
00186 ser = serial.Serial(port=options.target,baudrate=options.baudrate,timeout=0.25,rtscts=1)
00187 if ser.isOpen():
00188         ser.flushInput()
00189         ser.flushOutput()
00190         ser.setRTS()
00191 
00192 connected = 0
00193 print "Press RESET now..."
00194 
00195 while True:
00196         ser.write(ZEROCHAR)
00197         response = ser.read(100)
00198         if response == "\x00CONNECT" or response=="CONNECT":
00199                 print "Connected!"
00200                 break
00201 
00202 if options.SSL_flashprog:
00203         infile = open("ssl.bin")
00204         filesize = os.path.getsize("ssl.bin")
00205         print "Sending SSL flasher... (%dB)" % filesize
00206 elif options.flashprog:
00207         infile = open("flasher.bin")
00208         filesize = os.path.getsize("flasher.bin")
00209         print "Sending libmc1322x flasher... (%dB)" % filesize
00210 else:
00211         infile = open(options.filename)
00212         filesize = os.path.getsize(options.filename)
00213         print "Sending binary file to RAM... (%dB)" % filesize
00214 
00215 
00216 #ser.write(chr(filesize & 255))
00217 #ser.write(chr((filesize >> 8)&255))
00218 #ser.write(chr((filesize >> 16)&255))
00219 #ser.write(chr((filesize >> 24)&255))
00220 fileSizeBytes = pack('I',filesize)
00221 ser.write(fileSizeBytes)
00222 
00223 
00224 #bytes = [i for i in infile.read()]
00225 bytes = infile.read()
00226 
00227 starttime = time.time()
00228 #ser.write(bytes)
00229 for byte in bytes:
00230         ser.write(byte)
00231 
00232 #Make sure all bytes are sent
00233 while 1:
00234         if ser.inWaiting() == 0:
00235           break
00236 
00237 
00238 endtime = time.time()
00239 
00240 print "Speed: %.2f KBps" % (filesize/(endtime-starttime)/1000)
00241 
00242 #SSL section for sending binary
00243 if options.SSL_flashprog:
00244         print "Waiting for flasher to start..."
00245         for tries in range(100):
00246                 time.sleep(0.010)
00247                 if tries==99:
00248                         print "No response from flasher utility. Erase flash with jumpers and try again."
00249                         sys.exit(0)
00250                 if ser.readline().strip() == "READY":
00251                         print "Entering Second Stage Loader..."
00252                         break
00253         EraseFlash()
00254         DownloadBinary()
00255 #Section for libmc1322x flasher
00256 elif options.flashprog:
00257         print "Waiting for flasher to start..."
00258         for tries in range(100):
00259                 time.sleep(0.010)
00260                 if tries==99:
00261                         print "No response from flasher utility. Erase flash with jumpers and try again."
00262                         sys.exit(0)
00263                 if ser.readline().strip() == "ready":
00264                         break
00265 
00266         flashfile = open(options.filename)
00267         filesize = os.path.getsize(options.filename)
00268         print "Writing to flash... (%dB)" % filesize
00269         flashbytes = [i for i in flashfile.read()]
00270         ser.write(chr(filesize & 255))
00271         ser.write(chr(filesize >> 8))
00272         ser.write(chr(filesize >> 16))
00273         ser.write(chr(filesize >> 24))
00274         starttime = time.time()
00275         for byte in flashbytes:
00276                 ser.write(byte)
00277                 time.sleep(0.0005)
00278         endtime = time.time()
00279         print "Speed: %.2f KBps" % (filesize/(endtime-starttime)/1000)
00280 
00281 print "Done."
00282 
00283 ser.close()
00284 
00285 

Generated on Mon Oct 18 07:40:46 2010 for Python-on-a-chip by  doxygen 1.5.9