Skip to content

Commit 05946ba

Browse files
authored
Merge pull request pyocd#898 from flit/cleanup/dap
Miscellaneous DAP cleanup and small fixes
2 parents 3f5fca2 + 148b0c2 commit 05946ba

File tree

3 files changed

+72
-73
lines changed

3 files changed

+72
-73
lines changed

pyocd/coresight/ap.py

Lines changed: 60 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ def __init__(self, dp, ap_address, idr=None, name="", flags=0, cmpid=None):
485485
self._cached_csw = -1
486486

487487
## Supported transfer sizes.
488-
self._transfer_sizes = (32)
488+
self._transfer_sizes = (32,)
489489

490490
## Auto-increment wrap modulus.
491491
#
@@ -497,6 +497,9 @@ def __init__(self, dp, ap_address, idr=None, name="", flags=0, cmpid=None):
497497
## Number of DAR registers.
498498
self._dar_count = 0
499499

500+
## Mask of addresses. This indicates whether 32-bit or 64-bit addresses are supported.
501+
self._address_mask = 0xffffffff
502+
500503
# Ask the probe for an accelerated memory interface for this AP. If it provides one,
501504
# then bind our memory interface APIs to its methods. Otherwise use our standard
502505
# memory interface based on AP register accesses.
@@ -525,10 +528,7 @@ def init(self):
525528
self._init_transfer_sizes()
526529
self._init_hprot()
527530
self._init_rom_table_base()
528-
529-
# For v2 MEM-APs, read the CFG register.
530-
if self.ap_version == APVersion.APv2:
531-
self._init_cfg()
531+
self._init_cfg()
532532

533533
def _init_transfer_sizes(self):
534534
"""! @brief Determine supported transfer sizes.
@@ -593,44 +593,50 @@ def _init_hprot(self):
593593
def _init_rom_table_base(self):
594594
"""! @brief Read ROM table base address."""
595595
base = self.read_reg(self._reg_offset + MEM_AP_BASE)
596-
597596
is_adiv5_base = (base & AP_BASE_FORMAT_MASK) != 0
598597
is_base_present = (base & AP_BASE_ENTRY_PRESENT_MASK) != 0
599-
if (base == AP_BASE_LEGACY_NOTPRESENT) or (is_adiv5_base and not is_base_present):
598+
is_legacy_base_present = not is_adiv5_base and not is_base_present
599+
if is_legacy_base_present:
600+
self.has_rom_table = True
601+
self.rom_addr = base & AP_BASE_LEGACY_BASEADDR_MASK # clear format and present bits
602+
elif (base == AP_BASE_LEGACY_NOTPRESENT) or (not is_base_present):
600603
self.has_rom_table = False
601604
self.rom_addr = 0
602605
elif is_adiv5_base and is_base_present:
603606
self.has_rom_table = True
604607
self.rom_addr = base & AP_BASE_BASEADDR_MASK # clear format and present bits
605-
elif not is_adiv5_base:
606-
self.has_rom_table = True
607-
self.rom_addr = base & AP_BASE_LEGACY_BASEADDR_MASK # clear format and present bits
608608
else:
609-
assert False, "Unhandled AP BASE value 0x%08x" % base
609+
raise exceptions.TargetError("invalid AP BASE value 0x%08x" % base)
610610

611611
def _init_cfg(self):
612-
"""! @brief Read MEM-APv2 CFG register."""
612+
"""! @brief Read MEM-AP CFG register."""
613613
cfg = self.read_reg(self._reg_offset + MEM_AP_CFG)
614614

615-
# Set autoinc page size if TARINC is non-zero. Otherwise we've already set the
616-
# default of 1 kB in the ctor.
617-
tarinc = (cfg & MEM_AP_CFG_TARINC_MASK) >> MEM_AP_CFG_TARINC_SHIFT
618-
if tarinc != 0:
619-
self.auto_increment_page_size = 1 << (9 + tarinc)
615+
# Check for 64-bit address support.
616+
if cfg & MEM_AP_CFG_LA_MASK:
617+
self._address_mask = 0xffffffffffffffff
618+
619+
# Check v2 MEM-AP CFG fields.
620+
if self.ap_version == APVersion.APv2:
621+
# Set autoinc page size if TARINC is non-zero. Otherwise we've already set the
622+
# default of 1 kB in the ctor.
623+
tarinc = (cfg & MEM_AP_CFG_TARINC_MASK) >> MEM_AP_CFG_TARINC_SHIFT
624+
if tarinc != 0:
625+
self.auto_increment_page_size = 1 << (9 + tarinc)
620626

621-
# Determine supported err mode.
622-
err = (cfg & MEM_AP_CFG_ERR_MASK) >> MEM_AP_CFG_ERR_SHIFT
623-
if err == MEM_AP_CFG_ERR_V1:
624-
# Configure the error mode such that errors are passed upstream, but they don't
625-
# prevent future transactions.
626-
self._csw &= ~(CSW_ERRSTOP | CSW_ERRNPASS)
627+
# Determine supported err mode.
628+
err = (cfg & MEM_AP_CFG_ERR_MASK) >> MEM_AP_CFG_ERR_SHIFT
629+
if err == MEM_AP_CFG_ERR_V1:
630+
# Configure the error mode such that errors are passed upstream, but they don't
631+
# prevent future transactions.
632+
self._csw &= ~(CSW_ERRSTOP | CSW_ERRNPASS)
627633

628-
# Clear TRR in case we attach to a device with a sticky error already set.
629-
self.write_reg(self._reg_offset + MEM_AP_TRR, MEM_AP_TRR_ERR_MASK)
634+
# Clear TRR in case we attach to a device with a sticky error already set.
635+
self.write_reg(self._reg_offset + MEM_AP_TRR, MEM_AP_TRR_ERR_MASK)
630636

631-
# Init size of DAR register window.
632-
darsize = (cfg & MEM_AP_CFG_DARSIZE_MASK) >> MEM_AP_CFG_DARSIZE_SHIFT
633-
self._dar_count = (1 << darsize) // 4
637+
# Init size of DAR register window.
638+
darsize = (cfg & MEM_AP_CFG_DARSIZE_MASK) >> MEM_AP_CFG_DARSIZE_SHIFT
639+
self._dar_count = (1 << darsize) // 4
634640

635641
@locked
636642
def find_components(self):
@@ -758,7 +764,7 @@ def read_reg(self, addr, now=True):
758764
ap_regaddr = addr & APREG_MASK
759765
if ap_regaddr == self._reg_offset + MEM_AP_CSW and self._cached_csw != -1 and now:
760766
return self._cached_csw
761-
return super(MEM_AP, self).read_reg(addr, now)
767+
return self.dp.read_ap(self.address.address + addr, now)
762768

763769
@locked
764770
def write_reg(self, addr, data):
@@ -775,7 +781,7 @@ def write_reg(self, addr, data):
775781
self._cached_csw = data
776782

777783
try:
778-
super(MEM_AP, self).write_reg(addr, data)
784+
self.dp.write_ap(self.address.address + addr, data)
779785
except exceptions.ProbeError:
780786
# Invalidate cached CSW on exception.
781787
if ap_regaddr == self._reg_offset + MEM_AP_CSW:
@@ -796,6 +802,7 @@ def _write_memory(self, addr, data, transfer_size=32):
796802
@exception TransferError Raised if the requested transfer size is not supported by the AP.
797803
"""
798804
assert (addr & (transfer_size // 8 - 1)) == 0
805+
addr &= self._address_mask
799806
if transfer_size not in self._transfer_sizes:
800807
raise exceptions.TransferError("%d-bit transfers are not supported by %s"
801808
% (transfer_size, self.short_description))
@@ -831,6 +838,7 @@ def _read_memory(self, addr, transfer_size=32, now=True):
831838
@exception TransferError Raised if the requested transfer size is not supported by the AP.
832839
"""
833840
assert (addr & (transfer_size // 8 - 1)) == 0
841+
addr &= self._address_mask
834842
if transfer_size not in self._transfer_sizes:
835843
raise exceptions.TransferError("%d-bit transfers are not supported by %s"
836844
% (transfer_size, self.short_description))
@@ -878,11 +886,12 @@ def read_mem_cb():
878886
else:
879887
return read_mem_cb
880888

881-
@locked
882-
def _write_block32(self, addr, data):
889+
def _write_block32_page(self, addr, data):
883890
"""! @brief Write a single transaction's worth of aligned words.
884891
885892
The transaction must not cross the MEM-AP's auto-increment boundary.
893+
894+
This method is not locked because it is only called by _write_memory_block32(), which is locked.
886895
"""
887896
assert (addr & 0x3) == 0
888897
num = self.dp.next_access_number
@@ -904,11 +913,12 @@ def _write_block32(self, addr, data):
904913
raise
905914
TRACE.debug("_write_block32:%06d }", num)
906915

907-
@locked
908-
def _read_block32(self, addr, size):
916+
def _read_block32_page(self, addr, size):
909917
"""! @brief Read a single transaction's worth of aligned words.
910918
911919
The transaction must not cross the MEM-AP's auto-increment boundary.
920+
921+
This method is not locked because it is only called by _read_memory_block32(), which is locked.
912922
"""
913923
assert (addr & 0x3) == 0
914924
num = self.dp.next_access_number
@@ -935,12 +945,13 @@ def _read_block32(self, addr, size):
935945
def _write_memory_block32(self, addr, data):
936946
"""! @brief Write a block of aligned words in memory."""
937947
assert (addr & 0x3) == 0
948+
addr &= self._address_mask
938949
size = len(data)
939950
while size > 0:
940951
n = self.auto_increment_page_size - (addr & (self.auto_increment_page_size - 1))
941952
if size*4 < n:
942953
n = (size*4) & 0xfffffffc
943-
self._write_block32(addr, data[:n//4])
954+
self._write_block32_page(addr, data[:n//4])
944955
data = data[n//4:]
945956
size -= n//4
946957
addr += n
@@ -950,15 +961,16 @@ def _write_memory_block32(self, addr, data):
950961
def _read_memory_block32(self, addr, size):
951962
"""! @brief Read a block of aligned words in memory.
952963
953-
@return An array of word values
964+
@return A list of word values.
954965
"""
955966
assert (addr & 0x3) == 0
967+
addr &= self._address_mask
956968
resp = []
957969
while size > 0:
958970
n = self.auto_increment_page_size - (addr & (self.auto_increment_page_size - 1))
959971
if size*4 < n:
960972
n = (size*4) & 0xfffffffc
961-
resp += self._read_block32(addr, n//4)
973+
resp += self._read_block32_page(addr, n//4)
962974
size -= n//4
963975
addr += n
964976
return resp
@@ -970,54 +982,33 @@ def _handle_error(self, error, num):
970982
class AHB_AP(MEM_AP):
971983
"""! @brief AHB-AP access port subclass.
972984
973-
This subclass adds checking for the master type bit in the CSW register. Only the M3/M4 AHB-AP
974-
implements it. If supported, the master type is set to debugger.
985+
This subclass checks for the AP_MSTRTYPE flag, and if set configures that field in the CSW
986+
register to use debugger transactions. Only the M3 and M4 AHB-AP implements MSTRTYPE.
975987
976988
Another AHB-AP specific addition is that an attempt is made to set the TRCENA bit in the DEMCR
977989
register before reading the ROM table. This is required on some Cortex-M devices, otherwise
978-
certain ROM table entries will read as zeroes.
990+
certain ROM table entries will read as zeroes or other garbage.
979991
"""
980992

981993
@locked
982994
def init(self):
983995
super(AHB_AP, self).init()
984996

985997
# Check for and enable the Master Type bit on AHB-APs where it might be implemented.
986-
if (self.ap_version == APVersion.APv1) \
987-
or ((self._cmpid is not None) and (self._cmpid.archid == UNKNOWN_AP_ARCHID)):
998+
if self._flags & AP_MSTRTYPE:
988999
self._init_mstrtype()
9891000

9901001
def _init_mstrtype(self):
991-
"""! @brief Detect and set master type control in CSW.
1002+
"""! @brief Set master type control in CSW.
9921003
9931004
Only the v1 AHB-AP from Cortex-M3 and Cortex-M4 implements the MSTRTYPE flag to control
9941005
whether transactions appear as debugger or internal accesses.
9951006
"""
996-
# Read initial CSW value to check if the MSTRTYPE bit is implemented. It is most
997-
# likely already set.
998-
original_csw = AccessPort.read_reg(self, self._reg_offset + MEM_AP_CSW)
999-
impl_master_type = original_csw & CSW_MSTRTYPE
1000-
1001-
# If MSTRTYPE is not set, attempt to write it.
1002-
if impl_master_type == 0:
1003-
# Verify no transfer is in progress.
1004-
1005-
# Set MSTRTYPE and read back to see if it sticks.
1006-
AccessPort.write_reg(self, self._reg_offset + MEM_AP_CSW, original_csw | CSW_MSTRTYPE)
1007-
csw = AccessPort.read_reg(self, self._reg_offset + MEM_AP_CSW)
1008-
1009-
# Restore unmodified value of CSW.
1010-
if csw != original_csw:
1011-
AccessPort.write_reg(self, self._reg_offset + MEM_AP_CSW, original_csw)
1012-
1013-
impl_master_type = csw & CSW_MSTRTYPE
1014-
1015-
# Set the master type to debugger for AP's that support this field.
1016-
if impl_master_type != 0:
1017-
self._csw |= CSW_MSTRDBG
1007+
# Set the master type to "debugger" for AP's that support this field.
1008+
self._csw |= CSW_MSTRDBG
10181009

10191010
def find_components(self):
1020-
# Turn on DEMCR.TRCENA before reading the ROM table. Some ROM table entries will
1011+
# Turn on DEMCR.TRCENA before reading the ROM table. Some ROM table entries can
10211012
# come back as garbage if TRCENA is not set.
10221013
try:
10231014
demcr = self.read32(DEMCR)
@@ -1053,13 +1044,14 @@ def find_components(self):
10531044
# AP flags.
10541045
AP_4K_WRAP = 0x1 # The AP has a 4 kB auto-increment modulus.
10551046
AP_ALL_TX_SZ = 0x2 # The AP is known to support 8-, 16-, and 32-bit transfers.
1047+
AP_MSTRTYPE = 0x4 # The AP is known to support the MSTRTYPE field.
10561048

10571049
## Map from AP IDR fields to AccessPort subclass.
10581050
#
10591051
# The dict maps from a 4-tuple of (JEP106 code, AP class, variant, type) to 2-tuple (name, class, flags).
10601052
#
10611053
# Known AP IDRs:
1062-
# 0x24770011 AHB-AP with 0x1000 wrap
1054+
# 0x24770011 AHB-AP with 0x1000 wrap and MSTRTYPE
10631055
# Used on m4 & m3 - Documented in arm_cortexm4_processor_trm_100166_0001_00_en.pdf
10641056
# and arm_cortexm3_processor_trm_100165_0201_00_en.pdf
10651057
# 0x34770001 AHB-AP Documented in DDI0314H_coresight_components_trm.pdf
@@ -1078,7 +1070,7 @@ def find_components(self):
10781070
(AP_JEP106_ARM, AP_CLASS_JTAG_AP, 0, 0): ("JTAG-AP", AccessPort, 0 ),
10791071
(AP_JEP106_ARM, AP_CLASS_COM_AP, 0, 0): ("SDC-600", AccessPort, 0 ),
10801072
(AP_JEP106_ARM, AP_CLASS_MEM_AP, 0, AP_TYPE_AHB): ("AHB-AP", AHB_AP, AP_ALL_TX_SZ ),
1081-
(AP_JEP106_ARM, AP_CLASS_MEM_AP, 1, AP_TYPE_AHB): ("AHB-AP", AHB_AP, AP_ALL_TX_SZ|AP_4K_WRAP ),
1073+
(AP_JEP106_ARM, AP_CLASS_MEM_AP, 1, AP_TYPE_AHB): ("AHB-AP", AHB_AP, AP_ALL_TX_SZ|AP_4K_WRAP|AP_MSTRTYPE ),
10821074
(AP_JEP106_ARM, AP_CLASS_MEM_AP, 2, AP_TYPE_AHB): ("AHB-AP", AHB_AP, AP_ALL_TX_SZ ),
10831075
(AP_JEP106_ARM, AP_CLASS_MEM_AP, 3, AP_TYPE_AHB): ("AHB-AP", AHB_AP, AP_ALL_TX_SZ ),
10841076
(AP_JEP106_ARM, AP_CLASS_MEM_AP, 4, AP_TYPE_AHB): ("AHB-AP", AHB_AP, AP_ALL_TX_SZ ),

pyocd/coresight/dap.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ def power_up_debug(self):
331331
@return Boolean indicating whether the power up request succeeded.
332332
"""
333333
# Send power up request for system and debug.
334-
self.write_reg(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ)
334+
self.write_reg(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ | MASKLANE | TRNNORMAL)
335335

336336
with Timeout(DP_POWER_REQUEST_TIMEOUT) as time_out:
337337
while time_out.check():
@@ -341,7 +341,7 @@ def power_up_debug(self):
341341
else:
342342
return False
343343

344-
self.write_reg(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ | TRNNORMAL | MASKLANE)
344+
self.write_reg(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ | MASKLANE | TRNNORMAL)
345345

346346
return True
347347

@@ -356,7 +356,7 @@ def power_down_debug(self):
356356
@return Boolean indicating whether the power down request succeeded.
357357
"""
358358
# Power down system first.
359-
self.write_reg(DP_CTRL_STAT, CDBGPWRUPREQ)
359+
self.write_reg(DP_CTRL_STAT, CDBGPWRUPREQ | MASKLANE | TRNNORMAL)
360360

361361
with Timeout(DP_POWER_REQUEST_TIMEOUT) as time_out:
362362
while time_out.check():
@@ -367,7 +367,7 @@ def power_down_debug(self):
367367
return False
368368

369369
# Now power down debug.
370-
self.write_reg(DP_CTRL_STAT, 0)
370+
self.write_reg(DP_CTRL_STAT, MASKLANE | TRNNORMAL)
371371

372372
with Timeout(DP_POWER_REQUEST_TIMEOUT) as time_out:
373373
while time_out.check():
@@ -499,6 +499,8 @@ def _handle_error(self, error, num):
499499
self.clear_sticky_err()
500500
# For timeouts caused by WAIT responses, set DAPABORT to abort the transfer.
501501
elif isinstance(error, exceptions.TransferTimeoutError):
502+
# This may put the AP that was aborted into an unpredictable state. Should consider
503+
# attempting to reset debug logic.
502504
self.write_reg(DP_ABORT, ABORT_DAPABORT)
503505

504506
def clear_sticky_err(self):
@@ -507,7 +509,8 @@ def clear_sticky_err(self):
507509
if mode == DebugProbe.Protocol.SWD:
508510
self.write_reg(DP_ABORT, ABORT_ORUNERRCLR | ABORT_WDERRCLR | ABORT_STKERRCLR | ABORT_STKCMPCLR)
509511
elif mode == DebugProbe.Protocol.JTAG:
510-
self.write_reg(DP_CTRL_STAT, CTRLSTAT_STICKYERR | CTRLSTAT_STICKYCMP | CTRLSTAT_STICKYORUN)
512+
self.write_reg(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ | TRNNORMAL | MASKLANE
513+
| CTRLSTAT_STICKYERR | CTRLSTAT_STICKYCMP | CTRLSTAT_STICKYORUN)
511514
else:
512515
assert False
513516

pyocd/probe/stlink_probe.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ def write_memory(self, addr, data, transfer_size=32):
229229
By default the transfer size is a word.
230230
"""
231231
assert transfer_size in (8, 16, 32)
232+
addr &= 0xffffffff
232233
if transfer_size == 32:
233234
self._link.write_mem32(addr, conversion.u32le_list_to_byte_list([data]), self._apsel)
234235
elif transfer_size == 16:
@@ -242,6 +243,7 @@ def read_memory(self, addr, transfer_size=32, now=True):
242243
By default, a word will be read.
243244
"""
244245
assert transfer_size in (8, 16, 32)
246+
addr &= 0xffffffff
245247
if transfer_size == 32:
246248
result = conversion.byte_list_to_u32le_list(self._link.read_mem32(addr, 4, self._apsel))[0]
247249
elif transfer_size == 16:
@@ -254,8 +256,10 @@ def read_callback():
254256
return result if now else read_callback
255257

256258
def write_memory_block32(self, addr, data):
259+
addr &= 0xffffffff
257260
self._link.write_mem32(addr, conversion.u32le_list_to_byte_list(data), self._apsel)
258261

259262
def read_memory_block32(self, addr, size):
263+
addr &= 0xffffffff
260264
return conversion.byte_list_to_u32le_list(self._link.read_mem32(addr, size * 4, self._apsel))
261265

0 commit comments

Comments
 (0)