summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Schink <openocd-dev@marcschink.de>2017-04-13 19:23:36 +0200
committerMarc Schink <openocd-dev@marcschink.de>2017-04-18 12:42:17 +0200
commitb939e782fc36936317984c6a79a4d16f689b2941 (patch)
tree2a297bece0d0e98e9fbeab2cf87836d0dae93cbd
parentd83e37f8a69ecc007a8c22b3aa39a2df96494982 (diff)
TODO: adi_v5_swd: Add (initial) WAIT handlingwait_handling_swd
Change-Id: Idfc3d0005f184b7a125d64fba21b5dfd66e5638b
-rw-r--r--src/target/adi_v5_swd.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
index 1670d8f..8df6369 100644
--- a/src/target/adi_v5_swd.c
+++ b/src/target/adi_v5_swd.c
@@ -132,15 +132,64 @@ static int swd_run_inner(struct adiv5_dap *dap)
{
const struct swd_driver *swd = jtag_interface->swd;
int retval;
+ bool found_wait;
+ struct adiv5_dap_swd_cmd *el, *tmp, *prev;
+ LIST_HEAD(replay_list);
retval = swd->run();
+ prev = NULL;
+ found_wait = false;
+
+ list_for_each_entry(el, &dap->cmd_journal, lh) {
+ if (el->ack == SWD_ACK_WAIT) {
+ found_wait = true;
+ break;
+ }
+ }
+
+ /*
+ * If we found a stalled transaction and a previous transaction exsists,
+ * check if it's a READ access.
+ */
+ if (found_wait && el != list_first_entry(&dap->cmd_journal, struct adiv5_dap_swd_cmd, lh)) {
+ prev = list_entry(el->lh.prev, struct adiv5_dap_swd_cmd, lh);
+
+ if (prev->cmd & SWD_CMD_RnW)
+ LOG_INFO("WAIT: Previous command was read");
+ }
+
+ /* Move all remaining transactions over to the replay list. */
+ list_for_each_entry_safe_from(el, tmp, &dap->cmd_journal, lh) {
+ list_move_tail(&el->lh, &replay_list);
+ }
+
+ /* We're done with the journal, flush it. */
+ flush_journal(&dap->cmd_journal);
+
+ if (found_wait) {
+ /* TODO: Clear sticky overrun. */
+ struct adiv5_dap_swd_cmd *cmd;
+ uint32_t value = STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR;
+ cmd = dap_cmd_new(swd_cmd(false, false, DP_ABORT), &value, 0);
+ list_add(&cmd->lh, &replay_list);
+
+ list_for_each_entry(el, &replay_list, lh) {
+ if (el->cmd & SWD_CMD_RnW)
+ swd->read_reg(el);
+ else
+ swd->write_reg(el);
+ }
+
+ retval = swd->run();
+ }
+
if (retval != ERROR_OK) {
/* fault response */
dap->do_reconnect = true;
}
- flush_journal(&dap->cmd_journal);
+ flush_journal(&replay_list);
return retval;
}