When read memory on Blackfin via JTAG, we shift the following two instructions into EMUIR register of Blackfin and run the tap state to Run-Test/Idle to execute them:

R0 = [P0];
EMUDAT = R0;

When these instruction are completed, we shift out EMUDAT, which contains the data just read back. The problem is instruction execution needs time. If the instruction in EMUIR has not completed, but we try to scan out EMUDAT, we would get old data in EMUDAT. That caused a bug in our daily use. To fix it, we wait some clocks after starting instruction execution.

This patch adds a callback in part specific data structure and modifies code to call it when being Run-Test/Idle. Is it OK?


Jie

2010-02-03  Jie Zhang  <jie.zh...@analog.com>

  * include/urjtag/part.h (struct URJ_PART_PARAMS): Add wait_ready.
  * include/urjtag/bfin.h (bfin_wait_clocks): Declare.
  * include/urjtag/chain.h (urj_tap_chain_wait_ready): Declare.
  * src/tap/chain.c (urj_tap_chain_wait_ready): New.
  * src/tap/tap.c (urj_tap_defer_shift_register): Call
    urj_tap_chain_wait_ready if Run-Test/Idle.
  * src/bfin/bfin.c (bfin_wait_clocks): Define.
    (part_emudat_defer_get): Call chain_wait_ready when Run-Test/Idle.
    (part_emudat_get): Likewise.
  * src/bfin/bfin-part-bfin.c: Include <sysdep.h>, <urjtag/chain.h>,
    <urjtag/cable.h> and <urjtag/log.h>.
    (bfin_wait_ready): New.
    (bfin_part_init): Init wait_ready.


Index: include/urjtag/part.h
===================================================================
--- include/urjtag/part.h	(revision 1758)
+++ include/urjtag/part.h	(working copy)
@@ -34,6 +34,7 @@
 struct URJ_PART_PARAMS
 {
     void (*free) (void *);
+    void (*wait_ready) (void *);
     void *data;
 };
 
Index: include/urjtag/bfin.h
===================================================================
--- include/urjtag/bfin.h	(revision 1758)
+++ include/urjtag/bfin.h	(working copy)
@@ -212,6 +212,7 @@ enum {
 };
 
 extern int bfin_check_emuready;
+extern int bfin_wait_clocks;
 
 /* From src/bfin/bfin.c */
 
Index: include/urjtag/chain.h
===================================================================
--- include/urjtag/chain.h	(revision 1758)
+++ include/urjtag/chain.h	(working copy)
@@ -81,7 +81,8 @@ int urj_tap_chain_get_pod_signal (urj_ch
  *
  * @return NULL on error, and sets urj_error.
  */
-urj_part_t *urj_tap_chain_active_part(urj_chain_t *chain);
+urj_part_t *urj_tap_chain_active_part (urj_chain_t *chain);
+void urj_tap_chain_wait_ready (urj_chain_t *chain);
 
 typedef struct
 {
Index: src/tap/chain.c
===================================================================
--- src/tap/chain.c	(revision 1758)
+++ src/tap/chain.c	(working copy)
@@ -331,3 +331,17 @@ urj_tap_chain_active_part (urj_chain_t *
 
     return chain->parts->parts[chain->active_part];
 }
+
+void
+urj_tap_chain_wait_ready (urj_chain_t *chain)
+{
+    urj_part_t *part;
+
+    if (!chain || !chain->parts)
+        return;
+
+    part = chain->parts->parts[chain->main_part];
+    if (part->params && part->params->wait_ready)
+        part->params->wait_ready (chain);
+}
+
Index: src/tap/tap.c
===================================================================
--- src/tap/tap.c	(revision 1758)
+++ src/tap/tap.c	(working copy)
@@ -105,6 +105,7 @@ urj_tap_defer_shift_register (urj_chain_
     {
         urj_tap_chain_defer_clock (chain, 1, 0, 1);     /* Update-DR or Update-IR */
         urj_tap_chain_defer_clock (chain, 0, 0, 1);     /* Run-Test/Idle */
+        urj_tap_chain_wait_ready (chain);
     }
     else if (tap_exit == URJ_CHAIN_EXITMODE_UPDATE)
         urj_tap_chain_defer_clock (chain, 1, 0, 1);     /* Update-DR or Update-IR */
Index: src/bfin/bfin.c
===================================================================
--- src/bfin/bfin.c	(revision 1758)
+++ src/bfin/bfin.c	(working copy)
@@ -47,6 +47,7 @@ const char *scans[] = {
 
 
 int bfin_check_emuready = 1;
+int bfin_wait_clocks = -1;
 
 static struct timespec bfin_emu_wait_ts = {0, 5000000};
 
@@ -1062,6 +1063,7 @@ part_emudat_defer_get (urj_chain_t *chai
     {
         assert (urj_tap_state (chain) & URJ_TAP_STATE_IDLE);
         urj_tap_chain_defer_clock (chain, 0, 0, 1);
+        urj_tap_chain_wait_ready (chain);
     }
 
     if (part_scan_select (chain, n, EMUDAT_SCAN) < 0)
@@ -1146,6 +1148,7 @@ part_emudat_get (urj_chain_t *chain, int
     {
         assert (urj_tap_state (chain) & URJ_TAP_STATE_IDLE);
         urj_tap_chain_defer_clock (chain, 0, 0, 1);
+        urj_tap_chain_wait_ready (chain);
     }
 
     if (part_scan_select (chain, n, EMUDAT_SCAN) < 0)
Index: src/bfin/bfin-part-bfin.c
===================================================================
--- src/bfin/bfin-part-bfin.c	(revision 1758)
+++ src/bfin/bfin-part-bfin.c	(working copy)
@@ -17,16 +17,20 @@
  */
 
 
+#include <sysdep.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 
 #include <urjtag/part.h>
+#include <urjtag/chain.h>
+#include <urjtag/cable.h>
 #include <urjtag/data_register.h>
 #include <urjtag/part_instruction.h>
 #include <urjtag/tap_register.h>
 #include <urjtag/bfin.h>
+#include <urjtag/log.h>
 
 /* The helper functions for Blackfin DBGCTL and DBGSTAT operations.  */
 
@@ -114,6 +118,48 @@ struct emu_oab bfin_emu_oab =
 };
 
 static void
+bfin_wait_ready (void *data)
+{
+    urj_chain_t *chain = (urj_chain_t *) data;
+
+    /* When CCLK is 62MHz and SCLK is 31MHz, which is the lowest frequency I
+       can set in bf537 stamp linux kernel, set the gnICE+ cable frequency to
+       15MHz (current default), --wait-clocks >= 12 is required.
+
+       When CCLK is 62MHz and SCLK is 31MHz, set the gnICE+ cable frequency to
+       30MHz, --wait-clocks >= 21 is required.
+
+       When CCLK is 62MHz and SCLK is 31MHz, set the gnICE+ cable frequency to
+       6MHz (default), --wait-clocks >= 5 is required.
+
+       When CCLK is 62MHz and SCLK is 31MHz, set the gnICE cable frequency to
+       6MHz (default), --wait-clocks >= 2 is required.  */
+
+    if (bfin_wait_clocks == -1)
+    {
+        urj_cable_t *cable = chain->cable;
+        uint32_t frequency = cable->frequency;
+        const char *name = cable->driver->name;
+
+        if (strcmp (name, "gnICE+") == 0 && frequency == 15000000)
+            bfin_wait_clocks = 12;
+        else if (strcmp (name, "gnICE+") == 0 && frequency == 30000000)
+            bfin_wait_clocks = 21;
+        else if (strcmp (name, "gnICE+") == 0 && frequency == 6000000)
+            bfin_wait_clocks = 5;
+        else if (strcmp (name, "gnICE") == 0 && frequency == 6000000)
+            bfin_wait_clocks = 2;
+        else
+        {
+            bfin_wait_clocks = 21;
+            urj_warning (_("untested cable or frequency, set wait_clocks to %d\n"), bfin_wait_clocks);
+        }
+    }
+
+    urj_tap_chain_defer_clock (chain, 0, 0, bfin_wait_clocks);
+}
+
+static void
 bfin_part_init (urj_part_t *part)
 {
     int i;
@@ -121,6 +167,7 @@ bfin_part_init (urj_part_t *part)
     assert (part && part->params);
 
     part->params->free = free;
+    part->params->wait_ready = bfin_wait_ready;
     part->params->data = malloc (sizeof (struct bfin_part_data));
     EMU_OAB (part) = &bfin_emu_oab;
 
------------------------------------------------------------------------------
The Planet: dedicated and managed hosting, cloud storage, colocation
Stay online with enterprise data centers and the best network in the business
Choose flexible plans and management services without long-term contracts
Personal 24x7 support from experience hosting pros just a phone call away.
http://p.sf.net/sfu/theplanet-com
_______________________________________________
UrJTAG-development mailing list
UrJTAG-development@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/urjtag-development

Reply via email to