On Monday 18 January 2010, Alan Carvalho de Assis wrote:

> When I type halt the prompt get blocked and about 1 minute after I
> receive this error:
> 
> > halt
> AHBAP Cached values: dp_select 0x10, ap_csw 0xa2000002, ap_tar 0x54011080
> JTAG-DP OVERRUN - check clock or reduce jtag speed
> Read MEM_AP_CSW 0x80000042, MEM_AP_TAR 0x54011080
> 
> I already reduced the jtag speed to 500khz and this error remain.
> 
> What could I investigate now to fix this error?

Unfortunately I think you're starting to hit some of the ways
that the DAP code is ... a bit flakey.  Especially with respect
to how it handles errors reported by the DP or AP; it triggers
faults a bit more often (and randomly) than I would expect, and
the cleanup -- and mode selection -- looks a bit iffy to me.

I attach a couple patches which I've been using, which might
change things (or might not).  If they help, good.

 - adi-shrink.patch ... code shrinkage and fault path fixes

 - adi-write.patch ... goes over that, basically just cleanup

If not, then there's something else you could build on top
of these.  Basically, after adi-shrink.patch there is ONE
"REVISIT" comment about putting the memaccess_tck cycles in
the proper place.  Fix that issue -- just put those cycles
at the end of adi_jtag_dp_scan() not the beginning, after
the jtag_add_dr_scan().  (Before that patch, that was done
wrong in *two* places.)

The OVERRUN error comes from throwing data at the MEM-AP
faster than it can handle it.  MEM-AP speed is a system
specific issue.  Exactly the sort of thing MX51 could very
reasonably do differently from the other Cortex parts which
now mostly work.  (I'm not quite clear on how much of that
is driven by the JTAG clock vs by whatever core clock your
chip may be using.)  There are two issues I'd wonder about:

 * First, whether the code is correct ... ergo the
   attached patches and that REVISIT comment.

 * Second, whether you need a different memaccess_tck
   value.

The ADIv5 spec will be useful to sort out such issues.

- Dave

From: David Brownell <dbrown...@users.sourceforge.net>
Subject: ARM: ADIv5, deadcode cleanup

I have no idea what the scan_inout_check() was *expecting* to achieve by
issuing a read of the DP_RDBUFF register.  But in any case, that code was
clearly never being called ("invalue" always NULL) ... so remove it, and
the associated comment.

Also rename it as ap_write_check(), allowing a cleanup of its remaining
call site by removing constant parameters.
---
 src/target/arm_adi_v5.c |   26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -177,23 +177,24 @@ static int adi_jtag_dp_scan_u32(struct s
 	return retval;
 }
 
-/* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */
-static int scan_inout_check(struct swjdp_common *swjdp,
-		uint8_t instr, uint8_t reg_addr, uint8_t RnW,
-		uint8_t *outvalue, uint8_t *invalue)
+/**
+ * Utility to write AP registers.
+ */
+static int ap_write_check(struct swjdp_common *dap,
+		uint8_t reg_addr, uint8_t *outvalue)
 {
-	adi_jtag_dp_scan(swjdp, instr, reg_addr, RnW, outvalue, NULL, NULL);
+	adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE,
+			outvalue, NULL, NULL);
 
-	if ((RnW == DPAP_READ) && (invalue != NULL))
-		adi_jtag_dp_scan(swjdp, JTAG_DP_DPACC,
-				DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack);
+	/* REVISIT except in dap_setup_accessport() almost all call paths
+	 * set up COMPOSITE.  Probably worth just inlining the scan...
+	 */
 
 	/* In TRANS_MODE_ATOMIC all JTAG_DP_APACC transactions wait for
 	 * ack = OK/FAULT and the check CTRL_STAT
 	 */
-	if ((instr == JTAG_DP_APACC)
-			&& (swjdp->trans_mode == TRANS_MODE_ATOMIC))
-		return swjdp_transaction_endcheck(swjdp);
+	if (dap->trans_mode == TRANS_MODE_ATOMIC)
+		return swjdp_transaction_endcheck(dap);
 
 	return ERROR_OK;
 }
@@ -396,8 +397,7 @@ static int dap_ap_write_reg(struct swjdp
 		uint32_t reg_addr, uint8_t *out_value_buf)
 {
 	dap_dp_bankselect(swjdp, reg_addr);
-	return scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr,
-			DPAP_WRITE, out_value_buf, NULL);
+	return ap_write_check(swjdp, reg_addr, out_value_buf);
 }
 
 int dap_ap_write_reg_u32(struct swjdp_common *swjdp, uint32_t reg_addr, uint32_t value)
From: David Brownell <dbrown...@users.sourceforge.net>
Subject: ARM: ADIv5 code shrinkage, cleanup

Make two functions become 32-bit wrappers for lower level code which
is, for some curious reason, ignoring the architecture by pretending
the DAP access primitives aren't all 32-bits wide:

 - adi_jtag_dp_scan_u32() now wraps adi_jtag_dp_scan(), removing
   code duplication.  Include doxygen for the former, and comment
   some particularly relevant points.

 - dap_ap_write_reg_u32() now wraps dap_ap_write_reg(), removing
   code duplication.

Make various routines pass up fault codes from the code they call,
instead of pretending no fault could be reported:

	dap_ap_read_reg_u32()
	dap_ap_write_reg()
	dap_ap_write_reg_u32()
	dap_dp_bankselect()

	mem_ap_read_u32()
	mem_ap_write_u32()

	dap_info_command()

---
 src/target/arm_adi_v5.c |   79 +++++++++++-----------------------------------
 1 file changed, 19 insertions(+), 60 deletions(-)

