This allows minidrivers to e.g. hardware accelerate memory
writes.

Same trick as is used for arm7/9 dcc writes.

Added error propagation for memory transfer failures in
code rearrangement.

Also the JTAG end state is not updated until after
the memory write run is complete.

Signed-off-by: Øyvind Harboe <oyvind.har...@zylin.com>
---
 src/jtag/minidummy/minidummy.c |    8 ++-
 src/jtag/zy1000/zy1000.c       |    8 ++
 src/target/arm11_dbgtap.c      |  139 +++++++++++++++++++++++++++-------------
 3 files changed, 108 insertions(+), 47 deletions(-)

diff --git a/src/jtag/minidummy/minidummy.c b/src/jtag/minidummy/minidummy.c
index 9c608cd..6f58e31 100644
--- a/src/jtag/minidummy/minidummy.c
+++ b/src/jtag/minidummy/minidummy.c
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2007-2008 by Øyvind Harboe                              *
+ *   Copyright (C) 2007-2010 by Øyvind Harboe                              *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
@@ -156,3 +156,9 @@ void embeddedice_write_dcc(struct jtag_tap *tap, int 
reg_addr, uint8_t *buffer,
                buffer += 4;
        }
 }
+
+int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap * tap, uint32_t 
opcode, uint32_t * data, size_t count)
+{
+       int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap * 
tap, uint32_t opcode, uint32_t * data, size_t count);
+       return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, 
data, count);
+}
diff --git a/src/jtag/zy1000/zy1000.c b/src/jtag/zy1000/zy1000.c
index 2c205b7..e07e2da 100644
--- a/src/jtag/zy1000/zy1000.c
+++ b/src/jtag/zy1000/zy1000.c
@@ -838,6 +838,14 @@ void embeddedice_write_dcc(struct jtag_tap *tap, int 
reg_addr, uint8_t *buffer,
 }
 
 
+int arm11_run_instr_data_to_core_noack_inner_default(struct arm11_common * 
arm11, uint32_t opcode, uint32_t * data, size_t count);
+
+int arm11_run_instr_data_to_core_noack_inner(struct arm11_common * arm11, 
uint32_t opcode, uint32_t * data, size_t count)
+{
+       return arm11_run_instr_data_to_core_noack_inner_default(arm11, opcode, 
data, count);
+}
+
+
 static const struct command_registration zy1000_commands[] = {
        {
                .name = "power",
diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c
index 088981f..9dca83a 100644
--- a/src/target/arm11_dbgtap.c
+++ b/src/target/arm11_dbgtap.c
@@ -2,7 +2,7 @@
  *   Copyright (C) 2008 digenius technology GmbH.                          *
  *   Michael Bruck                                                         *
  *                                                                         *
- *   Copyright (C) 2008,2009 Oyvind Harboe oyvind.har...@zylin.com         *
+ *   Copyright (C) 2008-2010 Oyvind Harboe oyvind.har...@zylin.com         *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
@@ -569,43 +569,31 @@ static const tap_state_t 
arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay[] =
        TAP_DREXIT2, TAP_DRUPDATE, TAP_IDLE, TAP_IDLE, TAP_IDLE, TAP_DRSELECT, 
TAP_DRCAPTURE, TAP_DRSHIFT
 };
 
-
-
-/** Execute one instruction via ITR repeatedly while
- *  passing data to the core via DTR on each execution.
- *
- * Caller guarantees that processor is in debug state, that DSCR_ITR_EN
- * is set, the ITR Ready flag is set (as seen on the previous entry to
- * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear.
- *
- *  No Ready check during transmission.
- *
- *  The executed instruction \em must read data from DTR.
- *
- * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
- *
- * \param arm11                Target state variable.
- * \param opcode       ARM opcode
- * \param data         Pointer to the data words to be passed to the core
- * \param count                Number of data words and instruction repetitions
- *
+/* This inner loop can be implemented by the minidriver, oftentimes in 
hardware... The
+ * minidriver can call the default implementation as a fallback or implement it
+ * from scratch.
  */
-int arm11_run_instr_data_to_core_noack(struct arm11_common * arm11, uint32_t 
opcode, uint32_t * data, size_t count)
+int arm11_run_instr_data_to_core_noack_inner_default(struct jtag_tap * tap, 
uint32_t opcode, uint32_t * data, size_t count)
 {
-       arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
+       struct scan_field       chain5_fields[3];
 
-       arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE);
+       chain5_fields[0].tap                    = tap;
+       chain5_fields[0].num_bits               = 32;
+       chain5_fields[0].out_value              = NULL; /*&Data*/
+       chain5_fields[0].in_value               = NULL;
 
-       arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
+       chain5_fields[1].tap                    = tap;
+       chain5_fields[1].num_bits               = 1;
+       chain5_fields[1].out_value              = NULL;
+       chain5_fields[1].in_value               = NULL; /*&Ready*/
 
-       struct scan_field       chain5_fields[3];
-
-       arm11_setup_field(arm11, 32,    NULL/*&Data*/,  NULL,                   
        chain5_fields + 0);
-       arm11_setup_field(arm11,  1,    NULL,                   NULL 
/*&Ready*/,        chain5_fields + 1);
-       arm11_setup_field(arm11,  1,    NULL,                   NULL,           
                chain5_fields + 2);
+       chain5_fields[2].tap                    = tap;
+       chain5_fields[2].num_bits               = 1;
+       chain5_fields[2].out_value              = NULL;
+       chain5_fields[2].in_value               = NULL;
 
        uint8_t                 *Readies;
-       unsigned readiesNum = count + 1;
+       unsigned readiesNum = count;
        unsigned bytes = sizeof(*Readies)*readiesNum;
 
        Readies = (uint8_t *) malloc(bytes);
@@ -616,31 +604,22 @@ int arm11_run_instr_data_to_core_noack(struct 
arm11_common * arm11, uint32_t opc
        }
 
        uint8_t *               ReadyPos                        = Readies;
-
        while (count--)
        {
                chain5_fields[0].out_value      = (void *)(data++);
                chain5_fields[1].in_value       = ReadyPos++;
 
-               if (count)
+               if (count > 0)
                {
-                       jtag_add_dr_scan(ARRAY_SIZE(chain5_fields), 
chain5_fields, jtag_set_end_state(TAP_DRPAUSE));
+                       jtag_add_dr_scan(ARRAY_SIZE(chain5_fields), 
chain5_fields, TAP_DRPAUSE);
                        
jtag_add_pathmove(ARRAY_SIZE(arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay),
                                arm11_MOVE_DRPAUSE_IDLE_DRPAUSE_with_delay);
-               }
-               else
+               } else
                {
-                       jtag_add_dr_scan(ARRAY_SIZE(chain5_fields), 
chain5_fields, jtag_set_end_state(TAP_IDLE));
+                       jtag_add_dr_scan(ARRAY_SIZE(chain5_fields), 
chain5_fields, TAP_IDLE);
                }
        }
 
