Gene Smith wrote:
Magnus Lundin wrote:
Here is a patch that helps against the well known OVERRUN errors for
Cortex-M3 ( the problem is even worse for Cortex-A8 )
Basically the patch adds a fixed number ( default 8 ) of extra tck
clocks before every DR scan that accesses the target memory bus through
the DAP_MEMAP.
This makes it possible to increase the jtag_khz, tested with JLink at
12MHz, improving total speed.
Contents:
+ change signature for adi_jtag_dp_scan and adi_jtag_dp_scan_u32 to use
swjdp_common_t *swjdp instead of arm_jtag_t *jtag_info
+ change SWJDP_IR/DR_APACC to DAP_IR/DR_APACC to conform with ARM_ADI docs.
+ add swjdp->memaccess_tck field and code for extra tck clocks before
accessing memory bus
+ Set default memaccess value to 8 for Cortex-M3
+ Add dap memaccess command
Tested with STM32 andOMAP3530 for several weeks, no known problems.
This should apply and build cleanly against trunk.
Apparently armv7m.c has some sort of problem against r2003. Something
about the copyright I think.
Seems like a editor screwup with Norweian letters.
I remove that part and repost
Index: src/target/arm_adi_v5.c
===================================================================
--- src/target/arm_adi_v5.c (revision 1977)
+++ src/target/arm_adi_v5.c (working copy)
@@ -59,43 +59,39 @@
***************************************************************************/
/* Scan out and in from target ordered u8 buffers */
-int adi_jtag_dp_scan(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack)
+int adi_jtag_dp_scan(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack)
{
+ arm_jtag_t *jtag_info = swjdp->jtag_info;
scan_field_t fields[2];
u8 out_addr_buf;
jtag_add_end_state(TAP_IDLE);
arm_jtag_set_instr(jtag_info, instr, NULL);
+ /* Add specified number of tck clocks before accessing memory bus */
+ if ((instr == DAP_IR_APACC) && ((reg_addr == AP_REG_DRW)||((reg_addr&0xF0) == AP_REG_BD0) )&& (swjdp->memaccess_tck != 0))
+ jtag_add_runtest(swjdp->memaccess_tck, 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;
-
-
-
-
fields[1].tap = jtag_info->tap;
fields[1].num_bits = 32;
fields[1].out_value = outvalue;
-
fields[1].in_value = invalue;
-
-
-
-
jtag_add_dr_scan(2, fields, TAP_INVALID);
return ERROR_OK;
}
/* Scan out and in from host ordered u32 variables */
-int adi_jtag_dp_scan_u32(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack)
+int adi_jtag_dp_scan_u32(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack)
{
+ arm_jtag_t *jtag_info = swjdp->jtag_info;
scan_field_t fields[2];
u8 out_value_buf[4];
u8 out_addr_buf;
@@ -103,20 +99,21 @@
jtag_add_end_state(TAP_IDLE);
arm_jtag_set_instr(jtag_info, instr, NULL);
+ /* Add specified number of tck clocks before accessing memory bus */
+ if ((instr == DAP_IR_APACC) && ((reg_addr == AP_REG_DRW)||((reg_addr&0xF0) == AP_REG_BD0) )&& (swjdp->memaccess_tck != 0))
+ jtag_add_runtest(swjdp->memaccess_tck, 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;
-
-
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)
{
@@ -136,14 +133,15 @@
/* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */
int scan_inout_check(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue)
{
- adi_jtag_dp_scan(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
+ adi_jtag_dp_scan(swjdp, instr, reg_addr, RnW, outvalue, NULL, NULL);
+
if ((RnW == DPAP_READ) && (invalue != NULL))
{
- adi_jtag_dp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack);
+ adi_jtag_dp_scan(swjdp, DAP_IR_DPACC, DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack);
}
- /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */
- if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
+ /* In TRANS_MODE_ATOMIC all DAP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */
+ if ((instr == DAP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
{
return swjdp_transaction_endcheck(swjdp);
}
@@ -153,14 +151,15 @@
int scan_inout_check_u32(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue)
{
- adi_jtag_dp_scan_u32(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
+ adi_jtag_dp_scan_u32(swjdp, instr, reg_addr, RnW, outvalue, NULL, NULL);
+
if ((RnW==DPAP_READ) && (invalue != NULL))
{
- adi_jtag_dp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack);
+ adi_jtag_dp_scan_u32(swjdp, DAP_IR_DPACC, DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack);
}
- /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and then check CTRL_STAT */
- if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
+ /* In TRANS_MODE_ATOMIC all DAP_IR_APACC transactions wait for ack=OK/FAULT and then check CTRL_STAT */
+ if ((instr == DAP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
{
return swjdp_transaction_endcheck(swjdp);
}
@@ -177,7 +176,7 @@
#if 0
/* Danger!!!! BROKEN!!!! */
- scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+ scan_inout_check_u32(swjdp, DAP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
/* Danger!!!! BROKEN!!!! Why will jtag_execute_queue() fail here????
R956 introduced the check on return value here and now Michael Schwingen reports
that this code no longer works....
@@ -191,7 +190,7 @@
/* Why??? second time it works??? */
#endif
- scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+ scan_inout_check_u32(swjdp, DAP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
if ((retval=jtag_execute_queue())!=ERROR_OK)
return retval;
@@ -216,7 +215,7 @@
return ERROR_JTAG_DEVICE_ERROR;
}
- scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+ scan_inout_check_u32(swjdp, DAP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
if ((retval=jtag_execute_queue())!=ERROR_OK)
return retval;
swjdp->ack = swjdp->ack & 0x7;
@@ -248,8 +247,8 @@
LOG_ERROR("SWJ-DP STICKY ERROR");
/* Clear Sticky Error Bits */
- scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat | SSTICKYORUN | SSTICKYERR, NULL);
- scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+ scan_inout_check_u32(swjdp, DAP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat | SSTICKYORUN | SSTICKYERR, NULL);
+ scan_inout_check_u32(swjdp, DAP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
if ((retval=jtag_execute_queue())!=ERROR_OK)
return retval;
@@ -278,12 +277,12 @@
int dap_dp_write_reg(swjdp_common_t *swjdp, u32 value, u8 reg_addr)
{
- return scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, value, NULL);
+ return scan_inout_check_u32(swjdp, DAP_IR_DPACC, reg_addr, DPAP_WRITE, value, NULL);
}
int dap_dp_read_reg(swjdp_common_t *swjdp, u32 *value, u8 reg_addr)
{
- return scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value);
+ return scan_inout_check_u32(swjdp, DAP_IR_DPACC, reg_addr, DPAP_READ, 0, value);
}
int dap_ap_select(swjdp_common_t *swjdp,u8 apsel)
@@ -294,7 +293,7 @@
if (select != swjdp->apsel)
{
swjdp->apsel = select;
- /* Switchin AP invalidates cached values */
+ /* Switching AP invalidates cached values */
swjdp->dp_select_value = -1;
swjdp->ap_csw_value = -1;
swjdp->ap_tar_value = -1;
@@ -320,7 +319,7 @@
int dap_ap_write_reg(swjdp_common_t *swjdp, u32 reg_addr, u8* out_value_buf)
{
dap_dp_bankselect(swjdp, reg_addr);
- scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+ scan_inout_check(swjdp, DAP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
return ERROR_OK;
}
@@ -328,7 +327,7 @@
int dap_ap_read_reg(swjdp_common_t *swjdp, u32 reg_addr, u8 *in_value_buf)
{
dap_dp_bankselect(swjdp, reg_addr);
- scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, in_value_buf);
+ scan_inout_check(swjdp, DAP_IR_APACC, reg_addr, DPAP_READ, 0, in_value_buf);
return ERROR_OK;
}
@@ -338,7 +337,7 @@
buf_set_u32(out_value_buf, 0, 32, value);
dap_dp_bankselect(swjdp, reg_addr);
- scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+ scan_inout_check(swjdp, DAP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
return ERROR_OK;
}
@@ -346,7 +345,7 @@
int dap_ap_read_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 *value)
{
dap_dp_bankselect(swjdp, reg_addr);
- scan_inout_check_u32(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, value);
+ scan_inout_check_u32(swjdp, DAP_IR_APACC, reg_addr, DPAP_READ, 0, value);
return ERROR_OK;
}
@@ -723,15 +722,15 @@
dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
/* Scan out first read */
- adi_jtag_dp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AP_REG_DRW, DPAP_READ, 0, NULL, NULL);
+ adi_jtag_dp_scan(swjdp, DAP_IR_APACC, AP_REG_DRW, DPAP_READ, 0, NULL, NULL);
for (readcount = 0; readcount < blocksize - 1; readcount++)
{
/* Scan out read instruction and scan in previous value */
- adi_jtag_dp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AP_REG_DRW, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
+ adi_jtag_dp_scan(swjdp, DAP_IR_APACC, AP_REG_DRW, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
}
/* Scan in last value */
- adi_jtag_dp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, DP_RDBUFF, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
+ adi_jtag_dp_scan(swjdp, DAP_IR_DPACC, DP_RDBUFF, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
{
wcount = wcount - blocksize;
Index: src/target/arm_adi_v5.h
===================================================================
--- src/target/arm_adi_v5.h (revision 1977)
+++ src/target/arm_adi_v5.h (working copy)
@@ -27,8 +27,8 @@
#include "register.h"
#include "arm_jtag.h"
-#define SWJDP_IR_DPACC 0xA
-#define SWJDP_IR_APACC 0xB
+#define DAP_IR_DPACC 0xA
+#define DAP_IR_APACC 0xB
#define DPAP_WRITE 0
#define DPAP_READ 1
@@ -97,6 +97,9 @@
u8 trans_mode;
u8 trans_rw;
u8 ack;
+ /* extra tck clocks for memory bus access */
+ u32 memaccess_tck;
+
} swjdp_common_t;
/* Internal functions used in the module, partial transactions, use with caution */
@@ -141,4 +145,5 @@
extern int handle_dap_apsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
extern int handle_dap_apid_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
extern int handle_dap_baseaddr_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+extern int handle_dap_memaccess_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
#endif
Index: src/target/armv7m.c
===================================================================
--- src/target/armv7m.c (revision 1977)
+++ src/target/armv7m.c (working copy)
@@ -266,7 +266,6 @@
{
(*reg_list)[i] = &armv7m->core_cache->reg_list[i];
}
-
for (i = 16; i < 24; i++)
{
(*reg_list)[i] = &armv7m_gdb_dummy_fp_reg;
@@ -548,6 +547,7 @@
register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apsel", handle_dap_apsel_command, COMMAND_EXEC, "select a different AP [num] (default 0)");
register_command(cmd_ctx, arm_adi_v5_dap_cmd, "apid", handle_dap_apid_command, COMMAND_EXEC, "return id reg from AP [num], default currently selected AP");
register_command(cmd_ctx, arm_adi_v5_dap_cmd, "baseaddr", handle_dap_baseaddr_command, COMMAND_EXEC, "return debug base address from AP [num], default currently selected AP");
+ register_command(cmd_ctx, arm_adi_v5_dap_cmd, "memaccess", handle_dap_memaccess_command, COMMAND_EXEC, "set/get number of extra tck for mem-ap memory bus access [0-255]");
return ERROR_OK;
}
@@ -786,6 +786,25 @@
return retval;
}
+int handle_dap_memaccess_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+ target_t *target = get_current_target(cmd_ctx);
+ armv7m_common_t *armv7m = target->arch_info;
+ swjdp_common_t *swjdp = &armv7m->swjdp_info;
+ u32 memaccess_tck;
+
+ memaccess_tck = swjdp->memaccess_tck;
+ if (argc > 0)
+ {
+ memaccess_tck = strtoul(args[0], NULL, 0);
+ }
+
+ swjdp->memaccess_tck = memaccess_tck;
+ command_print(cmd_ctx, "memory bus access delay set to %i tck", swjdp->memaccess_tck);
+
+ return ERROR_OK;
+}
+
int handle_dap_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
target_t *target = get_current_target(cmd_ctx);
Index: src/target/cortex_m3.c
===================================================================
--- src/target/cortex_m3.c (revision 1977)
+++ src/target/cortex_m3.c (working copy)
@@ -1564,9 +1564,12 @@
int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, jtag_tap_t *tap)
{
+ int retval;
armv7m_common_t *armv7m;
armv7m = &cortex_m3->armv7m;
+ armv7m_init_arch_info(target, armv7m);
+
/* prepare JTAG information for the new target */
cortex_m3->jtag_info.tap = tap;
cortex_m3->jtag_info.scann_size = 4;
@@ -1575,6 +1578,7 @@
armv7m->swjdp_info.ap_csw_value = -1;
armv7m->swjdp_info.ap_tar_value = -1;
armv7m->swjdp_info.jtag_info = &cortex_m3->jtag_info;
+ armv7m->swjdp_info.memaccess_tck = 8;
/* initialize arch-specific breakpoint handling */
@@ -1589,13 +1594,16 @@
armv7m->pre_restore_context = NULL;
armv7m->post_restore_context = NULL;
-
- armv7m_init_arch_info(target, armv7m);
+
armv7m->arch_info = cortex_m3;
armv7m->load_core_reg_u32 = cortex_m3_load_core_reg_u32;
armv7m->store_core_reg_u32 = cortex_m3_store_core_reg_u32;
target_register_timer_callback(cortex_m3_handle_target_request, 1, 1, target);
+ if((retval = arm_jtag_setup_connection(&cortex_m3->jtag_info)) != ERROR_OK)
+ {
+ return retval;
+ }
return ERROR_OK;
}
_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development