[adiv5] Improvements in ADIv5

* Reference latest version of the ARM specification
* ROM tables - more debug information, including printing SYSMEM bit
* MEM-AP - reject when Debug Base Address entry is not
  present/invalid. These would only have errored in
  adiv5_component_probe.
* Fix maximum number of entries in Class 0x1 ROM Table to 960. See ARM
  IHI 0031E Table D3-1 ROM Table register summary.
* Resolve note in STM32H7 driver with explaination

blackmagic PR #474
This commit is contained in:
Richard Meadows 2019-05-18 18:54:26 +01:00 committed by UweBonnes
parent 703f88a969
commit 61e9607594
3 changed files with 53 additions and 12 deletions

View File

@ -18,8 +18,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
/* This file implements the transport generic functions of the /* This file implements the transport generic functions.
* ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A. * See the following ARM Reference Documents:
*
* ARM Debug Interface v5 Architecure Specification, ARM IHI 0031E
*/ */
#include "general.h" #include "general.h"
#include "target.h" #include "target.h"
@ -287,8 +289,22 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
/* Extract Component ID class nibble */ /* Extract Component ID class nibble */
uint32_t cid_class = (cidr & CID_CLASS_MASK) >> CID_CLASS_SHIFT; uint32_t cid_class = (cidr & CID_CLASS_MASK) >> CID_CLASS_SHIFT;
if (cid_class == cidc_romtab) { /* ROM table, probe recursively */ /* ROM table */
for (int i = 0; i < 256; i++) { if (cid_class == cidc_romtab) {
/* Check SYSMEM bit */
#ifdef ENABLE_DEBUG
uint32_t memtype = adiv5_mem_read32(ap, addr | ADIV5_ROM_MEMTYPE) &
ADIV5_ROM_MEMTYPE_SYSMEM;
if (adiv5_dp_error(ap->dp)) {
DEBUG("Fault reading ROM table entry\n");
}
DEBUG("\nROM: Table BASE=0x%"PRIx32" SYSMEM=0x%"PRIx32"\n",
addr, memtype);
#endif
for (int i = 0; i < 960; i++) {
uint32_t entry = adiv5_mem_read32(ap, addr + i*4); uint32_t entry = adiv5_mem_read32(ap, addr + i*4);
if (adiv5_dp_error(ap->dp)) { if (adiv5_dp_error(ap->dp)) {
DEBUG("Fault reading ROM table entry\n"); DEBUG("Fault reading ROM table entry\n");
@ -297,11 +313,19 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
if (entry == 0) if (entry == 0)
break; break;
if ((entry & 1) == 0) if (!(entry & ADIV5_ROM_ROMENTRY_PRESENT)) {
DEBUG("%d Entry 0x%"PRIx32" -> Not present\n", i, entry);
continue; continue;
}
res |= adiv5_component_probe(ap, addr + (entry & ~0xfff)); DEBUG("%d Entry 0x%"PRIx32" -> 0x%"PRIx32"\n",
i, entry, addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET));
/* Probe recursively */
res |= adiv5_component_probe(ap,
addr + (entry & ADIV5_ROM_ROMENTRY_OFFSET));
} }
DEBUG("ROM: Table END\n\n");
} else { } else {
/* Check if the component was designed by ARM, we currently do not support, /* Check if the component was designed by ARM, we currently do not support,
* any components by other designers. * any components by other designers.
@ -320,10 +344,10 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
int i; int i;
for (i = 0; pidr_pn_bits[i].arch != aa_end; i++) { for (i = 0; pidr_pn_bits[i].arch != aa_end; i++) {
if (pidr_pn_bits[i].part_number == part_number) { if (pidr_pn_bits[i].part_number == part_number) {
DEBUG("0x%"PRIx32": %s - %s %s\n", addr, DEBUG("0x%"PRIx32": %s - %s %s (PIDR = 0x%"PRIx64")\n", addr,
cidc_debug_strings[cid_class], cidc_debug_strings[cid_class],
pidr_pn_bits[i].type, pidr_pn_bits[i].type,
pidr_pn_bits[i].full); pidr_pn_bits[i].full, pidr);
/* Perform sanity check, if we know what to expect as component ID /* Perform sanity check, if we know what to expect as component ID
* class. * class.
*/ */
@ -366,8 +390,9 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
tmpap.dp = dp; tmpap.dp = dp;
tmpap.apsel = apsel; tmpap.apsel = apsel;
tmpap.idr = adiv5_ap_read(&tmpap, ADIV5_AP_IDR); tmpap.idr = adiv5_ap_read(&tmpap, ADIV5_AP_IDR);
tmpap.base = adiv5_ap_read(&tmpap, ADIV5_AP_BASE);
if(!tmpap.idr) /* IDR Invalid - Should we not continue here? */ if(!tmpap.idr) /* IDR Invalid */
return NULL; return NULL;
/* It's valid to so create a heap copy */ /* It's valid to so create a heap copy */
@ -459,7 +484,11 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
extern void nrf51_mdm_probe(ADIv5_AP_t *); extern void nrf51_mdm_probe(ADIv5_AP_t *);
nrf51_mdm_probe(ap); nrf51_mdm_probe(ap);
if (ap->base == 0xffffffff) { /* Check the Debug Base Address register. See ADIv5
* Specification C2.6.1 */
if (!(ap->base & ADIV5_AP_BASE_PRESENT) ||
(ap->base == 0xffffffff)) {
/* Debug Base Address not present in this MEM-AP */
/* No debug entries... useless AP */ /* No debug entries... useless AP */
adiv5_ap_unref(ap); adiv5_ap_unref(ap);
continue; continue;

View File

@ -106,6 +106,18 @@
#define ADIV5_AP_CSW_SIZE_WORD (2u << 0) #define ADIV5_AP_CSW_SIZE_WORD (2u << 0)
#define ADIV5_AP_CSW_SIZE_MASK (7u << 0) #define ADIV5_AP_CSW_SIZE_MASK (7u << 0)
/* AP Debug Base Address Register (BASE) */
#define ADIV5_AP_BASE_BASEADDR (0xFFFFF000u)
#define ADIV5_AP_BASE_PRESENT (1u << 0)
/* ADIv5 Class 0x1 ROM Table Registers */
#define ADIV5_ROM_MEMTYPE 0xFCC
#define ADIV5_ROM_MEMTYPE_SYSMEM (1u << 0)
#define ADIV5_ROM_ROMENTRY_PRESENT (1u << 0)
#define ADIV5_ROM_ROMENTRY_OFFSET (0xFFFFF000u)
/* Constants to make RnW parameters more clear in code */ /* Constants to make RnW parameters more clear in code */
#define ADIV5_LOW_WRITE 0 #define ADIV5_LOW_WRITE 0
#define ADIV5_LOW_READ 1 #define ADIV5_LOW_READ 1
@ -190,4 +202,3 @@ void adiv5_mem_write_sized(ADIv5_AP_t *ap, uint32_t dest, const void *src,
size_t len, enum align align); size_t len, enum align align);
#endif #endif

View File

@ -129,7 +129,8 @@ enum stm32h7_regs
#define OPTKEY2 0x4C5D6E7F #define OPTKEY2 0x4C5D6E7F
#define DBGMCU_IDCODE 0x5c001000 #define DBGMCU_IDCODE 0x5c001000
/* Access via 0xe00e1000 does not show device! */ /* Access from processor address space.
* Access via the APB-D is at 0xe00e1000 */
#define DBGMCU_IDC (DBGMCU_IDCODE + 0) #define DBGMCU_IDC (DBGMCU_IDCODE + 0)
#define DBGMCU_CR (DBGMCU_IDCODE + 4) #define DBGMCU_CR (DBGMCU_IDCODE + 4)
#define DBGSLEEP_D1 (1 << 0) #define DBGSLEEP_D1 (1 << 0)