X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fjtag%2Fjtag.h;h=81d8748b75be068c0de364bbbb4bd9c6ecc4cdcb;hb=35082f788b457b8f5fde9943d9b4246592f29c1d;hp=a14edb481bd331bba8eaa832a8925704ba716bfb;hpb=447a615dc33f324d44c73b282174be44e876cf41;p=openocd.git diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h index a14edb481b..81d8748b75 100644 --- a/src/jtag/jtag.h +++ b/src/jtag/jtag.h @@ -23,12 +23,9 @@ #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) @@ -40,6 +37,17 @@ #define DEBUG_JTAG_IOZ 64 #endif +/*-------------------------------------------------------*/ + +/** When given an array, compute its DIMension, i.e. number of elements in the array */ +#define DIM(x) (sizeof(x)/sizeof((x)[0])) + +/** Calculate the number of bytes required to hold @a n TAP scan bits */ +#define TAP_SCAN_BYTES(n) CEIL(n, 8) + +/*------------------------------------------------------*/ + + /* * Tap states from ARM7TDMI-S Technical reference manual. @@ -170,6 +178,25 @@ tap_state_t tap_get_end_state(void); */ int tap_get_tms_path(tap_state_t from, tap_state_t to); + +/** + * Function int tap_get_tms_path_len + * returns the total number of bits that represents a TMS path + * transition as given by the function tap_get_tms_path(). + * + * For at least one interface (JLink) it's not OK to simply "pad" TMS sequences + * to fit a whole byte. (I suspect this is a general TAP problem within OOCD.) + * Padding TMS causes all manner of instability that's not easily + * discovered. Using this routine we can apply EXACTLY the state transitions + * required to make something work - no more - no less. + * + * @param from is the starting state + * @param to is the resultant or final state + * @return int - the total number of bits in a transition. + */ +int tap_get_tms_path_len(tap_state_t from, tap_state_t to); + + /** * Function tap_move_ndx * when given a stable state, returns an index from 0-5. The index corresponds to a @@ -206,32 +233,46 @@ tap_state_t tap_state_transition(tap_state_t current_state, bool tms); */ const char* tap_state_name(tap_state_t state); +#ifdef _DEBUG_JTAG_IO_ +/** + * @brief Prints verbose TAP state transitions for the given TMS/TDI buffers. + * @param tms_buf must points to a buffer containing the TMS bitstream. + * @param tdi_buf must points to a buffer containing the TDI bitstream. + * @param tap_len must specify the length of the TMS/TDI bitstreams. + * @param start_tap_state must specify the current TAP state. + * @returns the final TAP state; pass as @a start_tap_state in following call. + */ +tap_state_t jtag_debug_state_machine(const void *tms_buf, const void *tdi_buf, + unsigned tap_len, tap_state_t start_tap_state); +#else +static inline tap_state_t jtag_debug_state_machine(const void *tms_buf, + const void *tdi_buf, unsigned tap_len, tap_state_t start_tap_state) +{ + return start_tap_state; +} +#endif // _DEBUG_JTAG_IO_ + /*-----------------------------------------------*/ 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); - -/// @brief calculates number of bytes required to hold @a n TAP scan bits -#define TAP_SCAN_BYTES(n) (((n) / 8) + !!((n) % 8)) - 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 { @@ -241,7 +282,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 */ @@ -304,7 +345,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 @@ -349,7 +389,6 @@ struct jtag_tap_s }; extern jtag_tap_t* jtag_AllTaps(void); extern jtag_tap_t* jtag_TapByPosition(int n); -extern jtag_tap_t* jtag_TapByPosition(int n); extern jtag_tap_t* jtag_TapByString(const char* dotted_name); extern jtag_tap_t* jtag_TapByJimObj(Jim_Interp* interp, Jim_Obj* obj); extern jtag_tap_t* jtag_TapByAbsPosition(int abs_position); @@ -470,8 +509,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; @@ -493,6 +530,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. */ @@ -515,21 +555,117 @@ 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); -/* Do not use jtag_add_pathmove() unless you need to, but do use it +/* Application code *must* assume that interfaces will + * implement transitions between states with different + * paths and path lengths through the state diagram. The + * path will vary across interface and also across versions + * 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. * * DANGER! If the target is dependent upon a particular sequence @@ -559,8 +695,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 @@ -570,7 +705,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. * @@ -596,18 +730,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); /** @@ -616,7 +740,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); /* @@ -641,17 +764,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); @@ -672,6 +824,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 @@ -680,8 +867,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 * @@ -696,13 +890,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) { @@ -713,4 +907,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 */