class ValueWidget(QWidget, Ui_Widget): def __init__(self, iface): self.hasqwt=hasqwt self.hasmpl=hasmpl self.layerMap=dict() self.statsChecked=False self.ymin=0 self.ymax=250 self.iface=iface self.canvas=self.iface.mapCanvas() self.legend=self.iface.legendInterface() self.logger = logging.getLogger('.'.join((__name__, self.__class__.__name__))) QWidget.__init__(self) self.setupUi(self) self.setupUi_extra() QObject.connect(self.cbxActive,SIGNAL("stateChanged(int)"),self.changeActive) QObject.connect(self.cbxGraph,SIGNAL("stateChanged(int)"),self.changePage) QObject.connect(self.canvas, SIGNAL( "keyPressed( QKeyEvent * )" ), self.pauseDisplay ) QObject.connect(self.plotSelector, SIGNAL( "currentIndexChanged ( int )" ), self.changePlot ) def setupUi_extra(self): # checkboxes #self.changeActive(Qt.Checked) #set inactive by default - should save last state in user config self.cbxActive.setCheckState(Qt.Unchecked) # plot self.plotSelector.setVisible( False ) self.cbxStats.setVisible( False ) self.graphControls.setVisible( False ) if self.hasqwt: self.plotSelector.addItem( 'Qwt' ) if self.hasmpl: self.plotSelector.addItem( 'mpl' ) self.plotSelector.setCurrentIndex( 0 ); if (not self.hasqwt or not self.hasmpl): #self.plotSelector.setVisible(False) self.plotSelector.setEnabled(False) # Page 2 - qwt if self.hasqwt: self.qwtPlot = QwtPlot(self.stackedWidget) self.qwtPlot.setAutoFillBackground(False) self.qwtPlot.setObjectName("qwtPlot") self.curve = QwtPlotCurve() self.curve.setSymbol( QwtSymbol(QwtSymbol.Ellipse, QBrush(Qt.white), QPen(Qt.red, 2), QSize(9, 9))) self.curve.attach(self.qwtPlot) self.qwtPlot.setVisible(False) else: self.qwtPlot = QtGui.QLabel("Need Qwt >= 5.0 or matplotlib >= 1.0 !") sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.qwtPlot.sizePolicy().hasHeightForWidth()) self.qwtPlot.setSizePolicy(sizePolicy) self.qwtPlot.setObjectName("qwtPlot") self.qwtPlot.updateGeometry() self.stackedWidget.addWidget(self.qwtPlot) #Page 3 - matplotlib self.mplLine = None #make sure to invalidate when layers change if self.hasmpl: # mpl stuff # should make figure light gray self.mplBackground = None #http://www.scipy.org/Cookbook/Matplotlib/Animations self.mplFig = plt.Figure(facecolor='w', edgecolor='w') self.mplFig.subplots_adjust(left=0.1, right=0.975, bottom=0.13, top=0.95) self.mplPlt = self.mplFig.add_subplot(111) self.mplPlt.tick_params(axis='both', which='major', labelsize=12) self.mplPlt.tick_params(axis='both', which='minor', labelsize=10) # qt stuff self.pltCanvas = FigureCanvasQTAgg(self.mplFig) self.pltCanvas.setParent(self.stackedWidget) self.pltCanvas.setAutoFillBackground(False) self.pltCanvas.setObjectName("mplPlot") self.mplPlot = self.pltCanvas self.mplPlot.setVisible(False) else: self.mplPlot = QtGui.QLabel("Need Qwt >= 5.0 or matplotlib >= 1.0 !") sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,QtGui.QSizePolicy.Expanding) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.mplPlot.sizePolicy().hasHeightForWidth()) self.mplPlot.setSizePolicy(sizePolicy) self.qwtPlot.setObjectName("qwtPlot") self.mplPlot.updateGeometry() self.stackedWidget.addWidget(self.mplPlot) self.stackedWidget.setCurrentIndex(0) def disconnect(self): self.changeActive(False) QObject.disconnect(self.canvas, SIGNAL( "keyPressed( QKeyEvent * )" ), self.pauseDisplay ) def pauseDisplay(self,e): if ( e.modifiers() == Qt.ShiftModifier or e.modifiers() == Qt.MetaModifier ) and e.key() == Qt.Key_A: self.cbxActive.toggle() return True return False def keyPressEvent( self, e ): if ( e.modifiers() == Qt.ControlModifier or e.modifiers() == Qt.MetaModifier ) and e.key() == Qt.Key_C: items = QString() for rec in range( self.tableWidget.rowCount() ): items.append( '"' + self.tableWidget.item( rec, 0 ).text() + '",' + self.tableWidget.item( rec, 1 ).text() + "\n" ) if not items.isEmpty(): clipboard = QApplication.clipboard() clipboard.setText( items ) elif (self.pauseDisplay(e)): pass else: QWidget.keyPressEvent( self, e ) def changePage(self,state): if (state==Qt.Checked): self.plotSelector.setVisible( True ) self.cbxStats.setVisible( True ) self.graphControls.setVisible( True ) if (self.plotSelector.currentText()=='mpl'): self.stackedWidget.setCurrentIndex(2) else: self.stackedWidget.setCurrentIndex(1) else: self.plotSelector.setVisible( False ) self.cbxStats.setVisible( False ) self.graphControls.setVisible( False ) self.stackedWidget.setCurrentIndex(0) def changePlot(self): self.changePage(self.cbxActive.checkState()) def changeActive(self,state): if (state==Qt.Checked): #QObject.connect(self.legend, SIGNAL( "itemAdded ( QModelIndex )" ), self.statsNeedChecked ) #QObject.connect(self.legend, SIGNAL( "itemRemoved ()" ), self.invalidatePlot ) QObject.connect(self.canvas, SIGNAL( "layersChanged ()" ), self.invalidatePlot ) if int(QGis.QGIS_VERSION[2]) > 2: # for QGIS >= 1.3 QObject.connect(self.canvas, SIGNAL("xyCoordinates(const QgsPoint &)"), self.printValue) else: QObject.connect(self.canvas, SIGNAL("xyCoordinates(QgsPoint &)"), self.printValue) else: QObject.disconnect(self.canvas, SIGNAL( "layersChanged ()" ), self.invalidatePlot ) if int(QGis.QGIS_VERSION[2]) > 2: # for QGIS >= 1.3 QObject.disconnect(self.canvas, SIGNAL("xyCoordinates(const QgsPoint &)"), self.printValue) else: QObject.disconnect(self.canvas, SIGNAL("xyCoordinates(QgsPoint &)"), self.printValue) def printValue(self,position): if self.canvas.layerCount() == 0: self.values=[] self.showValues() return needextremum = self.cbxGraph.isChecked() # if plot is checked # count the number of requires rows and remember the raster layers nrow=0 rasterlayers=[] layersWOStatistics=[] for i in range(self.canvas.layerCount()): layer = self.canvas.layer(i) if (layer!=None and layer.isValid() and layer.type()==QgsMapLayer.RasterLayer): if QGis.QGIS_VERSION_INT >= 10900: # for QGIS >= 1.9 if not layer.dataProvider(): continue if not layer.dataProvider().capabilities() & QgsRasterDataProvider.IdentifyValue: continue nrow+=layer.bandCount() rasterlayers.append(layer) else: # < 1.9 if layer.providerKey()=="wms": continue if layer.providerKey()=="grassraster": nrow+=1 rasterlayers.append(layer) else: # normal raster layer nrow+=layer.bandCount() rasterlayers.append(layer) # check statistics for each band if needextremum: for i in range( 1,layer.bandCount()+1 ): if int(QGis.QGIS_VERSION[2]) > 8: # for QGIS > 1.8 has_stats=layer.dataProvider().hasStatistics(i) else: has_stats=layer.hasStatistics(i) if not layer.id() in self.layerMap and not has_stats\ and not layer in layersWOStatistics: layersWOStatistics.append(layer) if layersWOStatistics and not self.statsChecked: self.calculateStatistics(layersWOStatistics) # create the row if necessary self.tableWidget.setRowCount(nrow) irow=0 self.values=[] self.ymin=1e38 self.ymax=-1e38 mapCanvasSrs = self.iface.mapCanvas().mapRenderer().destinationSrs() # TODO - calculate the min/max values only once, instead of every time!!! # keep them in a dict() with key=layer.id() for layer in rasterlayers: layername=unicode(layer.name()) layerSrs = layer.srs() pos = position # if given no position, get dummy values if position is None: pos = QgsPoint(0,0) # transform points if needed elif not mapCanvasSrs == layerSrs and self.iface.mapCanvas().hasCrsTransformEnabled(): srsTransform = QgsCoordinateTransform(mapCanvasSrs, layerSrs) try: pos = srsTransform.transform(position) except QgsCsException, err: # ignore transformation errors continue if QGis.QGIS_VERSION_INT >= 10900: # for QGIS >= 1.9 if not layer.dataProvider(): continue ident = None if position is not None: canvas = self.iface.mapCanvas() # we can only use context if layer is not projected if canvas.hasCrsTransformEnabled() and layer.dataProvider().crs() != canvas.mapRenderer().destinationCrs(): ident = layer.dataProvider().identify(pos, QgsRasterDataProvider.IdentifyFormatValue ) else: extent = canvas.extent() width = round(extent.width() / canvas.mapUnitsPerPixel()); height = round(extent.height() / canvas.mapUnitsPerPixel()); extent = canvas.mapRenderer().mapToLayerCoordinates( layer, extent ); ident = layer.dataProvider().identify(pos, QgsRasterDataProvider.IdentifyFormatValue, canvas.extent(), width, height ) if not len( ident ) > 0: continue # if given no position, set values to 0 if position is None: for key in ident.iterkeys(): ident[key] = layer.dataProvider().noDataValue(key) for iband in range(1,layer.bandCount()+1): # loop over the bands layernamewithband=layername if len(ident)>1: layernamewithband+=' '+layer.bandName(iband) if not ident or not ident.has_key( iband ): # should not happen bandvalue = "?" else: doubleValue = ident[iband].toDouble()[0] if layer.dataProvider().isNoDataValue ( iband, doubleValue ): bandvalue = "no data" else: bandvalue = QgsRasterBlock.printValue( doubleValue ) self.values.append((layernamewithband,bandvalue)) if needextremum: has_stats=layer.hasStatistics(i) if has_stats: cstr=layer.bandStatistics(iband) if has_stats: self.ymin=min(self.ymin,cstr.minimumValue) self.ymax=max(self.ymax,cstr.maximumValue) else: self.ymin=min(self.ymin,layer.minimumValue(i)) self.ymax=max(self.ymax,layer.maximumValue(i)) else: # QGIS < 1.9 isok,ident = layer.identify(pos) if not isok: continue # if given no position, set values to 0 if position is None: for key in ident.iterkeys(): ident[key] = 0 if layer.providerKey()=="grassraster": if not ident.has_key(QString("value")): continue cstr = ident[QString("value")] if cstr.isNull(): continue value = cstr.toDouble() if not value[1]: # if this is not a double, it is probably a (GRASS string like # 'out of extent' or 'null (no data)'. Let's just show that: self.values.append((layername, cstr)) continue self.values.append((layername,cstr)) if needextremum: self.ymin = min(self.ymin,value[0]) self.ymax = max(self.ymax,value[0]) else: for iband in range(1,layer.bandCount()+1): # loop over the bands bandvalue=ident[layer.bandName(iband)] layernamewithband=layername if len(ident)>1: layernamewithband+=' '+layer.bandName(iband) self.values.append((layernamewithband,bandvalue)) if needextremum: if int(QGis.QGIS_VERSION[2]) > 8: # for QGIS > 1.8 has_stats=layer.dataProvider().hasStatistics(i) if has_stats: cstr=layer.dataProvider().bandStatistics(iband) else: has_stats=layer.hasStatistics(i) if has_stats: cstr=layer.bandStatistics(iband) if has_stats: self.ymin=min(self.ymin,cstr.minimumValue) self.ymax=max(self.ymax,cstr.maximumValue) else: self.ymin=min(self.ymin,layer.minimumValue(i)) self.ymax=max(self.ymax,layer.maximumValue(i)) self.showValues()
class RTTView(QtGui.QWidget, Ui_RTTView): def __init__(self, parent=None): super(RTTView, self).__init__(parent) self.setupUi(self) self.initSetting() self.initQwtPlot() self.daplink = None self.tmrDAP = QtCore.QTimer() self.tmrDAP.setInterval(10) self.tmrDAP.timeout.connect(self.on_tmrDAP_timeout) self.tmrDAP.start() self.tmrCntr = 0 # tmrDAP超时一次,tmrCntr加一 def initSetting(self): if not os.path.exists('setting.ini'): open('setting.ini', 'w') self.conf = ConfigParser.ConfigParser() self.conf.read('setting.ini') if not self.conf.has_section('globals'): self.conf.add_section('globals') self.conf.set('globals', 'mappath', '[]') for path in eval(self.conf.get('globals', 'mappath')): self.cmbMap.insertItem(10, path) def initQwtPlot(self): self.PlotBuff = '' self.PlotData = [0] * 1000 self.qwtPlot = QwtPlot(self) self.vLayout0.insertWidget(0, self.qwtPlot) self.PlotCurve = QwtPlotCurve() self.PlotCurve.attach(self.qwtPlot) self.PlotCurve.setData(range(1, len(self.PlotData) + 1), self.PlotData) self.on_cmbMode_currentIndexChanged(u'文本') def parseRTTAddr(self): with open(self.cmbMap.currentText(), 'r') as f: for line in f: match = re.match( '\s+_SEGGER_RTT\s+(0x[0-9a-fA-F]{8})\s+Data.+', line) if match: return int(match.group(1), 16) else: raise Exception('Can not found _SEGGER_RTT') @QtCore.pyqtSlot() def on_btnOpen_clicked(self): if self.btnOpen.text() == u'打开连接': try: self.daplink.open() self.dp = coresight.dap.DebugPort(self.daplink) self.dp.init() self.dp.power_up_debug() self.ap = coresight.ap.AHB_AP(self.dp, 0) self.ap.init() self.RTTAddr = self.parseRTTAddr() except Exception as e: print e else: self.btnOpen.setText(u'关闭连接') self.lblOpen.setPixmap(QtGui.QPixmap("./Image/inopening.png")) else: try: self.daplink.close() except Exception as e: print e finally: self.btnOpen.setText(u'打开连接') self.lblOpen.setPixmap(QtGui.QPixmap("./Image/inclosing.png")) def aUpEmpty(self): LEN = (16 + 4 * 2) + (4 * 6) * 4 buf = self.ap.readBlockMemoryUnaligned8(self.RTTAddr, LEN) arr = struct.unpack('16sLLLLLLLL24xLLLLLL24x', ''.join([chr(x) for x in buf])) self.aUp = RingBuffer(arr[3:9]) print 'WrOff=%d, RdOff=%d' % (self.aUp.WrOff, self.aUp.RdOff) self.aDown = RingBuffer(arr[9:15]) return (self.aUp.RdOff == self.aUp.WrOff) def aUpRead(self): if self.aUp.RdOff < self.aUp.WrOff: len_ = self.aUp.WrOff - self.aUp.RdOff arr = self.ap.readBlockMemoryUnaligned8( self.aUp.pBuffer + self.aUp.RdOff, len_) self.aUp.RdOff += len_ self.ap.write32(self.RTTAddr + (16 + 4 * 2) + 4 * 4, self.aUp.RdOff) else: len_ = self.aUp.SizeOfBuffer - self.aUp.RdOff + 1 arr = self.ap.readBlockMemoryUnaligned8( self.aUp.pBuffer + self.aUp.RdOff, len_) self.aUp.RdOff = 0 #这样下次再读就会进入执行上个条件 self.ap.write32(self.RTTAddr + (16 + 4 * 2) + 4 * 4, self.aUp.RdOff) return ''.join([chr(x) for x in arr]) def on_tmrDAP_timeout(self): if self.btnOpen.text() == u'关闭连接': ss = '' try: if not self.aUpEmpty(): ss = self.aUpRead() except Exception as e: pass if ss: if self.mode == u'文本': if len(self.txtMain.toPlainText()) > 50000: self.txtMain.clear() self.txtMain.moveCursor(QtGui.QTextCursor.End) self.txtMain.insertPlainText(ss) elif self.mode == u'波形': self.PlotBuff += ss if self.PlotBuff.rfind(',') == -1: return try: d = [ int(x) for x in self. PlotBuff[0:self.PlotBuff.rfind(',')].split(',') ] for x in d: self.PlotData.pop(0) self.PlotData.append(x) except: self.PlotBuff = '' else: self.PlotBuff = self.PlotBuff[self.PlotBuff. rfind(',') + 1:] self.PlotCurve.setData(range(1, len(self.PlotData) + 1), self.PlotData) self.qwtPlot.replot() self.detect_daplink() # 自动检测 DAPLink 的热插拔 def detect_daplink(self): daplinks = pyDAPAccess.DAPAccess.get_connected_devices() if self.daplink and (daplinks == []): # daplink被拔下 try: self.daplink.close() except Exception as e: print e finally: self.daplink = None self.linDAP.clear() self.btnOpen.setText(u'打开连接') self.lblOpen.setPixmap(QtGui.QPixmap("./Image/inclosing.png")) if not self.daplink and daplinks != []: self.daplink = daplinks[0] self.linDAP.clear() self.linDAP.setText(self.daplink._product_name) @QtCore.pyqtSlot() def on_btnMap_clicked(self): path = QtGui.QFileDialog.getOpenFileName( caption=u'项目.map文件路径', filter=u'MDK .map file (*.map)', directory=self.cmbMap.currentText()) if path != '': self.cmbMap.insertItem(0, path) self.cmbMap.setCurrentIndex(0) @QtCore.pyqtSlot(str) def on_cmbMode_currentIndexChanged(self, str): self.mode = str self.txtMain.setVisible(self.mode == u'文本') self.qwtPlot.setVisible(self.mode == u'波形') @QtCore.pyqtSlot() def on_btnClear_clicked(self): self.txtMain.clear() def closeEvent(self, evt): paths = [] for i in range(min(10, self.cmbMap.count())): paths.append(self.cmbMap.itemText(i)) self.conf.set('globals', 'mappath', repr(paths)) self.conf.write(open('setting.ini', 'w'))
class RTTView(QtGui.QWidget): def __init__(self, parent=None): super(RTTView, self).__init__(parent) uic.loadUi('RTTView.ui', self) self.initSetting() self.initQwtPlot() self.rcvbuff = b'' self.tmrRTT = QtCore.QTimer() self.tmrRTT.setInterval(10) self.tmrRTT.timeout.connect(self.on_tmrRTT_timeout) self.tmrRTT.start() def initSetting(self): if not os.path.exists('setting.ini'): open('setting.ini', 'w') self.conf = ConfigParser.ConfigParser() self.conf.read('setting.ini') if not self.conf.has_section('J-Link'): self.conf.add_section('J-Link') self.conf.set('J-Link', 'dllpath', '') self.conf.add_section('Memory') self.conf.set('Memory', 'StartAddr', '0x20000000') self.linDLL.setText(self.conf.get('J-Link', 'dllpath').decode('gbk')) def initQwtPlot(self): self.PlotData = [0]*1000 self.qwtPlot = QwtPlot(self) self.qwtPlot.setVisible(False) self.vLayout.insertWidget(0, self.qwtPlot) self.PlotCurve = QwtPlotCurve() self.PlotCurve.attach(self.qwtPlot) self.PlotCurve.setData(range(1, len(self.PlotData)+1), self.PlotData) @QtCore.pyqtSlot() def on_btnOpen_clicked(self): if self.btnOpen.text() == u'打开连接': try: self.jlink = ctypes.cdll.LoadLibrary(self.linDLL.text()) err_buf = (ctypes.c_char * 64)() self.jlink.JLINKARM_ExecCommand('Device = Cortex-M0', err_buf, 64) self.jlink.JLINKARM_TIF_Select(1) self.jlink.JLINKARM_SetSpeed(8000) buff = ctypes.create_string_buffer(1024) Addr = int(self.conf.get('Memory', 'StartAddr'), 16) for i in range(256): self.jlink.JLINKARM_ReadMem(Addr + 1024*i, 1024, buff) index = buff.raw.find('SEGGER RTT') if index != -1: self.RTTAddr = Addr + 1024*i + index buff = ctypes.create_string_buffer(ctypes.sizeof(SEGGER_RTT_CB)) self.jlink.JLINKARM_ReadMem(self.RTTAddr, ctypes.sizeof(SEGGER_RTT_CB), buff) rtt_cb = SEGGER_RTT_CB.from_buffer(buff) self.aUpAddr = self.RTTAddr + 16 + 4 + 4 self.aDownAddr = self.aUpAddr + ctypes.sizeof(RingBuffer) * rtt_cb.MaxNumUpBuffers self.txtMain.append('\n_SEGGER_RTT @ 0x%08X with %d aUp and %d aDown\n' %(self.RTTAddr, rtt_cb.MaxNumUpBuffers, rtt_cb.MaxNumDownBuffers)) break else: raise Exception('Can not find _SEGGER_RTT') except Exception as e: self.txtMain.append('\n%s\n' %str(e)) else: self.linDLL.setEnabled(False) self.btnDLL.setEnabled(False) self.btnOpen.setText(u'关闭连接') else: self.linDLL.setEnabled(True) self.btnDLL.setEnabled(True) self.btnOpen.setText(u'打开连接') def aUpRead(self): buf = ctypes.create_string_buffer(ctypes.sizeof(RingBuffer)) self.jlink.JLINKARM_ReadMem(self.aUpAddr, ctypes.sizeof(RingBuffer), buf) aUp = RingBuffer.from_buffer(buf) if aUp.RdOff == aUp.WrOff: str = ctypes.create_string_buffer(0) elif aUp.RdOff < aUp.WrOff: cnt = aUp.WrOff - aUp.RdOff str = ctypes.create_string_buffer(cnt) self.jlink.JLINKARM_ReadMem(ctypes.cast(aUp.pBuffer, ctypes.c_void_p).value + aUp.RdOff, cnt, str) aUp.RdOff += cnt self.jlink.JLINKARM_WriteU32(self.aUpAddr + 4*4, aUp.RdOff) else: cnt = aUp.SizeOfBuffer - aUp.RdOff str = ctypes.create_string_buffer(cnt) self.jlink.JLINKARM_ReadMem(ctypes.cast(aUp.pBuffer, ctypes.c_void_p).value + aUp.RdOff, cnt, str) aUp.RdOff = 0 #这样下次再读就会进入执行上个条件 self.jlink.JLINKARM_WriteU32(self.aUpAddr + 4*4, aUp.RdOff) return str.raw def on_tmrRTT_timeout(self): if self.btnOpen.text() == u'关闭连接': try: self.rcvbuff += self.aUpRead() if self.txtMain.isVisible(): if self.chkHEXShow.isChecked(): text = ''.join('%02X ' %ord(c) for c in self.rcvbuff) else: text = self.rcvbuff if len(self.txtMain.toPlainText()) > 25000: self.txtMain.clear() self.txtMain.moveCursor(QtGui.QTextCursor.End) self.txtMain.insertPlainText(text) self.rcvbuff = b'' else: if self.rcvbuff.rfind(',') == -1: return d = [int(x) for x in self.rcvbuff[0:self.rcvbuff.rfind(',')].split(',')] for x in d: self.PlotData.pop(0) self.PlotData.append(x) self.PlotCurve.setData(range(1, len(self.PlotData)+1), self.PlotData) self.qwtPlot.replot() self.rcvbuff = self.rcvbuff[self.rcvbuff.rfind(',')+1:] except Exception as e: self.rcvbuff = b'' self.txtMain.append('\n%s\n' %str(e)) def aDownWrite(self, bytes): buf = ctypes.create_string_buffer(ctypes.sizeof(RingBuffer)) self.jlink.JLINKARM_ReadMem(self.aDownAddr, ctypes.sizeof(RingBuffer), buf) aDown = RingBuffer.from_buffer(buf) if aDown.WrOff >= aDown.RdOff: if aDown.RdOff != 0: cnt = min(aDown.SizeOfBuffer - aDown.WrOff, len(bytes)) else: cnt = min(aDown.SizeOfBuffer - 1 - aDown.WrOff, len(bytes)) # 写入操作不能使得 aDown.WrOff == aDown.RdOff,以区分满和空 str = ctypes.create_string_buffer(bytes[:cnt]) self.jlink.JLINKARM_WriteMem(ctypes.cast(aDown.pBuffer, ctypes.c_void_p).value + aDown.WrOff, cnt, str) aDown.WrOff += cnt if aDown.WrOff == aDown.SizeOfBuffer: aDown.WrOff = 0 bytes = bytes[cnt:] if bytes and aDown.RdOff != 0 and aDown.RdOff != 1: # != 0 确保 aDown.WrOff 折返回 0,!= 1 确保有空间可写入 cnt = min(aDown.RdOff - 1 - aDown.WrOff, len(bytes)) # - 1 确保写入操作不导致WrOff与RdOff指向同一位置 str = ctypes.create_string_buffer(bytes[:cnt]) self.jlink.JLINKARM_WriteMem(ctypes.cast(aDown.pBuffer, ctypes.c_void_p).value + aDown.WrOff, cnt, str) aDown.WrOff += cnt self.jlink.JLINKARM_WriteU32(self.aDownAddr + 4*3, aDown.WrOff) @QtCore.pyqtSlot() def on_btnSend_clicked(self): if self.btnOpen.text() == u'关闭连接': text = self.txtSend.toPlainText() try: if self.chkHEXSend.isChecked(): bytes = ''.join([chr(int(x, 16)) for x in text.split()]) else: bytes = text self.aDownWrite(bytes) except Exception as e: self.txtMain.append('\n%s\n' %str(e)) @QtCore.pyqtSlot() def on_btnDLL_clicked(self): path = QtGui.QFileDialog.getOpenFileName(caption=u'JLinkARM.dll路径', filter=u'动态链接库文件 (*.dll)', directory=self.linDLL.text()) if path != '': self.linDLL.setText(path) @QtCore.pyqtSlot(int) def on_chkWavShow_stateChanged(self, state): self.qwtPlot.setVisible(state == QtCore.Qt.Checked) self.txtMain.setVisible(state == QtCore.Qt.Unchecked) @QtCore.pyqtSlot() def on_btnClear_clicked(self): self.txtMain.clear() def closeEvent(self, evt): self.conf.set('J-Link', 'dllpath', self.linDLL.text().encode('gbk')) self.conf.write(open('setting.ini', 'w'))
class RTTView(QtGui.QWidget): def __init__(self, parent=None): super(RTTView, self).__init__(parent) uic.loadUi('RTTView.ui', self) self.initSetting() self.initQwtPlot() self.rcvbuff = b'' self.daplink = None self.tmrRTT = QtCore.QTimer() self.tmrRTT.setInterval(10) self.tmrRTT.timeout.connect(self.on_tmrRTT_timeout) self.tmrRTT.start() self.tmrRTT_Cnt = 0 def initSetting(self): if not os.path.exists('setting.ini'): open('setting.ini', 'w') self.conf = ConfigParser.ConfigParser() self.conf.read('setting.ini') if not self.conf.has_section('Memory'): self.conf.add_section('Memory') self.conf.set('Memory', 'StartAddr', '0x20000000') def initQwtPlot(self): self.PlotData = [0] * 1000 self.qwtPlot = QwtPlot(self) self.qwtPlot.setVisible(False) self.vLayout.insertWidget(0, self.qwtPlot) self.PlotCurve = QwtPlotCurve() self.PlotCurve.attach(self.qwtPlot) self.PlotCurve.setData(range(1, len(self.PlotData) + 1), self.PlotData) @QtCore.pyqtSlot() def on_btnOpen_clicked(self): if self.btnOpen.text() == u'打开连接': try: self.daplink = self.daplinks[self.cmbDAP.currentText()] self.daplink.open() dp = coresight.dap.DebugPort(self.daplink, None) dp.init() dp.power_up_debug() ap = coresight.ap.AHB_AP(dp, 0) ap.init() self.dap = coresight.cortex_m.CortexM(None, ap) Addr = int(self.conf.get('Memory', 'StartAddr'), 16) for i in range(256): buff = self.dap.read_memory_block8(Addr + 1024 * i, 1024) buff = ''.join([chr(x) for x in buff]) index = buff.find('SEGGER RTT') if index != -1: self.RTTAddr = Addr + 1024 * i + index buff = self.dap.read_memory_block8( self.RTTAddr, ctypes.sizeof(SEGGER_RTT_CB)) rtt_cb = SEGGER_RTT_CB.from_buffer(bytearray(buff)) self.aUpAddr = self.RTTAddr + 16 + 4 + 4 self.aDownAddr = self.aUpAddr + ctypes.sizeof( RingBuffer) * rtt_cb.MaxNumUpBuffers self.txtMain.append( '\n_SEGGER_RTT @ 0x%08X with %d aUp and %d aDown\n' % (self.RTTAddr, rtt_cb.MaxNumUpBuffers, rtt_cb.MaxNumDownBuffers)) break else: raise Exception('Can not find _SEGGER_RTT') except Exception as e: self.txtMain.append('\n%s\n' % str(e)) else: self.cmbDAP.setEnabled(False) self.btnOpen.setText(u'关闭连接') else: self.daplink.close() self.cmbDAP.setEnabled(True) self.btnOpen.setText(u'打开连接') def aUpRead(self): buf = self.dap.read_memory_block8(self.aUpAddr, ctypes.sizeof(RingBuffer)) aUp = RingBuffer.from_buffer(bytearray(buf)) if aUp.RdOff == aUp.WrOff: buf = [] elif aUp.RdOff < aUp.WrOff: cnt = aUp.WrOff - aUp.RdOff buf = self.dap.read_memory_block8( ctypes.cast(aUp.pBuffer, ctypes.c_void_p).value + aUp.RdOff, cnt) aUp.RdOff += cnt self.dap.write32(self.aUpAddr + 4 * 4, aUp.RdOff) else: cnt = aUp.SizeOfBuffer - aUp.RdOff buf = self.dap.read_memory_block8( ctypes.cast(aUp.pBuffer, ctypes.c_void_p).value + aUp.RdOff, cnt) aUp.RdOff = 0 #这样下次再读就会进入执行上个条件 self.dap.write32(self.aUpAddr + 4 * 4, aUp.RdOff) return ''.join([chr(x) for x in buf]) def on_tmrRTT_timeout(self): if self.btnOpen.text() == u'关闭连接': try: self.rcvbuff += self.aUpRead() if self.txtMain.isVisible(): if self.chkHEXShow.isChecked(): text = ''.join('%02X ' % ord(c) for c in self.rcvbuff) else: text = self.rcvbuff if len(self.txtMain.toPlainText()) > 25000: self.txtMain.clear() self.txtMain.moveCursor(QtGui.QTextCursor.End) self.txtMain.insertPlainText(text) self.rcvbuff = b'' else: if self.rcvbuff.rfind(',') == -1: return d = [ int(x) for x in self.rcvbuff[0:self.rcvbuff.rfind(',')].split(',') ] for x in d: self.PlotData.pop(0) self.PlotData.append(x) self.PlotCurve.setData(range(1, len(self.PlotData) + 1), self.PlotData) self.qwtPlot.replot() self.rcvbuff = self.rcvbuff[self.rcvbuff.rfind(',') + 1:] except Exception as e: self.rcvbuff = b'' self.txtMain.append('\n%s\n' % str(e)) else: self.tmrRTT_Cnt += 1 if self.tmrRTT_Cnt % 20 == 0: self.detect_daplink() # 自动检测 DAPLink 的热插拔 def aDownWrite(self, bytes): buf = self.dap.read_memory_block8(self.aDownAddr, ctypes.sizeof(RingBuffer)) aDown = RingBuffer.from_buffer(bytearray(buf)) if aDown.WrOff >= aDown.RdOff: if aDown.RdOff != 0: cnt = min(aDown.SizeOfBuffer - aDown.WrOff, len(bytes)) else: cnt = min( aDown.SizeOfBuffer - 1 - aDown.WrOff, len(bytes)) # 写入操作不能使得 aDown.WrOff == aDown.RdOff,以区分满和空 self.dap.write_memory_block8( ctypes.cast(aDown.pBuffer, ctypes.c_void_p).value + aDown.WrOff, [ord(x) for x in bytes[:cnt]]) aDown.WrOff += cnt if aDown.WrOff == aDown.SizeOfBuffer: aDown.WrOff = 0 bytes = bytes[cnt:] if bytes and aDown.RdOff != 0 and aDown.RdOff != 1: # != 0 确保 aDown.WrOff 折返回 0,!= 1 确保有空间可写入 cnt = min(aDown.RdOff - 1 - aDown.WrOff, len(bytes)) # - 1 确保写入操作不导致WrOff与RdOff指向同一位置 self.dap.write_memory_block8( ctypes.cast(aDown.pBuffer, ctypes.c_void_p).value + aDown.WrOff, [ord(x) for x in bytes[:cnt]]) aDown.WrOff += cnt self.dap.write32(self.aDownAddr + 4 * 3, aDown.WrOff) @QtCore.pyqtSlot() def on_btnSend_clicked(self): if self.btnOpen.text() == u'关闭连接': text = self.txtSend.toPlainText() try: if self.chkHEXSend.isChecked(): bytes = ''.join([chr(int(x, 16)) for x in text.split()]) else: bytes = text self.aDownWrite(bytes) except Exception as e: self.txtMain.append('\n%s\n' % str(e)) def detect_daplink(self): daplinks = aggregator.DebugProbeAggregator.get_all_connected_probes() if len(daplinks) != self.cmbDAP.count(): self.cmbDAP.clear() for daplink in daplinks: self.cmbDAP.addItem(daplink.product_name) self.daplinks = collections.OrderedDict([ (daplink.product_name, daplink) for daplink in daplinks ]) if self.daplink and self.daplink.product_name in self.daplinks: self.cmbDAP.setCurrentIndex(self.daplinks.keys().index( self.daplink.product_name)) else: # daplink被拔掉 self.btnOpen.setText(u'打开连接') @QtCore.pyqtSlot(int) def on_chkWavShow_stateChanged(self, state): self.qwtPlot.setVisible(state == QtCore.Qt.Checked) self.txtMain.setVisible(state == QtCore.Qt.Unchecked) @QtCore.pyqtSlot() def on_btnClear_clicked(self): self.txtMain.clear() def closeEvent(self, evt): self.conf.write(open('setting.ini', 'w'))