Ejemplo n.º 1
0
 def upload(self, cogid_to_filename_mapping, run=True, eeprom=False):
   # Very important to select right timeout. Non-blocking mode is not allowed.
   self.serial.timeout = 5
   self.__total_upload_size = 0
   # Extract and sort a list of target COG id's in increase order
   target_cogids = cogid_to_filename_mapping.keys()
   target_cogids.sort()
   # Put a little bit of useful information to the log if it's
   # required
   if True:
     logging.info("Task:")
     for cogid in target_cogids:
       path = cogid_to_filename_mapping[cogid]
       logging.info("\t%s => COG #%d", path, cogid)
       self.__total_upload_size += Image.get_file_size(path)
     print "Total upload size: %d (bytes)" % self.__total_upload_size
   # Send the command that will describe the further steps
   command = MulticogBootloaderCommands.get_code_list()[eeprom * 2 + run]
   # self.send_byte(command)
   # Send synch signal in order to describe target
   # number of images to be sent
   self.__send_sync_signal(len(cogid_to_filename_mapping))
   # Start uploading images on cogs one by one
   i = 0
   for cogid in target_cogids:
     filename = cogid_to_filename_mapping.get(cogid)
     if not self.__upload_to_cog(i, cogid, filename):
       raise UploadingError("Uploading has been broken.")
     i += 1
Ejemplo n.º 2
0
 def __send_sync_signal(self, byte):
   """Send two-bytes sync signal: [0xFF|BYTE]. These sequences can
   never be generated accidentally because during normal sending 0xFF
   is stuffed to 0xFF 0x00, so we can wait for this without the risk
   of accidentally being triggered by a program being sent to another
   cog.
   """
   assert(byte < 256)
   logging.info("Sending sync signal: 0x%4x" % ((0xFF << 8) + byte))
   self.send_byte(chr(0xFF))
   self.send_byte(chr(byte))
Ejemplo n.º 3
0
 def __send_page(self, cogid, seq_no, addr, buf, size):
   """Send bytes that have to be stored to Hub RAM. Return True it
   the data from was successfully transmitted (data LRC-checksum
   should be equal to result LRC-checksum recevied from device).
   """
   logging.info('Sending packet #%d [COG=%d, ADDR=0x%08x, SIZE=%d]' \
                  % (seq_no, cogid, addr, size))
   # 4-bytes address: [COG_ID |    ADDR   ]
   addr_hdr = (addr & 0xFFFFFF) | (cogid << 24)
   logging.info("Sending header: 0x%08x 0x%08x"
                % (Long.reverse_bytes(addr_hdr), Long.reverse_bytes(size)))
   self.stuff_and_send_long(Long.reverse_bytes(addr_hdr))
   # Sending page 4 bytes size
   self.stuff_and_send_long(Long.reverse_bytes(size))
   # IF
   if addr == MARKER:
     self.send_byte(chr(cogid))
     return
   # LRC-checksum value (xor of each byte)
   lrc_checksum = 0x00
   # Start transmitting page bytes
   i = 0
   while i < size:
     self.stuff_and_send_byte(buf[i], timeout=BYTE_DELAY)
     # Calculate the XOR value for this byte
     lrc_checksum = operator.xor(lrc_checksum, ord(buf[i]))
     i += 1
   # Wait for calculation LRC value
   # Waiting for sync
   logging.info("Waiting for sync...")
   # Receive and verify first sync byte, should be 0xFF
   ff = self.receive(1, None)
   if not ff:
     logging.error("Timeout while expecting for '0xFF' value.")
     raise UploadingError()
   elif not ord(ff) == 0xFF:
     logging.error("PACKET#%d: expecting '0xFF' value as the first byte of "
                   "sync signal, but received '%d'", seq_no, ord(ff))
     raise UploadingError()
   # Receive and verify second sync byte. Should be our COG id.
   result_cog_id = self.receive(1) # timeout=None <== wait
   if ord(result_cog_id) != cogid:
     logging.error("Waiting for %d but received %d", cogid, ord(result_cog_id))
     raise UploadingError()
   # Receive and verify LRC value
   logging.info("Waiting for result LRC checksum value... ")
   result_lrc_checksum = ord(self.receive(1))
   logging.info("Result LRC checksum value: %d", result_lrc_checksum)
   # Compare our LRC value and result LRC value from device
   logging.info("Verifying LRC-checksum: %d and %d" \
                  % (lrc_checksum, result_lrc_checksum))
   if not lrc_checksum == result_lrc_checksum:
     logging.error("LRC-checksum didn't match.")
     raise UploadingError()
Ejemplo n.º 4
0
 def __upload_to_cog(self, i, cogid, filename):
   # Extract image from the file
   data = Image.extract_from_file(filename)
   sz = len(data)
   if sz % 4 != 0:
     raise Exception("Invalid code size: must be a multiple of 4")
   logging.info("Uploading %s (%d bytes) on COG#%d" % (filename, sz, cogid))
   print "Uploading %s (%d bytes) on COG#%d to 0x%08x" \
       % (filename, sz, cogid, self.__offset)
   # The following blocks aims to edit binary image
   vars_size = 512 # 16
   stack_size = 1024 # 128
   # Compute an offset for working space for our program
   offset = self.__total_upload_size + i * (vars_size + stack_size)
   # Read and fix header
   # XXX: do we need to recalculate checksum value once the
   #      header has been updated?
   data_p = c_char_p(data)
   hdr_p = cast(data_p, POINTER(SpinHeader))
   hdr_p.contents.pbase = self.__offset + hdr_p.contents.pbase
   hdr_p.contents.vbase = offset + 0
   hdr_p.contents.dbase = offset + vars_size
   hdr_p.contents.pcurr = self.__offset + hdr_p.contents.pcurr
   hdr_p.contents.dcurr = offset + vars_size + 4
   logging.info(str(hdr_p.contents))
   data = list(data)
   # The data may be changed till this point, thus we have to double
   # check its size
   assert(len(data) == sz)
   # Sorry, but checksum can be broken since we'are trying to hack
   # the header. Thus assert(is_valid_image(data)) is not working
   # anymore here.
   #
   # OK. Now we're starting to transmit the data...
   #
   # Send sync signal to start binary transmitting
   self.__send_sync_signal(cogid)
   # Note, that only a max of PAGE_SIZE will actually get loaded, thus
   # we split data on chunks and send them in pages
   chunks = [PAGE_SIZE] * (sz / PAGE_SIZE)
   if sz % PAGE_SIZE:
     chunks.append(sz % PAGE_SIZE)
   i = 1
   addr = 0
   page_sending_delay = 0.050
   try:
     for size in chunks:
       page = data[addr:addr + size]
       done = float(i) / float(len(chunks))
       sys.stdout.write("Downloading [{0:50s}] {1:.1f}%".format('#' * int(done * 50), done * 100))
       sys.stdout.write("\r")
       sys.stdout.flush()
       # Do not forget about total offset
       time.sleep(page_sending_delay)
       self.__send_page(cogid, i, self.__offset + addr, page, size)
       i += 1
       addr += size
     print
     self.__send_page(cogid, i, MARKER, '', 0)
   except UploadingError:
     return False
   finally:
     self.__offset += sz
   return True