--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -150,58 +150,31 @@ static int adi_jtag_dp_scan(struct swjdp
 
 	jtag_add_dr_scan(2, fields, jtag_get_end_state());
 
-	return ERROR_OK;
+	return jtag_get_error();
 }
 
-/* Scan out and in from host ordered uint32_t variables */
+/**
+ * Scan DPACC or APACC out and in from host ordered uint32_t buffers.
+ * This is exactly like adi_jtag_dp_scan(), except that endianness
+ * conversions are performed (so the types of invalue and outvalue
+ * must be different).
+ */
 static int adi_jtag_dp_scan_u32(struct swjdp_common *swjdp,
 		uint8_t instr, uint8_t reg_addr, uint8_t RnW,
 		uint32_t outvalue, uint32_t *invalue, uint8_t *ack)
 {
-	struct arm_jtag *jtag_info = swjdp->jtag_info;
-	struct scan_field fields[2];
 	uint8_t out_value_buf[4];
-	uint8_t out_addr_buf;
-
-	jtag_set_end_state(TAP_IDLE);
-	arm_jtag_set_instr(jtag_info, instr, NULL);
-
-	/* Add specified number of tck clocks before accessing memory bus */
-
-	/* REVISIT these TCK cycles should be *AFTER*  updating APACC, since
-	 * they provide more time for the (MEM) AP to complete the read ...
-	 */
-	if ((instr == JTAG_DP_APACC)
-			&& ((reg_addr == AP_REG_DRW)
-				|| ((reg_addr & 0xF0) == AP_REG_BD0))
-			&& (swjdp->memaccess_tck != 0))
-		jtag_add_runtest(swjdp->memaccess_tck, jtag_set_end_state(TAP_IDLE));
-
-	fields[0].tap = jtag_info->tap;
-	fields[0].num_bits = 3;
-	buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));
-	fields[0].out_value = &out_addr_buf;
-	fields[0].in_value = ack;
+	int retval;
 
-	fields[1].tap = jtag_info->tap;
-	fields[1].num_bits = 32;
 	buf_set_u32(out_value_buf, 0, 32, outvalue);
-	fields[1].out_value = out_value_buf;
-	fields[1].in_value = NULL;
 
-	if (invalue)
-	{
-		fields[1].in_value = (uint8_t *)invalue;
-		jtag_add_dr_scan(2, fields, jtag_get_end_state());
+	retval = adi_jtag_dp_scan(swjdp, instr, reg_addr, RnW,
+			out_value_buf, (uint8_t *)invalue, ack);
 
+	if (invalue)
 		jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t) invalue);
-	} else
-	{
 
-		jtag_add_dr_scan(2, fields, jtag_get_end_state());
-	}
-
-	return ERROR_OK;
+	return retval;
 }
 
 /* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */
@@ -412,8 +385,8 @@ static int dap_dp_bankselect(struct swjd
 
 	if (select != swjdp->dp_select_value)
 	{
-		dap_dp_write_reg(swjdp, select | swjdp->apsel, DP_SELECT);
 		swjdp->dp_select_value = select;
+		return dap_dp_write_reg(swjdp, select | swjdp->apsel, DP_SELECT);
 	}
 
 	return ERROR_OK;
@@ -423,10 +396,8 @@ static int dap_ap_write_reg(struct swjdp
 		uint32_t reg_addr, uint8_t *out_value_buf)
 {
 	dap_dp_bankselect(swjdp, reg_addr);
-	scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr,
+	return scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr,
 			DPAP_WRITE, out_value_buf, NULL);
-
-	return ERROR_OK;
 }
 
 int dap_ap_write_reg_u32(struct swjdp_common *swjdp, uint32_t reg_addr, uint32_t value)
@@ -434,20 +405,14 @@ int dap_ap_write_reg_u32(struct swjdp_co
 	uint8_t out_value_buf[4];
 
 	buf_set_u32(out_value_buf, 0, 32, value);
-	dap_dp_bankselect(swjdp, reg_addr);
-	scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr,
-			DPAP_WRITE, out_value_buf, NULL);
-
-	return ERROR_OK;
+	return dap_ap_write_reg(swjdp, reg_addr, out_value_buf);
 }
 
 int dap_ap_read_reg_u32(struct swjdp_common *swjdp, uint32_t reg_addr, uint32_t *value)
 {
 	dap_dp_bankselect(swjdp, reg_addr);
-	scan_inout_check_u32(swjdp, JTAG_DP_APACC, reg_addr,
+	return scan_inout_check_u32(swjdp, JTAG_DP_APACC, reg_addr,
 			DPAP_READ, 0, value);
-
-	return ERROR_OK;
 }
 
 /***************************************************************************
@@ -492,9 +457,7 @@ int mem_ap_read_u32(struct swjdp_common 
 	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
 
 	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);
-	dap_ap_read_reg_u32(swjdp, AP_REG_BD0 | (address & 0xC), value);
-
-	return ERROR_OK;
+	return dap_ap_read_reg_u32(swjdp, AP_REG_BD0 | (address & 0xC), value);
 }
 
 int mem_ap_read_atomic_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t *value)
@@ -516,9 +479,7 @@ int mem_ap_write_u32(struct swjdp_common
 	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
 
 	dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);
-	dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (address & 0xC), value);
-
-	return ERROR_OK;
+	return dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (address & 0xC), value);
 }
 
 int mem_ap_write_atomic_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t value)
@@ -1491,9 +1452,7 @@ int dap_info_command(struct command_cont
 	{
 		command_print(cmd_ctx, "\tNo ROM table present");
 	}
-	dap_ap_select(swjdp, apselold);
-
-	return ERROR_OK;
+	return dap_ap_select(swjdp, apselold);
 }
 
 DAP_COMMAND_HANDLER(dap_baseaddr_command)
_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to