Mercurial > lcfOS
diff python/ide/st-util.py @ 292:534b94b40aa8
Fixup reorganize
author | Windel Bouwman |
---|---|
date | Wed, 27 Nov 2013 08:06:42 +0100 |
parents | python/st-util.py@2ccd57b1d78c |
children | dcae6574c974 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/ide/st-util.py Wed Nov 27 08:06:42 2013 +0100 @@ -0,0 +1,385 @@ +#!/usr/bin/python + +import sys +from PyQt4.QtCore import * +from PyQt4.QtGui import * +import stlink, devices, stm32, usb +from devices import Interface, Device +from hexedit import HexEdit + + +class InformationDialog(QDialog): + def __init__(self, parent): + super().__init__(parent) + self.setWindowTitle('Info') + fl = QFormLayout(self) + if parent.stl: + fl.addRow('ST link version:', QLabel(parent.stl.Version)) + fl.addRow('Chip id:', QLabel('0x{0:X}'.format(parent.stl.ChipId))) + fl.addRow('Current mode:', QLabel(parent.stl.CurrentModeString)) + fl.addRow('Status:', QLabel(parent.stl.StatusString)) + + +class RegisterModel(QAbstractTableModel): + def __init__(self): + super().__init__() + self.regCount = 15 + self.device = None + + def rowCount(self, parent): + if parent.isValid(): + return 0 + if self.device: + return 21 # TODO make variable + else: + return 0 + + def setDevice(self, dev): + self.device = dev + self.modelReset.emit() + + def columnCount(self, parent): + if parent.isValid(): + return 0 + return 2 + + def data(self, index, role): + if index.isValid(): + row, col = index.row(), index.column() + if role == Qt.DisplayRole: + if col == 0: + if row == 15: + return 'PC' + elif row == 14: + return 'LR' + elif row == 13: + return 'SP' + else: + return 'R{0}'.format(row) + elif col == 1: + v = self.device.iface.read_reg(row) + return '0x{0:X}'.format(v) + + def setData(self, index, value, role): + if index.isValid(): + row = index.row() + col = index.column() + if role == Qt.EditRole and col == 1: + value = int(value, 16) + self.device.iface.write_reg(row, value) + return True + return False + + def flags(self, index): + if index.isValid(): + row = index.row() + col = index.column() + if col == 1: + return super().flags(index) | Qt.ItemIsEditable + return super().flags(index) + + def refresh(self): + if self.device: + fromIndex = self.index(0, 1) + toIndex = self.index(21, 1) + self.dataChanged.emit(fromIndex, toIndex) + + +class RegisterView(QTableView): + def __init__(self): + super().__init__() + self.mdl = RegisterModel() + self.setModel(self.mdl) + + def refresh(self): + if self.mdl.device: + self.setEnabled(not self.mdl.device.Running) + self.mdl.refresh() + + +class MemoryView(QWidget): + BlockSize = 0x100 + def __init__(self): + super().__init__() + l = QVBoxLayout(self) + l2 = QHBoxLayout() + l2.addWidget(QLabel('Address')) + self.addressLine = QLineEdit() + self.addressLine.setInputMask('Hhhhhhhh') + l2.addWidget(self.addressLine) + upButton = QPushButton('up') + l2.addWidget(upButton) + upButton.clicked.connect(self.doUp) + downButton = QPushButton('down') + downButton.clicked.connect(self.doDown) + l2.addWidget(downButton) + l.addLayout(l2) + self.device = None + self.hexEdit = HexEdit() + self.Address = 0x8000000 + l.addWidget(self.hexEdit) + self.addressLine.returnPressed.connect(self.refresh) + + def refresh(self): + address = self.Address + if self.device: + data = self.device.iface.read_mem32(address, self.BlockSize) + else: + data = bytearray(self.BlockSize) + self.hexEdit.bv.Data = data + self.hexEdit.bv.Offset = address + + def getAddress(self): + txt = self.addressLine.text() + return int(txt, 16) + + def doUp(self): + self.Address -= self.BlockSize + + def doDown(self): + self.Address += self.BlockSize + + def setAddress(self, address): + self.addressLine.setText('{0:08X}'.format(address)) + self.refresh() + Address = property(getAddress, setAddress) + def setDevice(self, dev): + self.device = dev + self.Address = 0x8000000 + + +class DebugToolbar(QToolBar): + statusChange = pyqtSignal() + codePosition = pyqtSignal(int) + def __init__(self): + super().__init__() + self.device = None + # generate actions: + def genAction(name, callback): + a = QAction(name, self) + a.triggered.connect(callback) + self.addAction(a) + return a + self.stepAction = genAction('Step', self.doStep) + self.runAction = genAction('Run', self.doRun) + self.stopAction = genAction('Stop', self.doHalt) + self.resetAction = genAction('Reset', self.doReset) + self.enableTraceAction = genAction('Enable trace', self.doEnableTrace) + self.updateEnables() + def updateEnables(self): + if self.device: + self.resetAction.setEnabled(True) + self.enableTraceAction.setEnabled(True) + self.runAction.setEnabled(not self.device.Running) + self.stepAction.setEnabled(not self.device.Running) + self.stopAction.setEnabled(self.device.Running) + self.statusChange.emit() + if not self.device.Running: + PC = 15 + v = self.device.iface.read_reg(PC) + self.codePosition.emit(v) + else: + self.resetAction.setEnabled(False) + self.enableTraceAction.setEnabled(False) + self.runAction.setEnabled(False) + self.stepAction.setEnabled(False) + self.stopAction.setEnabled(False) + def doStep(self): + self.device.iface.step() + self.updateEnables() + def doReset(self): + self.device.iface.reset() + self.updateEnables() + def doRun(self): + self.device.iface.run() + self.updateEnables() + def doHalt(self): + self.device.iface.halt() + self.updateEnables() + def doEnableTrace(self): + self.device.iface.traceEnable() + self.updateEnables() + def setDevice(self, dev): + self.device = dev + self.updateEnables() + + +class FlashTool(QWidget): + def __init__(self): + super().__init__() + # TODO! + + +class DeviceTreeModel(QAbstractItemModel): + def __init__(self): + super().__init__() + self.chipPixmap = QPixmap('icons/chip.png').scaled(32, 32) + self.hardwarePixmap = QPixmap('icons/hardware.png').scaled(32, 32) + self.refresh() + def refresh(self): + """ Check all usb interfaces for interfaces """ + self.interfaces = devices.createInterfaces() + self.devices = [] + self.modelReset.emit() + def addDevice(self, device): + if device.iface in [lambda d: d.iface for d in self.devices]: + print('device already open') + return + self.devices.append(device) + self.modelReset.emit() + def index(self, row, column, parent): + if parent.isValid(): + ip = parent.internalPointer() + if isinstance(ip, Interface): + devs = [d for d in self.devices if d.iface is ip] + return self.createIndex(row, column, devs[row]) + else: + iface = self.interfaces[row] + return self.createIndex(row, column, iface) + return idx + def parent(self, index): + if index.isValid(): + ip = index.internalPointer() + if isinstance(ip, Interface): + return QModelIndex() + elif isinstance(ip, Device): + iface = ip.iface + row = self.interfaces.index(iface) + return self.createIndex(row, 0, iface) + return QModelIndex() + def rowCount(self, parent): + if parent.isValid(): + # non-root level: + ip = parent.internalPointer() + if isinstance(ip, Interface): + devs = [d for d in self.devices if d.iface is ip] + return len(devs) + else: + # root level: + return len(self.interfaces) + return 0 + def columnCount(self, parent): + return 1 + def data(self, index, role): + if index.isValid(): + ip = index.internalPointer() + if role == Qt.DisplayRole: + return str(ip) + elif role == Qt.DecorationRole: + if isinstance(ip, Interface): + return self.hardwarePixmap + if isinstance(ip, Device): + return self.chipPixmap + +class DeviceExplorer(QTreeView): + """ Lists all interfaces plugged in and allows selection """ + deviceSelected = pyqtSignal(Device) + def __init__(self): + super().__init__() + self.mdl = DeviceTreeModel() + self.setModel(self.mdl) + self.activated.connect(self.openItem) + self.header().close() + self.customContextMenuRequested.connect(self.openMenu) + self.setContextMenuPolicy(Qt.CustomContextMenu) + def openItem(self, idx): + if idx.isValid(): + ip = idx.internalPointer() + if isinstance(ip, Interface): + if not ip.IsOpen: + try: + ip.open() + except usb.UsbError as e: + QMessageBox.critical(self, "Error", 'Error opening interface: "{0}"'.format(e)) + else: + # Try to get a device: + self.mdl.addDevice(ip.createDevice()) + if isinstance(ip, Device): + self.deviceSelected.emit(ip) + def openMenu(self, pt): + idx = self.indexAt(pt) + menu = QMenu() + menu.addAction('Refresh', self.mdl.refresh) + if idx.isValid(): + ip = idx.internalPointer() + if isinstance(ip, Interface): + if ip.IsOpen: + def closeInterface(): + self.mdl.closeInterface(ip) + menu.addAction('Close', closeInterface) + else: + def openInterface(): + ip.open() + # Try to get a device: + self.mdl.addDevice(ip.createDevice()) + menu.addAction('Open', openInterface) + elif isinstance(ip, Device): + def selectDevice(): + self.deviceSelected.emit(ip) + menu.addAction('Select', selectDevice) + menu.exec(self.mapToGlobal(pt)) + + +class StUtil(QMainWindow): + connected = pyqtSignal(bool) + def __init__(self): + super().__init__() + self.stl = None + def buildAction(name, callback, shortcut=None): + a = QAction(name, self) + a.triggered.connect(callback) + if shortcut: + a.setShortcut(shortcut) + return a + mb = self.menuBar() + fileMenu = mb.addMenu("File") + self.connectAction = buildAction('Connect', self.connect) + fileMenu.addAction(self.connectAction) + self.disconnectAction = buildAction('Disconnect', self.disconnect) + fileMenu.addAction(self.disconnectAction) + + self.miscMenu = mb.addMenu("Misc") + infoAction = buildAction('Info', self.info) + self.miscMenu.addAction(infoAction) + + sb = self.statusBar() + + devexplr = DeviceExplorer() + self.setCentralWidget(devexplr) + devexplr.deviceSelected.connect(self.handleDeviceSelected) + + self.connected.connect(self.handleConnectedChange) + self.connected.emit(False) + def handleDeviceSelected(self, dev): + self.dev = dev + self.handleConnectedChange(True) + def handleConnectedChange(self, state): + self.miscMenu.setEnabled(state) + self.connectAction.setEnabled(not state) + self.disconnectAction.setEnabled(state) + msg = 'Connected!' if state else 'Disconnected!' + self.statusBar().showMessage(msg) + def info(self): + infoDialog = InformationDialog(self) + infoDialog.exec() + def connect(self): + try: + self.stl = stlink.STLink() + self.stl.open() + except (stlink.STLinkException, usb.UsbError) as e: + QMessageBox.warning(self, "Error", str(e)) + self.stl = None + if self.stl: + self.connected.emit(True) + def disconnect(self): + if self.stl: + self.stl.close() + self.connected.emit(False) + self.stl = None + +if __name__ == '__main__': + app = QApplication(sys.argv) + stu = StUtil() + stu.show() + app.exec() +