Exemplo n.º 1
0
 def __init__(self, interface):
     super(CMSIS_DAP, self).__init__(interface)
     self.protocol = CMSIS_DAP_Protocol(interface)
     self.packet_max_count = 0
     self.packet_max_size = 0
     self.csw = -1
     self.dp_select = -1
     self.deferred_transfer = False
     self.request_list = []
     self.data_list = []
     self.data_read_list = []
Exemplo n.º 2
0
 def __init__(self, interface):
     super(CMSIS_DAP, self).__init__(interface)
     self.protocol = CMSIS_DAP_Protocol(interface)
     self.packet_max_count = 0
     self.packet_max_size = 0
     self.csw = -1
     self.dp_select = -1
     self.deferred_transfer = False
     self.request_list = []
     self.data_list = []
     self.data_read_list = []
Exemplo n.º 3
0
class CMSIS_DAP(Transport):
    """
    This class implements the CMSIS-DAP protocol
    """
    def __init__(self, interface):
        super(CMSIS_DAP, self).__init__(interface)
        self.protocol = CMSIS_DAP_Protocol(interface)
        self.packet_max_count = 0
        self.packet_max_size = 0
        self.csw = -1
        self.dp_select = -1
        self.deferred_transfer = False
        self.request_list = []
        self.data_list = []
        self.data_read_list = []

    def init(self, frequency = 1000000):
        # Flush to be safe
        self.flush()
        # connect to DAP, check for SWD or JTAG
        self.mode = self.protocol.connect()
        # set clock frequency
        self.protocol.setSWJClock(frequency)
        # configure transfer
        self.protocol.transferConfigure()
        if (self.mode == DAP_MODE_SWD):
            # configure swd protocol
            self.protocol.swdConfigure()
            # switch from jtag to swd
            self.JTAG2SWD()
            # read ID code
            logging.info('IDCODE: 0x%X', self.readDP(DP_REG['IDCODE']))
            # clear errors
            self.protocol.writeAbort(0x1e);
        elif (self.mode == DAP_MODE_JTAG):
            # configure jtag protocol
            self.protocol.jtagConfigure(4)
            # Test logic reset, run test idle
            self.protocol.swjSequence([0x1F])
            # read ID code
            logging.info('IDCODE: 0x%X', self.protocol.jtagIDCode())
            # clear errors
            self.writeDP(DP_REG['CTRL_STAT'], CTRLSTAT_STICKYERR | CTRLSTAT_STICKYCMP | CTRLSTAT_STICKYORUN)
        return

    def uninit(self):
        self.flush()
        self.protocol.disconnect()
        return

    def JTAG2SWD(self):
        data = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
        self.protocol.swjSequence(data)

        data = [0x9e, 0xe7]
        self.protocol.swjSequence(data)

        data = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
        self.protocol.swjSequence(data)

        data = [0x00]
        self.protocol.swjSequence(data)

    def info(self, request):
        self.flush()
        resp = None
        try:
            resp = self.protocol.dapInfo(request)
        except KeyError:
            logging.error('request %s not supported', request)
        return resp

    def clearStickyErr(self):
        if (self.mode == DAP_MODE_SWD):
            self.writeDP(0x0, (1 << 2))
        elif (self.mode == DAP_MODE_JTAG):
            self.writeDP(DP_REG['CTRL_STAT'], CTRLSTAT_STICKYERR)

    def writeMem(self, addr, data, transfer_size = 32):
        self.writeAP(AP_REG['CSW'], CSW_VALUE | TRANSFER_SIZE[transfer_size])

        if transfer_size == 8:
            data = data << ((addr & 0x03) << 3)
        elif transfer_size == 16:
            data = data << ((addr & 0x02) << 3)

        self._write(WRITE | AP_ACC | AP_REG['TAR'], addr)
        self._write(WRITE | AP_ACC | AP_REG['DRW'], data)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()

    def readMem(self, addr, transfer_size = 32, mode = READ_NOW):
        res = None
        if mode in (READ_START, READ_NOW):
            self.writeAP(AP_REG['CSW'], CSW_VALUE | TRANSFER_SIZE[transfer_size])
            self._write(WRITE | AP_ACC | AP_REG['TAR'], addr)
            self._write(READ | AP_ACC | AP_REG['DRW'])

        if mode in (READ_NOW, READ_END):
            resp = self._read()
            res =   (resp[0] << 0)  | \
                    (resp[1] << 8)  | \
                    (resp[2] << 16) | \
                    (resp[3] << 24)

            # All READ_STARTs must have been finished with READ_END before using READ_NOW
            assert (mode != READ_NOW) or (len(self.data_read_list) == 0)

            if transfer_size == 8:
                res = (res >> ((addr & 0x03) << 3) & 0xff)
            elif transfer_size == 16:
                res = (res >> ((addr & 0x02) << 3) & 0xffff)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()
        return res

    # write aligned word ("data" are words)
    def writeBlock32(self, addr, data):
        # put address in TAR
        self.writeAP(AP_REG['CSW'], CSW_VALUE | CSW_SIZE32)
        self.writeAP(AP_REG['TAR'], addr)
        try:
            self._transferBlock(len(data), WRITE | AP_ACC | AP_REG['DRW'], data)
        except TransferError:
            self.clearStickyErr()
            raise
        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()

    # read aligned word (the size is in words)
    def readBlock32(self, addr, size):
        # put address in TAR
        self.writeAP(AP_REG['CSW'], CSW_VALUE | CSW_SIZE32)
        self.writeAP(AP_REG['TAR'], addr)
        data = []
        try:
            resp = self._transferBlock(size, READ | AP_ACC | AP_REG['DRW'])
        except TransferError:
            self.clearStickyErr()
            raise
        for i in range(len(resp)/4):
            data.append( (resp[i*4 + 0] << 0)   | \
                         (resp[i*4 + 1] << 8)   | \
                         (resp[i*4 + 2] << 16)  | \
                         (resp[i*4 + 3] << 24))
        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()
        return data


    def readDP(self, addr, mode = READ_NOW):
        res = None
        if mode in (READ_START, READ_NOW):
            self._write(READ | DP_ACC | (addr & 0x0c))

        if mode in (READ_NOW, READ_END):
            resp = self._read()
            res =   (resp[0] << 0)  | \
                    (resp[1] << 8)  | \
                    (resp[2] << 16) | \
                    (resp[3] << 24)

            # All READ_STARTs must have been finished with READ_END before using READ_NOW
            assert (mode != READ_NOW) or (len(self.data_read_list) == 0)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()
        return res

    def writeDP(self, addr, data):
        if addr == DP_REG['SELECT']:
            if data == self.dp_select:
                return
            self.dp_select = data

        self._write(WRITE | DP_ACC | (addr & 0x0c), data)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()
        return True

    def writeAP(self, addr, data):
        ap_sel = addr & 0xff000000
        bank_sel = addr & APBANKSEL
        self.writeDP(DP_REG['SELECT'], ap_sel | bank_sel)

        if addr == AP_REG['CSW']:
            if data == self.csw:
                return
            self.csw = data

        self._write(WRITE | AP_ACC | (addr & 0x0c), data)
        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()

        return True

    def readAP(self, addr, mode = READ_NOW):
        res = None
        if mode in (READ_START, READ_NOW):
            ap_sel = addr & 0xff000000
            bank_sel = addr & APBANKSEL

            self.writeDP(DP_REG['SELECT'], ap_sel | bank_sel)
            self._write(READ | AP_ACC | (addr & 0x0c))

        if mode in (READ_NOW, READ_END):
            resp = self._read()
            res =   (resp[0] << 0)  | \
                    (resp[1] << 8)  | \
                    (resp[2] << 16) | \
                    (resp[3] << 24)

            # All READ_STARTs must have been finished with READ_END before using READ_NOW
            assert (mode != READ_NOW) or (len(self.data_read_list) == 0)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()

        return res

    def reset(self):
        self.flush()
        self.protocol.setSWJPins(0, 'nRESET')
        sleep(0.1)
        self.protocol.setSWJPins(0x80, 'nRESET')
        sleep(0.1)

    def assertReset(self, asserted):
        self.flush()
        if asserted:
            self.protocol.setSWJPins(0, 'nRESET')
        else:
            self.protocol.setSWJPins(0x80, 'nRESET')

    def setClock(self, frequency):
        self.flush()
        self.protocol.setSWJClock(frequency)

    def setDeferredTransfer(self, enable):
        """
        Allow transfers to be delayed and buffered

        By default deferred transfers are turned off.  All reads and
        writes will be completed by the time the function returns.

        When enabled packets are buffered and sent all at once, which
        increases speed.  When memory is written to, the transfer
        might take place immediately, or might take place on a future
        memory write.  This means that an invalid write could cause an
        exception to occur on a later, unrelated write.  To guarantee
        that previous writes are complete call the flush() function.

        The behaviour of read operations is determined by the modes
        READ_START, READ_NOW and READ_END.  The option READ_NOW is the
        default and will cause the read to flush all previous writes,
        and read the data immediately.  To improve performance, multiple
        reads can be made using READ_START and finished later with READ_NOW.
        This allows the reads to be buffered and sent at once.  Note - All
        READ_ENDs must be called before a call using READ_NOW can be made.
        """
        if self.deferred_transfer and not enable:
            self.flush()
        self.deferred_transfer = enable

    def flush(self):
        """
        Flush out all commands
        """
        transfer_count = len(self.request_list)
        if transfer_count > 0:
            assert transfer_count <= COMMANDS_PER_DAP_TRANSFER
            try:
                data = self.protocol.transfer(transfer_count, self.request_list, self.data_list)
                self.data_read_list.extend(data)
            except TransferError:
                # Dump any pending commands
                self.request_list = []
                self.data_list = []
                # Dump any data read
                self.data_read_list = []
                # Invalidate cached registers
                self.csw = -1
                self.dp_select = -1
                # Clear error
                self.clearStickyErr()
                raise
            self.request_list = []
            self.data_list = []

    def _write(self, request, data = 0):
        """
        Write a single command
        """
        self.request_list.append(request)
        self.data_list.append(data)
        transfer_count = len(self.request_list)
        if (transfer_count >= COMMANDS_PER_DAP_TRANSFER):
            self.flush()

    def _read(self):
        """
        Read the response from a single command
        """
        if len(self.data_read_list) < 4:
            self.flush()
        data = self.data_read_list[0:4]
        self.data_read_list = self.data_read_list[4:]
        return data

    def _transferBlock(self, count, request, data = [0]):
        self.flush()
        return self.protocol.transferBlock(count, request, data)
