|
|
@@ -0,0 +1,145 @@ |
|
|
|
#!/usr/bin/env python3 |
|
|
|
""" |
|
|
|
OpenOCD RPC example, covered by GNU GPLv3 or later |
|
|
|
Copyright (C) 2014 Andreas Ortmann (ortmann@finf.uni-hannover.de) |
|
|
|
|
|
|
|
|
|
|
|
Example output: |
|
|
|
./ocd_rpc_example.py |
|
|
|
echo says hi! |
|
|
|
|
|
|
|
target state: halted |
|
|
|
target halted due to debug-request, current mode: Thread |
|
|
|
xPSR: 0x01000000 pc: 0x00000188 msp: 0x10000fd8 |
|
|
|
|
|
|
|
variable @ 0x10000000: 0x01c9c380 |
|
|
|
|
|
|
|
variable @ 0x10000000: 0xdeadc0de |
|
|
|
|
|
|
|
memory (before): ['0xdeadc0de', '0x00000011', '0xaaaaaaaa', '0x00000023', |
|
|
|
'0x00000042', '0x0000ffff'] |
|
|
|
|
|
|
|
memory (after): ['0x00000001', '0x00000000', '0xaaaaaaaa', '0x00000023', |
|
|
|
'0x00000042', '0x0000ffff'] |
|
|
|
""" |
|
|
|
|
|
|
|
import socket |
|
|
|
import itertools |
|
|
|
|
|
|
|
def strToHex(data): |
|
|
|
return map(strToHex, data) if isinstance(data, list) else int(data, 16) |
|
|
|
|
|
|
|
def hexify(data): |
|
|
|
return "<None>" if data is None else ("0x%08x" % data) |
|
|
|
|
|
|
|
def compareData(a, b): |
|
|
|
for i, j, num in zip(a, b, itertools.count(0)): |
|
|
|
if i != j: |
|
|
|
print("difference at %d: %s != %s" % (num, hexify(i), hexify(j))) |
|
|
|
|
|
|
|
|
|
|
|
class OpenOcd: |
|
|
|
COMMAND_TOKEN = '\x1a' |
|
|
|
def __init__(self, verbose=False): |
|
|
|
self.verbose = verbose |
|
|
|
self.tclRpcIp = "127.0.0.1" |
|
|
|
self.tclRpcPort = 6666 |
|
|
|
self.bufferSize = 4096 |
|
|
|
|
|
|
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
|
|
|
|
|
|
|
def __enter__(self): |
|
|
|
self.sock.connect((self.tclRpcIp, self.tclRpcPort)) |
|
|
|
return self |
|
|
|
|
|
|
|
def __exit__(self, type, value, traceback): |
|
|
|
try: |
|
|
|
self.send("exit") |
|
|
|
finally: |
|
|
|
self.sock.close() |
|
|
|
|
|
|
|
def send(self, cmd): |
|
|
|
"""Send a command string to TCL RPC. Return the result that was read.""" |
|
|
|
data = (cmd + OpenOcd.COMMAND_TOKEN).encode("utf-8") |
|
|
|
if self.verbose: |
|
|
|
print("<- ", data) |
|
|
|
|
|
|
|
self.sock.send(data) |
|
|
|
return self._recv() |
|
|
|
|
|
|
|
def _recv(self): |
|
|
|
"""Read from the stream until the token (\x1a) was received.""" |
|
|
|
data = bytes() |
|
|
|
while True: |
|
|
|
chunk = self.sock.recv(self.bufferSize) |
|
|
|
data += chunk |
|
|
|
if bytes(OpenOcd.COMMAND_TOKEN, encoding="utf-8") in chunk: |
|
|
|
break |
|
|
|
|
|
|
|
if self.verbose: |
|
|
|
print("-> ", data) |
|
|
|
|
|
|
|
data = data.decode("utf-8").strip() |
|
|
|
data = data[:-1] # strip trailing \x1a |
|
|
|
|
|
|
|
return data |
|
|
|
|
|
|
|
def readVariable(self, address): |
|
|
|
raw = self.send("ocd_mdw 0x%x" % address).split(": ") |
|
|
|
return None if (len(raw) < 2) else strToHex(raw[1]) |
|
|
|
|
|
|
|
def readMemory(self, wordLen, address, n): |
|
|
|
self.send("array unset output") # better to clear the array before |
|
|
|
self.send("mem2array output %d 0x%x %d" % (wordLen, address, n)) |
|
|
|
|
|
|
|
output = self.send("ocd_echo $output").split(" ") |
|
|
|
|
|
|
|
return [int(output[2*i+1]) for i in range(len(output)//2)] |
|
|
|
|
|
|
|
def writeVariable(self, address, value): |
|
|
|
assert value is not None |
|
|
|
self.send("mww 0x%x 0x%x" % (address, value)) |
|
|
|
|
|
|
|
def writeMemory(self, wordLen, address, n, data): |
|
|
|
array = " ".join(["%d 0x%x" % (a, b) for a, b in enumerate(data)]) |
|
|
|
|
|
|
|
self.send("array unset 1986ве1т") # better to clear the array before |
|
|
|
self.send("array set 1986ве1т { %s }" % array) |
|
|
|
self.send("array2mem 1986ве1т 0x%x %s %d" % (wordLen, address, n)) |
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
|
|
def show(*args): |
|
|
|
print(*args, end="\n\n") |
|
|
|
|
|
|
|
with OpenOcd() as ocd: |
|
|
|
ocd.send("reset") |
|
|
|
|
|
|
|
show(ocd.send("ocd_echo \"echo says hi!\"")[:-1]) |
|
|
|
show(ocd.send("capture \"ocd_halt\"")[:-1]) |
|
|
|
|
|
|
|
# Read the first few words at the RAM region (put starting adress of RAM |
|
|
|
# region into 'addr') |
|
|
|
addr = 0x10000000 |
|
|
|
|
|
|
|
value = ocd.readVariable(addr) |
|
|
|
show("variable @ %s: %s" % (hexify(addr), hexify(value))) |
|
|
|
|
|
|
|
ocd.writeVariable(addr, 0xdeadc0de) |
|
|
|
show("variable @ %s: %s" % (hexify(addr), hexify(ocd.readVariable(addr)))) |
|
|
|
|
|
|
|
data = [1, 0, 0xaaaaaaaa, 0x23, 0x42, 0xffff] |
|
|
|
wordlen = 32 |
|
|
|
n = len(data) |
|
|
|
|
|
|
|
read = ocd.readMemory(wordlen, addr, n) |
|
|
|
show("memory (before):", list(map(hexify, read))) |
|
|
|
|
|
|
|
ocd.writeMemory(wordlen, addr, n, data) |
|
|
|
|
|
|
|
read = ocd.readMemory(wordlen, addr, n) |
|
|
|
show("memory (after):", list(map(hexify, read))) |
|
|
|
|
|
|
|
compareData(read, data) |
|
|
|
|
|
|
|
ocd.send("resume") |