| Line 126... |
Line 126... |
| 126 |
in the memory of the device. Can handle up to 0xff0 bytes.
|
126 |
in the memory of the device. Can handle up to 0xff0 bytes.
|
| 127 |
"""
|
127 |
"""
|
| 128 |
return self.lib.monitorcommand(struct.pack("<IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
|
128 |
return self.lib.monitorcommand(struct.pack("<IIII%ds" % len(data), 5, addr, len(data), 0, data), "III", (None, None, None))
|
| 129 |
|
129 |
|
| 130 |
@command()
|
130 |
@command()
|
| - |
|
131 |
def _readmem_bulk(self, addr, size):
|
| - |
|
132 |
""" Reads the memory from location 'addr' with size 'size'
|
| - |
|
133 |
from the device. Can handle unlimited amounts of bytes,
|
| - |
|
134 |
however the address and size should be cacheline aligned.
|
| - |
|
135 |
"""
|
| - |
|
136 |
return self.lib.recvbulk(struct.pack("<III", 1, addr, size), size)
|
| - |
|
137 |
|
| - |
|
138 |
@command()
|
| - |
|
139 |
def _writemem_bulk(self, addr, data):
|
| - |
|
140 |
""" Writes the data in 'data' to the location 'addr'
|
| - |
|
141 |
in the memory of the device. Can handle unlimited amounts of bytes,
|
| - |
|
142 |
however the address and size should be cacheline aligned.
|
| - |
|
143 |
|
| - |
|
144 |
"""
|
| - |
|
145 |
return self.lib.sendbulk(struct.pack("<III", 1, addr, len(data)), data)
|
| - |
|
146 |
|
| - |
|
147 |
@command()
|
| 131 |
def getversioninfo(self):
|
148 |
def getversioninfo(self):
|
| 132 |
""" This returns the emCORE version and device information. """
|
149 |
""" This returns the emCORE version and device information. """
|
| 133 |
resp = self.lib.monitorcommand(struct.pack("<IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
|
150 |
resp = self.lib.monitorcommand(struct.pack("<IIII", 1, 0, 0, 0), "IBBBBI", ("revision", "majorv", "minorv", "patchv", "swtypeid", "hwtypeid"))
|
| 134 |
self.lib.dev.version.revision = resp.revision
|
151 |
self.lib.dev.version.revision = resp.revision
|
| 135 |
self.lib.dev.version.majorv = resp.majorv
|
152 |
self.lib.dev.version.majorv = resp.majorv
|
| Line 171... |
Line 188... |
| 171 |
""" Reads the memory from location 'addr' with size 'size'
|
188 |
""" Reads the memory from location 'addr' with size 'size'
|
| 172 |
from the device. This takes care of splitting long requests.
|
189 |
from the device. This takes care of splitting long requests.
|
| 173 |
"""
|
190 |
"""
|
| 174 |
data = b""
|
191 |
data = b""
|
| 175 |
self.logger.debug("Downloading %d bytes from 0x%X\n" % (size, addr))
|
192 |
self.logger.debug("Downloading %d bytes from 0x%X\n" % (size, addr))
|
| - |
|
193 |
try:
|
| - |
|
194 |
if self.lib.bulkin and size > 0x800:
|
| - |
|
195 |
if addr & 63:
|
| - |
|
196 |
align = 64 - (addr & 63)
|
| - |
|
197 |
data += self._readmem(addr, align)
|
| - |
|
198 |
addr += align
|
| - |
|
199 |
size -= align
|
| - |
|
200 |
align = size & 63
|
| - |
|
201 |
size -= align
|
| - |
|
202 |
data += self._readmem_bulk(addr, size)
|
| - |
|
203 |
addr += size
|
| - |
|
204 |
size = align
|
| - |
|
205 |
except: self.logger.warn("Bulk read interface failed, falling back to slow reads\n")
|
| 176 |
while size > 0:
|
206 |
while size > 0:
|
| 177 |
readsize = min(size, 0xf00)
|
207 |
readsize = min(size, 0xf00)
|
| 178 |
data += self._readmem(addr, readsize)
|
208 |
data += self._readmem(addr, readsize)
|
| 179 |
addr += readsize
|
209 |
addr += readsize
|
| 180 |
size -= readsize
|
210 |
size -= readsize
|
| Line 186... |
Line 216... |
| 186 |
in the memory of the device. This takes care of splitting long requests.
|
216 |
in the memory of the device. This takes care of splitting long requests.
|
| 187 |
"""
|
217 |
"""
|
| 188 |
size = len(data)
|
218 |
size = len(data)
|
| 189 |
self.logger.debug("Uploading %d bytes to 0x%X\n" % (size, addr))
|
219 |
self.logger.debug("Uploading %d bytes to 0x%X\n" % (size, addr))
|
| 190 |
offset = 0
|
220 |
offset = 0
|
| - |
|
221 |
try:
|
| - |
|
222 |
if self.lib.bulkin and size > 0x800:
|
| - |
|
223 |
if addr & 63:
|
| - |
|
224 |
align = 64 - (addr & 63)
|
| - |
|
225 |
self._writemem(addr, data[offset:offset+align])
|
| - |
|
226 |
offset += align
|
| - |
|
227 |
addr += align
|
| - |
|
228 |
size -= align
|
| - |
|
229 |
align = size & 63
|
| - |
|
230 |
size -= align
|
| - |
|
231 |
self._writemem_bulk(addr, data[offset:offset+size])
|
| - |
|
232 |
offset += size
|
| - |
|
233 |
addr += size
|
| - |
|
234 |
size = align
|
| - |
|
235 |
except: self.logger.warn("Bulk write interface failed, falling back to slow writes\n")
|
| 191 |
while size > 0:
|
236 |
while size > 0:
|
| 192 |
writesize = min(size, 0xf00)
|
237 |
writesize = min(size, 0xf00)
|
| 193 |
self._writemem(addr, data[offset:offset+writesize])
|
238 |
self._writemem(addr, data[offset:offset+writesize])
|
| 194 |
offset += writesize
|
239 |
offset += writesize
|
| 195 |
addr += writesize
|
240 |
addr += writesize
|
| Line 1017... |
Line 1062... |
| 1017 |
self.connect()
|
1062 |
self.connect()
|
| 1018 |
|
1063 |
|
| 1019 |
def connect(self):
|
1064 |
def connect(self):
|
| 1020 |
self.dev = Dev(self.idVendor, self.idProduct, self.idProductMask, self.logger)
|
1065 |
self.dev = Dev(self.idVendor, self.idProduct, self.idProductMask, self.logger)
|
| 1021 |
self.connected = True
|
1066 |
self.connected = True
|
| - |
|
1067 |
self.bulkout = True if self.dev.bulkout else False
|
| - |
|
1068 |
self.bulkin = True if self.dev.bulkin else False
|
| 1022 |
|
1069 |
|
| 1023 |
def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
|
1070 |
def monitorcommand(self, cmd, rcvdatatypes=None, rcvstruct=None):
|
| 1024 |
self.logger.debug("Sending monitorcommand [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
|
1071 |
self.logger.debug("Sending monitorcommand [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
|
| 1025 |
writelen = self.dev.send(cmd)
|
1072 |
writelen = self.dev.send(cmd)
|
| 1026 |
if rcvdatatypes:
|
1073 |
if rcvdatatypes:
|
| Line 1053... |
Line 1100... |
| 1053 |
elif response == "BUSY":
|
1100 |
elif response == "BUSY":
|
| 1054 |
self.logger.debug("Response: BUSY\n")
|
1101 |
self.logger.debug("Response: BUSY\n")
|
| 1055 |
raise DeviceError("Device busy")
|
1102 |
raise DeviceError("Device busy")
|
| 1056 |
else:
|
1103 |
else:
|
| 1057 |
return writelen
|
1104 |
return writelen
|
| - |
|
1105 |
|
| - |
|
1106 |
def sendbulk(self, cmd, data):
|
| - |
|
1107 |
self.logger.debug("Sending bulk command [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
|
| - |
|
1108 |
return self.dev.sendbulk(cmd, data)
|
| - |
|
1109 |
|
| - |
|
1110 |
def recvbulk(self, cmd, size):
|
| - |
|
1111 |
self.logger.debug("Receiving bulk command [0x%s]\n" % base64.b16encode(cmd[3::-1]).decode("ascii"))
|
| - |
|
1112 |
return self.dev.recvbulk(cmd, size)
|
| 1058 |
|
1113 |
|
| 1059 |
|
1114 |
|
| 1060 |
class Dev(object):
|
1115 |
class Dev(object):
|
| 1061 |
def __init__(self, idVendor, idProduct, idProductMask, logger):
|
1116 |
def __init__(self, idVendor, idProduct, idProductMask, logger):
|
| 1062 |
self.idVendor = idVendor
|
1117 |
self.idVendor = idVendor
|
| Line 1066... |
Line 1121... |
| 1066 |
self.logger = logger
|
1121 |
self.logger = logger
|
| 1067 |
self.logger.debug("Initializing Dev object\n")
|
1122 |
self.logger.debug("Initializing Dev object\n")
|
| 1068 |
|
1123 |
|
| 1069 |
self.dev = None
|
1124 |
self.dev = None
|
| 1070 |
self.interface = None
|
1125 |
self.interface = None
|
| - |
|
1126 |
self.bulkout = None
|
| - |
|
1127 |
self.bulkin = None
|
| 1071 |
self.claimed = False
|
1128 |
self.claimed = False
|
| 1072 |
self.timeout = 1000
|
1129 |
self.timeout = 1000
|
| 1073 |
|
1130 |
|
| 1074 |
self.connect()
|
1131 |
self.connect()
|
| 1075 |
|
1132 |
|
| Line 1106... |
Line 1163... |
| 1106 |
for cfg in self.dev:
|
1163 |
for cfg in self.dev:
|
| 1107 |
for intf in cfg:
|
1164 |
for intf in cfg:
|
| 1108 |
self.logger.debug("%02x:%02x:%02x\n" % (intf.bInterfaceClass, intf.bInterfaceSubClass, intf.bInterfaceProtocol))
|
1165 |
self.logger.debug("%02x:%02x:%02x\n" % (intf.bInterfaceClass, intf.bInterfaceSubClass, intf.bInterfaceProtocol))
|
| 1109 |
if intf.bInterfaceClass == 0xff and intf.bInterfaceSubClass == 0 and intf.bInterfaceProtocol == 0:
|
1166 |
if intf.bInterfaceClass == 0xff and intf.bInterfaceSubClass == 0 and intf.bInterfaceProtocol == 0:
|
| 1110 |
self.interface = intf.bInterfaceNumber
|
1167 |
self.interface = intf.bInterfaceNumber
|
| - |
|
1168 |
for ep in intf:
|
| - |
|
1169 |
if not ep.bEndpointAddress & 0x80:
|
| - |
|
1170 |
self.bulkout = ep
|
| - |
|
1171 |
break
|
| - |
|
1172 |
for ep in intf:
|
| - |
|
1173 |
if ep.bEndpointAddress & 0x80:
|
| - |
|
1174 |
self.bulkin = ep
|
| - |
|
1175 |
break
|
| 1111 |
break
|
1176 |
break
|
| 1112 |
if self.interface is None:
|
1177 |
if self.interface is None:
|
| 1113 |
raise DeviceNotFoundError()
|
1178 |
raise DeviceNotFoundError()
|
| 1114 |
self.logger.debug("Debugger interface found!\n")
|
1179 |
self.logger.debug("Debugger interface found!\n")
|
| 1115 |
self.logger.debug("Claiming interface...\n")
|
1180 |
self.logger.debug("Claiming interface...\n")
|
| Line 1121... |
Line 1186... |
| 1121 |
self.claimed = False
|
1186 |
self.claimed = False
|
| 1122 |
|
1187 |
|
| 1123 |
def send(self, data):
|
1188 |
def send(self, data):
|
| 1124 |
if len(data) > 0x1000: raise DeviceError("Attempting to send a message that is too big!")
|
1189 |
if len(data) > 0x1000: raise DeviceError("Attempting to send a message that is too big!")
|
| 1125 |
size = self.dev.ctrl_transfer(0x41, 0x00, 0, self.interface, data, self.timeout)
|
1190 |
size = self.dev.ctrl_transfer(0x41, 0x00, 0, self.interface, data, self.timeout)
|
| 1126 |
if size != len(data):
|
- |
|
| 1127 |
raise SendError("Not all data was written!")
|
1191 |
if size != len(data): raise SendError("Not all data was written!")
|
| 1128 |
return len
|
1192 |
return size
|
| 1129 |
|
1193 |
|
| 1130 |
def receive(self, size):
|
1194 |
def receive(self, size):
|
| 1131 |
if size > 0x1000: raise DeviceError("Attempting to receive a message that is too big!")
|
1195 |
if size > 0x1000: raise DeviceError("Attempting to receive a message that is too big!")
|
| 1132 |
read = self.dev.ctrl_transfer(0xc1, 0x00, 0, self.interface, size, self.timeout)
|
1196 |
data = self.dev.ctrl_transfer(0xc1, 0x00, 0, self.interface, size, self.timeout)
|
| - |
|
1197 |
if len(data) != size: raise ReceiveError("Requested size and read size don't match!")
|
| - |
|
1198 |
return data
|
| - |
|
1199 |
|
| - |
|
1200 |
def sendbulk(self, cmd, data):
|
| - |
|
1201 |
size = self.dev.ctrl_transfer(0x42, 0x00, 0, self.bulkout.bEndpointAddress, cmd, self.timeout)
|
| - |
|
1202 |
if size != len(cmd):
|
| - |
|
1203 |
raise SendError("Bulk send command could not be fully sent (%d of %d)!" % (size, len(cmd)))
|
| - |
|
1204 |
size = self.bulkout.write(data, self.timeout)
|
| - |
|
1205 |
if size != len(data):
|
| - |
|
1206 |
raise SendError("Bulk data could not be fully sent (%d of %d)!" % (size, len(data)))
|
| - |
|
1207 |
return size
|
| - |
|
1208 |
|
| - |
|
1209 |
def recvbulk(self, cmd, size):
|
| - |
|
1210 |
size = self.dev.ctrl_transfer(0x42, 0x00, 0, self.bulkin.bEndpointAddress, cmd, self.timeout)
|
| - |
|
1211 |
if size != len(cmd):
|
| - |
|
1212 |
raise ReceiveError("Bulk receive command could not be fully sent (%d of %d)!" % (size, len(cmd)))
|
| - |
|
1213 |
data = self.bulkin.read(size, self.timeout)
|
| 1133 |
if len(read) != size:
|
1214 |
if len(data) != size:
|
| 1134 |
raise ReceiveError("Requested size and read size don't match!")
|
1215 |
raise SendError("Bulk data could not be fully received (%d of %d)!" % (len(cmd), size))
|
| 1135 |
return read
|
1216 |
return data
|
| 1136 |
|
1217 |
|
| 1137 |
|
1218 |
|
| 1138 |
if __name__ == "__main__":
|
1219 |
if __name__ == "__main__":
|
| 1139 |
from misc import Logger
|
1220 |
from misc import Logger
|
| 1140 |
logger = Logger()
|
1221 |
logger = Logger()
|