Skip to content

Commit 4b45409

Browse files
authored
Merge pull request #1017 from flit/refactor/dp_reset
DP reset refactoring
2 parents 2824cce + 21ff629 commit 4b45409

File tree

13 files changed

+188
-55
lines changed

13 files changed

+188
-55
lines changed

docs/command_reference.md

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ Write DP register.
196196
<tr><td>
197197
<a href="#reset"><tt>reset</tt></a>
198198
</td><td>
199-
[halt|-halt|-h]
199+
[halt|-halt|-h] [TYPE]
200200
</td><td>
201-
Reset the target.
201+
Reset the target, optionally specifying the reset type.
202202
</td></tr>
203203

204204
<tr><td>
@@ -297,6 +297,15 @@ ADDR [LEN]
297297
Read 32-bit words.
298298
</td></tr>
299299

300+
<tr><td>
301+
<a href="#read64"><tt>read64</tt></a>,
302+
<a href="#read64"><tt>rd</tt></a>
303+
</td><td>
304+
ADDR [LEN]
305+
</td><td>
306+
Read 64-bit words.
307+
</td></tr>
308+
300309
<tr><td>
301310
<a href="#read8"><tt>read8</tt></a>,
302311
<a href="#read8"><tt>rb</tt></a>
@@ -332,6 +341,15 @@ ADDR DATA+
332341
Write 32-bit words to memory.
333342
</td></tr>
334343

344+
<tr><td>
345+
<a href="#write64"><tt>write64</tt></a>,
346+
<a href="#write64"><tt>wd</tt></a>
347+
</td><td>
348+
ADDR DATA...
349+
</td><td>
350+
Write 64-bit double-words to memory.
351+
</td></tr>
352+
335353
<tr><td>
336354
<a href="#write8"><tt>write8</tt></a>,
337355
<a href="#write8"><tt>wb</tt></a>
@@ -749,8 +767,8 @@ Write DP register.
749767

750768
##### `reset`
751769

752-
**Usage**: [halt|-halt|-h] \
753-
Reset the target.
770+
**Usage**: [halt|-halt|-h] [TYPE] \
771+
Reset the target, optionally specifying the reset type. The reset type must be one of 'default', 'hw', 'sw', 'hardware', 'software', 'sw_sysresetreq', 'sw_vectreset', 'sw_emulated', 'sysresetreq', 'vectreset', or 'emulated'.
754772

755773

756774
##### `unlock`
@@ -818,14 +836,21 @@ Load a binary file to an address in memory (RAM or flash). This command is depre
818836

819837
**Aliases**: `rh` \
820838
**Usage**: ADDR [LEN] \
821-
Read 16-bit halfwords. Optional length parameter is the number of bytes to read. It must be divisible by 2. If the length is not provided, one halfword is read. The address may be unaligned.
839+
Read 16-bit halfwords. Optional length parameter is the number of bytes (not half-words) to read. It must be divisible by 2. If the length is not provided, one halfword is read. The address may be unaligned.
822840

823841

824842
##### `read32`
825843

826844
**Aliases**: `rw` \
827845
**Usage**: ADDR [LEN] \
828-
Read 32-bit words. Optional length parameter is the number of bytes to read. It must be divisible by 4. If the length is not provided, one word is read. The address may be unaligned.
846+
Read 32-bit words. Optional length parameter is the number of bytes (not words) to read. It must be divisible by 4. If the length is not provided, one word is read. The address may be unaligned.
847+
848+
849+
##### `read64`
850+
851+
**Aliases**: `rd` \
852+
**Usage**: ADDR [LEN] \
853+
Read 64-bit words. Optional length parameter is the number of bytes (not double-words!) to read. It must be divisible by 8. If the length is not provided, one word is read. The address may be unaligned.
829854

830855

831856
##### `read8`
@@ -855,6 +880,13 @@ Write 16-bit halfwords to memory. The data arguments are 16-bit halfwords in big
855880
Write 32-bit words to memory. The data arguments are 32-bit words in big-endian format and are written as little-endian. The address may be unaligned. Can write to both RAM and flash. Flash writes are subject to minimum write size and alignment, and the flash page must have been previously erased.
856881

857882

