Encapsulate JTAG Cable API and interface structure, plan for new header file.
[fw/openocd] / src / jtag / jtag.h
index 5dfbbdce42ff527bdc219eeaa666c058325ad93b..83ce28af9c7ac7c6de223d337f8174b55db7a6f5 100644 (file)
 #ifndef JTAG_H
 #define JTAG_H
 
-#include "types.h"
 #include "binarybuffer.h"
 #include "log.h"
 
-#include "command.h"
-
 
 #ifdef _DEBUG_JTAG_IO_
 #define DEBUG_JTAG_IO(expr ...)                LOG_DEBUG(expr)
@@ -108,6 +105,8 @@ typedef struct tap_transition_s
 //extern tap_transition_t tap_transitions[16];    /* describe the TAP state diagram */
 
 
+#ifdef INCLUDE_JTAG_INTERFACE_H
+
 /*-----<Cable Helper API>-------------------------------------------*/
 
 /* The "Cable Helper API" is what the cable drivers can use to help implement
@@ -257,27 +256,27 @@ static inline tap_state_t jtag_debug_state_machine(const void *tms_buf,
 
 /*-----</Cable Helper API>------------------------------------------*/
 
+#endif // INCLUDE_JTAG_INTERFACE_H
+
 
 extern tap_state_t cmd_queue_end_state;         /* finish DR scans in dr_end_state */
 extern tap_state_t cmd_queue_cur_state;         /* current TAP state */
 
