Skip to content

Commit 4026524

Browse files
committed
Refactor pyOCD in preperation for pyDapLink
Prepare pyOCD for daplink by using pyDapLink's interface. Prior to this patch the board class depending on having both a transport and an interface. This caused the code to be more tightly coupled to interfaces than it could be. This patch combines most of the logic from the interface and transport class and moves it into the DapLink class. The DapLink class is an implementation of the Link class, which provides all the functions needed to communicate with a board. More specific changes: -Raw packet transfer test removed from speed test since pyDapLink will now be responsible for testing this -References to 'transport' changed to 'link' -Transport interface removed -Interface code (usb drivers) moved into the transport folder to further isolate it from the rest of the codebase -File cmsis_dap.py renamed to dap.py and moved into target folder for use by cortex_m.py and target_kinetis.py. In the future dap.py will be removed and AP/DP drives will be used in its place.
1 parent 0524caa commit 4026524

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1330
-825
lines changed

README.rst

-11
Original file line numberDiff line numberDiff line change
@@ -222,17 +222,6 @@ gdb server:
222222

223223
Architecture
224224
------------
225-
226-
Interface
227-
~~~~~~~~~
228-
229-
An interface does the link between the target and the computer.
230-
This module contains basic functionalities to write and read data to and from
231-
an interface. You can inherit from ``Interface`` and overwrite
232-
``read()``, ``write()``, etc
233-
234-
Then declare your interface in ``INTERFACE`` (in ``pyOCD.interface.__init__.py``)
235-
236225
Target
237226
~~~~~~
238227

pyOCD/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
import board
1919
import flash
2020
import gdbserver
21-
import interface
2221
import target
2322
import transport
2423
import utility

pyOCD/board/board.py