883+
##### `write64`
884+
885+
**Aliases**: `wd` \
886+
**Usage**: ADDR DATA... \
887+
Write 64-bit double-words to memory. The data arguments are 64-bit words in big-endian format and are written as little-endian. The address may be unaligned. Can write to both RAM and flash. Flash writes are subject to minimum write size and alignment, and the flash page must have been previously erased.
888+
889+
858890
##### `write8`
859891

860892
**Aliases**: `wb` \

pyocd/commands/commander.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ def run(self):
8181
status, self.session.board.unique_id))
8282
except exceptions.TransferFaultError:
8383
pass
84+
else:
85+
# Say what we're connected to, but without status.
86+
print("Connected to %s [no init mode]: %s" % (self.context.target.part_number,
87+
self.session.board.unique_id))
8488

8589
# Run the REPL interface.
8690
console = PyocdRepl(self.context)

pyocd/commands/commands.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@
2929
from ..flash.file_programmer import FileProgrammer
3030
from ..gdbserver.gdbserver import GDBServer
3131
from ..utility import conversion
32-
from ..utility.cmdline import UniquePrefixMatcher
32+
from ..utility.cmdline import (
33+
UniquePrefixMatcher,
34+
convert_reset_type,
35+
)
3336
from ..utility.hex import (
3437
format_hex_width,
3538
dump_hex_data_to_str,
@@ -328,20 +331,29 @@ class ResetCommand(CommandBase):
328331
'names': ['reset'],
329332
'group': 'standard',
330333
'category': 'device',
331-
'nargs': [0, 1],
332-
'usage': "[halt|-halt|-h]",
333-
'help': "Reset the target.",
334+
'nargs': [0, 1, 2],
335+
'usage': "[halt|-halt|-h] [TYPE]",
336+
'help': "Reset the target, optionally specifying the reset type.",
337+
'extra_help': "The reset type must be one of 'default', 'hw', 'sw', 'hardware', 'software', "
338+
"'sw_sysresetreq', 'sw_vectreset', 'sw_emulated', 'sysresetreq', 'vectreset', "
339+
"or 'emulated'.",
340+
334341
}
335342

336343
def parse(self, args):
337344
self.do_halt = False
338-
if len(args) == 1:
345+
self.reset_type = None
346+
if len(args) >= 1:
339347
self.do_halt = (args[0] in ('-h', '--halt', 'halt'))
348+
if self.do_halt:
349+
args.pop(0)
350+
if len(args) == 1:
351+
self.reset_type = convert_reset_type(args[0])
340352

341353
def execute(self):
342354
if self.do_halt:
343355
self.context.write("Resetting target with halt")
344-
self.context.selected_core.reset_and_halt()
356+
self.context.selected_core.reset_and_halt(self.reset_type)
345357

346358
status = self.context.selected_core.get_state()
347359
if status != Target.State.HALTED:
@@ -350,7 +362,7 @@ def execute(self):
350362
self.context.write("Successfully halted device on reset")
351363
else:
352364
self.context.write("Resetting target")
353-
self.context.selected_core.reset()
365+
self.context.selected_core.reset(self.reset_type)
354366

355367
class DisassembleCommand(CommandBase):
356368
INFO = {
@@ -428,7 +440,7 @@ class Read16Command(ReadCommandBase):
428440
'nargs': [1, 2],
429441
'usage': "ADDR [LEN]",
430442
'width': 16,
431-
'help': "Read 16-bit halfwords",
443+
'help': "Read 16-bit halfwords.",
432444
'extra_help': "Optional length parameter is the number of bytes (not half-words) to read. It "
433445
"must be divisible by 2. If the length is not provided, one halfword is read. "
434446
"The address may be unaligned."
@@ -442,21 +454,21 @@ class Read32Command(ReadCommandBase):
442454
'nargs': [1, 2],
443455
'usage': "ADDR [LEN]",
444456
'width': 32,
445-
'help': "Read 32-bit words",
457+
'help': "Read 32-bit words.",
446458
'extra_help': "Optional length parameter is the number of bytes (not words) to read. It must be "
447459
"divisible by 4. If the length is not provided, one word is read. "
448460
"The address may be unaligned.",
449461
}
450462

451463
class Read64Command(ReadCommandBase):
452464
INFO = {
453-
'names': ['read64', 'r64', 'rd'],
465+
'names': ['read64', 'rd'],
454466
'group': 'standard',
455467
'category': 'memory',
456468
'nargs': [1, 2],
457469
'usage': "ADDR [LEN]",
458470
'width': 64,
459-
'help': "Read 64-bit words",
471+
'help': "Read 64-bit words.",
460472
'extra_help': "Optional length parameter is the number of bytes (not double-words!) to read. "
461473
"It must be divisible by 8. If the length is not provided, one word is read. "
462474
"The address may be unaligned."
@@ -549,13 +561,13 @@ class Write32Command(WriteCommandBase):
549561

550562
class Write64Command(WriteCommandBase):
551563
INFO = {
552-
'names': ['write64', 'w64', 'wd'],
564+
'names': ['write64', 'wd'],
553565
'group': 'standard',
554566
'category': 'memory',
555567
'nargs': '*',
556568
'usage': "ADDR DATA...",
557569
'width': 64,
558-
'help': "Write 64-bit double-words to memory",
570+
'help': "Write 64-bit double-words to memory.",
559571
'extra_help': "The data arguments are 64-bit words in big-endian format and are written as "
560572
"little-endian. The address may be unaligned. Can write to both RAM and flash. "
561573
"Flash writes are subject to minimum write size and alignment, and the flash "

pyocd/commands/execution_context.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ def attach_session(self, session):
202202
@retval False An error occurred when opening the session or initing the context state.
203203
"""
204204
assert self._session is None
205-
assert session.is_open
205+
assert session.is_open or self._no_init
206206
self._session = session
207207

208208
# Select the first core's MEM-AP by default.

pyocd/commands/values.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,13 @@ def modify(self, args):
243243
raise exceptions.CommandError("missing reset state")
244244
state = int(args[0], base=0)
245245
self.context.writef("nRESET = {}", state)
246-
self.context.probe.assert_reset((state == 0))
246+
247+
# Use the probe to assert reset if the DP doesn't exist for some reason, otherwise
248+
# use the DP so reset notifications are sent.
249+
if self.context.target.dp is None:
250+
self.context.probe.assert_reset((state == 0))
251+
else:
252+
self.context.target.dp.assert_reset((state == 0))
247253

248254
class SessionOptionValue(ValueBase):
249255
INFO = {

pyocd/core/soc_target.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,11 @@ def remove_watchpoint(self, addr, size, type):
211211
def reset(self, reset_type=None):
212212
# Perform a hardware reset if there is not a core.
213213
if self.selected_core is None:
214-
self.session.probe.reset()
214+
# Use the probe to reset if the DP doesn't exist yet.
215+
if self.dp is None:
216+
self.session.probe.reset()
217+
else:
218+
self.dp.reset()
215219
return
216220
self.selected_core.reset(reset_type)
217221

pyocd/coresight/ap.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from enum import Enum
2121

2222
from ..core import (exceptions, memory_interface)
23+
from ..core.target import Target
2324
from ..utility.concurrency import locked
2425

2526
LOG = logging.getLogger(__name__)
@@ -413,10 +414,6 @@ def read_reg(self, addr, now=True):
413414
def write_reg(self, addr, data):
414415
self.dp.write_ap(self.address.address + addr, data)
415416

416-
def reset_did_occur(self):
417-
"""! @brief Invoked by the DebugPort to inform APs that a reset was performed."""
418-
pass
419-
420417
def lock(self):
421418
"""! @brief Lock the AP from access by other threads."""
422419
self.dp.probe.lock()
@@ -523,6 +520,9 @@ def __init__(self, dp, ap_address, idr=None, name="", flags=0, cmpid=None):
523520
self.read_memory = self._read_memory
524521
self.write_memory_block32 = self._write_memory_block32
525522
self.read_memory_block32 = self._read_memory_block32
523+
524+
# Subscribe to reset events.
525+
self.dp.session.subscribe(self._reset_did_occur, (Target.Event.PRE_RESET, Target.Event.POST_RESET))
526526

527527
@property
528528
def supported_transfer_sizes(self):
@@ -707,7 +707,7 @@ def find_components(self):
707707
self.rom_table.init()
708708
except exceptions.TransferError as error:
709709
LOG.error("Transfer error while reading %s ROM table: %s", self.short_description, error,
710-
exc_info=self.dp.target.session.log_tracebacks)
710+
exc_info=self.dp.session.log_tracebacks)
711711

712712
@property
713713
def implemented_hprot_mask(self):
@@ -837,13 +837,17 @@ def write_reg(self, addr, data):
837837
except exceptions.ProbeError:
838838
# Invalidate cached CSW on exception.
839839
if ap_regaddr == self._reg_offset + MEM_AP_CSW:
840-
self._cached_csw = -1
840+
self._invalidate_cache()
841841
raise
842842

843-
def reset_did_occur(self):
844-
"""! @copydoc AccessPort.reset_did_occur()"""
845-
# TODO use notifications to invalidate CSW cache.
843+
def _invalidate_cache(self):
844+
"""! @brief Invalidate cached registers associated with this AP."""
846845
self._cached_csw = -1
846+
847+
def _reset_did_occur(self, notification):
848+
"""! @brief Handles reset notifications to invalidate CSW cache."""
849+
# We clear the cache on all resets just to be safe.
850+
self._invalidate_cache()
847851

848852
@locked
849853
def _write_memory(self, addr, data, transfer_size=32):
@@ -1045,7 +1049,7 @@ def _read_memory_block32(self, addr, size):
10451049

10461050
def _handle_error(self, error, num):
10471051
self.dp._handle_error(error, num)
1048-
self._cached_csw = -1
1052+
self._invalidate_cache()
10491053

10501054
class AHB_AP(MEM_AP):
10511055
"""! @brief AHB-AP access port subclass.

pyocd/coresight/coresight_target.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,10 +105,10 @@ def pre_connect(self):
105105
mode = self.session.options.get('connect_mode')
106106
if mode == 'pre-reset':
107107
LOG.info("Performing connect pre-reset")
108-
self.session.probe.reset()
108+
self.dp.reset()
109109
elif mode == 'under-reset':
110110
LOG.info("Asserting reset prior to connect")
111-
self.session.probe.assert_reset(True)
111+
self.dp.assert_reset(True)
112112

113113
def perform_halt_on_connect(self):
114114
"""! @brief Halt cores.
@@ -139,7 +139,7 @@ def post_connect(self):
139139
mode = self.session.options.get('connect_mode')
140140
if mode == 'under-reset':
141141
LOG.info("Deasserting reset post connect")
142-
self.session.probe.assert_reset(False)
142+
self.dp.assert_reset(False)
143143

144144
LOG.debug("Clearing reset catch")
145145
# Apply to all cores.

pyocd/coresight/cortex_m.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ def _perform_reset(self, reset_type):
706706
"""! @brief Perform a reset of the specified type."""
707707
assert isinstance(reset_type, Target.ResetType)
708708
if reset_type is Target.ResetType.HW:
709-
self.session.probe.reset()
709+
self.session.target.dp.reset()
710710
elif reset_type is Target.ResetType.SW_EMULATED:
711711
self._perform_emulated_reset()
712712
else:
@@ -739,12 +739,14 @@ def reset(self, reset_type=None):
739739
740740
After a call to this function, the core is running.
741741
"""
742-
self.session.notify(Target.Event.PRE_RESET, self)
743-
744742
reset_type = self._get_actual_reset_type(reset_type)
745743

746744
LOG.debug("reset, core %d, type=%s", self.core_number, reset_type.name)
747745

746+
# The HW reset type is passed to the DP, which itself sends reset notifications.
747+
if reset_type is not Target.ResetType.HW:
748+
self.session.notify(Target.Event.PRE_RESET, self)
749+
748750
self._run_token += 1
749751

750752
# Give the delegate a chance to overide reset. If the delegate returns True, then it
@@ -766,7 +768,8 @@ def reset(self, reset_type=None):
766768
self.flush()
767769
sleep(0.01)
768770

769-
self.session.notify(Target.Event.POST_RESET, self)
771+
if reset_type is not Target.ResetType.HW:
772+
self.session.notify(Target.Event.POST_RESET, self)
770773

771774
def set_reset_catch(self, reset_type=None):
772775
"""! @brief Prepare to halt core on reset."""

0 commit comments

Comments
 (0)