arm_adi_v5: put SWJ-DP back to JTAG mode at exit
When SWD mode is used, current OpenOCD code left the SWJ-DP in SWD mode at exit. Also, current code is unable to switch back the SWJ-DP in JTAG at next run, thus a power cycle of both target and interface is required in order to run OpenOCD in JTAG mode again. Put the SWJ-DP back to JTAG mode before exit from OpenOCD. Use switch_seq(SWD_TO_JTAG) instead of dap_to_jtag(), because the latter is not implemented on some interfaces. This is aligned with the use of switch_seq(JTAG_TO_SWD) in swd_connect(). Change-Id: I55d3faebe60d6402037ec39dd9700dc5f17c53b0 Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com> Reviewed-on: http://openocd.zylin.com/4493 Tested-by: jenkins Reviewed-by: Bohdan Tymkiv <bhdt@cypress.com> Reviewed-by: Matthias Welwarsky <matthias@welwarsky.de>bscan_tunnel
parent
c5658364b2
commit
9363705820
|
@ -276,6 +276,16 @@ static int swd_run(struct adiv5_dap *dap)
|
||||||
return swd_run_inner(dap);
|
return swd_run_inner(dap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Put the SWJ-DP back to JTAG mode */
|
||||||
|
static void swd_quit(struct adiv5_dap *dap)
|
||||||
|
{
|
||||||
|
const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
|
||||||
|
|
||||||
|
swd->switch_seq(SWD_TO_JTAG);
|
||||||
|
/* flush the queue before exit */
|
||||||
|
swd->run();
|
||||||
|
}
|
||||||
|
|
||||||
const struct dap_ops swd_dap_ops = {
|
const struct dap_ops swd_dap_ops = {
|
||||||
.connect = swd_connect,
|
.connect = swd_connect,
|
||||||
.queue_dp_read = swd_queue_dp_read,
|
.queue_dp_read = swd_queue_dp_read,
|
||||||
|
@ -284,6 +294,7 @@ const struct dap_ops swd_dap_ops = {
|
||||||
.queue_ap_write = swd_queue_ap_write,
|
.queue_ap_write = swd_queue_ap_write,
|
||||||
.queue_ap_abort = swd_queue_ap_abort,
|
.queue_ap_abort = swd_queue_ap_abort,
|
||||||
.run = swd_run,
|
.run = swd_run,
|
||||||
|
.quit = swd_quit,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -286,6 +286,9 @@ struct dap_ops {
|
||||||
/** Executes all queued DAP operations but doesn't check
|
/** Executes all queued DAP operations but doesn't check
|
||||||
* sticky error conditions */
|
* sticky error conditions */
|
||||||
int (*sync)(struct adiv5_dap *dap);
|
int (*sync)(struct adiv5_dap *dap);
|
||||||
|
|
||||||
|
/** Optional; called at OpenOCD exit */
|
||||||
|
void (*quit)(struct adiv5_dap *dap);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -132,8 +132,13 @@ static int dap_init_all(void)
|
||||||
int dap_cleanup_all(void)
|
int dap_cleanup_all(void)
|
||||||
{
|
{
|
||||||
struct arm_dap_object *obj, *tmp;
|
struct arm_dap_object *obj, *tmp;
|
||||||
|
struct adiv5_dap *dap;
|
||||||
|
|
||||||
list_for_each_entry_safe(obj, tmp, &all_dap, lh) {
|
list_for_each_entry_safe(obj, tmp, &all_dap, lh) {
|
||||||
|
dap = &obj->dap;
|
||||||
|
if (dap->ops && dap->ops->quit)
|
||||||
|
dap->ops->quit(dap);
|
||||||
|
|
||||||
free(obj->name);
|
free(obj->name);
|
||||||
free(obj);
|
free(obj);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue