예제 #1
0
파일: devices.py 프로젝트: duparq/hwa
    def appstat(self, data):
        """
        Compute length of application code and CRC.

        The CRC is computed from the end to the beginning of the memory, skipping
        the 0xFF bytes at the end.

        For devices without boot section the first two bytes of reset vector
        (rjmp to Diabolo) are not computed.

        """
        crc = CRC.init()
        if not self.bootsection:
            end = 1
        else:
            end = -1

        top = min( len(data), self.bladdr )-1
        for x in range(top, end, -1):
            if data[x] != '\xFF':
                break
        for i in range(x, end, -1):
            crc = CRC.add(crc, data[i])
        return x+1, crc
예제 #2
0
    def appstat(self, data):
        """
        Compute length of application code and CRC.

        The CRC is computed from the end to the beginning of the memory, skipping
        the 0xFF bytes at the end.

        For devices without boot section the first two bytes of reset vector
        (rjmp to Diabolo) are not computed.

        """
        crc = CRC.init()
        if not self.bootsection:
            end = 1
        else:
            end = -1

        top = min(len(data), self.bladdr) - 1
        for x in range(top, end, -1):
            if data[x] != '\xFF':
                break
        for i in range(x, end, -1):
            crc = CRC.add(crc, data[i])
        return x + 1, crc
예제 #3
0
파일: diabolo.py 프로젝트: z13z4ck/hwa
                p = self.device.read_flash_page(a)
                if p == None:
                    cerr(_("\nRead page failed at 0x%04X.\n" % a))
                    return False
                cout('.')
                flushout()
                data += p

            #  Compute the CRC
            #
            crc = CRC.init()
            i = len(data) - 1
            while i >= 0 and data[i] == '\xFF':
                i -= 1
            while i >= 0:
                crc = CRC.add(crc, data[i])
                i -= 1

            # x, crc = self.device.appstat(data)
            cout(
                _("\nRead %d bytes of firmware, CRC=0x%04X.\n" %
                  (len(data), crc)))
            return

        #  Read flash memory?
        #
        if self.options.read_flash:
            data = self.read_flash()
            if self.options.hexdump:
                sys.stdout.write(hexdump(0, data) + "\n")
            if self.options.cache:
예제 #4
0
파일: diabolo.py 프로젝트: duparq/hwa
                p = self.device.read_flash_page(a)
                if p == None:
                    cerr(_("\nRead page failed at 0x%04X.\n" % a))
                    return False
                cout('.')
                flushout()
                data += p

            #  Compute the CRC
            #
            crc = CRC.init()
            i = len(data)-1
            while i>=0 and data[i]=='\xFF':
                i -= 1
            while i>=0:
                crc = CRC.add(crc, data[i])
                i -= 1

            # x, crc = self.device.appstat(data)
            cout(_("\nRead %d bytes of firmware, CRC=0x%04X.\n"
                   % (len(data), crc)))
            return


        #  Read flash memory?
        #
        if self.options.read_flash:
            data = self.read_flash()
            if self.options.hexdump:
                sys.stdout.write(hexdump(0,data)+"\n")
            if self.options.cache:
예제 #5
0
    def run(self):
        flash = None  # Data to burn into flash

        start_time = timer()

        #  Compute a CRC?
        #
        if self.options.stat or self.options.crc or self.options.size:
            if not self.options.filename:
                die(_("Input file is required for CRC computation.\n"))
            if not self.options.mcu:
                die(_("Target device is required for CRC computation.\n"))

            try:
                self.device = devices.devices[self.options.mcu.lower()]()
            except:
                die(_("\"%s\": no such device.\n" % self.options.mcu.lower()))

            data = self.read_file(self.options.filename)
            x, crc = self.device.appstat(data)
            if self.options.stat:
                #
                #  Use sys.stdout.write instead of cout to bypass '--quiet'
                #
                sys.stdout.write(
                    _("%s: %d /%d application bytes, CRC=0x%04X.\n" %
                      (self.options.filename, x, self.device.flashsize, crc)))
            elif self.options.crc:
                sys.stdout.write("%04X\n" % crc)
            else:
                sys.stdout.write("%d\n" % x)
            return

        #  Compute a CRC32?
        #
        if self.options.crc32:
            if not self.options.filename:
                die(_("Input file is required for CRC32 computation.\n"))

            import binascii
            s = open(self.options.filename, 'rb').read()
            crc32 = binascii.crc32(s)
            sys.stdout.write("%08x\n" % (crc32 & 0xFFFFFFFF))
            return

        #  List available ttys?
        #
        if self.options.tty == "list":
            ttys = link.list()
            cout(_("Available ttys:\n" + str(ttys)))
            return

        #  Open the communication channel
        #
        try:
            self.link = link.get(self.options)
        except link.serial.SerialException as e:
            die(str(e))

        #  Reset the device connected to the serial interface
        #
        self.link.set_TXD(0)
        self.link.set_RESET(0)

        if self.options.reset_length:
            time.sleep(self.options.reset_length)

        self.link.set_RESET(1)

        #  Just reset the device and quit?
        #
        if self.options.reset_and_exit:
            return

        if self.options.keep_txd_low == 0:
            cout(
                "WARNING: target will probably not remain in Diabolo if TXD is not "
                "maintained low long enough!\n")
        else:
            time.sleep(self.options.keep_txd_low)

        self.link.set_TXD(1)

        #  This is the best moment for detecting how many wires are used for the
        #  serial communication since the target device is supposed to be
        #  waiting in Diabolo for the synchronization.
        #
        #  It is safe to send data on the serial line now even if the RESET
        #  signal is used to drive the power supply (sending data while the
        #  device is not powered could cause troubles).
        #
        self.link.detect_wires(b'?')
        cout(_("Tty wires: %d\n") % self.link.wires)

        #  We can now send synchronization sequences
        #
        if not self.link.sync():
            die(_("Synchronization failed.\n"))

        #  Identify device
        #
        self.device = devices.get_device(self.link)
        cout(_("Connected to device (protocol %d):\n" % self.device.protocol))
        cout(
            self.device.str(self.options.show_fuses,
                            self.options.decode_fuses))

        #  Check target name
        #
        if self.options.mcu and self.device.name.lower(
        ) != self.options.mcu.lower():
            die(
                _("Target mismatch: connected to %s, %s expected.\n" %
                  (self.device.name, self.options.mcu)))

        #  Compute the CRC of the firmware?
        #
        if self.options.fwcrc:
            cout("\nReading firmware flash: ")
            data = bytearray()
            if self.device.protocol == 4:
                step = self.device.pagesize
            else:  # protocol 5
                step = 256
            for a in range(self.device.bladdr, self.device.flashsize, step):
                page = self.device.read_flash_page(a)
                if page == None:
                    cerr(_("\nRead page failed at 0x%04X.\n" % a))
                    return False
                cout('.')
                flushout()
                data.extend(page)

            #  Compute the CRC
            #
            crc = CRC.init()
            i = len(data) - 1
            while i >= 0 and data[i] == 0xFF:
                i -= 1
            while i >= 0:
                crc = CRC.add(crc, data[i])
                i -= 1

            # x, crc = self.device.appstat(data)
            cout(
                _("\nRead %d bytes of firmware, CRC=0x%04X.\n" %
                  (len(data), crc)))
            return

        #  Read flash memory?
        #
        if self.options.read_flash:
            data = self.read_flash()
            if self.options.hexdump:
                cout(hexdump(0, data) + "\n")
            if self.options.cache:
                self.write_file(self.options.cache, data)
            #return

        #  Read eeprom memory?
        #
        if self.options.read_eeprom:
            data = self.read_eeprom()
            if self.options.hexdump:
                cout(hexdump(0, data) + "\n")
            if self.options.cache:
                self.write_file(self.options.cache, data)
            #return

        #  Erase flash memory?
        #
        if self.options.clear_flash:
            flash = bytearray.fromhex('FF' * self.device.flashsize)

        #  Write flash memory?
        #
        if self.options.burn_flash:
            if not self.options.filename:
                die(_("Input file is required to program flash memory.\n"))
            cache = None
            if self.options.cache:
                if os.path.isfile(self.options.cache):
                    cache = self.read_file(self.options.cache)
                    if len(cache) < self.device.bladdr:
                        cout(_("Wrong cache size. Dropping cache data.\n"))
                        cache = None
                    else:
                        x, cache_crc = self.device.appstat(cache)
                        if self.device.appcrc != cache_crc:
                            cout(_("Cache CRC (%04X) does not match device CRC. "\
                                   "Dropping cache data.\n" % cache_crc))
                            cache = None
                else:
                    cout(
                        _("Cache file does not exist yet, reading flash"
                          " memory is required.\n"))
            if cache == None:
                cache = self.read_flash()
                if self.options.cache:
                    self.write_file(self.options.cache, cache)

            x, cache_crc = self.device.appstat(cache)
            flash = self.read_file(self.options.filename)
            if len(flash) < self.device.bladdr:
                cout(_("Padding data with 0xFF bytes\n"))
                flash.extend(
                    bytes.fromhex('FF' * (self.device.bladdr - len(flash))))

        #  Program flash memory
        #
        if flash:
            #
            #  Override RESET vector for device without bootsection
            #    RJMP opcode: 1111 aaaa aaaa aaaa = 0xC000 + Addr
            #
            if not self.device.bootsection:
                addr = int(self.device.bladdr / 2) - 1
                if addr > 0x0FFF:
                    die(_("Can not set RESET vector opcode.\n"))
                opcode = 0xC000 + addr
                byte0 = opcode & 0xFF
                byte1 = opcode >> 8
                cout(
                    _("Device without bootsection, "
                      "setting RESET vector to computed opcode: %02x %02x\n") %
                    (byte0, byte1))
                #flash = opcode.to_bytes(2,byteorder="little")+flash[2:]
                flash[0] = byte0
                flash[1] = byte1

            x, flash_crc = self.device.appstat(flash)
            if flash_crc == cache_crc:
                cout(
                    _("Cache and data CRC match, nothing to program in Flash memory.\n"
                      ))
                if self.device.eeappcrc != flash_crc:
                    self.device.write_eeprom_appcrc(flash_crc)
                    check = self.device.read_eeprom_appcrc()
                    if check == flash_crc:
                        cout(
                            _("Updated application CRC in EEPROM: 0x%04X\n" %
                              flash_crc))
                    else:
                        raise Exception(_("update of application CRC in EEPROM failed: %04X!=%04X" %\
                                (check, flash_crc)) )
                    x_restart = True
            else:
                self.write_flash(flash, cache)

            x_restart = False
            if self.device.flash_changed:
                # trace()
                self.device.pgmcount += 1
                self.device.write_eeprom_pgmcount(self.device.pgmcount)
                check = self.device.read_eeprom_pgmcount()
                if check == self.device.pgmcount:
                    cout(_("Set program count to %d\n" % self.device.pgmcount))
                else:
                    cout(
                        _("Failed to set program count to %d (read %d)." %
                          (self.device.pgmcount, check)))
                x_restart = True

            if self.device.eeappcrc != flash_crc:
                # trace()
                self.device.write_eeprom_appcrc(flash_crc)
                cout(
                    _("Stored application CRC in EEPROM: 0x%04X\n" %
                      flash_crc))
                x_restart = True

            if x_restart:
                # trace()
                #cout(_("Reset device's Diabolo\n"))
                self.device.resume()
                self.link.tx(
                    b'*')  # Send a bad command to force CRC re-computation
                #
                #  Wait up to 1 s for CRC computation (~50 cycles/byte)
                #
                t = timer() + 1.0
                while timer() < t and not self.link.rx(1):
                    pass
                if timer() >= t:
                    raise Exception("timeout waiting CRC recomputation")
                if self.link.lastchar != ord('!'):
                    raise Exception(
                        "unexpected reply (0x%02X) to '*' command" % ord(c))
                self.link.tx(b'\n')  # Resume
                self.link.rx(1)
                self.device = self.device.identify()
                cout("  Application CRC:\n")
                cout(_("    computed: 0x%04X\n" % self.device.appcrc))
                cout(_("      EEPROM: 0x%04X\n" % self.device.eeappcrc))
                cout(_("  Programmings: %d\n" % self.device.pgmcount))

            #  Update flash cache
            #
            if self.options.cache:
                # trace()
                self.write_file(self.options.cache, flash)

        #  Start application
        #
        if self.device.appcrc == self.device.eeappcrc \
           and self.device.appcrc != 0xFFFF:
            if self.device.start_application():
                cout("Target started its application.\n")
            else:
                cout("ERROR: target did not start its application.\n")

        self.link.close()

        if self.options.diag:
            cout(
                _("%d commands, %d fails, %d resumes, %d crc errors, total time: %.1f s.\n"
                  % (self.device.ncmds, self.device.ncmdfails,
                     self.device.nresumes, self.device.ncrcerrors,
                     timer() - start_time + 0.05)))