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, 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 = []
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)
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)