CVS: msp430simu gdbserver.py,NONE,1.1 core.py,1.16,1.17
Chris Liechti <[email protected]>
| Newsgroups | gmane.comp.hardware.texas-instruments.msp430.gcc.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/mspgcc/msp430simu In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6761/msp430simu Modified Files: core.py Added Files: gdbserver.py Log Message: - added gdbserver this means that msp430-gdb can connect to this sim as "remote target", currently with similar features as the builtin simulator in gdb, but this one is expandable with python scripts - bugfixes --- NEW FILE: gdbserver.py --- #!/usr/bin/env python # # GDB server for the MSP430 simulator. This meas that msp430-gdb can # connect to the simulator and manipulate the simulated core. # An unllimited number of breakpoints is supported. # # (C) 2002-2004 Chris Liechti <[email protected]> # this is distributed under a free software license, see license.txt # # $Id: gdbserver.py,v 1.1 2005/12/30 00:19:10 cliechti Exp $ import sys, socket, threading, binascii import Queue import core import logging import time def checksum(data): checksum = 0 for c in data: checksum = (checksum + ord(c)) & 0xff return checksum class BreakpointRunner(threading.Thread): def __init__(self, core): self.log = logging.getLogger("runner") self.core = core self.interrupted = False self.breakpoints = {} self.cmd_queue = Queue.Queue(1) threading.Thread.__init__(self) self.setName('msp430 core') self.setDaemon(1) def set_breakpoint(self, address): self.breakpoints[address] = True def remove_breakpoint(self, address): if address in self.breakpoints: del self.breakpoints[address] def command(self, cmd, action): self.log.info('queing remote command %r' % cmd) self.cmd_queue.put((cmd, action)) def interrupt(self): self.interrupted = True def run(self): """worker thread""" self.log.debug('worker thread started') while True: try: command, action = self.cmd_queue.get() self.log.info('executing remote command %r' % command) if command == 'run': self.interrupted = False last_time = time.time() step_delta = 0 self.log.info('continuing from 0x%04x (cycle %d)' % (self.core.PC.get(), self.core.cycles)) while not self.interrupted: self.core.step() if self.core.PC.get() in self.breakpoints: self.log.info('breakpoint @0x%04x (cycle %d)' % (self.core.PC.get(), self.core.cycles)) action() break step_delta += 1 if step_delta > 1000: #after a few steps.. #time check is not done at every step for better performance step_delta = 0 if time.time() - last_time > 3: #check time, more than 1s passed? #yes, make a log message so that the user knows we're alive last_time = time.time() self.log.info('still running @0x%04x (cycle %d)' % (self.core.PC.get(), self.core.cycles)) else: self.log.info('interrupted @0x%04x (cycle %d)' % (self.core.PC.get(), self.core.cycles)) action() elif command == 'step': self.log.info('single step @0x%04x (cycle %d)' % (self.core.PC.get(), self.core.cycles)) self.core.step() if self.core.PC.get() in self.breakpoints: self.log.info('breakpoint @0x%04x (cycle %d)' % (self.core.PC.get(), self.core.cycles)) action() else: self.log.error('unknown command %r' % (command, )) except: self.log.exception('error in runner') class GDBServer(threading.Thread): def __init__(self, core, port = 3333): self.core = core self.port = port threading.Thread.__init__(self) self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.bind( ('localhost', port) ) def run(self): print "gdbserver listening on port %d" % self.port self.sock.listen(1) while 1: conn, addr = self.sock.accept() print 'connected by', addr GDBClientHandler(self.core, conn).start() class GDBClientHandler(threading.Thread): def __init__(self, core, clientsocket): threading.Thread.__init__(self) self.setName('gdb remote connection %r' % clientsocket) self.clientsocket = clientsocket self.netin = clientsocket.makefile("r") self.netout = clientsocket.makefile("w") self.setDaemon(1) self.core = core self.log = logging.getLogger("gdbclient") self.runner = BreakpointRunner(core) self.runner.start() def close(self): self.log.info("closing...") self.netin.close() self.netout.close() self.clientsocket.close() self.log.info("closed") #~ def _answer_ok(self): def _answer_sigtrap(self): self.writePacket("S%02x" % (5,)) #SIGTRAP def run(self): try: self.log.info("client loop ready...") while 1: try: pkt = self.readPacket() self.log.debug('processing remote command %r' % pkt) except ValueError: self.netout.write("-") self.netout.flush() else: self.netout.write("+") self.netout.flush() if pkt[0] == "?": sig = 0 #self.writePacket("T%02x%02x:%04x" % (sig, 0, 0x1234)) self.writePacket("S%02x" % (sig,)) elif pkt[0] == "c": #continue if len(pkt) > 1: adr = int(pkt[1:],16) self.core.PC.set(adr) self.runner.command('run', self._answer_sigtrap) #~ self.writePacket("S%02x" % (5,)) #SIGTRAP elif pkt[0] == "D": #detach self.core.reset() elif pkt[0] == "g": #Read general registers self.log.debug("Reading device registers") self.writePacket(''.join(["%02x%02x" % (r.get()&0xff, (r.get()>>8)&0xff) for r in self.core.R])) elif pkt[0] == "G": #write regs self.log.debug("Writing device registers") for n, value in enumerate([int(pkt[i:i+2],16) + int(pkt[i+2:i+4],16)<<8 for i in range(1, 1+16*4, 4)]): self.core.R[n].set(value) self.writePacket("OK") elif pkt[0] == "H": self.writePacket("OK") elif pkt[0] == "k": #kill request self.core.reset() self.writePacket("OK") elif pkt[0] == "m": #read memory self.log.debug("Reading device memory") fromadr, length = [int(x, 16) for x in pkt[1:].split(',')] mem = self.core.memory.read(fromadr, length) self.writePacket(''.join(["%02x" % ord(x) for x in mem])) elif pkt[0] == "M": #write memory self.log.debug("Writing device memory") meta, data = pkt.split(':') fromadr, length = [int(x, 16) for x in meta[1:].split(',')] sdata = ''.join([chr(int(data[i:i+2],16)) for i in range(0,len(data),2)]) try: self.core.memory.write(fromadr, sdata) except IOError: self.writePacket("E01") #write error else: self.writePacket("OK") elif pkt[0] == "q": #remote commands if pkt[1:5] == "Rcmd": cmd = binascii.unhexlify(pkt.split(',')[1]).strip() self.log.info("monitor command: %r" % cmd) if cmd[0:1] == '"': #its a string, execute python code !Security risk! ans = eval(cmd[1:-1]) self.writePacket(binascii.hexlify(repr(ans))) #~ elif cmd == 'erase': #~ print "Erasing the device MAIN memory..." #~ self.writePacket("OK") else: self.writePacket("E01") else: self.writePacket("E01") #write error elif pkt[0] == "s": #single step if len(pkt) > 1: adr = int(pkt[1:],16) self.core.PC.set(adr) self.runner.command('step', self._answer_sigtrap) elif pkt[0] == "Z": #set break or watchpoint ty, adr, length = pkt[1:].split(',') if ty == '0': self.log.debug("Setting breakpoint") self.runner.set_breakpoint(int(adr,16)) self.writePacket("OK") else: self.writePacket("E%02x" % (1,)) elif pkt[0] == "z": #remove break or watchpoint ty, adr, length = pkt[1:].split(',') if ty == '0': self.log.debug("Clearing breakpoint") adr = int(adr,16) if adr in self.runner.breakpoints: self.runner.remove_breakpoint(adr) self.writePacket("OK") else: self.writePacket("E%02x" % (2,)) else: self.writePacket("E%02x" % (1,)) else: #command not supported self.log.debug("Unsupported comand %r" % pkt) self.writePacket("") finally: self.close() def readPacket(self): self.log.debug("readPacket") gdbcommand = 0 csum = 0 packet = [] while 1: c = self.netin.read(1) if not c: self.close() #EOF if c == '\x03': #ctrl+c self.runner.interrupt() continue #print repr(c), if gdbcommand: if c == '#': if csum != int(self.netin.read(1) + self.netin.read(1), 16): raise ValueError("wrong checksum") return ''.join(packet) else: packet.append(c) csum = (csum + ord(c)) % 256 else: if c == '$': gdbcommand = 1 def writePacket(self, msg): self.log.debug("writePacket(%r)" % msg) self.netout.write("$%s#%02x" % (msg, checksum(msg))) self.netout.flush() if __name__ == '__main__': logging.basicConfig(level=logging.INFO) #~ logging.basicConfig(level=logging.DEBUG) log = logging.getLogger('trace') msp430 = core.Core() msp430.memory.append(core.Multiplier()) GDBServer(msp430).start() Index: core.py =================================================================== RCS file: /cvsroot/mspgcc/msp430simu/core.py,v retrieving revision 1.16 retrieving revision 1.17 diff -u -w -d -r1.16 -r1.17 --- core.py 29 Dec 2005 21:17:23 -0000 1.16 +++ core.py 30 Dec 2005 00:19:10 -0000 1.17 @@ -1,4 +1,12 @@ #!/usr/bin/env python +# +# MSP430 simulator core. +# +# (C) 2002-2004 Chris Liechti <[email protected]> +# this is distributed under a free software license, see license.txt +# +# $Id$ + import sys import logging @@ -544,6 +552,7 @@ def _set(self, address, value, bytemode=0): """quiet set without logging""" + address &= 0xffff #16 bit wrap around for p in self.peripherals: if address in p: p.set(address, value, bytemode) @@ -557,6 +566,9 @@ def set(self, address, value, bytemode=0): """write value to address""" + if address > 0xffff: + self.log.error('write outside valid address range (0x%04x)' % (address, )) + address &= 0xffff #16 bit wrap around self.log.debug('write 0x%04x <- 0x%04x mode:%s' % (address, value, bytemode and 'b' or 'w')) if self.setwatches.has_key(address): self.setwatches[address](address, bytemode, self.memory[address], value) #call watch for a in self.accesswatches: a(self, bytemode, 1, address) @@ -565,6 +577,7 @@ def _get(self, address, bytemode=0): """quiet get without logging""" + address &= 0xffff #16 bit wrap around for p in self.peripherals: if address in p: value = p.get(address, bytemode) @@ -578,12 +591,22 @@ def get(self, address, bytemode=0): """read value from address""" + if address > 0xffff: + self.log.error('read outside valid address range (0x%04x)' % (address, )) + address &= 0xffff #16 bit wrap around if self.getwatches.has_key(address): self.getwatches[address](address, bytemode, self.memory[address], None) #call watch for a in self.accesswatches: a(self, bytemode, 0, address) value = self._get(address, bytemode) self.log.debug('read 0x%04x -> 0x%04x mode:%s' % (address, value, bytemode and 'b' or 'w')) return value + def read(self, address, length): + return ''.join([chr(self._get(a,1)) for a in range(address, address+length)]) + + def write(self, address, data): + for n, byte in enumerate(data): + self._set(address+n, ord(byte), 1) + def hexline(self, address, width=16): """build a tuple with (address, hex values, ascii values)""" bytes = [self._get(a, bytemode=1) for a in range(address, address+width)] ------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Do you grep through log files for problems? Stop! Download the new AJAX search engine that makes searching your log files as easy as surfing the web. DOWNLOAD SPLUNK! http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click