Exemplo n.º 4
0
class CMSIS_DAP(Transport):
    """
    This class implements the CMSIS-DAP protocol
    """
    def __init__(self, interface):
        super(CMSIS_DAP, self).__init__(interface)
        self.protocol = CMSIS_DAP_Protocol(interface)
        self.packet_max_count = 0
        self.packet_max_size = 0
        self.csw = -1
        self.dp_select = -1
        self.deferred_transfer = False
        self.request_list = []
        self.data_list = []
        self.data_read_list = []

    def init(self, frequency=1000000):
        # Flush to be safe
        self.flush()
        # connect to DAP, check for SWD or JTAG
        self.mode = self.protocol.connect()
        # set clock frequency
        self.protocol.setSWJClock(frequency)
        # configure transfer
        self.protocol.transferConfigure()
        if (self.mode == DAP_MODE_SWD):
            # configure swd protocol
            self.protocol.swdConfigure()
            # switch from jtag to swd
            self.JTAG2SWD()
            # read ID code
            logging.info('IDCODE: 0x%X', self.readDP(DP_REG['IDCODE']))
            # clear errors
            self.protocol.writeAbort(0x1e)
        elif (self.mode == DAP_MODE_JTAG):
            # configure jtag protocol
            self.protocol.jtagConfigure(4)
            # Test logic reset, run test idle
            self.protocol.swjSequence([0x1F])
            # read ID code
            logging.info('IDCODE: 0x%X', self.protocol.jtagIDCode())
            # clear errors
            self.writeDP(
                DP_REG['CTRL_STAT'],
                CTRLSTAT_STICKYERR | CTRLSTAT_STICKYCMP | CTRLSTAT_STICKYORUN)
        return

    def uninit(self):
        self.flush()
        self.protocol.disconnect()
        return

    def JTAG2SWD(self):
        data = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
        self.protocol.swjSequence(data)

        data = [0x9e, 0xe7]
        self.protocol.swjSequence(data)

        data = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
        self.protocol.swjSequence(data)

        data = [0x00]
        self.protocol.swjSequence(data)

    def info(self, request):
        self.flush()
        resp = None
        try:
            resp = self.protocol.dapInfo(request)
        except KeyError:
            logging.error('request %s not supported', request)
        return resp

    def clearStickyErr(self):
        if (self.mode == DAP_MODE_SWD):
            self.writeDP(0x0, (1 << 2))
        elif (self.mode == DAP_MODE_JTAG):
            self.writeDP(DP_REG['CTRL_STAT'], CTRLSTAT_STICKYERR)

    def writeMem(self, addr, data, transfer_size=32):
        self.writeAP(AP_REG['CSW'], CSW_VALUE | TRANSFER_SIZE[transfer_size])

        if transfer_size == 8:
            data = data << ((addr & 0x03) << 3)
        elif transfer_size == 16:
            data = data << ((addr & 0x02) << 3)

        self._write(WRITE | AP_ACC | AP_REG['TAR'], addr)
        self._write(WRITE | AP_ACC | AP_REG['DRW'], data)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()

    def readMem(self, addr, transfer_size=32, mode=Transport.READ_NOW):
        res = None
        if mode in (Transport.READ_START, Transport.READ_NOW):
            self.writeAP(AP_REG['CSW'],
                         CSW_VALUE | TRANSFER_SIZE[transfer_size])
            self._write(WRITE | AP_ACC | AP_REG['TAR'], addr)
            self._write(READ | AP_ACC | AP_REG['DRW'])

        if mode in (Transport.READ_NOW, Transport.READ_END):
            resp = self._read()
            res = (resp[0] << 0) | \
                    (resp[1] << 8) | \
                    (resp[2] << 16) | \
                    (resp[3] << 24)

            # All READ_STARTs must have been finished with READ_END before using READ_NOW
            assert (mode != Transport.READ_NOW) or (len(self.data_read_list)
                                                    == 0)

            if transfer_size == 8:
                res = (res >> ((addr & 0x03) << 3) & 0xff)
            elif transfer_size == 16:
                res = (res >> ((addr & 0x02) << 3) & 0xffff)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()
        return res

    # write aligned word ("data" are words)
    def writeBlock32(self, addr, data):
        # put address in TAR
        self.writeAP(AP_REG['CSW'], CSW_VALUE | CSW_SIZE32)
        self.writeAP(AP_REG['TAR'], addr)
        try:
            self._transferBlock(len(data), WRITE | AP_ACC | AP_REG['DRW'],
                                data)
        except Transport.TransferError:
            self.clearStickyErr()
            raise
        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()

    # read aligned word (the size is in words)
    def readBlock32(self, addr, size):
        # put address in TAR
        self.writeAP(AP_REG['CSW'], CSW_VALUE | CSW_SIZE32)
        self.writeAP(AP_REG['TAR'], addr)
        data = []
        try:
            resp = self._transferBlock(size, READ | AP_ACC | AP_REG['DRW'])
        except Transport.TransferError:
            self.clearStickyErr()
            raise
        for i in range(len(resp) / 4):
            data.append((resp[i * 4 + 0] << 0) | \
                         (resp[i * 4 + 1] << 8) | \
                         (resp[i * 4 + 2] << 16) | \
                         (resp[i * 4 + 3] << 24))
        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()
        return data

    def readDP(self, addr, mode=Transport.READ_NOW):
        res = None
        if mode in (Transport.READ_START, Transport.READ_NOW):
            self._write(READ | DP_ACC | (addr & 0x0c))

        if mode in (Transport.READ_NOW, Transport.READ_END):
            resp = self._read()
            res = (resp[0] << 0) | \
                    (resp[1] << 8) | \
                    (resp[2] << 16) | \
                    (resp[3] << 24)

            # All READ_STARTs must have been finished with READ_END before using READ_NOW
            assert (mode != Transport.READ_NOW) or (len(self.data_read_list)
                                                    == 0)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()
        return res

    def writeDP(self, addr, data):
        if addr == DP_REG['SELECT']:
            if data == self.dp_select:
                return
            self.dp_select = data

        self._write(WRITE | DP_ACC | (addr & 0x0c), data)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()
        return True

    def writeAP(self, addr, data):
        ap_sel = addr & 0xff000000
        bank_sel = addr & APBANKSEL
        self.writeDP(DP_REG['SELECT'], ap_sel | bank_sel)

        if addr == AP_REG['CSW']:
            if data == self.csw:
                return
            self.csw = data

        self._write(WRITE | AP_ACC | (addr & 0x0c), data)
        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()

        return True

    def readAP(self, addr, mode=Transport.READ_NOW):
        res = None
        if mode in (Transport.READ_START, Transport.READ_NOW):
            ap_sel = addr & 0xff000000
            bank_sel = addr & APBANKSEL

            self.writeDP(DP_REG['SELECT'], ap_sel | bank_sel)
            self._write(READ | AP_ACC | (addr & 0x0c))

        if mode in (Transport.READ_NOW, Transport.READ_END):
            resp = self._read()
            res = (resp[0] << 0) | \
                    (resp[1] << 8) | \
                    (resp[2] << 16) | \
                    (resp[3] << 24)

            # All READ_STARTs must have been finished with READ_END before using READ_NOW
            assert (mode != Transport.READ_NOW) or (len(self.data_read_list)
                                                    == 0)

        # If not in deferred mode flush after calls to _read or _write
        if not self.deferred_transfer:
            self.flush()

        return res

    def reset(self):
        self.flush()
        self.protocol.setSWJPins(0, 'nRESET')
        sleep(0.1)
        self.protocol.setSWJPins(0x80, 'nRESET')
        sleep(0.1)

    def assertReset(self, asserted):
        self.flush()
        if asserted:
            self.protocol.setSWJPins(0, 'nRESET')
        else:
            self.protocol.setSWJPins(0x80, 'nRESET')

    def setClock(self, frequency):
        self.flush()
        self.protocol.setSWJClock(frequency)

    def setDeferredTransfer(self, enable):
        """
        Allow transfers to be delayed and buffered

        By default deferred transfers are turned off.  All reads and
        writes will be completed by the time the function returns.

        When enabled packets are buffered and sent all at once, which
        increases speed.  When memory is written to, the transfer
        might take place immediately, or might take place on a future
        memory write.  This means that an invalid write could cause an
        exception to occur on a later, unrelated write.  To guarantee
        that previous writes are complete call the flush() function.

        The behaviour of read operations is determined by the modes
        READ_START, READ_NOW and READ_END.  The option READ_NOW is the
        default and will cause the read to flush all previous writes,
        and read the data immediately.  To improve performance, multiple
        reads can be made using READ_START and finished later with READ_NOW.
        This allows the reads to be buffered and sent at once.  Note - All
        READ_ENDs must be called before a call using READ_NOW can be made.
        """
        if self.deferred_transfer and not enable:
            self.flush()
        self.deferred_transfer = enable

    def flush(self):
        """
        Flush out all commands
        """
        transfer_count = len(self.request_list)
        if transfer_count > 0:
            assert transfer_count <= COMMANDS_PER_DAP_TRANSFER
            try:
                data = self.protocol.transfer(transfer_count,
                                              self.request_list,
                                              self.data_list)
                self.data_read_list.extend(data)
            except Transport.TransferError:
                # Dump any pending commands
                self.request_list = []
                self.data_list = []
                # Dump any data read
                self.data_read_list = []
                # Invalidate cached registers
                self.csw = -1
                self.dp_select = -1
                # Clear error
                self.clearStickyErr()
                raise
            self.request_list = []
            self.data_list = []

    def _write(self, request, data=0):
        """
        Write a single command
        """
        assert type(request) in (int, long), "request is not an int"
        assert type(data) in (int, long), "data is not an int"
        self.request_list.append(request)
        self.data_list.append(data)
        transfer_count = len(self.request_list)
        if (transfer_count >= COMMANDS_PER_DAP_TRANSFER):
            self.flush()

    def _read(self):
        """
        Read the response from a single command
        """
        if len(self.data_read_list) < 4:
            self.flush()
        data = self.data_read_list[0:4]
        self.data_read_list = self.data_read_list[4:]
        return data

    def _transferBlock(self, count, request, data=[0]):
        self.flush()
        return self.protocol.transferBlock(count, request, data)