summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Schink <sigrok-dev@marcschink.de>2017-04-12 11:05:09 +0200
committerMarc Schink <sigrok-dev@marcschink.de>2017-04-12 11:05:09 +0200
commit5a27727c2d71c8da8d1a5d54712ad95d29ec010f (patch)
tree222dfdaf9c2ceddaa5b7c99878dcbb473c4b2c23
parente5af429b31f63f93fec63fa4317a52700bc88d35 (diff)
TODO: Add the replay listswd_wait_handling
-rw-r--r--src/jtag/drivers/jlink.c6
-rw-r--r--src/target/adi_v5_swd.c69
2 files changed, 73 insertions, 2 deletions
diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c
index 35bd429..f763c8f 100644
--- a/src/jtag/drivers/jlink.c
+++ b/src/jtag/drivers/jlink.c
@@ -2088,12 +2088,18 @@ static int jlink_swd_run_queue(void)
*pending_scan_results_buffer[i].ack = ack;
+#if 0
if (ack != SWD_ACK_OK) {
LOG_DEBUG("SWD ack not OK: %d %s", ack,
ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK");
queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL;
goto skip;
} else if (pending_scan_results_buffer[i].length) {
+#endif
+ if (ack == SWD_ACK_WAIT) {
+ queued_retval = ERROR_WAIT;
+ goto skip;
+ } else if (pending_scan_results_buffer[i].length) {
uint32_t data = buf_get_u32(tdo_buffer, 3 + pending_scan_results_buffer[i].first, 32);
int parity = buf_get_u32(tdo_buffer, 3 + 32 + pending_scan_results_buffer[i].first, 1);
diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
index fe2c639..513eea5 100644
--- a/src/target/adi_v5_swd.c
+++ b/src/target/adi_v5_swd.c
@@ -154,11 +154,15 @@ static int swd_run_inner(struct adiv5_dap *dap)
{
const struct swd_driver *swd = jtag_interface->swd;
int retval;
+ bool found_wait;
+ LIST_HEAD(replay_list);
- struct swd_cmd *el, *tmp;
- struct list_head *lh = &dap->cmd_journal;
+ struct swd_cmd *el, *tmp, *prev = NULL;
+ struct list_head *lh;
+ lh = &dap->cmd_journal;
list_for_each_entry_safe(el, tmp, lh, lh) {
+ LOG_INFO("LALA: %x", el->cmd);
if (el->read) {
swd->read_reg(el->cmd, el->read_value, &el->ack, el->memaccess_tck);
} else {
@@ -168,7 +172,68 @@ static int swd_run_inner(struct adiv5_dap *dap)
retval = swd->run();
+ found_wait = false;
+
+#if 1
+ list_for_each_entry(el, &dap->cmd_journal, lh) {
+ LOG_INFO("%i", el->ack);
+ if (el->ack == SWD_ACK_OK) {
+ } else if (el->ack == SWD_ACK_WAIT) {
+ found_wait = true;
+ break;
+ } else {
+ LOG_ERROR("Found FAULT in journal!");
+ return ERROR_FAIL;
+ }
+ }
+
+ if (found_wait)
+ LOG_INFO("FOUND WAIT!");
+
+ /*
+ * If we found a stalled transaction and a previous transaction
+ * exists, check if it's a READ access.
+ */
+ if (found_wait && el != list_first_entry(&dap->cmd_journal, struct swd_cmd, lh)) {
+ prev = list_entry(el->lh.prev, struct swd_cmd, lh);
+ if (prev->read) {
+ LOG_INFO("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) {
+ LOG_INFO(" X: %x", el->cmd);
+ 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. */
+ uint8_t dummy;
+ swd->write_reg(swd_cmd(false, false, DP_ABORT),
+ STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, &dummy, 0);
+
+ LOG_INFO("Handle WAIT");
+
+ list_for_each_entry(el, &replay_list, lh) {
+ LOG_INFO(" REP: %x", el->cmd);
+
+ if (el->read) {
+ swd->read_reg(el->cmd, el->read_value, &el->ack, el->memaccess_tck);
+ } else {
+ swd->write_reg(el->cmd, el->write_value, &el->ack, el->memaccess_tck);
+ }
+ }
+
+ retval = swd->run();
+ }
+
flush_journal(&dap->cmd_journal);
+ flush_journal(&replay_list);
+#endif
LOG_INFO("Run SWD queue\n");
if (retval != ERROR_OK) {