[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/>.
*/
/* This file implements the transport generic functions of the
* ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A.
/* This file implements the transport generic functions.
* See the following ARM Reference Documents:
*
* ARM Debug Interface v5 Architecure Specification, ARM IHI 0031E
*/
#include "general.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 */
uint32_t cid_class = (cidr & CID_CLASS_MASK) >> CID_CLASS_SHIFT;
if (cid_class == cidc_romtab) { /* ROM table, probe recursively */
for (int i = 0; i < 256; i++) {
/* ROM table */
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);
if (adiv5_dp_error(ap->dp)) {
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)
break;
if ((entry & 1) == 0)
if (!(entry & ADIV5_ROM_ROMENTRY_PRESENT)) {
DEBUG("%d Entry 0x%"PRIx32" -> Not present\n", i, entry);
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 {
/* Check if the component was designed by ARM, we currently do not support,
* any components by other designers.
@ -320,10 +344,10 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr)
int i;
for (i = 0; pidr_pn_bits[i].arch != aa_end; i++) {
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],
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
* class.
*/
@ -366,8 +390,9 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel)
tmpap.dp = dp;
tmpap.apsel = apsel;
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;
/* 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 *);
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 */
adiv5_ap_unref(ap);
continue;

View File

@ -106,6 +106,18 @@
#define ADIV5_AP_CSW_SIZE_WORD (2u << 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 */
#define ADIV5_LOW_WRITE 0
#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);
#endif

View File

@ -129,7 +129,8 @@ enum stm32h7_regs
#define OPTKEY2 0x4C5D6E7F
#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_CR (DBGMCU_IDCODE + 4)
#define DBGSLEEP_D1 (1 << 0)