Mercurial > lcfOS
diff python/stlink.py @ 114:f42268da614f
Connected to stm32f4discovery
author | Windel Bouwman |
---|---|
date | Sat, 05 Jan 2013 19:07:14 +0100 |
parents | 1f40be088ee8 |
children | 92b2bf0da1ec |
line wrap: on
line diff
--- a/python/stlink.py Sat Jan 05 00:06:27 2013 +0100 +++ b/python/stlink.py Sat Jan 05 19:07:14 2013 +0100 @@ -1,3 +1,4 @@ +import struct, time from usb import UsbContext class STLinkException(Exception): @@ -8,11 +9,28 @@ STLINK2_PID=0x3748 return device.VendorId == ST_VID and device.ProductId == STLINK2_PID -XFER_TO_DEV=0 -XFER_FROM_DEV=0x80 +DFU_MODE, MASS_MODE, DEBUG_MODE = range(3) +# Commands: +GET_VERSION = 0xf1 +DEBUG_COMMAND = 0xf2 +DFU_COMMAND = 0xf3 +GET_CURRENT_MODE = 0xf5 + +# dfu commands: +DFU_EXIT = 0x7 -class STLink(object): - DFU_MODE = 222 +# debug commands: +DEBUG_ENTER = 0x20 +DEBUG_EXIT = 0x21 +DEBUG_ENTER_SWD = 0xa3 +DEBUG_GETSTATUS = 0x01 + +JTAG_READDEBUG_32BIT = 0x36 + +# cortex M3 +CM3_REG_CPUID = 0xE000ED00 + +class STLink: def __init__(self): self.context = UsbContext() def open(self): @@ -23,22 +41,129 @@ if len(stlink2s) > 1: print('More then one stlink2 found, picking first one') stlink2 = stlink2s[0] - dev = stlink2.open() - if dev.Configuration != 1: - dev.Configuration = 1 - dev.claimInterface(0) + self.devHandle = stlink2.open() + if self.devHandle.Configuration != 1: + self.devHandle.Configuration = 1 + self.devHandle.claimInterface(0) + def close(self): + pass def getCurrentMode(self): - print('get cur mode') - rep_len = 2 - self.fillCommand(self, XFER_FROM_DEV, rep_len) - size = self.send_recv(1, cmd, data) - return self.q_buf[0] + cmd = bytearray(16) + cmd[0] = GET_CURRENT_MODE + reply = self.send_recv(cmd, 2) # Expect 2 bytes back + return reply[0] CurrentMode = property(getCurrentMode) - def fillCommand(self, di, rl): - bytes(b'USBC') - pass - def reset(self): - pass - def send_recv(self, txbuf, rxbuf): - pass + @property + def CurrentModeString(self): + modes = {DFU_MODE: 'dfu', MASS_MODE: 'massmode', DEBUG_MODE:'debug'} + return modes[self.CurrentMode] + def exitDfuMode(self): + cmd = bytearray(16) + cmd[0] = DFU_COMMAND + cmd[1] = DFU_EXIT + self.send_recv(cmd) + def enterSwdMode(self): + cmd = bytearray(16) + cmd[0] = DEBUG_COMMAND + cmd[1] = DEBUG_ENTER + cmd[2] = DEBUG_ENTER_SWD + self.send_recv(cmd) + def exitDebugMode(self): + cmd = bytearray(16) + cmd[0] = DEBUG_COMMAND + cmd[1] = DEBUG_EXIT + self.send_recv(cmd) + + def getVersion(self): + cmd = bytearray(16) + cmd[0] = GET_VERSION + data = self.send_recv(cmd, 6) # Expect 6 bytes back + # Parse 6 bytes into various versions: + b0, b1, b2, b3, b4, b5 = data + stlink_v = b0 >> 4 + jtag_v = ((b0 & 0xf) << 2) | (b1 >> 6) + swim_v = b1 & 0x3f + vid = (b3 << 8) | b2 + pid = (b5 << 8) | b4 + + return 'stlink={0} jtag={1} swim={2} vid:pid={3:04X}:{4:04X}'.format(\ + stlink_v, jtag_v, swim_v, vid, pid) + Version = property(getVersion) + + @property + def ChipId(self): + return self.read_debug32(0xE0042000) + @property + def CpuId(self): + u32 = self.read_debug32(CM3_REG_CPUID) + implementer_id = (u32 >> 24) & 0x7f + variant = (u32 >> 20) & 0xf + part = (u32 >> 4) & 0xfff + revision = u32 & 0xf + return implementer_id, variant, part, revision + + def status(self): + cmd = bytearray(16) + cmd[0] = DEBUG_COMMAND + cmd[1] = DEBUG_GETSTATUS + reply = self.send_recv(cmd, 2) + return reply[0] + def step(self): + cmd = bytearray(16) + cmd[0] = DEBUG_COMMAND + cmd[1] = DEBUG_STEPCORE + self.send_recv(cmd, 2) + def run(self): + cmd = bytearray(16) + cmd[0] = DEBUG_COMMAND + cmd[1] = DEBUG_RUNCORE + self.send_recv(cmd, 2) + + # Helper 1 functions: + def read_debug32(self, address): + cmd = bytearray(16) + cmd[0] = DEBUG_COMMAND + cmd[1] = JTAG_READDEBUG_32BIT + cmd[2:6] = struct.pack('<I', address) # pack into u32 little endian + reply = self.send_recv(cmd, 8) + return struct.unpack('<I', reply[4:8])[0] + + # Helper 2 functions: + def send_recv(self, tx, rxsize=0): + """ Helper function that transmits and receives data. """ + # TODO: we could use here the non-blocking libusb api. + tx = bytes(tx) + self.devHandle.bulkWrite(2, tx) # write to endpoint 2 + if rxsize > 0: + return self.devHandle.bulkRead(1, rxsize) # read from endpoint 1 + +knownChipIds = {0x1: 'x'} + +if __name__ == '__main__': + # Test program + sl = STLink() + sl.open() + print('version:', sl.Version) + print('mode before doing anything:', sl.CurrentModeString) + if sl.CurrentMode == DFU_MODE: + sl.exitDfuMode() + sl.enterSwdMode() + print('mode after entering swd mode:', sl.CurrentModeString) + + i = sl.ChipId + if i in knownChipIds: + print('chip id: 0x{0:X} -> {1}'.format(i, knownChipIds[i])) + else: + print('chip id: 0x{0:X}'.format(i)) + print('cpu: {0}'.format(sl.CpuId)) + + print('status: {0}'.format(sl.status())) + + time.sleep(2.2) + + sl.exitDebugMode() + print('mode at end:', sl.CurrentModeString) + + sl.close() +