-typedef void* error_handler_t;  /* Later on we can delete error_handler_t, but keep it for now to make patches more readable */
-
-struct scan_field_s;
-typedef int (*in_handler_t)(u8* in_value, void* priv, struct scan_field_s* field);
-
 typedef struct scan_field_s
 {
        jtag_tap_t* tap;                /* tap pointer this instruction refers to */
        int         num_bits;           /* number of bits this field specifies (up to 32) */
        u8*         out_value;          /* value to be scanned into the device */
-       u8*         out_mask;           /* only masked bits care */
        u8*         in_value;           /* pointer to a 32-bit memory location to take data scanned out */
-       /* in_check_value/mask, in_handler_error_handler, in_handler_priv can be used by the in handler, otherwise they contain garbage  */
-       u8*          in_check_value;    /* used to validate scan results */
-       u8*          in_check_mask;     /* check specified bits against check_value */
-       in_handler_t in_handler;        /* process received buffer using this handler */
-       void*        in_handler_priv;   /* additional information for the in_handler */
+
+       u8*         check_value;        /* Used together with jtag_add_dr_scan_check() to check data clocked
+                                          in */
+       u8*         check_mask;         /* mask to go with check_value */
+
+       /* internal work space */
+       int                     allocated;                      /* in_value has been allocated for the queue */
+       int                     modified;                       /* did we modify the in_value? */
+       u8                      intmp[4];                       /* temporary storage for checking synchronously */
 } scan_field_t;
 
 enum scan_type {
@@ -287,7 +286,7 @@ enum scan_type {
 
 typedef struct scan_command_s
 {
-       int           ir_scan;      /* instruction/not data scan */
+       bool          ir_scan;      /* instruction/not data scan */
        int           num_fields;   /* number of fields in *fields array */
        scan_field_t* fields;       /* pointer to an array of data scan fields */
        tap_state_t   end_state;    /* TAP state in which JTAG commands should finish */
@@ -350,7 +349,6 @@ enum jtag_command_type {
        JTAG_STATEMOVE    = 2,
        JTAG_RUNTEST      = 3,
        JTAG_RESET        = 4,
-       JTAG_END_STATE    = 5,
        JTAG_PATHMOVE     = 6,
        JTAG_SLEEP        = 7,
        JTAG_STABLECLOCKS = 8
@@ -434,6 +432,8 @@ enum reset_line_mode {
        LINE_PUSH_PULL  = 0x1,
 };
 
+#ifdef INCLUDE_JTAG_INTERFACE_H
+
 typedef struct jtag_interface_s
 {
        char* name;
@@ -483,6 +483,8 @@ typedef struct jtag_interface_s
        int (*srst_asserted)(int* srst_asserted);
 } jtag_interface_t;
 
+#endif // INCLUDE_JTAG_INTERFACE_H
+
 enum jtag_event {
        JTAG_TRST_ASSERTED
 };
@@ -515,8 +517,6 @@ typedef struct jtag_event_callback_s
 
 extern jtag_event_callback_t* jtag_event_callbacks;
 
-extern jtag_interface_t*      jtag; /* global pointer to configured JTAG interface */
-
 extern int jtag_speed;
 extern int jtag_speed_post_reset;
 
@@ -538,6 +538,9 @@ extern enum reset_types jtag_reset_config;
  */
 extern int  jtag_interface_init(struct command_context_s* cmd_ctx);
 
+/// Shutdown the JTAG interface upon program exit.
+extern int  jtag_interface_quit(void);
+
 /* initialize JTAG chain using only a RESET reset. If init fails,
  * try reset + init.
  */
@@ -560,19 +563,104 @@ extern int  jtag_register_commands(struct command_context_s* cmd_ctx);
  *
  */
 extern void jtag_add_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int  interface_jtag_add_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern void jtag_add_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int  interface_jtag_add_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern void jtag_add_plain_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int  interface_jtag_add_plain_ir_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern void jtag_add_plain_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
-extern int  interface_jtag_add_plain_dr_scan(int num_fields, scan_field_t* fields, tap_state_t endstate);
+/* same as jtag_add_ir_scan except no verify is performed */
+extern void jtag_add_ir_scan_noverify(int num_fields, const scan_field_t *fields, tap_state_t state);
+extern void jtag_add_dr_scan(int num_fields, const scan_field_t* fields, tap_state_t endstate);
+
+/* set in_value to point to 32 bits of memory to scan into. This function
+ * is a way to handle the case of synchronous and asynchronous
+ * JTAG queues.
+ *
+ * In the event of an asynchronous queue execution the queue buffer
+ * allocation method is used, for the synchronous case the temporary 32 bits come
+ * from the input field itself.
+ */
+
+#ifndef HAVE_JTAG_MINIDRIVER_H
+extern void jtag_alloc_in_value32(scan_field_t *field);
+#else
+static __inline__ void jtag_alloc_in_value32(scan_field_t *field)
+{
+       field->in_value=field->intmp;
+}
+#endif
+
+
+
+/* This version of jtag_add_dr_scan() uses the check_value/mask fields */
+extern void jtag_add_dr_scan_check(int num_fields, scan_field_t* fields, tap_state_t endstate);
+extern void jtag_add_plain_ir_scan(int num_fields, const scan_field_t* fields, tap_state_t endstate);
+extern void jtag_add_plain_dr_scan(int num_fields, const scan_field_t* fields, tap_state_t endstate);
+
+
+/* Simplest/typical callback - do some conversion on the data clocked in.
+ * This callback is for such conversion that can not fail.
+ * For conversion types or checks that can
+ * fail, use the jtag_callback_t variant */
+typedef void (*jtag_callback1_t)(u8 *in);
+
+#ifndef HAVE_JTAG_MINIDRIVER_H
+/* A simpler version of jtag_add_callback4 */
+extern void jtag_add_callback(jtag_callback1_t, u8 *in);
+#else
+/* implemented by minidriver */
+#endif
+
+
+/* This type can store an integer safely by a normal cast on 64 and
+ * 32 bit systems. */
+typedef intptr_t jtag_callback_data_t;
+
+/* The generic callback mechanism.
+ *
+ * The callback is invoked with three arguments. The first argument is
+ * the pointer to the data clocked in.
+ */
+typedef int (*jtag_callback_t)(u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3);
+
+
+/* This callback can be executed immediately the queue has been flushed. Note that
+ * the JTAG queue can either be executed synchronously or asynchronously. Typically
+ * for USB the queue is executed asynchronously. For low latency interfaces, the
+ * queue may be executed synchronously.
+ *
+ * These callbacks are typically executed *after* the *entire* JTAG queue has been
+ * executed for e.g. USB interfaces.
+ *
+ * The callbacks are guaranteeed to be invoked in the order that they were queued.
+ *
+ * The strange name is due to C's lack of overloading using function arguments
+ *
+ * The callback mechansim is very general and does not really make any assumptions
+ * about what the callback does and what the arguments are.
+ *
+ * in - typically used to point to the data to operate on. More often than not
+ * this will be the data clocked in during a shift operation
+ *
+ * data1 - an integer that is big enough to be used either as an 'int' or
+ * cast to/from a pointer
+ *
+ * data2 - an integer that is big enough to be used either as an 'int' or
+ * cast to/from a pointer
+ *
+ * Why stop at 'data2' for arguments? Somewhat historical reasons. This is
+ * sufficient to implement the jtag_check_value_mask(), besides the
+ * line is best drawn somewhere...
+ *
+ * If the execution of the queue fails before the callbacks, then the
+ * callbacks may or may not be invoked depending on driver implementation.
+ */
+#ifndef HAVE_JTAG_MINIDRIVER_H
+extern void jtag_add_callback4(jtag_callback_t, u8 *in, jtag_callback_data_t data1, jtag_callback_data_t data2, jtag_callback_data_t data3);
+#else
+/* implemented by minidriver */
+#endif
+
 
 /* run a TAP_RESET reset. End state is TAP_RESET, regardless
  * of start state.
  */
 extern void jtag_add_tlr(void);
-extern int  interface_jtag_add_tlr(void);
 
 /* Application code *must* assume that interfaces will
  * implement transitions between states with different
@@ -581,10 +669,10 @@ extern int  interface_jtag_add_tlr(void);
  * of the same interface over time. Even if the OpenOCD code
  * is unchanged, the actual path taken may vary over time
  * and versions of interface firmware or PCB revisions.
- * 
+ *
  * Use jtag_add_pathmove() when specific transition sequences
  * are required.
- * 
+ *
  * Do not use jtag_add_pathmove() unless you need to, but do use it
  * if you have to.
  *
@@ -615,8 +703,7 @@ extern int  interface_jtag_add_tlr(void);
  * a partial implementation of pathmove would have little practical
  * application.
  */
-extern void jtag_add_pathmove(int num_states, tap_state_t* path);
-extern int  interface_jtag_add_pathmove(int num_states, tap_state_t* path);
+extern void jtag_add_pathmove(int num_states, const tap_state_t* path);
 
 /* go to TAP_IDLE, if we're not already there and cycle
  * precisely num_cycles in the TAP_IDLE after which move
@@ -626,7 +713,6 @@ extern int  interface_jtag_add_pathmove(int num_states, tap_state_t* path);
  * to endstate via TAP_IDLE
  */
 extern void jtag_add_runtest(int num_cycles, tap_state_t endstate);
-extern int  interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
 
 /* A reset of the TAP state machine can be requested.
  *
@@ -652,18 +738,8 @@ extern int  interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
  */
 extern void jtag_add_reset(int req_tlr_or_trst, int srst);
 
-/* this drives the actual srst and trst pins. srst will always be 0
- * if jtag_reset_config & RESET_SRST_PULLS_TRST != 0 and ditto for
- * trst.
- *
- * the higher level jtag_add_reset will invoke jtag_add_tlr() if
- * approperiate
- */
-extern int  interface_jtag_add_reset(int trst, int srst);
 extern void jtag_add_end_state(tap_state_t endstate);
-extern int  interface_jtag_add_end_state(tap_state_t endstate);
 extern void jtag_add_sleep(u32 us);
-extern int  interface_jtag_add_sleep(u32 us);
 
 
 /**
@@ -672,7 +748,6 @@ extern int  interface_jtag_add_sleep(u32 us);
  * stable, then queues up clock_count clocks for transmission.
  */
 void jtag_add_clocks(int num_cycles);
-int  interface_jtag_add_clocks(int num_cycles);
 
 
 /*
@@ -697,17 +772,46 @@ int  interface_jtag_add_clocks(int num_cycles);
  */
 extern int            jtag_execute_queue(void);
 
+/* same as jtag_execute_queue() but does not clear the error flag */
+extern void jtag_execute_queue_noclear(void);
+
+/* this flag is set when an error occurs while executing the queue. cleared
+ * by jtag_execute_queue()
+ *
+ * this flag can also be set from application code if some error happens
+ * during processing that should be reported during jtag_execute_queue().
+ */
+extern int jtag_error;
+
+static __inline__ void jtag_set_error(int error)
+{
+       if ((error==ERROR_OK)||(jtag_error!=ERROR_OK))
+       {
+               /* keep first error */
+               return;
+       }
+       jtag_error=error;
+}
+
+
+
 /* can be implemented by hw+sw */
-extern int            interface_jtag_execute_queue(void);
 extern int            jtag_power_dropout(int* dropout);
 extern int            jtag_srst_asserted(int* srst_asserted);
 
 /* JTAG support functions */
-extern void           jtag_set_check_value(scan_field_t* field, u8* value, u8* mask, error_handler_t* in_error_handler);
-extern enum scan_type jtag_scan_type(scan_command_t* cmd);
-extern int            jtag_scan_size(scan_command_t* cmd);
-extern int            jtag_read_buffer(u8* buffer, scan_command_t* cmd);
-extern int            jtag_build_buffer(scan_command_t* cmd, u8** buffer);
+struct invalidstruct
+{
+
+};
+
+/* execute jtag queue and check value and use mask if mask is != NULL. invokes
+ * jtag_set_error() with any error. */
+extern void jtag_check_value_mask(scan_field_t *field, u8 *value, u8 *mask);
+extern enum scan_type jtag_scan_type(const scan_command_t* cmd);
+extern int            jtag_scan_size(const scan_command_t* cmd);
+extern int            jtag_read_buffer(u8* buffer, const scan_command_t* cmd);
+extern int            jtag_build_buffer(const scan_command_t* cmd, u8** buffer);
 
 extern void           jtag_sleep(u32 us);
 extern int            jtag_call_event_callbacks(enum jtag_event event);
@@ -728,6 +832,41 @@ void jtag_tap_handle_event(jtag_tap_t* tap, enum jtag_tap_event e);
 #define ERROR_JTAG_NOT_STABLE_STATE  (-105)
 #define ERROR_JTAG_DEVICE_ERROR      (-107)
 
+#ifdef INCLUDE_JTAG_MINIDRIVER_H
+
+extern int interface_jtag_add_ir_scan(
+               int num_fields, const scan_field_t* fields,
+               tap_state_t endstate);
+extern int interface_jtag_add_plain_ir_scan(
+               int num_fields, const scan_field_t* fields,
+               tap_state_t endstate);
+
+extern int interface_jtag_add_dr_scan(
+               int num_fields, const scan_field_t* fields,
+               tap_state_t endstate);
+extern int interface_jtag_add_plain_dr_scan(
+               int num_fields, const scan_field_t* fields,
+               tap_state_t endstate);
+
+extern int interface_jtag_add_tlr(void);
+extern int interface_jtag_add_pathmove(int num_states, const tap_state_t* path);
+extern int interface_jtag_add_runtest(int num_cycles, tap_state_t endstate);
+
+/**
+ * This drives the actual srst and trst pins. srst will always be 0
+ * if jtag_reset_config & RESET_SRST_PULLS_TRST != 0 and ditto for
+ * trst.
+ *
+ * the higher level jtag_add_reset will invoke jtag_add_tlr() if
+ * approperiate
+ */
+extern int interface_jtag_add_reset(int trst, int srst);
+extern int interface_jtag_add_end_state(tap_state_t endstate);
+extern int interface_jtag_add_sleep(u32 us);
+extern int interface_jtag_add_clocks(int num_cycles);
+extern int interface_jtag_execute_queue(void);
+
+#endif // INCLUDE_JTAG_MINIDRIVER_H
 
 /* this allows JTAG devices to implement the entire jtag_xxx() layer in hw/sw */
 #ifdef HAVE_JTAG_MINIDRIVER_H
@@ -736,8 +875,15 @@ void jtag_tap_handle_event(jtag_tap_t* tap, enum jtag_tap_event e);
 #define MINIDRIVER(a) notused ## a
 #else
 #define MINIDRIVER(a) a
+extern void interface_jtag_add_dr_out(jtag_tap_t* tap, int num_fields, const int* num_bits, const u32* value,
+               tap_state_t end_state);
+
+#endif
 
-/* jtag_add_dr_out() is a faster version of jtag_add_dr_scan()
+/* jtag_add_dr_out() is a version of jtag_add_dr_scan() which
+ * only scans data out. It operates on 32 bit integers instead
+ * of 8 bit, which makes it a better impedance match with
+ * the calling code which often operate on 32 bit integers.
  *
  * Current or end_state can not be TAP_RESET. end_state can be TAP_INVALID
  *
@@ -752,13 +898,13 @@ void jtag_tap_handle_event(jtag_tap_t* tap, enum jtag_tap_event e);
  * return an error. There is no way to determine if there was a failure
  * during this function call.
  *
- * Note that this jtag_add_dr_out can be defined as an inline function.
+ * This is an inline fn to speed up embedded hosts. Also note that
+ * interface_jtag_add_dr_out() can be a *small* inline function for
+ * embedded hosts.
+ *
+ * There is no jtag_add_dr_outin() version of this fn that also allows
+ * clocking data back in. Patches gladly accepted!
  */
-extern void interface_jtag_add_dr_out(jtag_tap_t* tap, int num_fields, const int* num_bits, const u32* value,
-               tap_state_t end_state);
-
-#endif
-
 static __inline__ void jtag_add_dr_out(jtag_tap_t* tap, int num_fields, const int* num_bits, const u32* value,
                tap_state_t end_state)
 {
@@ -769,4 +915,14 @@ static __inline__ void jtag_add_dr_out(jtag_tap_t* tap, int num_fields, const in
 }
 
 
+
+
+/**
+ * Function jtag_add_statemove
+ * moves from the current state to the goal \a state. This needs
+ * to be handled according to the xsvf spec, see the XSTATE command
+ * description.
+ */
+extern int jtag_add_statemove(tap_state_t goal_state);
+
 #endif /* JTAG_H */