+12-35
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,18 @@
1616
"""
1717

1818
from pyOCD.target import TARGET
19-
from pyOCD.transport import TRANSPORT
20-
from pyOCD.interface import INTERFACE
2119
from pyOCD.flash import FLASH
2220

2321
import logging
2422
import traceback
2523

2624
class Board(object):
2725
"""
28-
This class associates a target, a flash, a transport and an interface
29-
to create a board
26+
This class associates a target, a flash and a link to create a board
3027
"""
31-
def __init__(self, target, flash, interface, transport="cmsis_dap", frequency=1000000):
32-
self.interface = interface
33-
self.transport = TRANSPORT[transport](self.interface)
34-
self.target = TARGET[target](self.transport)
28+
def __init__(self, target, flash, link, frequency=1000000):
29+
self.link = link
30+
self.target = TARGET[target](self.link)
3531
self.flash = FLASH[flash](self.target)
3632
self.target.setFlash(self.flash)
3733
self.debug_clock_frequency = frequency
@@ -47,22 +43,15 @@ def __exit__(self, type, value, traceback):
4743

4844
def init(self):
4945
"""
50-
Initialize the board: interface, transport and target
46+
Initialize the board
5147
"""
5248
logging.debug("init board %s", self)
53-
self.interface.init()
54-
packet_count = self.getPacketCount()
55-
logging.info("board allows %i concurrent packets", packet_count)
56-
if packet_count < 1:
57-
logging.error('packet count of %i outside of expected range', packet_count)
58-
packet_count = 1
59-
self.interface.setPacketCount(packet_count)
60-
self.transport.init(self.debug_clock_frequency)
49+
self.link.set_clock(self.debug_clock_frequency)
6150
self.target.init()
6251

6352
def uninit(self, resume=True):
6453
"""
65-
Uninitialize the board: interface, transport and target.
54+
Uninitialize the board: link and target.
6655
This function resumes the target
6756
"""
6857
if self.closed:
@@ -77,27 +66,15 @@ def uninit(self, resume=True):
7766
logging.error("target exception during uninit:")
7867
traceback.print_exc()
7968
try:
80-
self.transport.uninit()
69+
self.link.disconnect()
8170
except:
82-
logging.error("transport exception during uninit:")
71+
logging.error("link exception during disconnect:")
8372
traceback.print_exc()
8473
try:
85-
self.interface.close()
74+
self.link.close()
8675
except:
87-
logging.error("interface exception during uninit:")
76+
logging.error("link exception during uninit:")
8877
traceback.print_exc()
8978

9079
def getInfo(self):
91-
# If the product name starts with the vendor name, we don't want to duplicate
92-
# the vendor name, so just return the product name. Otherwise combined the two.
93-
if self.interface.product_name.startswith(self.interface.vendor_name):
94-
info = self.interface.product_name
95-
else:
96-
info = self.interface.vendor_name + " " + self.interface.product_name
97-
return info
98-
99-
def getPacketCount(self):
100-
"""
101-
Return the number of commands the remote device's buffer can hold.
102-
"""
103-
return 1
80+
return ""

pyOCD/board/mbed_board.py

+37-70
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
from time import sleep
2222
from board import Board
23-
from pyOCD.interface import INTERFACE, usb_backend
23+
from pyOCD.transport.daplink import DapLink
2424

2525
class BoardInfo(object):
2626
def __init__(self, name, target, binary):
@@ -65,13 +65,15 @@ class MbedBoard(Board):
6565
Particularly, this class allows you to dynamically determine
6666
the type of all boards connected based on the id board
6767
"""
68-
def __init__(self, interface, board_id, unique_id, target=None, transport="cmsis_dap", frequency=1000000):
68+
def __init__(self, link, target=None, frequency=1000000):
6969
"""
7070
Init the board
7171
"""
7272
self.name = None
7373
self.native_target = None
7474
self.test_binary = None
75+
unique_id = link.get_unique_id()
76+
board_id = unique_id[0:4]
7577
if board_id in BOARD_ID_TO_INFO:
7678
board_info = BOARD_ID_TO_INFO[board_id]
7779
self.name = board_info.name
@@ -85,7 +87,7 @@ def __init__(self, interface, board_id, unique_id, target=None, transport="cmsis
8587
if target is None:
8688
raise Exception("Unknown board target")
8789

88-
super(MbedBoard, self).__init__(target, target, interface, transport, frequency)
90+
super(MbedBoard, self).__init__(target, target, link, frequency)
8991
self.unique_id = unique_id
9092
self.target_type = target
9193

@@ -120,11 +122,12 @@ def getInfo(self):
120122
return Board.getInfo(self) + " [" + self.target_type + "]"
121123

122124
@staticmethod
123-
def listConnectedBoards(transport="cmsis_dap"):
125+
def listConnectedBoards(link_class=DapLink):
124126
"""
125127
List the connected board info
126128
"""
127-
all_mbeds = MbedBoard.getAllConnectedBoards(close=True, blocking=False)
129+
all_mbeds = MbedBoard.getAllConnectedBoards(link_class, close=True,
130+
blocking=False)
128131
index = 0
129132
if len(all_mbeds) > 0:
130133
for mbed in all_mbeds:
@@ -134,74 +137,44 @@ def listConnectedBoards(transport="cmsis_dap"):
134137
print("No available boards are connected")
135138

136139
@staticmethod
137-
def getAllConnectedBoards(transport="cmsis_dap", close=False, blocking=True,
138-
target_override=None, frequency=1000000):
140+
def getAllConnectedBoards(link_class=DapLink, close=False, blocking=True,
141+
target_override=None, frequency=1000000):
139142
"""
140143
Return an array of all mbed boards connected
141144
"""
142-
first = True
143-
while True:
144-
while True:
145-
if not first:
146-
# Don't eat up all the cpu if an unsupported board is connected.
147-
# Sleep before getting connected interfaces. This way if a keyboard
148-
# exception comes in there will be no resources to close
149-
sleep(0.2)
150-
151-
all_mbeds = INTERFACE[usb_backend].getAllConnectedInterface(mbed_vid, mbed_pid)
152-
if all_mbeds == None:
153-
all_mbeds = []
154-
155-
if not blocking:
156-
# No blocking so break from loop
157-
break
158-
159-
if len(all_mbeds) > 0:
160-
# A board has been found so break from loop
161-
break
162145

163-
if (first == True):
164-
logging.info("Waiting for a USB device connected")
165-
first = False
146+
mbed_list = []
147+
while True:
166148

167-
mbed_boards = []
168-
for mbed in all_mbeds:
169-
try:
170-
mbed.write([0x80])
171-
u_id_ = mbed.read()
172-
board_id = array.array('B', [i for i in u_id_[2:6]]).tostring()
173-
unique_id = array.array('B', [i for i in u_id_[2:2 + u_id_[1]]]).tostring()
174-
if board_id not in BOARD_ID_TO_INFO:
175-
logging.info("Unsupported board found: %s" % board_id)
176-
if target_override is None:
177-
# TODO - if no board can be determined treat this as a generic cortex-m device
178-
logging.info("Target could not be determined. Specify target manually to use board")
179-
mbed.close()
180-
continue
149+
connected_daplinks = link_class.get_connected_devices()
150+
for daplink in connected_daplinks:
151+
new_mbed = MbedBoard(daplink, target_override, frequency)
152+
mbed_list.append(new_mbed)
181153

182-
new_mbed = MbedBoard(mbed, board_id, unique_id, target_override, transport, frequency)
183-
logging.info("new board id detected: %s", unique_id)
184-
mbed_boards.append(new_mbed)
185-
if close:
186-
mbed.close()
187-
except:
188-
#TODO - close all boards when an exception occurs
189-
mbed.close()
190-
raise
154+
#TODO - handle exception on open
155+
if not close:
156+
for daplink in connected_daplinks:
157+
daplink.open()
191158

192-
if len(mbed_boards) > 0 or not blocking:
193-
return mbed_boards
159+
if not blocking:
160+
break
161+
elif len(mbed_list) > 0:
162+
break
163+
else:
164+
sleep(0.01)
165+
assert len(mbed_list) == 0
194166

195-
if (first == True):
196-
logging.info("Waiting for a USB device connected")
197-
first = False
167+
return mbed_list
198168

199169
@staticmethod
200-
def chooseBoard(transport="cmsis_dap", blocking=True, return_first=False, board_id=None, target_override=None, frequency=1000000, init_board=True):
170+
def chooseBoard(link_class=DapLink, blocking=True, return_first=False,
171+
board_id=None, target_override=None, frequency=1000000,
172+
init_board=True):
201173
"""
202174
Allow you to select a board among all boards connected
203175
"""
204-
all_mbeds = MbedBoard.getAllConnectedBoards(transport, False, blocking, target_override, frequency)
176+
all_mbeds = MbedBoard.getAllConnectedBoards(link_class, False, blocking,
177+
target_override, frequency)
205178

206179
# If a board ID is specified close all other boards
207180
if board_id != None:
@@ -210,7 +183,7 @@ def chooseBoard(transport="cmsis_dap", blocking=True, return_first=False, board_
210183
if mbed.unique_id == (board_id):
211184
new_mbed_list.append(mbed)
212185
else:
213-
mbed.interface.close()
186+
mbed.link.close()
214187
assert len(new_mbed_list) <= 1
215188
all_mbeds = new_mbed_list
216189

@@ -225,7 +198,7 @@ def chooseBoard(transport="cmsis_dap", blocking=True, return_first=False, board_
225198
# Select first board and close others if True
226199
if return_first:
227200
for i in range(1, len(all_mbeds)):
228-
all_mbeds[i].interface.close()
201+
all_mbeds[i].link.close()
229202
all_mbeds = all_mbeds[0:1]
230203

231204
# Ask use to select boards if there is more than 1 left
@@ -255,7 +228,7 @@ def chooseBoard(transport="cmsis_dap", blocking=True, return_first=False, board_
255228
# close all others mbed connected
256229
for mbed in all_mbeds:
257230
if mbed != all_mbeds[ch]:
258-
mbed.interface.close()
231+
mbed.link.close()
259232
all_mbeds = all_mbeds[ch:ch + 1]
260233

261234
assert len(all_mbeds) == 1
@@ -264,12 +237,6 @@ def chooseBoard(transport="cmsis_dap", blocking=True, return_first=False, board_
264237
try:
265238
mbed.init()
266239
except:
267-
mbed.interface.close()
240+
mbed.link.close()
268241
raise
269242
return mbed
270-
271-
def getPacketCount(self):
272-
"""
273-
Return the number of commands the remote device's buffer can hold.
274-
"""
275-
return self.transport.info('PACKET_COUNT')

pyOCD/gdbserver/gdbserver.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"""
1717

1818
from ..target.target import Target
19-
from ..transport.transport import Transport
19+
from ..transport.link import Link
2020
from ..utility.conversion import hexToByteList, hexEncode, hexDecode
2121
from gdb_socket import GDBSocket
2222
from gdb_websocket import GDBWebSocket
@@ -789,7 +789,7 @@ def getMemory(self, data):
789789
val += hex(x)[2:4]
790790
else:
791791
val += '0' + hex(x)[2:3]
792-
except Transport.TransferError:
792+
except Link.Error:
793793
logging.debug("getMemory failed at 0x%x" % addr)
794794
val = 'E01' #EPERM
795795
return self.createRSPPacket(val)
@@ -813,7 +813,7 @@ def writeMemoryHex(self, data):
813813
# Flush so an exception is thrown now if invalid memory was accessed
814814
self.target.flush()
815815
resp = "OK"
816-
except Transport.TransferError:
816+
except Link.Error:
817817
logging.debug("writeMemory failed at 0x%x" % addr)
818818
resp = 'E01' #EPERM
819819

@@ -843,7 +843,7 @@ def writeMemory(self, data):
843843
# Flush so an exception is thrown now if invalid memory was accessed
844844
self.target.flush()
845845
resp = "OK"
846-
except Transport.TransferError:
846+
except Link.Error:
847847
logging.debug("writeMemory failed at 0x%x" % addr)
848848
resp = 'E01' #EPERM
849849

0 commit comments

Comments
 (0)