-       arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
-
-       chain5_fields[0].out_value      = 0;
-       chain5_fields[1].in_value   = ReadyPos++;
-
-       arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, 
TAP_DRPAUSE);
-
        int retval = jtag_execute_queue();
        if (retval == ERROR_OK)
        {
@@ -655,16 +634,84 @@ int arm11_run_instr_data_to_core_noack(struct 
arm11_common * arm11, uint32_t opc
                }
 
                if (error_count > 0 )
+               {
                        LOG_ERROR("%u words out of %u not transferred",
                                error_count, readiesNum);
-
+                       retval = ERROR_FAIL;
+               }
        }
-
        free(Readies);
 
        return retval;
 }
 
+int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap * tap, uint32_t 
opcode, uint32_t * data, size_t count);
+
+#ifndef HAVE_JTAG_MINIDRIVER_H
+int arm11_run_instr_data_to_core_noack_inner(struct jtag_tap * tap, uint32_t 
opcode, uint32_t * data, size_t count)
+{
+       return arm11_run_instr_data_to_core_noack_inner_default(tap, opcode, 
data, count);
+}
+#endif
+
+/** Execute one instruction via ITR repeatedly while
+ *  passing data to the core via DTR on each execution.
+ *
+ * Caller guarantees that processor is in debug state, that DSCR_ITR_EN
+ * is set, the ITR Ready flag is set (as seen on the previous entry to
+ * TAP_DRCAPTURE), and the DSCR sticky abort flag is clear.
+ *
+ *  No Ready check during transmission.
+ *
+ *  The executed instruction \em must read data from DTR.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11                Target state variable.
+ * \param opcode       ARM opcode
+ * \param data         Pointer to the data words to be passed to the core
+ * \param count                Number of data words and instruction repetitions
+ *
+ */
+int arm11_run_instr_data_to_core_noack(struct arm11_common * arm11, uint32_t 
opcode, uint32_t * data, size_t count)
+{
+       arm11_add_IR(arm11, ARM11_ITRSEL, ARM11_TAP_DEFAULT);
+
+       arm11_add_debug_INST(arm11, opcode, NULL, TAP_DRPAUSE);
+
+       arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
+
+       int retval = 
arm11_run_instr_data_to_core_noack_inner(arm11->arm.target->tap, opcode, data, 
count);
+
+       if (retval != ERROR_FAIL)
+               return retval;
+
+       arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
+
+       struct scan_field       chain5_fields[3];
+
+       arm11_setup_field(arm11, 32,    NULL/*&Data*/,  NULL,                   
        chain5_fields + 0);
+       arm11_setup_field(arm11,  1,    NULL,                   NULL 
/*&Ready*/,        chain5_fields + 1);
+       arm11_setup_field(arm11,  1,    NULL,                   NULL,           
                chain5_fields + 2);
+
+       uint8_t ready_flag;
+       chain5_fields[1].in_value   = &ready_flag;
+
+       arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, 
TAP_DRPAUSE);
+
+       retval = jtag_execute_queue();
+       if (retval == ERROR_OK)
+       {
+               if (ready_flag != 1)
+               {
+                       LOG_ERROR("last word not transferred");
+                       retval = ERROR_FAIL;
+               }
+       }
+
+       return retval;
+}
+
 
 /** Execute an instruction via ITR while handing data into the core via DTR.
  *
-- 
1.6.3.3

_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to