mirror of https://github.com/ARMmbed/mbed-os.git
pyOCD development moved to https://github.com/OpenHDK/pyOCD
parent
dfb472ceaf
commit
6b6bc938c5
|
@ -1,148 +0,0 @@
|
|||
pyOCD
|
||||
=====
|
||||
pyOCD is an Open Source python library in order to program and
|
||||
debug ARM Cortex-M microcontrollers using CMSIS-DAP. You can either
|
||||
use a python interpreter to control your target or start a GDB server.
|
||||
|
||||
|
||||
What allows this library?
|
||||
-------------------------
|
||||
1. From a python interpretor:
|
||||
* halt, step, resume execution
|
||||
* read/write memory
|
||||
* read/write block memory
|
||||
* read-write core register
|
||||
* set/remove hardware breakpoints
|
||||
* flash new binary
|
||||
* reset
|
||||
|
||||
2. From a GDB client, you have all the features provided by gdb:
|
||||
* load a .elf file
|
||||
* read/write memory
|
||||
* read/write core register
|
||||
* set/remove hardware breakpoints
|
||||
* high level stepping
|
||||
* ...
|
||||
|
||||
|
||||
DEPENDANCIES:
|
||||
-------------
|
||||
pyOCD relies on external libraries:
|
||||
* pyOCD has been tested with python 2.7
|
||||
* distutils
|
||||
* Windows: [pyWinUSB](https://github.com/rene-aguirre/pywinusb):
|
||||
```
|
||||
$ cd /path-to-pywinusb/
|
||||
$ python setup.py install
|
||||
```
|
||||
* Linux: [pyUSB](https://github.com/walac/pyusb):
|
||||
```
|
||||
$ sudo apt-get install python libusb-1.0-0-dev
|
||||
$ cd /path-to-pyusb/
|
||||
$ sudo python setup.py install
|
||||
```
|
||||
* Mac:
|
||||
|
||||
So far Mac OS X is not supported
|
||||
|
||||
|
||||
Installation:
|
||||
-------------
|
||||
|
||||
$ cd /path-to-pyOCD/
|
||||
$ python setup.py install
|
||||
|
||||
|
||||
Examples:
|
||||
---------
|
||||
## Tests
|
||||
A series of tests are on the test directory:
|
||||
* basic_test.py: simple test that checks:
|
||||
1. read/write core registers
|
||||
2. read/write memory
|
||||
3. stop/resume/step the execution
|
||||
4. reset the target
|
||||
5. flash a binary
|
||||
* gdb_test.py: launch a gdbserver
|
||||
|
||||
## Hello World example:
|
||||
|
||||
from pyOCD.board import MbedBoard
|
||||
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
board = MbedBoard.chooseBoard()
|
||||
|
||||
target = board.target
|
||||
flash = board.flash
|
||||
target.resume()
|
||||
target.halt()
|
||||
print "pc: 0x%X" % target.readCoreRegister("pc")
|
||||
pc: 0xA64
|
||||
target.step()
|
||||
print "pc: 0x%X" % target.readCoreRegister("pc")
|
||||
pc: 0xA30
|
||||
target.step()
|
||||
print "pc: 0x%X" % target.readCoreRegister("pc")
|
||||
pc: 0xA32
|
||||
flash.flashBinary("binaries/l1_lpc1768.bin")
|
||||
print "pc: 0x%X" % target.readCoreRegister("pc")
|
||||
pc: 0x10000000
|
||||
target.reset()
|
||||
target.halt()
|
||||
print "pc: 0x%X" % target.readCoreRegister("pc")
|
||||
pc: 0xAAC
|
||||
board.uninit()
|
||||
|
||||
##GDB server example:
|
||||
Python:
|
||||
|
||||
from pyOCD.gdbserver import GDBServer
|
||||
from pyOCD.board import MbedBoard
|
||||
|
||||
import logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
board = MbedBoard.chooseBoard()
|
||||
|
||||
# start gdbserver
|
||||
gdb = GDBServer(board, 3333)
|
||||
|
||||
gdb server:
|
||||
|
||||
arm-none-eabi-gdb basic.elf
|
||||
|
||||
<gdb> target remote localhost:3333
|
||||
<gdb> load
|
||||
<gdb> continue
|
||||
|
||||
|
||||
Architecture:
|
||||
-------------
|
||||
|
||||
# interface:
|
||||
An interface does the link between the target and the computer.
|
||||
This package contains basic functions to write and read data to and from
|
||||
an interface. You can inherit from Interface and overwrite read(), write(),...
|
||||
Then declare your interface in INTERFACE (in pyOCD.interface.__init__.py)
|
||||
|
||||
# target:
|
||||
A target defines basic functionalities such as step, resume, halt, readMemory,...
|
||||
You can inherit from Target to implement your own functions.
|
||||
Then declare your target in TARGET (in pyOCD.target.__init__.py)
|
||||
|
||||
# transport:
|
||||
Defines the transport used to communicate. In particular, you can find CMSIS-DAP.
|
||||
Defines functions such as memWriteAP, memReadAP, writeDP, readDP,...
|
||||
You can inherit from Transport and implement your own functions.
|
||||
Then declare your transport in TRANSPORT (in pyOCD.transport.__init__.py)
|
||||
|
||||
# flash:
|
||||
Contains flash algorithm in order to flash a new binary into the target.
|
||||
|
||||
# gdbserver:
|
||||
Start a GDB server. The server listens on a specific port. You can then
|
||||
connect a GDB client to it and debug/program the target
|
||||
|
||||
Then you can debug a board which is composed by an interface, a target, a transport and a flash
|
|
@ -1,16 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,16 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
|
@ -1,18 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from mbed_board import MbedBoard
|
|
@ -1,60 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from pyOCD.target import TARGET
|
||||
from pyOCD.transport import TRANSPORT
|
||||
from pyOCD.interface import INTERFACE
|
||||
from pyOCD.flash import FLASH
|
||||
|
||||
import logging
|
||||
|
||||
class Board():
|
||||
"""
|
||||
This class associates a target, a flash, a transport and an interface
|
||||
to create a board
|
||||
"""
|
||||
def __init__(self, target, flash, interface, transport = "cmsis_dap"):
|
||||
if isinstance(interface, str) == False:
|
||||
self.interface = interface
|
||||
else:
|
||||
self.interface = INTERFACE[interface].chooseInterface(INTERFACE[interface])
|
||||
self.transport = TRANSPORT[transport](self.interface)
|
||||
self.target = TARGET[target](self.transport)
|
||||
self.flash = FLASH[flash](self.target)
|
||||
return
|
||||
|
||||
def init(self):
|
||||
"""
|
||||
Initialize the board: interface, transport and target
|
||||
"""
|
||||
logging.debug("init board %s", self)
|
||||
self.interface.init()
|
||||
self.transport.init()
|
||||
self.target.init()
|
||||
|
||||
def uninit(self):
|
||||
"""
|
||||
Uninitialize the board: inetrface, transport and target.
|
||||
This function resets the target
|
||||
"""
|
||||
logging.debug("uninit board %s", self)
|
||||
self.target.resume()
|
||||
self.transport.uninit()
|
||||
self.interface.close()
|
||||
|
||||
def getInfo(self):
|
||||
return self.interface.getInfo()
|
|
@ -1,160 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import sys, os
|
||||
import logging, array
|
||||
|
||||
from time import sleep
|
||||
from board import Board
|
||||
from pyOCD.interface import INTERFACE
|
||||
|
||||
TARGET_TYPE = {"1010": "lpc1768",
|
||||
"0200": "kl25z",
|
||||
"1040": "lpc11u24",
|
||||
"0300": "lpc800",
|
||||
}
|
||||
|
||||
usb_backend = ""
|
||||
if os.name == "nt":
|
||||
usb_backend = "pywinusb"
|
||||
elif os.name == "posix":
|
||||
usb_backend = "pyusb"
|
||||
|
||||
mbed_vid = 0x0d28
|
||||
mbed_pid = 0x0204
|
||||
|
||||
class MbedBoard(Board):
|
||||
"""
|
||||
This class inherits from Board and is specific to mbed boards.
|
||||
Particularly, this class allows you to dynamically determine
|
||||
the type of all boards connected based on the id board
|
||||
"""
|
||||
def __init__(self, target, flash, interface, transport = "cmsis_dap"):
|
||||
"""
|
||||
Init the board
|
||||
"""
|
||||
Board.__init__(self, target, flash, interface, transport)
|
||||
self.unique_id = ""
|
||||
self.target_type = ""
|
||||
|
||||
def getUniqueID(self):
|
||||
"""
|
||||
Return the unique id of the board
|
||||
"""
|
||||
return self.unique_id
|
||||
|
||||
def getTargetType(self):
|
||||
"""
|
||||
Return the type of the board
|
||||
"""
|
||||
return self.target_type
|
||||
|
||||
def getInfo(self):
|
||||
"""
|
||||
Return info on the board
|
||||
"""
|
||||
return Board.getInfo(self) + " [" + self.target_type + "]"
|
||||
|
||||
@staticmethod
|
||||
def getAllConnectedBoards(transport = "cmsis_dap", close = False, blocking = True):
|
||||
"""
|
||||
Return an array of all mbed boards connected
|
||||
"""
|
||||
first = True
|
||||
while True:
|
||||
while True:
|
||||
all_mbeds = INTERFACE[usb_backend].getAllConnectedInterface(mbed_vid, mbed_pid)
|
||||
if all_mbeds != None or not blocking:
|
||||
break
|
||||
if (first == True):
|
||||
logging.info("Waiting for a USB device connected")
|
||||
first = False
|
||||
sleep(0.2)
|
||||
|
||||
mbed_boards = []
|
||||
for mbed in all_mbeds:
|
||||
mbed.write([0x80])
|
||||
u_id_ = mbed.read()
|
||||
try:
|
||||
target_type = array.array('B', [i for i in u_id_[2:6]]).tostring()
|
||||
target_type = TARGET_TYPE[target_type]
|
||||
new_mbed = MbedBoard("target_" + target_type, "flash_" + target_type, mbed, transport)
|
||||
new_mbed.target_type = target_type
|
||||
new_mbed.unique_id = array.array('B', [i for i in u_id_[2:2+u_id_[1]]]).tostring()
|
||||
logging.info("new board id detected: %s", new_mbed.unique_id)
|
||||
mbed_boards.append(new_mbed)
|
||||
if close:
|
||||
mbed.close()
|
||||
except Exception as e:
|
||||
print "received exception: %s" % e
|
||||
mbed.close()
|
||||
|
||||
if len(mbed_boards) > 0 or not blocking:
|
||||
return mbed_boards
|
||||
|
||||
if (first == True):
|
||||
logging.info("Waiting for a USB device connected")
|
||||
first = False
|
||||
|
||||
@staticmethod
|
||||
def chooseBoard(transport = "cmsis_dap", blocking = True, return_first = False):
|
||||
"""
|
||||
Allow you to select a board among all boards connected
|
||||
"""
|
||||
all_mbeds = MbedBoard.getAllConnectedBoards(transport, False, blocking)
|
||||
|
||||
if all_mbeds == None:
|
||||
return None
|
||||
|
||||
index = 0
|
||||
for mbed in all_mbeds:
|
||||
print "%d => %s" % (index, mbed.getInfo())
|
||||
index += 1
|
||||
|
||||
if len(all_mbeds) == 1:
|
||||
all_mbeds[0].init()
|
||||
return all_mbeds[0]
|
||||
|
||||
try:
|
||||
ch = 0
|
||||
if not return_first:
|
||||
while True:
|
||||
ch = sys.stdin.readline()
|
||||
sys.stdin.flush()
|
||||
if (int(ch) < 0) or (int(ch) >= len(all_mbeds)):
|
||||
logging.info("BAD CHOICE: %d", int(ch))
|
||||
index = 0
|
||||
for mbed in all_mbeds:
|
||||
print "%d => %s" % ( index, mbed.getInfo())
|
||||
index += 1
|
||||
else:
|
||||
break
|
||||
# close all others mbed connected
|
||||
for mbed in all_mbeds:
|
||||
if mbed != all_mbeds[int(ch)]:
|
||||
mbed.interface.close()
|
||||
|
||||
all_mbeds[int(ch)].init()
|
||||
return all_mbeds[int(ch)]
|
||||
except Exception as e:
|
||||
try:
|
||||
print e
|
||||
except:
|
||||
pass
|
||||
finally:
|
||||
for mbed in all_mbeds:
|
||||
mbed.interface.close()
|
|
@ -1,27 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from flash_lpc1768 import Flash_lpc1768
|
||||
from flash_kl25z import Flash_kl25z
|
||||
from flash_lpc11u24 import Flash_lpc11u24
|
||||
from flash_lpc800 import Flash_lpc800
|
||||
|
||||
FLASH = {'flash_lpc1768': Flash_lpc1768,
|
||||
'flash_kl25z': Flash_kl25z,
|
||||
'flash_lpc11u24': Flash_lpc11u24,
|
||||
'flash_lpc800': Flash_lpc800
|
||||
}
|
|
@ -1,145 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from pyOCD.target.target import TARGET_RUNNING
|
||||
import logging
|
||||
from struct import unpack
|
||||
from time import time
|
||||
"""
|
||||
import os,sys
|
||||
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
sys.path.insert(0,parentdir)
|
||||
"""
|
||||
|
||||
class Flash():
|
||||
"""
|
||||
This class is responsible to flash a new binary in a target
|
||||
"""
|
||||
|
||||
def __init__(self, target, flash_algo, memoryMapXML):
|
||||
self.target = target
|
||||
self.flash_algo = flash_algo
|
||||
self.end_flash_algo = flash_algo['load_address'] + len(flash_algo)*4
|
||||
self.begin_stack = flash_algo['begin_stack']
|
||||
self.begin_data = flash_algo['begin_data']
|
||||
self.static_base = flash_algo['static_base']
|
||||
self.page_size = flash_algo['page_size']
|
||||
self.memoryMapXML = memoryMapXML
|
||||
|
||||
def init(self):
|
||||
"""
|
||||
Download the flash algorithm in RAM
|
||||
"""
|
||||
self.target.halt()
|
||||
self.target.setTargetState("PROGRAM")
|
||||
|
||||
# download flash algo in RAM
|
||||
self.target.writeBlockMemoryAligned32(self.flash_algo['load_address'], self.flash_algo['instructions'])
|
||||
|
||||
# update core register to execute the init subroutine
|
||||
self.updateCoreRegister(0, 0, 0, 0, self.flash_algo['pc_init'])
|
||||
# resume and wait until the breakpoint is hit
|
||||
self.target.resume()
|
||||
while(self.target.getState() == TARGET_RUNNING):
|
||||
pass
|
||||
|
||||
return
|
||||
|
||||
def eraseAll(self):
|
||||
"""
|
||||
Erase all the flash
|
||||
"""
|
||||
|
||||
# update core register to execute the eraseAll subroutine
|
||||
self.updateCoreRegister(0, 0, 0, 0, self.flash_algo['pc_eraseAll'])
|
||||
|
||||
# resume and wait until the breakpoint is hit
|
||||
self.target.resume()
|
||||
while(self.target.getState() == TARGET_RUNNING):
|
||||
pass
|
||||
|
||||
return
|
||||
|
||||
def programPage(self, flashPtr, bytes):
|
||||
"""
|
||||
Flash one page
|
||||
"""
|
||||
# first transfer in RAM
|
||||
self.target.writeBlockMemoryUnaligned8(self.begin_data, bytes)
|
||||
|
||||
# update core register to execute the program_page subroutine
|
||||
self.updateCoreRegister(flashPtr, self.page_size, self.begin_data, 0, self.flash_algo['pc_program_page'])
|
||||
|
||||
# resume and wait until the breakpoint is hit
|
||||
self.target.resume()
|
||||
while(self.target.getState() == TARGET_RUNNING):
|
||||
pass
|
||||
return
|
||||
|
||||
def flashBinary(self, path_file):
|
||||
"""
|
||||
Flash a binary
|
||||
"""
|
||||
f = open(path_file, "rb")
|
||||
|
||||
start = time()
|
||||
self.init()
|
||||
logging.debug("flash init OK: pc: 0x%X", self.target.readCoreRegister('pc'))
|
||||
self.eraseAll()
|
||||
logging.debug("eraseAll OK: pc: 0x%X", self.target.readCoreRegister('pc'))
|
||||
|
||||
"""
|
||||
bin = open(os.path.join(parentdir, 'res', 'good_bin.txt'), "w+")
|
||||
"""
|
||||
|
||||
flashPtr = 0
|
||||
nb_bytes = 0
|
||||
try:
|
||||
bytes_read = f.read(1024)
|
||||
while bytes_read:
|
||||
bytes_read = unpack(str(len(bytes_read)) + 'B', bytes_read)
|
||||
nb_bytes += len(bytes_read)
|
||||
# page download
|
||||
self.programPage(flashPtr, bytes_read)
|
||||
"""
|
||||
i = 0
|
||||
while (i < len(bytes_read)):
|
||||
bin.write(str(list(bytes_read[i:i+16])) + "\n")
|
||||
i += 16
|
||||
"""
|
||||
flashPtr += 1024
|
||||
|
||||
bytes_read = f.read(1024)
|
||||
finally:
|
||||
f.close()
|
||||
"""
|
||||
bin.close()
|
||||
"""
|
||||
end = time()
|
||||
logging.info("%f kbytes flashed in %f seconds ===> %f kbytes/s" %(nb_bytes/1000, end-start, nb_bytes/(1000*(end - start))))
|
||||
|
||||
def updateCoreRegister(self, r0, r1, r2, r3, pc):
|
||||
self.target.writeCoreRegister('pc', pc)
|
||||
self.target.writeCoreRegister('r0', r0)
|
||||
self.target.writeCoreRegister('r1', r1)
|
||||
self.target.writeCoreRegister('r2', r2)
|
||||
self.target.writeCoreRegister('r3', r3)
|
||||
self.target.writeCoreRegister('r9', self.static_base)
|
||||
self.target.writeCoreRegister('sp', self.begin_stack)
|
||||
self.target.writeCoreRegister('lr', self.flash_algo['load_address'] + 1)
|
||||
return
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from flash import Flash
|
||||
|
||||
flash_algo = { 'load_address' : 0x20000000,
|
||||
'instructions' : [
|
||||
0xE00ABE00, 0x062D780D, 0x24084068, 0xD3000040, 0x1E644058, 0x1C49D1FA, 0x2A001E52, 0x4770D1F2,
|
||||
0xb510492f, 0x60084449, 0x2100482e, 0x482f6001, 0x44484a2d, 0x22016002, 0x04926041, 0x02926082,
|
||||
0x220560c2, 0x61420692, 0x03122201, 0x46026182, 0x70113220, 0x62411e49, 0xf929f000, 0xd0002800,
|
||||
0xbd102001, 0x47702000, 0xb5084a21, 0x0349447a, 0x0c0a9200, 0x481d4601, 0x44482300, 0xf9b7f000,
|
||||
0xd0002800, 0xbd082001, 0x4919b510, 0x48174479, 0x44483920, 0xf891f000, 0xd0002800, 0xbd102001,
|
||||
0x4b13b510, 0x4601447b, 0x22014810, 0x02923b38, 0xf0004448, 0x2800f8b4, 0x2001d000, 0xb538bd10,
|
||||
0x490b460c, 0x39584479, 0x46019100, 0x46134807, 0x44484622, 0xf948f000, 0xd0002800, 0xbd382001,
|
||||
0x00000004, 0x40048100, 0x40020000, 0x00000008, 0x00000085, 0x4604b570, 0x25006800, 0x061b7803,
|
||||
0x2370d5fc, 0x20007003, 0x0003e03a, 0xfa60f000, 0x0f0b070c, 0x1f1b1713, 0x2f2b2723, 0x68263633,
|
||||
0x71f37813, 0x6826e02a, 0x71b37853, 0x6826e026, 0x71737893, 0x6826e022, 0x713378d3, 0x6826e01e,
|
||||
0x72f37913, 0x6826e01a, 0x72b37953, 0x6826e016, 0x72737993, 0x6826e012, 0x723379d3, 0x6826e00e,
|
||||
0x73f37a13, 0x6826e00a, 0x73b37a53, 0x6826e006, 0x73737a93, 0x6826e002, 0x73337ad3, 0xb2c01c40,
|
||||
0xd9c24288, 0x20806821, 0xe0037008, 0x1c416a60, 0x4780d000, 0x78006820, 0xd5f70600, 0x78006820,
|
||||
0xd5010681, 0xe0062504, 0xd50106c1, 0xe0022508, 0xd00007c0, 0x46282510, 0xb508bd70, 0x2244460b,
|
||||
0x700a4669, 0x2100466a, 0xbd084798, 0x4614b538, 0xd002078a, 0x300120ff, 0x6843bd38, 0xd803428b,
|
||||
0x189a6882, 0xd80d428a, 0x428a68c2, 0x6903d803, 0x428b18d3, 0x2002d801, 0x1a89bd38, 0x05d22201,
|
||||
0xe0001889, 0x22081ac9, 0x701a466b, 0x705a0c0a, 0x709a0a0a, 0x466a70d9, 0x47a02103, 0xb5ffbd38,
|
||||
0x4615b081, 0x27019a01, 0x26006852, 0x02bf1948, 0xd804428a, 0x689b9b01, 0x428318d3, 0x9a01d20f,
|
||||
0x428a68d2, 0x9b01d804, 0x18d3691b, 0xd2014283, 0xe0292602, 0x21011a88, 0x184405c9, 0x1a8ce000,
|
||||
0x46204639, 0xf907f000, 0xd0022900, 0x360126ff, 0x4639e01a, 0xf0004628, 0x2900f8fe, 0x2601d012,
|
||||
0x2009e012, 0x70084669, 0x70480c20, 0x70880a20, 0x9b0470cc, 0x2103466a, 0x47989801, 0xd1030006,
|
||||
0x19e41bed, 0xd1ec2d00, 0xb0054630, 0xb5f0bdf0, 0x24006801, 0x0612780a, 0x2270d5fc, 0x6802700a,
|
||||
0x71d12103, 0x22806801, 0x6803718a, 0x71592100, 0x23fc6805, 0x6803712b, 0x680373d9, 0x6802701a,
|
||||
0x061b7813, 0x7a55d5fc, 0x07177a12, 0x0f3f2201, 0x105603d2, 0xf000003b, 0x0910f96b, 0x09100e0b,
|
||||
0x10090909, 0x09090e1f, 0x11090909, 0xe0056102, 0x03522203, 0x6106e7fa, 0x6101e000, 0x0f12072a,
|
||||
0xf0000013, 0x0c10f955, 0x120f0c0c, 0x1d1b1815, 0x0c0c0c1f, 0x0d0c0c0c, 0x03522201, 0x61c1e7e6,
|
||||
0xbdf04620, 0x02c92101, 0x2101e7f9, 0xe7f60289, 0x02492101, 0x21ffe7f3, 0xe7f03101, 0xe7ee2180,
|
||||
0xe7ec2140, 0xe7ea2120, 0x4607b5fe, 0x461d4616, 0x198a2000, 0xd002078b, 0x300120ff, 0x07b3bdfe,
|
||||
0x2001d001, 0x687bbdfe, 0xd803428b, 0x191c68bc, 0xd20d4294, 0x428b68fb, 0x693cd803, 0x4294191c,
|
||||
0x2002d201, 0x2201bdfe, 0x05d21ac9, 0xe01b188c, 0xe0191acc, 0x46692006, 0x0c207008, 0x0a207048,
|
||||
0x70cc7088, 0x710878e8, 0x714878a8, 0x71887868, 0x71c87828, 0x466a9b08, 0x46382107, 0x28004798,
|
||||
0x1d24d1e0, 0x1d2d1f36, 0xd1e32e00, 0xb5febdfe, 0x46044615, 0x00a86842, 0x461e1840, 0xd803428a,
|
||||
0x18d368a3, 0xd808428b, 0x428b68e3, 0x6927d803, 0x428b19db, 0x2002d801, 0x4282bdfe, 0x68a3d805,
|
||||
0x428318d3, 0x1a8fd301, 0x68e2e00a, 0xd9034282, 0x18d36923, 0xd3ee4283, 0x21011a88, 0x184705c9,
|
||||
0x46382104, 0xf817f000, 0xd0022900, 0x300120ff, 0x2001bdfe, 0x70084669, 0x70480c38, 0x70880a38,
|
||||
0x0a2870cf, 0x714d7108, 0x9b08718e, 0x2106466a, 0x47984620, 0x2200bdfe, 0x428b0903, 0x0a03d32c,
|
||||
0xd311428b, 0x469c2300, 0x4603e04e, 0xd43c430b, 0x08432200, 0xd331428b, 0x428b0903, 0x0a03d31c,
|
||||
0xd301428b, 0xe03f4694, 0x428b09c3, 0x01cbd301, 0x41521ac0, 0x428b0983, 0x018bd301, 0x41521ac0,
|
||||
0x428b0943, 0x014bd301, 0x41521ac0, 0x428b0903, 0x010bd301, 0x41521ac0, 0x428b08c3, 0x00cbd301,
|
||||
0x41521ac0, 0x428b0883, 0x008bd301, 0x41521ac0, 0x428b0843, 0x004bd301, 0x41521ac0, 0xd2001a41,
|
||||
0x41524601, 0x47704610, 0x0fcae05d, 0x4249d000, 0xd3001003, 0x40534240, 0x469c2200, 0x428b0903,
|
||||
0x0a03d32d, 0xd312428b, 0x018922fc, 0x0a03ba12, 0xd30c428b, 0x11920189, 0xd308428b, 0x11920189,
|
||||
0xd304428b, 0xd03a0189, 0xe0001192, 0x09c30989, 0xd301428b, 0x1ac001cb, 0x09834152, 0xd301428b,
|
||||
0x1ac0018b, 0x09434152, 0xd301428b, 0x1ac0014b, 0x09034152, 0xd301428b, 0x1ac0010b, 0x08c34152,
|
||||
0xd301428b, 0x1ac000cb, 0x08834152, 0xd301428b, 0x1ac0008b, 0xd2d94152, 0x428b0843, 0x004bd301,
|
||||
0x41521ac0, 0xd2001a41, 0x46634601, 0x105b4152, 0xd3014610, 0x2b004240, 0x4249d500, 0x46634770,
|
||||
0xd300105b, 0xb5014240, 0x46c02000, 0xbd0246c0, 0x4674b430, 0x78251e64, 0x42ab1c64, 0x461dd200,
|
||||
0x005b5d63, 0xbc3018e3, 0x00004718, 0xfffffffe
|
||||
],
|
||||
'pc_init' : 0x20000020,
|
||||
'pc_eraseAll' : 0x20000088,
|
||||
'pc_program_page' : 0x200000be,
|
||||
'begin_stack' : 0x20001000,
|
||||
'begin_data' : 0x20002000,
|
||||
'static_base' : 0x200005ec,
|
||||
'page_size' : 1024
|
||||
};
|
||||
|
||||
memoryMapXML = "<?xml version=\"1.0\"?>" \
|
||||
"<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\" \"http://sourceware.org/gdb/gdb-memory-map.dtd\">" \
|
||||
"<memory-map>" \
|
||||
"<memory type=\"flash\" start=\"0x0\" length=\"0x20000\"> <property name=\"blocksize\">0x400</property></memory>" \
|
||||
"<memory type=\"ram\" start=\"0x20000000\" length=\"0x3000\"> </memory>" \
|
||||
"</memory-map>"
|
||||
|
||||
|
||||
class Flash_kl25z(Flash):
|
||||
|
||||
def __init__(self, target):
|
||||
Flash.__init__(self, target, flash_algo, memoryMapXML)
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from flash import Flash
|
||||
|
||||
flash_algo = { 'load_address' : 0x10000000,
|
||||
'instructions' : [
|
||||
0xe00abe00, 0x062d780d, 0x24084068, 0xd3000040, 0x1e644058, 0x1c49d1fa, 0x2a001e52, 0x4770d1f2,
|
||||
0x7803e005, 0x42931c40, 0x2001d001, 0x1e494770, 0x2000d2f7, 0x00004770, 0x47700b00, 0x484e494f,
|
||||
0x60084449, 0x2100484e, 0x22016301, 0x63416342, 0x6b416342, 0xd0fc07c9, 0x49496382, 0x39402002,
|
||||
0x20007008, 0x20004770, 0xb5f84770, 0x20324c45, 0x2500444c, 0x46222607, 0x4621c261, 0x4f423114,
|
||||
0x91004620, 0x696047b8, 0xd10c2800, 0x46212034, 0x483ac161, 0x68004448, 0x462060e0, 0x47b89900,
|
||||
0x28006960, 0x2001d000, 0xb5f8bdf8, 0x0b044d35, 0x2032444d, 0x4629606c, 0x311460ac, 0x4e326028,
|
||||
0x4628460f, 0x696847b0, 0xd10d2800, 0x2034606c, 0x602860ac, 0x46394829, 0x68004448, 0x462860e8,
|
||||
0x696847b0, 0xd0002800, 0xbdf82001, 0x0006b5f8, 0xd11e4614, 0x0180200b, 0x6bc11820, 0x42814823,
|
||||
0x4823d038, 0xd0354281, 0x42814822, 0x4822d032, 0xd02f4281, 0x68206861, 0x184068e2, 0x188968a1,
|
||||
0x69211840, 0x69611840, 0x69a11840, 0x42401840, 0x4d1461e0, 0x444d0b30, 0x60682132, 0x60a86029,
|
||||
0x31144629, 0x46284f10, 0x47b89100, 0x28006968, 0x606ed110, 0x60ac2033, 0x20016028, 0x60e80280,
|
||||
0x44484806, 0x61286800, 0x99004628, 0x696847b8, 0xd0002800, 0xbdf82001, 0x00002ee0, 0x00000004,
|
||||
0x40048040, 0x00000008, 0x1fff1ff1, 0x4e697370, 0x12345678, 0x87654321, 0x43218765, 0x00000000,
|
||||
0x00000000
|
||||
],
|
||||
'pc_init' : 0x1000003d,
|
||||
'pc_eraseAll' : 0x1000006b,
|
||||
'pc_program_page' : 0x100000ed,
|
||||
'begin_data' : 0x100001c4,
|
||||
'begin_stack' : 0x10001000,
|
||||
'static_base' : 0x1000019c,
|
||||
'page_size' : 1024
|
||||
};
|
||||
|
||||
memoryMapXML = "<?xml version=\"1.0\"?>" \
|
||||
"<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\" \"http://sourceware.org/gdb/gdb-memory-map.dtd\">" \
|
||||
"<memory-map>" \
|
||||
"<memory type=\"flash\" start=\"0x0\" length=\"0x8000\"> <property name=\"blocksize\">0x400</property></memory>" \
|
||||
"<memory type=\"ram\" start=\"0x10000000\" length=\"0x1000\"> </memory>" \
|
||||
"</memory-map>"
|
||||
|
||||
|
||||
class Flash_lpc11u24(Flash):
|
||||
|
||||
def __init__(self, target):
|
||||
Flash.__init__(self, target, flash_algo, memoryMapXML)
|
|
@ -1,61 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from flash import Flash
|
||||
|
||||
flash_algo = { 'load_address' : 0x10000000,
|
||||
'instructions' : [
|
||||
0xe00abe00, 0x062d780d, 0x24084068, 0xd3000040, 0x1e644058, 0x1c49d1fa, 0x2a001e52, 0x4770d1f2,
|
||||
0x7803e005, 0x42931c40, 0x2001d001, 0x1e494770, 0x2000d2f7, 0x00004770, 0x28100b00, 0x210ed302,
|
||||
0x00d0eb01, 0x486c4770, 0x7801b510, 0x0102f021, 0x22aa7001, 0x23557302, 0x78017303, 0x0101f021,
|
||||
0x73027001, 0xf8d07303, 0xf0411120, 0xf8c00120, 0xf1a01120, 0xf8d00080, 0x064911a0, 0xf100d5fb,
|
||||
0x24010080, 0x408cf880, 0x0113f04f, 0x73026041, 0x78017303, 0x0101f041, 0x73027001, 0xf1a07303,
|
||||
0xf8d00080, 0x01491088, 0xf100d5fb, 0x2107006d, 0x1097f880, 0x0109f04f, 0x109bf880, 0xf0417cc1,
|
||||
0x74c10102, 0x77c377c2, 0x4c2df800, 0xf64e494b, 0x44492060, 0xf04f6008, 0xbd100000, 0x47702000,
|
||||
0x41f0e92d, 0x20324c46, 0x2500444c, 0xe884271d, 0xf10400a1, 0x4e430114, 0x46204688, 0x696047b0,
|
||||
0x2034b960, 0x00a1e884, 0x4641483c, 0x68004448, 0x462060e0, 0x696047b0, 0xd0002800, 0xe8bd2001,
|
||||
0xe92d81f0, 0xf7ff41f0, 0x4d35ff87, 0x444d4604, 0xe9c52032, 0xf1050400, 0x4e320114, 0x4628460f,
|
||||
0x47b060ac, 0xb9686968, 0xe9c52034, 0x482b0400, 0x444860ac, 0x68004639, 0x462860e8, 0x696847b0,
|
||||
0xd0dc2800, 0xe7da2001, 0x41f0e92d, 0x46140006, 0x4925d11d, 0x02fcf8d4, 0xd03a4288, 0x42884923,
|
||||
0x4923d037, 0xd0344288, 0x4131ea4f, 0xd0304288, 0x0100e9d4, 0xe9d44408, 0x44111202, 0x69214408,
|
||||
0x69614408, 0x69a14408, 0x42404408, 0x463061e0, 0xff42f7ff, 0x21324d12, 0x4f12444d, 0x1000e9c5,
|
||||
0x0114f105, 0x468860a8, 0x47b84628, 0xb9806968, 0xe9c52033, 0xf44f0600, 0xe9c56080, 0x48074002,
|
||||
0x44484641, 0x61286800, 0x47b84628, 0x28006968, 0x2001d095, 0x0000e793, 0x400fc080, 0x00000004,
|
||||
0x00000008, 0x1fff1ff1, 0x4e697370, 0x12345678, 0x87654321, 0x00000000, 0x00000000
|
||||
],
|
||||
'pc_init' : 0x10000047,
|
||||
'pc_eraseAll' : 0x100000e1,
|
||||
'pc_program_page' : 0x10000169,
|
||||
'begin_data' : 0x1000023c,
|
||||
'begin_stack' : 0x10001000,
|
||||
'static_base' : 0x10000214,
|
||||
'page_size' : 1024
|
||||
};
|
||||
|
||||
memoryMapXML = "<?xml version=\"1.0\"?>" \
|
||||
"<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\" \"http://sourceware.org/gdb/gdb-memory-map.dtd\">" \
|
||||
"<memory-map>" \
|
||||
"<memory type=\"flash\" start=\"0x0\" length=\"0x80000\"> <property name=\"blocksize\">0x400</property></memory>" \
|
||||
"<memory type=\"ram\" start=\"0x10000000\" length=\"0x8000\"> </memory>" \
|
||||
"<memory type=\"ram\" start=\"0x2007C000\" length=\"0x8000\"> </memory>" \
|
||||
"</memory-map>"
|
||||
|
||||
|
||||
class Flash_lpc1768(Flash):
|
||||
|
||||
def __init__(self, target):
|
||||
Flash.__init__(self, target, flash_algo, memoryMapXML)
|
|
@ -1,56 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from flash import Flash
|
||||
|
||||
flash_algo = { 'load_address' : 0x10000000,
|
||||
'instructions' : [
|
||||
0xE00ABE00, 0x062D780D, 0x24084068, 0xD3000040, 0x1E644058, 0x1C49D1FA, 0x2A001E52, 0x4770D1F2,
|
||||
0x47700a80, 0x484e494f, 0x60084449, 0x2100484e, 0x22016301, 0x63416342, 0x6b416342, 0xd0fc07c9,
|
||||
0x49496382, 0x39402002, 0x20007008, 0x20004770, 0xb5f84770, 0x20324c45, 0x2500444c, 0x4622260f,
|
||||
0x4621c261, 0x4f423114, 0x91004620, 0x696047b8, 0xd10c2800, 0x46212034, 0x483ac161, 0x68004448,
|
||||
0x462060e0, 0x47b89900, 0x28006960, 0x2001d000, 0xb5f8bdf8, 0x0a844d35, 0x2032444d, 0x4629606c,
|
||||
0x311460ac, 0x4e326028, 0x4628460f, 0x696847b0, 0xd10d2800, 0x2034606c, 0x602860ac, 0x46394829,
|
||||
0x68004448, 0x462860e8, 0x696847b0, 0xd0002800, 0xbdf82001, 0x4614b5f8, 0xd11e0006, 0x0180200b,
|
||||
0x6bc11820, 0x42814823, 0x4823d038, 0xd0354281, 0x42814822, 0x4822d032, 0xd02f4281, 0x68206861,
|
||||
0x184068e2, 0x188968a1, 0x69211840, 0x69611840, 0x69a11840, 0x42401840, 0x4d1461e0, 0x444d0ab0,
|
||||
0x60682132, 0x60a86029, 0x31144629, 0x46284f10, 0x47b89100, 0x28006968, 0x606ed110, 0x60ac2033,
|
||||
0x20016028, 0x60e80280, 0x44484806, 0x61286800, 0x99004628, 0x696847b8, 0xd0002800, 0xbdf82001,
|
||||
0x00002ee0, 0x00000004, 0x40048040, 0x00000008, 0x1fff1ff1, 0x4e697370, 0x12345678, 0x87654321,
|
||||
0x43218765
|
||||
],
|
||||
'pc_init' : 0x10000024,
|
||||
'pc_eraseAll' : 0x10000052,
|
||||
'pc_program_page' : 0x100000d4,
|
||||
'begin_data' : 0x10000400,
|
||||
'begin_stack' : 0x10001000,
|
||||
'static_base' : 0x10000300,
|
||||
'page_size' : 1024
|
||||
};
|
||||
|
||||
memoryMapXML = "<?xml version=\"1.0\"?>" \
|
||||
"<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\" \"http://sourceware.org/gdb/gdb-memory-map.dtd\">" \
|
||||
"<memory-map>" \
|
||||
"<memory type=\"flash\" start=\"0x0\" length=\"0x8000\"> <property name=\"blocksize\">0x400</property></memory>" \
|
||||
"<memory type=\"ram\" start=\"0x10000000\" length=\"0x1000\"> </memory>" \
|
||||
"</memory-map>"
|
||||
|
||||
|
||||
class Flash_lpc800(Flash):
|
||||
|
||||
def __init__(self, target):
|
||||
Flash.__init__(self, target, flash_algo, memoryMapXML)
|
|
@ -1,18 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from gdbserver import GDBServer
|
|
@ -1,55 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import socket, select
|
||||
|
||||
class GDBSocket():
|
||||
def __init__(self, port, packet_size):
|
||||
self.packet_size = packet_size
|
||||
self.s = None
|
||||
self.conn = None
|
||||
self.port = port
|
||||
return
|
||||
|
||||
def init(self):
|
||||
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.s.bind(('', self.port))
|
||||
self.s.listen(5)
|
||||
|
||||
def connect(self):
|
||||
self.conn = None
|
||||
self.init()
|
||||
rr,_,_ = select.select([self.s],[],[], 0.5)
|
||||
if rr:
|
||||
self.conn, _ = self.s.accept()
|
||||
|
||||
return self.conn
|
||||
|
||||
def read(self):
|
||||
return self.conn.recv(self.packet_size)
|
||||
|
||||
def write(self, data):
|
||||
return self.conn.send(data)
|
||||
|
||||
def close(self):
|
||||
if self.conn != None:
|
||||
self.conn.close()
|
||||
return self.s.close()
|
||||
|
||||
def setBlocking(self, blocking):
|
||||
return self.conn.setblocking(blocking)
|
|
@ -1,51 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
try:
|
||||
from websocket import create_connection
|
||||
except:
|
||||
pass
|
||||
|
||||
class GDBWebSocket():
|
||||
def __init__(self, url):
|
||||
self.url = url
|
||||
self.wss = None
|
||||
return
|
||||
|
||||
def connect(self):
|
||||
self.wss = None
|
||||
try:
|
||||
self.wss = create_connection(self.url)
|
||||
except:
|
||||
pass
|
||||
return self.wss
|
||||
|
||||
def read(self):
|
||||
return self.wss.recv()
|
||||
|
||||
def write(self, data):
|
||||
return self.wss.send(data)
|
||||
|
||||
def close(self):
|
||||
return self.wss.close()
|
||||
|
||||
def setBlocking(self, blocking):
|
||||
if blocking != 0:
|
||||
self.wss.settimeout(None)
|
||||
else:
|
||||
self.wss.settimeout(0)
|
||||
|
|
@ -1,594 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import logging, threading, socket
|
||||
from pyOCD.target.cortex_m import CORE_REGISTER
|
||||
from pyOCD.target.target import TARGET_HALTED
|
||||
from struct import unpack
|
||||
from time import sleep
|
||||
import sys
|
||||
from gdb_socket import GDBSocket
|
||||
from gdb_websocket import GDBWebSocket
|
||||
|
||||
"""
|
||||
import os
|
||||
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
sys.path.insert(0,parentdir)
|
||||
"""
|
||||
|
||||
SIGINT = (2)
|
||||
SIGSEGV = (11)
|
||||
SIGILL = (4)
|
||||
SIGSTOP = (17)
|
||||
SIGTRAP = (5)
|
||||
SIGBUS = (10)
|
||||
|
||||
FAULT = {0: "17", #SIGSTOP
|
||||
1: "17",
|
||||
2: "02", #SIGINT
|
||||
3: "11", #SIGSEGV
|
||||
4: "11",
|
||||
5: "10", #SIGBUS
|
||||
6: "04", #SIGILL
|
||||
7: "17",
|
||||
8: "17",
|
||||
9: "17",
|
||||
10: "17",
|
||||
11: "17",
|
||||
12: "17",
|
||||
13: "17",
|
||||
14: "17",
|
||||
15: "17",
|
||||
}
|
||||
|
||||
class GDBServer(threading.Thread):
|
||||
"""
|
||||
This class start a GDB server listening a gdb connection on a specific port.
|
||||
It implements the RSP (Remote Serial Protocol).
|
||||
"""
|
||||
def __init__(self, board, port_urlWSS):
|
||||
threading.Thread.__init__(self)
|
||||
self.board = board
|
||||
self.target = board.target
|
||||
self.flash = board.flash
|
||||
self.abstract_socket = None
|
||||
self.wss_server = None
|
||||
self.port = 0
|
||||
if isinstance(port_urlWSS, str) == True:
|
||||
self.wss_server = port_urlWSS
|
||||
else:
|
||||
self.port = port_urlWSS
|
||||
self.packet_size = 2048
|
||||
self.flashData = ""
|
||||
self.conn = None
|
||||
self.lock = threading.Lock()
|
||||
self.shutdown_event = threading.Event()
|
||||
self.detach_event = threading.Event()
|
||||
self.quit = False
|
||||
if self.wss_server == None:
|
||||
self.abstract_socket = GDBSocket(self.port, self.packet_size)
|
||||
else:
|
||||
self.abstract_socket = GDBWebSocket(self.wss_server)
|
||||
self.start()
|
||||
|
||||
def restart(self):
|
||||
if self.isAlive():
|
||||
self.detach_event.set()
|
||||
|
||||
def stop(self):
|
||||
if self.isAlive():
|
||||
self.shutdown_event.set()
|
||||
while self.isAlive():
|
||||
pass
|
||||
logging.info("GDB server thread killed")
|
||||
self.board.uninit()
|
||||
|
||||
def setBoard(self, board, stop = True):
|
||||
self.lock.acquire()
|
||||
if stop:
|
||||
self.restart()
|
||||
self.board = board
|
||||
self.target = board.target
|
||||
self.flash = board.flash
|
||||
self.lock.release()
|
||||
return
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
new_command = False
|
||||
data = []
|
||||
logging.info('GDB server started')
|
||||
|
||||
self.shutdown_event.clear()
|
||||
self.detach_event.clear()
|
||||
|
||||
while not self.shutdown_event.isSet() and not self.detach_event.isSet():
|
||||
connected = self.abstract_socket.connect()
|
||||
if connected != None:
|
||||
break
|
||||
|
||||
if self.shutdown_event.isSet():
|
||||
return
|
||||
|
||||
if self.detach_event.isSet():
|
||||
continue
|
||||
|
||||
logging.info("One client connected!")
|
||||
|
||||
while True:
|
||||
|
||||
if self.shutdown_event.isSet():
|
||||
return
|
||||
|
||||
if self.detach_event.isSet():
|
||||
continue
|
||||
|
||||
# read command
|
||||
while True:
|
||||
if (new_command == True):
|
||||
new_command = False
|
||||
break
|
||||
try:
|
||||
if self.shutdown_event.isSet() or self.detach_event.isSet():
|
||||
break
|
||||
self.abstract_socket.setBlocking(0)
|
||||
data = self.abstract_socket.read()
|
||||
if data.index("$") >= 0 and data.index("#") >= 0:
|
||||
break
|
||||
except (ValueError, socket.error):
|
||||
pass
|
||||
|
||||
if self.shutdown_event.isSet():
|
||||
return
|
||||
|
||||
if self.detach_event.isSet():
|
||||
continue
|
||||
|
||||
self.abstract_socket.setBlocking(1)
|
||||
|
||||
data = data[data.index("$"):]
|
||||
|
||||
self.lock.acquire()
|
||||
|
||||
if len(data) != 0:
|
||||
# decode and prepare resp
|
||||
[resp, ack, detach] = self.handleMsg(data)
|
||||
|
||||
if resp is not None:
|
||||
# ack
|
||||
if ack:
|
||||
resp = "+" + resp
|
||||
# send resp
|
||||
self.abstract_socket.write(resp)
|
||||
# wait a '+' from the client
|
||||
try:
|
||||
data = self.abstract_socket.read()
|
||||
if data[0] != '+':
|
||||
logging.debug('gdb client has not ack!')
|
||||
else:
|
||||
logging.debug('gdb client has ack!')
|
||||
if data.index("$") >= 0 and data.index("#") >= 0:
|
||||
new_command = True
|
||||
except:
|
||||
pass
|
||||
|
||||
if detach:
|
||||
self.abstract_socket.close()
|
||||
self.lock.release()
|
||||
break
|
||||
|
||||
self.lock.release()
|
||||
|
||||
|
||||
def handleMsg(self, msg):
|
||||
|
||||
if msg[0] != '$':
|
||||
logging.debug('msg ignored: first char != $')
|
||||
return None, 0, 0
|
||||
|
||||
#logging.debug('-->>>>>>>>>>>> GDB rsp packet: %s', msg)
|
||||
|
||||
# query command
|
||||
if msg[1] == 'q':
|
||||
return self.handleQuery(msg[2:]), 1, 0
|
||||
|
||||
elif msg[1] == 'H':
|
||||
return self.createRSPPacket(''), 1, 0
|
||||
|
||||
elif msg[1] == '?':
|
||||
return self.lastSignal(), 1, 0
|
||||
|
||||
elif msg[1] == 'g':
|
||||
return self.getRegister(), 1, 0
|
||||
|
||||
elif msg[1] == 'p':
|
||||
return self.readRegister(msg[2:]), 1, 0
|
||||
|
||||
elif msg[1] == 'P':
|
||||
return self.writeRegister(msg[2:]), 1, 0
|
||||
|
||||
elif msg[1] == 'm':
|
||||
return self.getMemory(msg[2:]), 1, 0
|
||||
|
||||
elif msg[1] == 'X':
|
||||
return self.writeMemory(msg[2:]), 1, 0
|
||||
|
||||
elif msg[1] == 'v':
|
||||
return self.flashOp(msg[2:]), 1, 0
|
||||
|
||||
# we don't send immediately the response for C and S commands
|
||||
elif msg[1] == 'C' or msg[1] == 'c':
|
||||
return self.resume()
|
||||
|
||||
elif msg[1] == 'S' or msg[1] == 's':
|
||||
return self.step()
|
||||
|
||||
elif msg[1] == 'Z' or msg[1] == 'z':
|
||||
return self.breakpoint(msg[1:]), 1, 0
|
||||
|
||||
elif msg[1] == 'D':
|
||||
return self.detach(msg[1:]), 1, 1
|
||||
|
||||
elif msg[1] == 'k':
|
||||
return self.kill(), 1, 1
|
||||
|
||||
else:
|
||||
logging.error("Unknown RSP packet: %s", msg)
|
||||
return None
|
||||
|
||||
def detach(self, data):
|
||||
resp = "OK"
|
||||
return self.createRSPPacket(resp)
|
||||
|
||||
def kill(self):
|
||||
return self.createRSPPacket("")
|
||||
|
||||
def breakpoint(self, data):
|
||||
# handle Z1/z1 commands
|
||||
addr = int(data.split(',')[1], 16)
|
||||
if data[1] == '1':
|
||||
if data[0] == 'Z':
|
||||
if self.target.setBreakpoint(addr) == False:
|
||||
resp = "ENN"
|
||||
return self.createRSPPacket(resp)
|
||||
else:
|
||||
self.target.removeBreakpoint(addr)
|
||||
resp = "OK"
|
||||
return self.createRSPPacket(resp)
|
||||
|
||||
return None
|
||||
|
||||
def resume(self):
|
||||
self.ack()
|
||||
self.target.resume()
|
||||
self.abstract_socket.setBlocking(0)
|
||||
|
||||
val = ''
|
||||
|
||||
while True:
|
||||
sleep(0.01)
|
||||
|
||||
try:
|
||||
data = self.abstract_socket.read()
|
||||
if (data[0] == '\x03'):
|
||||
self.target.halt()
|
||||
val = 'S05'
|
||||
logging.debug("receive CTRL-C")
|
||||
break
|
||||
except:
|
||||
pass
|
||||
|
||||
if self.target.getState() == TARGET_HALTED:
|
||||
logging.debug("state halted")
|
||||
val = 'S05'
|
||||
break
|
||||
|
||||
self.target.halt()
|
||||
ipsr = self.target.readCoreRegister('xpsr')
|
||||
logging.debug("GDB resume xpsr: 0x%X", ipsr)
|
||||
if (ipsr & 0x1f) == 3:
|
||||
val = "S" + FAULT[3]
|
||||
break
|
||||
self.target.resume()
|
||||
|
||||
self.abstract_socket.setBlocking(1)
|
||||
return self.createRSPPacket(val), 0, 0
|
||||
|
||||
def step(self):
|
||||
self.ack()
|
||||
self.target.step()
|
||||
return self.createRSPPacket("S05"), 0, 0
|
||||
|
||||
def halt(self):
|
||||
self.ack()
|
||||
self.target.halt()
|
||||
return self.createRSPPacket("S05"), 0, 0
|
||||
|
||||
def flashOp(self, data):
|
||||
ops = data.split(':')[0]
|
||||
#logging.debug("flash op: %s", ops)
|
||||
|
||||
if ops == 'FlashErase':
|
||||
self.flash.init()
|
||||
self.flash.eraseAll()
|
||||
return self.createRSPPacket("OK")
|
||||
|
||||
elif ops == 'FlashWrite':
|
||||
logging.debug("flash write addr: 0x%s", data.split(':')[1])
|
||||
# search for second ':' (beginning of data encoded in the message)
|
||||
second_colon = 0
|
||||
idx_begin = 0
|
||||
while second_colon != 2:
|
||||
if data[idx_begin] == ':':
|
||||
second_colon += 1
|
||||
idx_begin += 1
|
||||
|
||||
self.flashData += data[idx_begin:len(data) - 3]
|
||||
return self.createRSPPacket("OK")
|
||||
|
||||
# we need to flash everything
|
||||
elif 'FlashDone' in ops :
|
||||
flashPtr = 0
|
||||
|
||||
unescaped_data = self.unescape(self.flashData)
|
||||
|
||||
bytes_to_be_written = len(unescaped_data)
|
||||
|
||||
"""
|
||||
bin = open(os.path.join(parentdir, 'res', 'bad_bin.txt'), "w+")
|
||||
|
||||
i = 0
|
||||
while (i < bytes_to_be_written):
|
||||
bin.write(str(unescaped_data[i:i+16]) + "\n")
|
||||
i += 16
|
||||
"""
|
||||
|
||||
|
||||
logging.info("flashing %d bytes", bytes_to_be_written)
|
||||
|
||||
while len(unescaped_data) > 0:
|
||||
size_to_write = min(self.flash.page_size, len(unescaped_data))
|
||||
self.flash.programPage(flashPtr, unescaped_data[:size_to_write])
|
||||
flashPtr += size_to_write
|
||||
|
||||
unescaped_data = unescaped_data[size_to_write:]
|
||||
|
||||
# print progress bar
|
||||
sys.stdout.write('\r')
|
||||
i = int((float(flashPtr)/float(bytes_to_be_written))*20.0)
|
||||
# the exact output you're looking for:
|
||||
sys.stdout.write("[%-20s] %d%%" % ('='*i, 5*i))
|
||||
sys.stdout.flush()
|
||||
|
||||
sys.stdout.write("\n\r")
|
||||
|
||||
self.flashData = ""
|
||||
|
||||
"""
|
||||
bin.close()
|
||||
"""
|
||||
|
||||
# reset and stop on reset handler
|
||||
self.target.resetStopOnReset()
|
||||
|
||||
return self.createRSPPacket("OK")
|
||||
|
||||
elif 'Cont' in ops:
|
||||
if 'Cont?' in ops:
|
||||
return self.createRSPPacket("vCont;c;s;t")
|
||||
|
||||
return None
|
||||
|
||||
def unescape(self, data):
|
||||
data_idx = 0
|
||||
|
||||
# unpack the data into binary array
|
||||
str_unpack = str(len(data)) + 'B'
|
||||
data = unpack(str_unpack, data)
|
||||
data = list(data)
|
||||
|
||||
# check for escaped characters
|
||||
while data_idx < len(data):
|
||||
if data[data_idx] == 0x7d:
|
||||
data.pop(data_idx)
|
||||
data[data_idx] = data[data_idx] ^ 0x20
|
||||
data_idx += 1
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def getMemory(self, data):
|
||||
split = data.split(',')
|
||||
addr = int(split[0], 16)
|
||||
length = split[1]
|
||||
length = int(length[:len(length)-3],16)
|
||||
|
||||
val = ''
|
||||
|
||||
mem = self.target.readBlockMemoryUnaligned8(addr, length)
|
||||
for x in mem:
|
||||
if x >= 0x10:
|
||||
val += hex(x)[2:4]
|
||||
else:
|
||||
val += '0' + hex(x)[2:3]
|
||||
|
||||
return self.createRSPPacket(val)
|
||||
|
||||
def writeMemory(self, data):
|
||||
split = data.split(',')
|
||||
addr = int(split[0], 16)
|
||||
length = int(split[1].split(':')[0], 16)
|
||||
|
||||
idx_begin = 0
|
||||
for i in range(len(data)):
|
||||
if data[i] == ':':
|
||||
idx_begin += 1
|
||||
break
|
||||
idx_begin += 1
|
||||
|
||||
data = data[idx_begin:len(data) - 3]
|
||||
data = self.unescape(data)
|
||||
|
||||
if length > 0:
|
||||
self.target.writeBlockMemoryUnaligned8(addr, data)
|
||||
|
||||
return self.createRSPPacket("OK")
|
||||
|
||||
def readRegister(self, data):
|
||||
num = int(data.split('#')[0], 16)
|
||||
reg = self.target.readCoreRegister(num)
|
||||
logging.debug("GDB: read reg %d: 0x%X", num, reg)
|
||||
val = self.intToHexGDB(reg)
|
||||
return self.createRSPPacket(val)
|
||||
|
||||
def writeRegister(self, data):
|
||||
num = int(data.split('=')[0], 16)
|
||||
val = data.split('=')[1].split('#')[0]
|
||||
val = val[6:8] + val[4:6] + val[2:4] + val[0:2]
|
||||
logging.debug("GDB: write reg %d: 0x%X", num, int(val, 16))
|
||||
self.target.writeCoreRegister(num, int(val, 16))
|
||||
return self.createRSPPacket("OK")
|
||||
|
||||
def intToHexGDB(self, val):
|
||||
val = hex(int(val))[2:]
|
||||
size = len(val)
|
||||
r = ''
|
||||
for i in range(8-size):
|
||||
r += '0'
|
||||
r += str(val)
|
||||
|
||||
resp = ''
|
||||
for i in range(4):
|
||||
resp += r[8 - 2*i - 2: 8 - 2*i]
|
||||
|
||||
return resp
|
||||
|
||||
def getRegister(self):
|
||||
resp = ''
|
||||
for i in range(len(CORE_REGISTER)):
|
||||
reg = self.target.readCoreRegister(i)
|
||||
resp += self.intToHexGDB(reg)
|
||||
logging.debug("GDB reg: %s = 0x%X", i, reg)
|
||||
return self.createRSPPacket(resp)
|
||||
|
||||
def lastSignal(self):
|
||||
fault = self.target.readCoreRegister('xpsr') & 0xff
|
||||
fault = FAULT[fault]
|
||||
logging.debug("GDB lastSignal: %s", fault)
|
||||
return self.createRSPPacket('S' + fault)
|
||||
|
||||
def handleQuery(self, msg):
|
||||
query = msg.split(':')
|
||||
logging.debug('GDB received query: %s', query)
|
||||
|
||||
if query is None:
|
||||
logging.error('GDB received query packet malformed')
|
||||
return None
|
||||
|
||||
if query[0] == 'Supported':
|
||||
resp = "qXfer:memory-map:read+;qXfer:features:read+;PacketSize="
|
||||
resp += hex(self.packet_size)[2:]
|
||||
return self.createRSPPacket(resp)
|
||||
|
||||
elif query[0] == 'Xfer':
|
||||
|
||||
if query[1] == 'features' and query[2] == 'read' and \
|
||||
query[3] == 'target.xml':
|
||||
data = query[4].split(',')
|
||||
resp = self.handleQueryXML('read_feature', int(data[0], 16), int(data[1].split('#')[0], 16))
|
||||
return self.createRSPPacket(resp)
|
||||
|
||||
elif query[1] == 'memory-map' and query[2] == 'read':
|
||||
data = query[4].split(',')
|
||||
resp = self.handleQueryXML('momery_map', int(data[0], 16), int(data[1].split('#')[0], 16))
|
||||
return self.createRSPPacket(resp)
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
elif query[0] == 'C#b4':
|
||||
return self.createRSPPacket("")
|
||||
|
||||
elif query[0].find('Attached') != -1:
|
||||
return self.createRSPPacket("1")
|
||||
|
||||
elif query[0].find('TStatus') != -1:
|
||||
return self.createRSPPacket("")
|
||||
|
||||
elif query[0].find('Tf') != -1:
|
||||
return self.createRSPPacket("")
|
||||
|
||||
elif 'Offsets' in query[0]:
|
||||
resp = "Text=0;Data=0;Bss=0"
|
||||
return self.createRSPPacket(resp)
|
||||
|
||||
elif 'Symbol' in query[0]:
|
||||
resp = "OK"
|
||||
return self.createRSPPacket(resp)
|
||||
|
||||
else:
|
||||
return None
|
||||
|
||||
def handleQueryXML(self, query, offset, size):
|
||||
logging.debug('GDB query %s: offset: %s, size: %s', query, offset, size)
|
||||
xml = ''
|
||||
if query == 'momery_map':
|
||||
xml = self.flash.memoryMapXML
|
||||
elif query == 'read_feature':
|
||||
xml = self.target.targetXML
|
||||
|
||||
size_xml = len(xml)
|
||||
|
||||
prefix = 'm'
|
||||
|
||||
if offset > size_xml:
|
||||
logging.error('GDB: offset target.xml > size!')
|
||||
return
|
||||
|
||||
if size > (self.packet_size - 4):
|
||||
size = self.packet_size - 4
|
||||
|
||||
nbBytesAvailable = size_xml - offset
|
||||
|
||||
if size > nbBytesAvailable:
|
||||
prefix = 'l'
|
||||
size = nbBytesAvailable
|
||||
|
||||
resp = prefix + xml[offset:offset + size]
|
||||
|
||||
return resp
|
||||
|
||||
|
||||
def createRSPPacket(self, data):
|
||||
resp = '$' + data + '#'
|
||||
|
||||
c = 0
|
||||
checksum = 0
|
||||
for c in data:
|
||||
checksum += ord(c)
|
||||
checksum = checksum % 256
|
||||
checksum = hex(checksum)
|
||||
|
||||
if int(checksum[2:], 16) < 0x10:
|
||||
resp += '0'
|
||||
resp += checksum[2:]
|
||||
|
||||
#logging.debug('--<<<<<<<<<<<< GDB rsp packet: %s', resp)
|
||||
return resp
|
||||
|
||||
def ack(self):
|
||||
self.abstract_socket.write("+")
|
|
@ -1,23 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from pyusb_backend import PyUSB
|
||||
from pywinusb_backend import PyWinUSB
|
||||
|
||||
INTERFACE = {'pyusb': PyUSB,
|
||||
'pywinusb': PyWinUSB
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
class Interface:
|
||||
|
||||
def __init__(self):
|
||||
self.vid = 0
|
||||
self.pid = 0
|
||||
self.vendor_name = ""
|
||||
self.product_name = ""
|
||||
return
|
||||
|
||||
def init(self):
|
||||
return
|
||||
|
||||
def write(self, data):
|
||||
return
|
||||
|
||||
def read(self, size = -1, timeout = -1):
|
||||
return
|
||||
|
||||
def getInfo(self):
|
||||
return self.vendor_name + " " + \
|
||||
self.product_name + " (" + \
|
||||
str(hex(self.vid)) + ", " + \
|
||||
str(hex(self.pid)) + ")"
|
||||
|
||||
def close(self):
|
||||
return
|
||||
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from interface import Interface
|
||||
import logging, os
|
||||
|
||||
try:
|
||||
import usb.core
|
||||
import usb.util
|
||||
except:
|
||||
if os.name == "posix":
|
||||
logging.error("PyUSB is required on a Linux Machine")
|
||||
|
||||
class PyUSB(Interface):
|
||||
"""
|
||||
This class provides basic functions to access
|
||||
a USB HID device using pyusb:
|
||||
- write/read an endpoint
|
||||
"""
|
||||
|
||||
vid = 0
|
||||
pid = 0
|
||||
|
||||
def __init__(self):
|
||||
self.ep_out = None
|
||||
self.ep_in = None
|
||||
self.dev = None
|
||||
|
||||
@staticmethod
|
||||
def getAllConnectedInterface(vid, pid):
|
||||
"""
|
||||
returns all the connected devices which matches PyUSB.vid/PyUSB.pid.
|
||||
returns an array of PyUSB (Interface) objects
|
||||
"""
|
||||
# find all devices matching the vid/pid specified
|
||||
all_devices = usb.core.find(find_all=True, idVendor=vid, idProduct=pid)
|
||||
|
||||
if all_devices is None:
|
||||
logging.debug("No device connected")
|
||||
return None
|
||||
|
||||
boards = []
|
||||
|
||||
# iterate on all devices found
|
||||
for board in all_devices:
|
||||
intf_number = 0
|
||||
found = False
|
||||
|
||||
# get active config
|
||||
config = board.get_active_configuration()
|
||||
|
||||
# iterate on all interfaces:
|
||||
# - if we found a HID interface -> CMSIS-DAP
|
||||
for interface in config:
|
||||
if interface.bInterfaceClass == 0x03:
|
||||
intf_number = interface.bInterfaceNumber
|
||||
found = True
|
||||
break
|
||||
|
||||
if found == False:
|
||||
continue
|
||||
|
||||
try:
|
||||
if board.is_kernel_driver_active(intf_number) is True:
|
||||
board.detach_kernel_driver(intf_number)
|
||||
except Exception as e:
|
||||
print e
|
||||
pass
|
||||
|
||||
intf = usb.util.find_descriptor(config, bInterfaceNumber = intf_number)
|
||||
ep_out = usb.util.find_descriptor(intf,
|
||||
# match the first OUT endpoint
|
||||
custom_match = \
|
||||
lambda e: \
|
||||
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||
usb.util.ENDPOINT_OUT
|
||||
)
|
||||
ep_in = usb.util.find_descriptor(intf,
|
||||
# match the first IN endpoint
|
||||
custom_match = \
|
||||
lambda e: \
|
||||
usb.util.endpoint_direction(e.bEndpointAddress) == \
|
||||
usb.util.ENDPOINT_IN
|
||||
)
|
||||
product_name = usb.util.get_string(board, 256, 2)
|
||||
vendor_name = usb.util.get_string(board, 256, 1)
|
||||
if ep_out is None or ep_in is None:
|
||||
logging.error('Endpoints not found')
|
||||
return None
|
||||
|
||||
new_board = PyUSB()
|
||||
new_board.ep_in = ep_in
|
||||
new_board.ep_out = ep_out
|
||||
new_board.dev = board
|
||||
new_board.vid = vid
|
||||
new_board.pid = pid
|
||||
new_board.product_name = product_name
|
||||
new_board.vendor_name = vendor_name
|
||||
boards.append(new_board)
|
||||
|
||||
return boards
|
||||
|
||||
def write(self, data):
|
||||
"""
|
||||
write data on the OUT endpoint associated to the HID interface
|
||||
"""
|
||||
if self.ep_out is None:
|
||||
raise ValueError('EP_OUT endpoint is NULL')
|
||||
|
||||
self.ep_out.write(data)
|
||||
#logging.debug('sent: %s', data)
|
||||
return
|
||||
|
||||
|
||||
def read(self, timeout = -1):
|
||||
"""
|
||||
read data on the IN endpoint associated to the HID interface
|
||||
"""
|
||||
if self.ep_in is None:
|
||||
raise ValueError('EP_IN endpoint is NULL')
|
||||
|
||||
data = self.ep_in.read(self.ep_in.wMaxPacketSize, timeout)
|
||||
#logging.debug('received: %s', data)
|
||||
return data
|
|
@ -1,116 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from interface import Interface
|
||||
import logging, os
|
||||
|
||||
try:
|
||||
import pywinusb.hid as hid
|
||||
except:
|
||||
if os.name == "nt":
|
||||
logging.error("PyWinUSB is required on a Windows Machine")
|
||||
|
||||
class PyWinUSB(Interface):
|
||||
"""
|
||||
This class provides basic functions to access
|
||||
a USB HID device using pywinusb:
|
||||
- write/read an endpoint
|
||||
"""
|
||||
vid = 0
|
||||
pid = 0
|
||||
|
||||
def __init__(self):
|
||||
# Vendor page and usage_id = 2
|
||||
self.report = []
|
||||
self.rcv_data = []
|
||||
self.device = None
|
||||
return
|
||||
|
||||
# handler called when a report is received
|
||||
def rx_handler(self, data):
|
||||
#logging.debug("rcv: %s", data[1:])
|
||||
self.rcv_data.append(data[1:])
|
||||
|
||||
def open(self):
|
||||
self.device.set_raw_data_handler(self.rx_handler)
|
||||
self.device.open()
|
||||
|
||||
@staticmethod
|
||||
def getAllConnectedInterface(vid, pid):
|
||||
"""
|
||||
returns all the connected devices which matches PyWinUSB.vid/PyWinUSB.pid.
|
||||
returns an array of PyWinUSB (Interface) objects
|
||||
"""
|
||||
all_devices = hid.find_all_hid_devices()
|
||||
|
||||
# find devices with good vid/pid
|
||||
all_mbed_devices = []
|
||||
for d in all_devices:
|
||||
if (d.vendor_id == vid) and (d.product_id == pid):
|
||||
all_mbed_devices.append(d)
|
||||
|
||||
if not all_mbed_devices:
|
||||
logging.debug("No Mbed device connected")
|
||||
return
|
||||
|
||||
boards = []
|
||||
for dev in all_mbed_devices:
|
||||
try:
|
||||
dev.open()
|
||||
report = dev.find_output_reports()
|
||||
if (len(report) == 1):
|
||||
new_board = PyWinUSB()
|
||||
new_board.report = report[0]
|
||||
new_board.vendor_name = dev.vendor_name
|
||||
new_board.product_name = dev.product_name
|
||||
new_board.vid = dev.vendor_id
|
||||
new_board.pid = dev.product_id
|
||||
new_board.device = dev
|
||||
new_board.device.set_raw_data_handler(new_board.rx_handler)
|
||||
|
||||
boards.append(new_board)
|
||||
except Exception as e:
|
||||
logging.error("Receiving Exception: %s", e)
|
||||
dev.close()
|
||||
|
||||
return boards
|
||||
|
||||
def write(self, data):
|
||||
"""
|
||||
write data on the OUT endpoint associated to the HID interface
|
||||
"""
|
||||
for _ in range(64 - len(data)):
|
||||
data.append(0)
|
||||
#logging.debug("send: %s", data)
|
||||
self.report.send([0] + data)
|
||||
return
|
||||
|
||||
|
||||
def read(self, timeout = -1):
|
||||
"""
|
||||
read data on the IN endpoint associated to the HID interface
|
||||
"""
|
||||
while len(self.rcv_data) == 0:
|
||||
pass
|
||||
return self.rcv_data.pop(0)
|
||||
|
||||
def close(self):
|
||||
"""
|
||||
close the interface
|
||||
"""
|
||||
logging.debug("closing interface")
|
||||
self.device.close()
|
|
@ -1,29 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import cortex_m
|
||||
import target_lpc1768
|
||||
import target_kl25z
|
||||
import target_lpc11u24
|
||||
import target_lpc800
|
||||
|
||||
TARGET = {'cortex_m': cortex_m.CortexM,
|
||||
'target_lpc1768': target_lpc1768.LPC1768,
|
||||
'target_kl25z': target_kl25z.KL25Z,
|
||||
'target_lpc11u24': target_lpc11u24.LPC11U24,
|
||||
'target_lpc800': target_lpc800.LPC800,
|
||||
}
|
|
@ -1,554 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from pyOCD.target.target import Target
|
||||
from pyOCD.target.target import TARGET_RUNNING, TARGET_HALTED
|
||||
from pyOCD.transport.cmsis_dap import DP_REG
|
||||
import logging
|
||||
|
||||
# Debug Halting Control and Status Register
|
||||
DHCSR = 0xE000EDF0
|
||||
# Debug Core Register Selector Register
|
||||
DCRSR = 0xE000EDF4
|
||||
REGWnR = (1 << 16)
|
||||
# Debug Core Register Data Register
|
||||
DCRDR = 0xE000EDF8
|
||||
# Debug Exception and Monitor Control Register
|
||||
DEMCR = 0xE000EDFC
|
||||
TRACE_ENA = (1 << 24)
|
||||
VC_HARDERR = (1 << 9)
|
||||
VC_BUSERR = (1 << 8)
|
||||
VC_CORERESET = (1 << 0)
|
||||
|
||||
NVIC_AIRCR = (0xE000ED0C)
|
||||
NVIC_AIRCR_VECTKEY = (0x5FA << 16)
|
||||
NVIC_AIRCR_VECTRESET = (1 << 0)
|
||||
NVIC_AIRCR_SYSRESETREQ = (1 << 2)
|
||||
|
||||
CSYSPWRUPACK = 0x80000000
|
||||
CDBGPWRUPACK = 0x20000000
|
||||
CSYSPWRUPREQ = 0x40000000
|
||||
CDBGPWRUPREQ = 0x10000000
|
||||
|
||||
TRNNORMAL = 0x00000000
|
||||
MASKLANE = 0x00000f00
|
||||
|
||||
C_DEBUGEN = (1 << 0)
|
||||
C_HALT = (1 << 1)
|
||||
C_STEP = (1 << 2)
|
||||
C_MASKINTS = (1 << 3)
|
||||
C_SNAPSTALL = (1 << 4)
|
||||
DBGKEY = (0xA05F << 16)
|
||||
|
||||
# FPB (breakpoint)
|
||||
FP_CTRL = (0xE0002000)
|
||||
FP_CTRL_KEY = (1 << 1)
|
||||
FP_COMP0 = (0xE0002008)
|
||||
|
||||
CORE_REGISTER = {'r0': 0,
|
||||
'r1': 1,
|
||||
'r2': 2,
|
||||
'r3': 3,
|
||||
'r4': 4,
|
||||
'r5': 5,
|
||||
'r6': 6,
|
||||
'r7': 7,
|
||||
'r8': 8,
|
||||
'r9': 9,
|
||||
'r10': 10,
|
||||
'r11': 11,
|
||||
'r12': 12,
|
||||
'sp': 13,
|
||||
'lr': 14,
|
||||
'pc': 15,
|
||||
'xpsr': 16,
|
||||
}
|
||||
|
||||
targetXML = "<?xml version=\"1.0\"?>\n" \
|
||||
"<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n" \
|
||||
"<target>\n" \
|
||||
"<feature name=\"org.gnu.gdb.arm.m-profile\">\n" \
|
||||
"<reg name=\"r0\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r1\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r2\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r3\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r4\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r5\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r6\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r7\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r8\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r9\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r10\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r11\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"r12\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"sp\" bitsize=\"32\" type=\"data_ptr\"/>\n" \
|
||||
"<reg name=\"lr\" bitsize=\"32\"/>\n" \
|
||||
"<reg name=\"pc\" bitsize=\"32\" type=\"code_ptr\"/>\n" \
|
||||
"<reg name=\"xpsr\" bitsize=\"32\" regnum=\"16\"/>\n" \
|
||||
"</feature>\n" \
|
||||
"</target>\n"
|
||||
|
||||
"""
|
||||
convert a byte array into a word array
|
||||
"""
|
||||
def byte2word(data):
|
||||
res = []
|
||||
for i in range(len(data)/4):
|
||||
res.append(data[i*4 + 0] << 0 |
|
||||
data[i*4 + 1] << 8 |
|
||||
data[i*4 + 2] << 16 |
|
||||
data[i*4 + 3] << 24)
|
||||
return res
|
||||
|
||||
"""
|
||||
convert a word array into a byte array
|
||||
"""
|
||||
def word2byte(data):
|
||||
res = []
|
||||
for x in data:
|
||||
res.append((x >> 0) & 0xff)
|
||||
res.append((x >> 8) & 0xff)
|
||||
res.append((x >> 16) & 0xff)
|
||||
res.append((x >> 24) & 0xff)
|
||||
return res
|
||||
|
||||
|
||||
class Breakpoint():
|
||||
def __init__(self, comp_register_addr):
|
||||
self.comp_register_addr = comp_register_addr
|
||||
self.enabled = False
|
||||
self.addr = 0
|
||||
|
||||
|
||||
class CortexM(Target):
|
||||
|
||||
"""
|
||||
This class has basic functions to access a Cortex M core:
|
||||
- init
|
||||
- read/write memory
|
||||
- read/write core registers
|
||||
- set/remove hardware breakpoints
|
||||
"""
|
||||
|
||||
def __init__(self, transport):
|
||||
self.transport = transport
|
||||
self.auto_increment_page_size = 0
|
||||
self.idcode = 0
|
||||
self.breakpoints = []
|
||||
self.nb_code = 0
|
||||
self.num_breakpoint_used = 0
|
||||
self.nb_lit = 0
|
||||
self.fpb_enabled = False
|
||||
self.targetXML = targetXML
|
||||
return
|
||||
|
||||
def init(self, setup_fpb = True):
|
||||
"""
|
||||
Cortex M initialization
|
||||
"""
|
||||
self.idcode = self.readIDCode()
|
||||
# select bank 0 (to access DRW and TAR)
|
||||
self.transport.writeDP(DP_REG['SELECT'], 0)
|
||||
self.transport.writeDP(DP_REG['CTRL_STAT'], CSYSPWRUPREQ | CDBGPWRUPREQ)
|
||||
|
||||
while True:
|
||||
r = self.transport.readDP(DP_REG['CTRL_STAT'])
|
||||
if (r & (CDBGPWRUPACK | CSYSPWRUPACK)) == (CDBGPWRUPACK | CSYSPWRUPACK):
|
||||
break
|
||||
|
||||
self.transport.writeDP(DP_REG['CTRL_STAT'], CSYSPWRUPREQ | CDBGPWRUPREQ | TRNNORMAL | MASKLANE)
|
||||
self.transport.writeDP(DP_REG['SELECT'], 0)
|
||||
|
||||
if setup_fpb:
|
||||
self.halt()
|
||||
self.setupFPB()
|
||||
|
||||
return
|
||||
|
||||
def setupFPB(self):
|
||||
"""
|
||||
Reads the number of hardware breakpoints available on the core
|
||||
and disable the FPB (Flash Patch and Breakpoint Unit)
|
||||
which will be enabled when a first breakpoint will be set
|
||||
"""
|
||||
# setup FPB (breakpoint)
|
||||
fpcr = self.readMemory(FP_CTRL)
|
||||
self.nb_code = ((fpcr >> 8) & 0x70) | ((fpcr >> 4) & 0xF)
|
||||
logging.info("%d hardware breakpoints", self.nb_code)
|
||||
for i in range(self.nb_code):
|
||||
self.breakpoints.append(Breakpoint(FP_COMP0 + 4*i))
|
||||
|
||||
# disable FPB (will be enabled on first bp set)
|
||||
self.disableFPB()
|
||||
for bp in self.breakpoints:
|
||||
self.writeMemory(bp.comp_register_addr, 0)
|
||||
|
||||
def info(self, request):
|
||||
return self.transport.info(request)
|
||||
|
||||
def readIDCode(self):
|
||||
"""
|
||||
return the IDCODE of the core
|
||||
"""
|
||||
if self.idcode == 0:
|
||||
self.idcode = self.transport.readDP(DP_REG['IDCODE'])
|
||||
return self.idcode
|
||||
|
||||
def writeMemory(self, addr, value, transfer_size = 32):
|
||||
"""
|
||||
write a memory location.
|
||||
By default the transfer size is a word
|
||||
"""
|
||||
self.transport.writeMem(addr, value, transfer_size)
|
||||
return
|
||||
|
||||
def readMemory(self, addr, transfer_size = 32):
|
||||
"""
|
||||
read a memory location. By default, a word will
|
||||
be read
|
||||
"""
|
||||
return self.transport.readMem(addr, transfer_size)
|
||||
|
||||
def readBlockMemoryUnaligned8(self, addr, size):
|
||||
"""
|
||||
read a block of unaligned bytes in memory. Returns
|
||||
an array of byte values
|
||||
"""
|
||||
res = []
|
||||
|
||||
# try to read 8bits data
|
||||
if (size > 0) and (addr & 0x01):
|
||||
mem = self.readMemory(addr, 8)
|
||||
logging.debug("get 1 byte at %s: 0x%X", hex(addr), mem)
|
||||
res.append(mem)
|
||||
size -= 1
|
||||
addr += 1
|
||||
|
||||
# try to read 16bits data
|
||||
if (size > 1) and (addr & 0x02):
|
||||
mem = self.readMemory(addr, 16)
|
||||
logging.debug("get 2 bytes at %s: 0x%X", hex(addr), mem)
|
||||
res.append(mem & 0xff)
|
||||
res.append((mem >> 8) & 0xff)
|
||||
size -= 2
|
||||
addr += 2
|
||||
|
||||
# try to read aligned block of 32bits
|
||||
if (size >= 4):
|
||||
logging.debug("read blocks aligned at 0x%X, size: 0x%X", addr, (size/4)*4)
|
||||
mem = self.readBlockMemoryAligned32(addr, size/4)
|
||||
res += word2byte(mem)
|
||||
size -= 4*len(mem)
|
||||
addr += 4*len(mem)
|
||||
|
||||
if (size > 1):
|
||||
mem = self.readMemory(addr, 16)
|
||||
logging.debug("get 2 bytes at %s: 0x%X", hex(addr), mem)
|
||||
res.append(mem & 0xff)
|
||||
res.append((mem >> 8) & 0xff)
|
||||
size -= 2
|
||||
addr += 2
|
||||
|
||||
if (size > 0):
|
||||
mem = self.readMemory(addr, 8)
|
||||
logging.debug("get 1 byte remaining at %s: 0x%X", hex(addr), mem)
|
||||
res.append(mem)
|
||||
size -= 1
|
||||
addr += 1
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def writeBlockMemoryUnaligned8(self, addr, data):
|
||||
"""
|
||||
write a block of unaligned bytes in memory.
|
||||
"""
|
||||
size = len(data)
|
||||
idx = 0
|
||||
|
||||
#try to write 8 bits data
|
||||
if (size > 0) and (addr & 0x01):
|
||||
logging.debug("write 1 byte at 0x%X: 0x%X", addr, data[idx])
|
||||
self.writeMemory(addr, data[idx], 8)
|
||||
size -= 1
|
||||
addr += 1
|
||||
idx += 1
|
||||
|
||||
# try to write 16 bits data
|
||||
if (size > 1) and (addr & 0x02):
|
||||
logging.debug("write 2 bytes at 0x%X: 0x%X", addr, data[idx] | (data[idx+1] << 8))
|
||||
self.writeMemory(addr, data[idx] | (data[idx+1] << 8), 16)
|
||||
size -= 2
|
||||
addr += 2
|
||||
idx += 2
|
||||
|
||||
# write aligned block of 32 bits
|
||||
if (size >= 4):
|
||||
logging.debug("write blocks aligned at 0x%X, size: 0x%X", addr, (size/4)*4)
|
||||
data32 = byte2word(data[idx:idx + (size & ~0x03)])
|
||||
self.writeBlockMemoryAligned32(addr, data32)
|
||||
addr += size & ~0x03
|
||||
idx += size & ~0x03
|
||||
size -= size & ~0x03
|
||||
|
||||
# try to write 16 bits data
|
||||
if (size > 1):
|
||||
logging.debug("write 2 bytes at 0x%X: 0x%X", addr, data[idx] | (data[idx+1] << 8))
|
||||
self.writeMemory(addr, data[idx] | (data[idx+1] << 8), 16)
|
||||
size -= 2
|
||||
addr += 2
|
||||
idx += 2
|
||||
|
||||
#try to write 8 bits data
|
||||
if (size > 0):
|
||||
logging.debug("write 1 byte at 0x%X: 0x%X", addr, data[idx])
|
||||
self.writeMemory(addr, data[idx], 8)
|
||||
size -= 1
|
||||
addr += 1
|
||||
idx += 1
|
||||
|
||||
return
|
||||
|
||||
def writeBlockMemoryAligned32(self, addr, data):
|
||||
"""
|
||||
write a block of aligned words in memory.
|
||||
"""
|
||||
size = len(data)
|
||||
while size > 0:
|
||||
n = self.auto_increment_page_size - (addr & (self.auto_increment_page_size - 1))
|
||||
if size*4 < n:
|
||||
n = (size*4) & 0xfffffffc
|
||||
self.transport.writeBlock32(addr, data[:n/4])
|
||||
data = data[n/4:]
|
||||
size -= n/4
|
||||
addr += n
|
||||
return
|
||||
|
||||
def readBlockMemoryAligned32(self, addr, size):
|
||||
"""
|
||||
read a block of aligned words in memory. Returns
|
||||
an array of word values
|
||||
"""
|
||||
resp = []
|
||||
while size > 0:
|
||||
n = self.auto_increment_page_size - (addr & (self.auto_increment_page_size - 1))
|
||||
if size*4 < n:
|
||||
n = (size*4) & 0xfffffffc
|
||||
resp += self.transport.readBlock32(addr, n/4)
|
||||
size -= n/4
|
||||
addr += n
|
||||
return resp
|
||||
|
||||
def halt(self):
|
||||
"""
|
||||
halt the core
|
||||
"""
|
||||
self.writeMemory(DHCSR, DBGKEY | C_DEBUGEN | C_HALT)
|
||||
return
|
||||
|
||||
def step(self):
|
||||
"""
|
||||
perform an instruction level step
|
||||
"""
|
||||
if self.getState() != TARGET_HALTED:
|
||||
logging.debug('cannot step: target not halted')
|
||||
return
|
||||
if self.maybeSkipBreakpoint() is None:
|
||||
self.writeMemory(DHCSR, DBGKEY | C_DEBUGEN | C_STEP)
|
||||
return
|
||||
|
||||
def reset(self):
|
||||
"""
|
||||
reset a core. After a call to this function, the core
|
||||
is running
|
||||
"""
|
||||
self.transport.reset()
|
||||
|
||||
def resetStopOnReset(self):
|
||||
"""
|
||||
perform a reset and stop the core on the reset handler
|
||||
"""
|
||||
logging.debug("reset stop on Reset")
|
||||
# read address of reset handler
|
||||
reset_handler = self.readMemory(4)
|
||||
|
||||
# reset and halt the target
|
||||
self.transport.reset()
|
||||
self.halt()
|
||||
|
||||
# set a breakpoint to the reset handler and reset the target
|
||||
self.setBreakpoint(reset_handler)
|
||||
self.transport.reset()
|
||||
|
||||
# wait until the bp is reached
|
||||
while (self.getState() == TARGET_RUNNING):
|
||||
pass
|
||||
|
||||
# remove the breakpoint
|
||||
self.removeBreakpoint(reset_handler)
|
||||
|
||||
logging.debug("stopped on reset handler: 0x%X", reset_handler)
|
||||
|
||||
def setTargetState(self, state):
|
||||
if state == "PROGRAM":
|
||||
self.reset()
|
||||
self.writeMemory(DHCSR, DBGKEY | C_DEBUGEN)
|
||||
self.writeMemory(DEMCR, VC_CORERESET)
|
||||
self.writeMemory(NVIC_AIRCR, NVIC_AIRCR_VECTKEY | NVIC_AIRCR_SYSRESETREQ)
|
||||
while self.getState() == TARGET_RUNNING:
|
||||
pass
|
||||
self.writeMemory(DEMCR, 0)
|
||||
|
||||
|
||||
def getState(self):
|
||||
dhcsr = self.readMemory(DHCSR)
|
||||
if dhcsr & (C_STEP | C_HALT):
|
||||
return TARGET_HALTED
|
||||
return TARGET_RUNNING
|
||||
|
||||
def resume(self):
|
||||
"""
|
||||
resume the execution
|
||||
"""
|
||||
if self.getState() != TARGET_HALTED:
|
||||
logging.debug('cannot resume: target not halted')
|
||||
return
|
||||
self.maybeSkipBreakpoint()
|
||||
self.writeMemory(DHCSR, DBGKEY | C_DEBUGEN)
|
||||
return
|
||||
|
||||
def maybeSkipBreakpoint(self):
|
||||
pc = self.readCoreRegister('pc')
|
||||
bp = self.findBreakpoint(pc)
|
||||
if bp is not None:
|
||||
logging.debug('skip/resume breakpoint: pc 0x%X', pc)
|
||||
self.removeBreakpoint(pc)
|
||||
self.writeMemory(DHCSR, DBGKEY | C_DEBUGEN | C_STEP)
|
||||
self.setBreakpoint(pc)
|
||||
logging.debug('step over breakpoint: now pc0x%X', self.readCoreRegister('pc'))
|
||||
return bp
|
||||
return None
|
||||
|
||||
def findBreakpoint(self, addr):
|
||||
for bp in self.breakpoints:
|
||||
if bp.enabled and bp.addr == addr:
|
||||
return bp
|
||||
return None
|
||||
|
||||
def readCoreRegister(self, reg):
|
||||
"""
|
||||
read a core register (r0 .. r16).
|
||||
If reg is a string, find the number associated to this register
|
||||
in the lookup table CORE_REGISTER
|
||||
"""
|
||||
if isinstance(reg, str):
|
||||
try:
|
||||
reg = CORE_REGISTER[reg]
|
||||
except KeyError:
|
||||
logging.error('cannot find %s core register', id)
|
||||
return
|
||||
|
||||
if (reg < 0) or (reg > len(CORE_REGISTER)):
|
||||
logging.error("unknown reg: %d", reg)
|
||||
return
|
||||
|
||||
# write id in DCRSR
|
||||
self.writeMemory(DCRSR, reg)
|
||||
# read DCRDR
|
||||
return self.readMemory(DCRDR)
|
||||
|
||||
|
||||
def writeCoreRegister(self, reg, data):
|
||||
"""
|
||||
write a core register (r0 .. r16)
|
||||
If reg is a string, find the number associated to this register
|
||||
in the lookup table CORE_REGISTER
|
||||
"""
|
||||
if isinstance(reg, str):
|
||||
try:
|
||||
reg = CORE_REGISTER[reg]
|
||||
except KeyError:
|
||||
logging.error('cannot find %s core register', id)
|
||||
return
|
||||
|
||||
if (reg < 0) or (reg > len(CORE_REGISTER)):
|
||||
logging.error("unknown reg: %d", reg)
|
||||
return
|
||||
|
||||
# write id in DCRSR
|
||||
self.writeMemory(DCRDR, data)
|
||||
# read DCRDR
|
||||
self.writeMemory(DCRSR, reg | REGWnR)
|
||||
return
|
||||
|
||||
|
||||
def setBreakpoint(self, addr):
|
||||
"""
|
||||
set a hardware breakpoint at a specific location in flash
|
||||
"""
|
||||
if self.fpb_enabled is False:
|
||||
self.enableFPB()
|
||||
|
||||
if self.availableBreakpoint() == 0:
|
||||
logging.error('No more available breakpoint!!, dropped bp at 0x%X', addr)
|
||||
return False
|
||||
|
||||
for bp in self.breakpoints:
|
||||
if not bp.enabled:
|
||||
bp.enabled = True
|
||||
bp_match = (1 << 30)
|
||||
if addr & 0x2:
|
||||
bp_match = (2 << 30)
|
||||
self.writeMemory(bp.comp_register_addr, addr & 0x1ffffffc | bp_match | 1)
|
||||
bp.addr = addr
|
||||
self.num_breakpoint_used += 1
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def availableBreakpoint(self):
|
||||
return len(self.breakpoints) - self.num_breakpoint_used
|
||||
|
||||
def enableFPB(self):
|
||||
self.writeMemory(FP_CTRL, FP_CTRL_KEY | 1)
|
||||
self.fpb_enabled = True
|
||||
logging.debug('fpb has been enabled')
|
||||
return
|
||||
|
||||
def disableFPB(self):
|
||||
self.writeMemory(FP_CTRL, FP_CTRL_KEY | 0)
|
||||
self.fpb_enabled = False
|
||||
logging.debug('fpb has been disabled')
|
||||
return
|
||||
|
||||
def removeBreakpoint(self, addr):
|
||||
"""
|
||||
remove a hardware breakpoint at a specific location in flash
|
||||
"""
|
||||
for bp in self.breakpoints:
|
||||
if bp.enabled and bp.addr == addr:
|
||||
bp.enabled = False
|
||||
self.writeMemory(bp.comp_register_addr, 0)
|
||||
bp.addr = addr
|
||||
self.num_breakpoint_used -= 1
|
||||
return
|
||||
return
|
||||
|
||||
# GDB functions
|
||||
def getTargetXML(self):
|
||||
return self.targetXML, len(self.targetXML)
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
TARGET_RUNNING = (1 << 0)
|
||||
TARGET_HALTED = (1 << 1)
|
||||
|
||||
class Target():
|
||||
|
||||
def __init__(self, transport):
|
||||
return
|
||||
|
||||
def init(self):
|
||||
return
|
||||
|
||||
def info(self, request):
|
||||
return
|
||||
|
||||
def readIDCode(self):
|
||||
return
|
||||
|
||||
def halt(self):
|
||||
return
|
||||
|
||||
def step(self):
|
||||
return
|
||||
|
||||
def resume(self):
|
||||
return
|
||||
|
||||
def writeMemory(self, addr, value, transfer_size = 32):
|
||||
return
|
||||
|
||||
def readMemory(self, addr, transfer_size = 32):
|
||||
return
|
||||
|
||||
def writeBlockMemoryUnaligned8(self, addr, value):
|
||||
return
|
||||
|
||||
def writeBlockMemoryAligned32(self, addr, data):
|
||||
return
|
||||
|
||||
def readBlockMemoryUnaligned8(self, addr, size):
|
||||
return
|
||||
|
||||
def readBlockMemoryAligned32(self, addr, size):
|
||||
return
|
||||
|
||||
def readCoreRegister(self, id):
|
||||
return
|
||||
|
||||
def writeCoreRegister(self, id):
|
||||
return
|
||||
|
||||
def setBreakpoint(self, addr):
|
||||
return
|
||||
|
||||
def removeBreakpoint(self, addr):
|
||||
return
|
||||
|
||||
def reset(self):
|
||||
return
|
||||
|
||||
def getState(self):
|
||||
return
|
||||
|
||||
# GDB functions
|
||||
def getTargetXML(self):
|
||||
return
|
|
@ -1,57 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cortex_m import CortexM
|
||||
import logging
|
||||
|
||||
|
||||
MDM_STATUS = 0x01000000
|
||||
MDM_CTRL = 0x01000004
|
||||
MDM_IDR = 0x010000fc
|
||||
|
||||
class KL25Z(CortexM):
|
||||
|
||||
def __init__(self, transport):
|
||||
CortexM.__init__(self, transport)
|
||||
self.auto_increment_page_size = 0x400
|
||||
|
||||
def init(self):
|
||||
CortexM.init(self, False)
|
||||
|
||||
# check for flash security
|
||||
val = self.transport.readAP(MDM_IDR)
|
||||
if val != 0x001c0020:
|
||||
logging.error("KL25Z: bad flash ID")
|
||||
val = self.transport.readAP(MDM_STATUS)
|
||||
if (val & (1 << 2)):
|
||||
logging.warning("KL25Z secure state: will try to unlock")
|
||||
self.transport.assertReset(True)
|
||||
while True:
|
||||
self.transport.writeAP(MDM_CTRL, 1)
|
||||
val = self.transport.readAP(MDM_STATUS)
|
||||
logging.info(val)
|
||||
if (val & 1):
|
||||
break
|
||||
while True:
|
||||
self.transport.writeAP(MDM_CTRL, 0)
|
||||
val = self.transport.readAP(MDM_CTRL)
|
||||
if (val == 0):
|
||||
break
|
||||
|
||||
logging.info("KL25Z not in secure state")
|
||||
self.halt()
|
||||
self.setupFPB()
|
|
@ -1,24 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cortex_m import CortexM
|
||||
|
||||
class LPC11U24(CortexM):
|
||||
|
||||
def __init__(self, transport):
|
||||
CortexM.__init__(self, transport)
|
||||
self.auto_increment_page_size = 0x400
|
|
@ -1,40 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cortex_m import CortexM
|
||||
|
||||
class LPC1768(CortexM):
|
||||
|
||||
def __init__(self, transport):
|
||||
CortexM.__init__(self, transport)
|
||||
self.auto_increment_page_size = 0x1000
|
||||
|
||||
|
||||
def reset(self):
|
||||
# halt processor
|
||||
self.halt()
|
||||
# not remap 0x0000-0x0020 to anything but the flash
|
||||
self.writeMemory(0x400FC040, 1)
|
||||
CortexM.reset(self)
|
||||
|
||||
def resetStopOnReset(self):
|
||||
# halt processor
|
||||
self.halt()
|
||||
# not remap 0x0000-0x0020 to anything but the flash
|
||||
self.writeMemory(0x400FC040, 1)
|
||||
CortexM.resetStopOnReset(self)
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cortex_m import CortexM
|
||||
|
||||
class LPC800(CortexM):
|
||||
|
||||
def __init__(self, transport):
|
||||
CortexM.__init__(self, transport)
|
||||
self.auto_increment_page_size = 0x400
|
|
@ -1,21 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cmsis_dap import CMSIS_DAP
|
||||
|
||||
TRANSPORT = {'cmsis_dap': CMSIS_DAP
|
||||
}
|
|
@ -1,229 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from cmsis_dap_core import dapTransferBlock, dapWriteAbort, dapSWJPins, dapConnect, dapDisconnect, dapTransfer, dapSWJSequence, dapSWDConfigure, dapSWJClock, dapTransferConfigure, dapInfo
|
||||
from transport import Transport
|
||||
import logging
|
||||
from time import sleep
|
||||
|
||||
# !! This value are A[2:3] and not A[3:2]
|
||||
DP_REG = {'IDCODE' : 0x00,
|
||||
'ABORT' : 0x00,
|
||||
'CTRL_STAT': 0x04,
|
||||
'SELECT': 0x08
|
||||
}
|
||||
AP_REG = {'CSW' : 0x00,
|
||||
'TAR' : 0x04,
|
||||
'DRW' : 0x0C
|
||||
}
|
||||
|
||||
IDCODE = 0 << 2
|
||||
AP_ACC = 1 << 0
|
||||
DP_ACC = 0 << 0
|
||||
READ = 1 << 1
|
||||
WRITE = 0 << 1
|
||||
VALUE_MATCH = 1 << 4
|
||||
MATCH_MASK = 1 << 5
|
||||
|
||||
APBANKSEL = 0x000000f0
|
||||
|
||||
# AP Control and Status Word definitions
|
||||
CSW_SIZE = 0x00000007
|
||||
CSW_SIZE8 = 0x00000000
|
||||
CSW_SIZE16 = 0x00000001
|
||||
CSW_SIZE32 = 0x00000002
|
||||
CSW_ADDRINC = 0x00000030
|
||||
CSW_NADDRINC = 0x00000000
|
||||
CSW_SADDRINC = 0x00000010
|
||||
CSW_PADDRINC = 0x00000020
|
||||
CSW_DBGSTAT = 0x00000040
|
||||
CSW_TINPROG = 0x00000080
|
||||
CSW_HPROT = 0x02000000
|
||||
CSW_MSTRTYPE = 0x20000000
|
||||
CSW_MSTRCORE = 0x00000000
|
||||
CSW_MSTRDBG = 0x20000000
|
||||
CSW_RESERVED = 0x01000000
|
||||
|
||||
CSW_VALUE = (CSW_RESERVED | CSW_MSTRDBG | CSW_HPROT | CSW_DBGSTAT | CSW_SADDRINC)
|
||||
|
||||
TRANSFER_SIZE = {8: CSW_SIZE8,
|
||||
16: CSW_SIZE16,
|
||||
32: CSW_SIZE32
|
||||
}
|
||||
|
||||
|
||||
def JTAG2SWD(interface):
|
||||
data = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
|
||||
dapSWJSequence(interface, data)
|
||||
|
||||
data = [0x9e, 0xe7]
|
||||
dapSWJSequence(interface, data)
|
||||
|
||||
data = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
|
||||
dapSWJSequence(interface, data)
|
||||
|
||||
data = [0x00]
|
||||
dapSWJSequence(interface, data)
|
||||
|
||||
class CMSIS_DAP(Transport):
|
||||
"""
|
||||
This class implements the CMSIS-DAP protocol
|
||||
"""
|
||||
def __init__(self, interface):
|
||||
self.interface = interface
|
||||
self.packet_max_count = 0
|
||||
self.packet_max_size = 0
|
||||
self.csw = -1
|
||||
self.dp_select = -1
|
||||
return
|
||||
|
||||
def init(self):
|
||||
# init dap IO
|
||||
dapConnect(self.interface)
|
||||
# set clock freq at 1000000Hz
|
||||
dapSWJClock(self.interface)
|
||||
# configure transfer
|
||||
dapTransferConfigure(self.interface)
|
||||
# configure swd protocol
|
||||
dapSWDConfigure(self.interface)
|
||||
# switch from jtag to swd
|
||||
JTAG2SWD(self.interface)
|
||||
# read ID code
|
||||
logging.info('IDCODE: 0x%X', self.readDP(DP_REG['IDCODE']))
|
||||
# clear abort err
|
||||
dapWriteAbort(self.interface, 0x1e);
|
||||
return
|
||||
|
||||
def uninit(self):
|
||||
dapDisconnect(self.interface)
|
||||
return
|
||||
|
||||
def info(self, request):
|
||||
resp = None
|
||||
try:
|
||||
resp = dapInfo(self.interface, request)
|
||||
except KeyError:
|
||||
logging.error('request %s not supported', request)
|
||||
return resp
|
||||
|
||||
def writeMem(self, addr, data, transfer_size = 32):
|
||||
self.writeAP(AP_REG['CSW'], CSW_VALUE | TRANSFER_SIZE[transfer_size])
|
||||
|
||||
if transfer_size == 8:
|
||||
data = data << ((addr & 0x03) << 3)
|
||||
elif transfer_size == 16:
|
||||
data = data << ((addr & 0x02) << 3)
|
||||
|
||||
dapTransfer(self.interface, 2, [WRITE | AP_ACC | AP_REG['TAR'],
|
||||
WRITE | AP_ACC | AP_REG['DRW']],
|
||||
[addr, data])
|
||||
|
||||
def readMem(self, addr, transfer_size = 32):
|
||||
self.writeAP(AP_REG['CSW'], CSW_VALUE | TRANSFER_SIZE[transfer_size])
|
||||
|
||||
resp = dapTransfer(self.interface, 2, [WRITE | AP_ACC | AP_REG['TAR'],
|
||||
READ | AP_ACC | AP_REG['DRW']],
|
||||
[addr])
|
||||
|
||||
res = (resp[0] << 0) | \
|
||||
(resp[1] << 8) | \
|
||||
(resp[2] << 16) | \
|
||||
(resp[3] << 24)
|
||||
|
||||
if transfer_size == 8:
|
||||
res = (res >> ((addr & 0x03) << 3) & 0xff)
|
||||
elif transfer_size == 16:
|
||||
res = (res >> ((addr & 0x02) << 3) & 0xffff)
|
||||
|
||||
return res
|
||||
|
||||
# write aligned word ("data" are words)
|
||||
def writeBlock32(self, addr, data):
|
||||
# put address in TAR
|
||||
self.writeAP(AP_REG['CSW'], CSW_VALUE | CSW_SIZE32)
|
||||
self.writeAP(AP_REG['TAR'], addr)
|
||||
dapTransferBlock(self.interface, len(data), WRITE | AP_ACC | AP_REG['DRW'], data)
|
||||
return
|
||||
|
||||
# read aligned word (the size is in words)
|
||||
def readBlock32(self, addr, size):
|
||||
# put address in TAR
|
||||
self.writeAP(AP_REG['CSW'], CSW_VALUE | CSW_SIZE32)
|
||||
self.writeAP(AP_REG['TAR'], addr)
|
||||
data = []
|
||||
resp = dapTransferBlock(self.interface, size, READ | AP_ACC | AP_REG['DRW'])
|
||||
for i in range(len(resp)/4):
|
||||
data.append( (resp[i*4 + 0] << 0) | \
|
||||
(resp[i*4 + 1] << 8) | \
|
||||
(resp[i*4 + 2] << 16) | \
|
||||
(resp[i*4 + 3] << 24))
|
||||
return data
|
||||
|
||||
|
||||
def readDP(self, addr):
|
||||
resp = dapTransfer(self.interface, 1, [READ | DP_ACC | (addr & 0x0c)])
|
||||
return (resp[0] << 0) | \
|
||||
(resp[1] << 8) | \
|
||||
(resp[2] << 16) | \
|
||||
(resp[3] << 24)
|
||||
|
||||
def writeDP(self, addr, data):
|
||||
if addr == DP_REG['SELECT']:
|
||||
if data == self.dp_select:
|
||||
return
|
||||
self.dp_select = data
|
||||
|
||||
dapTransfer(self.interface, 1, [WRITE | DP_ACC | (addr & 0x0c)], [data])
|
||||
return True
|
||||
|
||||
def writeAP(self, addr, data):
|
||||
if addr == AP_REG['CSW']:
|
||||
if data == self.csw:
|
||||
return
|
||||
self.csw = data
|
||||
|
||||
ap_sel = addr & 0xff000000
|
||||
bank_sel = addr & APBANKSEL
|
||||
|
||||
self.writeDP(DP_REG['SELECT'], ap_sel | bank_sel)
|
||||
dapTransfer(self.interface, 1, [WRITE | AP_ACC | (addr & 0x0c)], [data])
|
||||
return True
|
||||
|
||||
def readAP(self, addr):
|
||||
ap_sel = addr & 0xff000000
|
||||
bank_sel = addr & APBANKSEL
|
||||
|
||||
self.writeDP(DP_REG['SELECT'], ap_sel | bank_sel)
|
||||
resp = dapTransfer(self.interface, 1, [READ | AP_ACC | (addr & 0x0c)])
|
||||
return (resp[0] << 0) | \
|
||||
(resp[1] << 8) | \
|
||||
(resp[2] << 16) | \
|
||||
(resp[3] << 24)
|
||||
|
||||
def reset(self):
|
||||
dapSWJPins(self.interface, 0, 'nRESET')
|
||||
sleep(0.1)
|
||||
dapSWJPins(self.interface, 0x80, 'nRESET')
|
||||
sleep(0.1)
|
||||
|
||||
def assertReset(self, asserted):
|
||||
if asserted:
|
||||
dapSWJPins(self.interface, 0, 'nRESET')
|
||||
else:
|
||||
dapSWJPins(self.interface, 0x80, 'nRESET')
|
||||
|
||||
|
|
@ -1,315 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import array
|
||||
|
||||
COMMAND_ID = {'DAP_INFO': 0x00,
|
||||
'DAP_LED': 0x01,
|
||||
'DAP_CONNECT': 0x02,
|
||||
'DAP_DISCONNECT': 0x03,
|
||||
'DAP_TRANSFER_CONFIGURE': 0x04,
|
||||
'DAP_TRANSFER': 0x05,
|
||||
'DAP_TRANSFER_BLOCK': 0x06,
|
||||
'DAP_TRANSFER_ABORT': 0x07,
|
||||
'DAP_WRITE_ABORT': 0x08,
|
||||
'DAP_DELAY': 0x09,
|
||||
'DAP_RESET_TARGET': 0x0a,
|
||||
'DAP_SWJ_PINS': 0x10,
|
||||
'DAP_SWJ_CLOCK': 0x11,
|
||||
'DAP_SWJ_SEQUENCE': 0x12,
|
||||
'DAP_SWD_CONFIGURE': 0x13,
|
||||
}
|
||||
|
||||
ID_INFO = {'VENDOR_ID': 0x01,
|
||||
'PRODUCT_ID': 0x02,
|
||||
'SERIAL_NUMBER': 0x03,
|
||||
'CMSIS_DAP_FW_VERSION': 0x04,
|
||||
'TARGET_DEVICE_VENDOR': 0x05,
|
||||
'TARGET_DEVICE_NAME': 0x06,
|
||||
'CAPABILITIES': 0xf0,
|
||||
'PACKET_COUNT': 0xfe,
|
||||
'PACKET_SIZE': 0xff
|
||||
}
|
||||
|
||||
PINS = {'None': 0x00,
|
||||
'SWCLK_TCK': (1 << 0),
|
||||
'SWDIO_TMS': (1 << 1),
|
||||
'TDI': (1 << 2),
|
||||
'TDO': (1 << 3),
|
||||
'nTRST': (1 << 5),
|
||||
'nRESET': (1 << 7),
|
||||
}
|
||||
|
||||
DAP_DEFAULT_PORT = 0
|
||||
DAP_SWD_PORT = 1
|
||||
DAP_JTAG_POR = 2
|
||||
|
||||
DAP_OK = 0
|
||||
DAP_ERROR = 0xff
|
||||
|
||||
MAX_PACKET_SIZE = 0x0E
|
||||
|
||||
def dapInfo(interface, id_):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_INFO'])
|
||||
cmd.append(ID_INFO[id_])
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_INFO']:
|
||||
raise ValueError('DAP_INFO response error')
|
||||
|
||||
if resp[1] == 0:
|
||||
return
|
||||
|
||||
if resp[1] == 1:
|
||||
return resp[2]
|
||||
|
||||
if resp[1] == 2:
|
||||
return (resp[3] << 8) | resp[2]
|
||||
|
||||
x = array.array('B', [i for i in resp[2:2+resp[1]]])
|
||||
|
||||
return x.tostring()
|
||||
|
||||
|
||||
def dapLed(interface):
|
||||
#not yet implemented
|
||||
return
|
||||
|
||||
def dapConnect(interface, mode = DAP_DEFAULT_PORT):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_CONNECT'])
|
||||
cmd.append(mode)
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_CONNECT']:
|
||||
raise ValueError('DAP_CONNECT response error')
|
||||
|
||||
if resp[1] == 0:
|
||||
raise ValueError('DAP Connect failed')
|
||||
|
||||
if resp[1] == 1:
|
||||
logging.info('DAP SWD MODE initialised')
|
||||
|
||||
if resp[1] == 2:
|
||||
logging.info('DAP JTAG MODE initialised')
|
||||
|
||||
return resp[1]
|
||||
|
||||
def dapDisconnect(interface):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_DISCONNECT'])
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_DISCONNECT']:
|
||||
raise ValueError('DAP_DISCONNECT response error')
|
||||
|
||||
if resp[1] != DAP_OK:
|
||||
raise ValueError('DAP Disconnect failed')
|
||||
|
||||
return resp[1]
|
||||
|
||||
|
||||
def dapWriteAbort(interface, data, dap_index = 0):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_WRITE_ABORT'])
|
||||
cmd.append(dap_index)
|
||||
cmd.append((data >> 0) & 0xff)
|
||||
cmd.append((data >> 8) & 0xff)
|
||||
cmd.append((data >> 16) & 0xff)
|
||||
cmd.append((data >> 24) & 0xff)
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_WRITE_ABORT']:
|
||||
raise ValueError('DAP_WRITE_ABORT response error')
|
||||
|
||||
if resp[1] != DAP_OK:
|
||||
raise ValueError('DAP Write Abort failed')
|
||||
|
||||
return True
|
||||
|
||||
def dapResetTarget(interface):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_RESET_TARGET'])
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_RESET_TARGET']:
|
||||
raise ValueError('DAP_RESET_TARGET response error')
|
||||
|
||||
if resp[1] != DAP_OK:
|
||||
raise ValueError('DAP Reset target failed')
|
||||
|
||||
return resp[1]
|
||||
|
||||
def dapTransferConfigure(interface, idle_cycles = 0x00, wait_retry = 0x0050, match_retry = 0x0000):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_TRANSFER_CONFIGURE'])
|
||||
cmd.append(idle_cycles)
|
||||
cmd.append(wait_retry & 0xff)
|
||||
cmd.append(wait_retry >> 8)
|
||||
cmd.append(match_retry & 0xff)
|
||||
cmd.append(match_retry >> 8)
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_TRANSFER_CONFIGURE']:
|
||||
raise ValueError('DAP_TRANSFER_CONFIGURE response error')
|
||||
|
||||
if resp[1] != DAP_OK:
|
||||
raise ValueError('DAP Transfer Configure failed')
|
||||
|
||||
return resp[1]
|
||||
|
||||
def dapTransfer(interface, count, request, data = [0], dap_index = 0):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_TRANSFER'])
|
||||
cmd.append(dap_index)
|
||||
cmd.append(count)
|
||||
count_write = count
|
||||
for i in range(count):
|
||||
cmd.append(request[i])
|
||||
if not ( request[i] & ((1 << 1) | (1 << 4))):
|
||||
cmd.append(data[i] & 0xff)
|
||||
cmd.append((data[i] >> 8) & 0xff)
|
||||
cmd.append((data[i] >> 16) & 0xff)
|
||||
cmd.append((data[i] >> 24) & 0xff)
|
||||
count_write -= 1
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_TRANSFER']:
|
||||
raise ValueError('DAP_TRANSFER response error')
|
||||
|
||||
if resp[1] != count:
|
||||
raise ValueError('Transfer not completed')
|
||||
|
||||
if resp[2] != 0x01:
|
||||
raise ValueError('SWD Fault')
|
||||
|
||||
return resp[3:3+count_write*4]
|
||||
|
||||
def dapTransferBlock(interface, count, request, data = [0], dap_index = 0):
|
||||
packet_count = count
|
||||
nb = 0
|
||||
resp = []
|
||||
# we send successfully several packets if the size is bigger than MAX_PACKET_COUNT
|
||||
while packet_count > 0:
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_TRANSFER_BLOCK'])
|
||||
cmd.append(dap_index)
|
||||
packet_written = min(packet_count, MAX_PACKET_SIZE)
|
||||
cmd.append(packet_written & 0xff)
|
||||
cmd.append((packet_written >> 8) & 0xff)
|
||||
cmd.append(request)
|
||||
if not (request & ((1 << 1))):
|
||||
for i in range(packet_written):
|
||||
cmd.append(data[i + nb*MAX_PACKET_SIZE] & 0xff)
|
||||
cmd.append((data[i + nb*MAX_PACKET_SIZE] >> 8) & 0xff)
|
||||
cmd.append((data[i + nb*MAX_PACKET_SIZE] >> 16) & 0xff)
|
||||
cmd.append((data[i + nb*MAX_PACKET_SIZE] >> 24) & 0xff)
|
||||
interface.write(cmd)
|
||||
packet_count = packet_count - MAX_PACKET_SIZE
|
||||
nb = nb + 1
|
||||
|
||||
# we then read
|
||||
tmp = interface.read()
|
||||
if tmp[0] != COMMAND_ID['DAP_TRANSFER_BLOCK'] or tmp[3] != 0x01:
|
||||
raise ValueError('DAP_TRANSFER_BLOCK response error')
|
||||
size_transfer = tmp[1] | (tmp[2] << 8)
|
||||
resp.extend(tmp[4:4+size_transfer*4])
|
||||
|
||||
return resp
|
||||
|
||||
def dapSWJClock(interface, clock = 1000000):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_SWJ_CLOCK'])
|
||||
cmd.append(clock & 0xff)
|
||||
cmd.append((clock >> 8) & 0xff)
|
||||
cmd.append((clock >> 16) & 0xff)
|
||||
cmd.append((clock >> 24) & 0xff)
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_SWJ_CLOCK']:
|
||||
raise ValueError('DAP_SWJ_CLOCK response error')
|
||||
|
||||
if resp[1] != DAP_OK:
|
||||
raise ValueError('DAP SWJ Clock failed')
|
||||
|
||||
return resp[1]
|
||||
|
||||
def dapSWJPins(interface, output, pin, wait = 0):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_SWJ_PINS'])
|
||||
try:
|
||||
p = PINS[pin]
|
||||
except KeyError:
|
||||
logging.error('cannot find %s pin', pin)
|
||||
return
|
||||
cmd.append(output & 0xff)
|
||||
cmd.append(p)
|
||||
cmd.append(wait & 0xff)
|
||||
cmd.append((wait >> 8) & 0xff)
|
||||
cmd.append((wait >> 16) & 0xff)
|
||||
cmd.append((wait >> 24) & 0xff)
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_SWJ_PINS']:
|
||||
raise ValueError('DAP_SWJ_PINS response error')
|
||||
|
||||
return resp[1]
|
||||
|
||||
|
||||
def dapSWDConfigure(interface, conf = 0):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_SWD_CONFIGURE'])
|
||||
cmd.append(conf)
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_SWD_CONFIGURE']:
|
||||
raise ValueError('DAP_SWD_CONFIGURE response error')
|
||||
|
||||
if resp[1] != DAP_OK:
|
||||
raise ValueError('DAP SWD Configure failed')
|
||||
|
||||
return resp[1]
|
||||
|
||||
def dapSWJSequence(interface, data):
|
||||
cmd = []
|
||||
cmd.append(COMMAND_ID['DAP_SWJ_SEQUENCE'])
|
||||
cmd.append(len(data)*8)
|
||||
for i in range(len(data)):
|
||||
cmd.append(data[i])
|
||||
interface.write(cmd)
|
||||
|
||||
resp = interface.read()
|
||||
if resp[0] != COMMAND_ID['DAP_SWJ_SEQUENCE']:
|
||||
raise ValueError('DAP_SWJ_SEQUENCE response error')
|
||||
|
||||
if resp[1] != DAP_OK:
|
||||
raise ValueError('DAP SWJ Sequence failed')
|
||||
|
||||
return resp[1]
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
class Transport():
|
||||
|
||||
def __init__(self, interface):
|
||||
self.interface = interface
|
||||
return
|
||||
|
||||
def init(self):
|
||||
return
|
||||
|
||||
def uninit(self):
|
||||
return
|
||||
|
||||
def info(self, request):
|
||||
return
|
||||
|
||||
def readDP(self, addr):
|
||||
return
|
||||
|
||||
def writeDP(self, addr, data):
|
||||
return
|
||||
|
||||
def writeAP(self, addr, data):
|
||||
return
|
||||
|
||||
def readAP(self, addr):
|
||||
return
|
||||
|
||||
def writeMem(self, addr, data, transfer_size = 32):
|
||||
return
|
||||
|
||||
def readMem(self, addr, transfer_size = 32):
|
||||
return
|
||||
|
||||
def writeBlock32(self, addr, data):
|
||||
return
|
||||
|
||||
def readBlock32(self, addr, data):
|
||||
return
|
||||
|
||||
def assertReset(self, asserted):
|
||||
return
|
||||
|
||||
def getUniqueID(self):
|
||||
return
|
||||
|
||||
def reset(self):
|
||||
return
|
|
@ -1,33 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
setup(
|
||||
name="pyOCD",
|
||||
version="0.1",
|
||||
description="CMSIS-DAP debugger for python",
|
||||
author="samux",
|
||||
author_email="samuel.mokrani@gmail.com",
|
||||
license="Apache 2.0",
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"License :: Apache 2.0",
|
||||
"Programming Language :: Python",
|
||||
],
|
||||
packages=["pyOCD", "pyOCD.flash", "pyOCD.gdbserver", "pyOCD.interface", "pyOCD.target", "pyOCD.transport", "pyOCD.board"]
|
||||
)
|
|
@ -1,165 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import argparse, os
|
||||
from time import sleep
|
||||
from random import randrange
|
||||
|
||||
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
from pyOCD.board import MbedBoard
|
||||
|
||||
addr = 0
|
||||
size = 0
|
||||
f = None
|
||||
binary_file = "l1_"
|
||||
|
||||
interface = None
|
||||
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
parser = argparse.ArgumentParser(description='A CMSIS-DAP python debugger')
|
||||
parser.add_argument('-f', help='binary file', dest = "file")
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
|
||||
board = MbedBoard.chooseBoard()
|
||||
target_type = board.getTargetType()
|
||||
|
||||
if args.file is None:
|
||||
binary_file += target_type + ".bin"
|
||||
binary_file = os.path.join(parentdir, 'binaries', binary_file)
|
||||
else:
|
||||
binary_file = args.file
|
||||
|
||||
print "binary file: %s" % binary_file
|
||||
|
||||
if target_type == "lpc1768":
|
||||
addr = 0x10000001
|
||||
size = 0x1102
|
||||
elif target_type == "lpc11u24":
|
||||
addr = 0x10000001
|
||||
size = 0x502
|
||||
elif target_type == "kl25z":
|
||||
addr = 0x20000001
|
||||
size = 0x502
|
||||
elif target_type == "lpc800":
|
||||
addr = 0x10000001
|
||||
size = 0x502
|
||||
|
||||
target = board.target
|
||||
transport = board.transport
|
||||
flash = board.flash
|
||||
interface = board.interface
|
||||
|
||||
|
||||
print "\r\n\r\n------ GET Unique ID ------"
|
||||
print "Unique ID: %s" % board.getUniqueID()
|
||||
|
||||
print "\r\n\r\n------ TEST READ / WRITE CORE REGISTER ------"
|
||||
pc = target.readCoreRegister('pc')
|
||||
print "initial pc: 0x%X" % target.readCoreRegister('pc')
|
||||
# write in pc dummy value
|
||||
target.writeCoreRegister('pc', 0x3D82)
|
||||
print "now pc: 0x%X" % target.readCoreRegister('pc')
|
||||
# write initial pc value
|
||||
target.writeCoreRegister('pc', pc)
|
||||
print "initial pc value rewritten: 0x%X" % target.readCoreRegister('pc')
|
||||
|
||||
|
||||
print "\r\n\r\n------ TEST HALT / RESUME ------"
|
||||
|
||||
print "resume"
|
||||
target.resume()
|
||||
sleep(0.2)
|
||||
|
||||
print "halt"
|
||||
target.halt()
|
||||
print "HALT: pc: 0x%X" % target.readCoreRegister('pc')
|
||||
sleep(0.2)
|
||||
|
||||
|
||||
|
||||
print "\r\n\r\n------ TEST READ / WRITE MEMORY ------"
|
||||
target.halt()
|
||||
print "READ32/WRITE32"
|
||||
val = randrange(0, 0xffffffff)
|
||||
print "write32 0x%X at 0x%X" % (val, addr)
|
||||
target.writeMemory(addr, val)
|
||||
res = target.readMemory(addr)
|
||||
print "read32 at 0x%X: 0x%X" % (addr, res)
|
||||
if res != val:
|
||||
print "ERROR in READ/WRITE 32"
|
||||
|
||||
print "\r\nREAD16/WRITE316"
|
||||
val = randrange(0, 0xffff)
|
||||
print "write16 0x%X at 0x%X" % (val, addr + 2)
|
||||
target.writeMemory(addr + 2, val, 16)
|
||||
res = target.readMemory(addr + 2, 16)
|
||||
print "read16 at 0x%X: 0x%X" % (addr + 2, res)
|
||||
if res != val:
|
||||
print "ERROR in READ/WRITE 16"
|
||||
|
||||
print "\r\nREAD8/WRITE8"
|
||||
val = randrange(0, 0xff)
|
||||
print "write8 0x%X at 0x%X" % (val, addr + 1)
|
||||
target.writeMemory(addr + 1, val, 8)
|
||||
res = target.readMemory(addr + 1, 8)
|
||||
print "read8 at 0x%X: 0x%X" % (addr + 1, res)
|
||||
if res != val:
|
||||
print "ERROR in READ/WRITE 8"
|
||||
|
||||
|
||||
print "\r\n\r\n------ TEST READ / WRITE MEMORY BLOCK ------"
|
||||
data = [randrange(1, 50) for x in range(size)]
|
||||
target.writeBlockMemoryUnaligned8(addr, data)
|
||||
block = target.readBlockMemoryUnaligned8(addr, size)
|
||||
error = False
|
||||
for i in range(len(block)):
|
||||
if (block[i] != data[i]):
|
||||
error = True
|
||||
print "ERROR: 0x%X, 0x%X, 0x%X!!!" % ((addr + i), block[i], data[i])
|
||||
if error:
|
||||
print "TEST FAILED"
|
||||
else:
|
||||
print "TEST PASSED"
|
||||
|
||||
|
||||
print "\r\n\r\n------ TEST RESET ------"
|
||||
target.reset()
|
||||
sleep(0.1)
|
||||
target.halt()
|
||||
|
||||
for i in range(5):
|
||||
target.step()
|
||||
print "pc: 0x%X" % target.readCoreRegister('pc')
|
||||
|
||||
|
||||
print "\r\n\r\n----- FLASH NEW BINARY -----"
|
||||
flash.flashBinary(binary_file)
|
||||
|
||||
target.reset()
|
||||
|
||||
except Exception as e:
|
||||
print "Unknown exception: %s" % e
|
||||
|
||||
finally:
|
||||
if board != None:
|
||||
board.uninit()
|
|
@ -1,36 +0,0 @@
|
|||
"""
|
||||
mbed CMSIS-DAP debugger
|
||||
Copyright (c) 2006-2013 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from pyOCD.gdbserver import GDBServer
|
||||
from pyOCD.board import MbedBoard
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
try:
|
||||
board_selected = MbedBoard.chooseBoard()
|
||||
if board_selected != None:
|
||||
gdb = GDBServer(board_selected, 3333)
|
||||
while gdb.isAlive():
|
||||
gdb.join(timeout = 0.5)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
gdb.stop()
|
||||
except Exception as e:
|
||||
print "uncaught exception: %s" % e
|
||||
gdb.stop()
|
Loading…
Reference in New Issue