X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fbitq.c;h=ee7a073abbd9e066fd35f60dadfd0295761163b1;hp=a4ec626f3c7655f0721808746606e18d97600eb8;hb=2ddeec9db5a8771c948294b7194778a95295b7a0;hpb=2e01a1ad1930aabb9e3bc7a0e3eb98b2b3331b1c diff --git a/src/jtag/bitq.c b/src/jtag/bitq.c index a4ec626f3c..ee7a073abb 100644 --- a/src/jtag/bitq.c +++ b/src/jtag/bitq.c @@ -1,195 +1,204 @@ /*************************************************************************** - * Copyright (C) 2007 by Pavel Chromy * - * chromy@asix.cz * - * * - * 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 * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ +* Copyright (C) 2007 by Pavel Chromy * +* chromy@asix.cz * +* * +* 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 * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the * +* Free Software Foundation, Inc., * +* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * +***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "bitq.h" +#include "interface.h" -/* project specific includes */ -#include "log.h" -#include "types.h" -#include "jtag.h" -#include "configuration.h" -/* system includes */ -#include -#include -#include +struct bitq_interface* bitq_interface; /* low level bit queue interface */ -#include -#include - - -bitq_interface_t *bitq_interface; /* low level bit queue interface */ - -bitq_state_t bitq_in_state; /* state of input queue */ - -u8 *bitq_in_buffer; /* buffer dynamically reallocated as needed */ -unsigned long bitq_in_bufsize=32; /* min. buffer size */ +/* state of input queue */ +struct bitq_state { + jtag_command_t *cmd; /* command currently processed */ + int field_idx; /* index of field currently being processed */ + int bit_pos; /* position of bit curently being processed */ + int status; /* processing status */ +}; +static struct bitq_state bitq_in_state; +static uint8_t* bitq_in_buffer; /* buffer dynamically reallocated as needed */ +static int bitq_in_bufsize = 32; /* min. buffer size */ /* * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead * also the buffer for incomming data is reallocated only if necessary * no parameters, makes use of stored state information - */ + */ void bitq_in_proc(void) { /* static information preserved between calls to increase performance */ - static u8 *in_buff; /* pointer to buffer for scanned data */ - static int in_idx; /* index of byte being scanned */ - static u8 in_mask; /* mask of next bit to be scanned */ + static uint8_t* in_buff; /* pointer to buffer for scanned data */ + static int in_idx; /* index of byte being scanned */ + static uint8_t in_mask; /* mask of next bit to be scanned */ + + struct scan_field* field; + int tdo; - scan_field_t *field; - int tdo; - /* loop through the queue */ - while (bitq_in_state.cmd) { + while (bitq_in_state.cmd) + { /* only JTAG_SCAN command may return data */ - if (bitq_in_state.cmd->type==JTAG_SCAN) { + if (bitq_in_state.cmd->type == JTAG_SCAN) + { /* loop through the fields */ - while (bitq_in_state.field_idxcmd.scan->num_fields) { - - field=&bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx]; - if ( field->in_value || field->in_handler) { - - if (bitq_in_state.bit_pos==0) { + while (bitq_in_state.field_idx < bitq_in_state.cmd->cmd.scan->num_fields) + { + field = &bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx]; + if (field->in_value) + { + if (bitq_in_state.bit_pos == 0) + { /* initialize field scanning */ - in_mask=0x01; - in_idx=0; - if (field->in_value) in_buff=field->in_value; - else { + in_mask = 0x01; + in_idx = 0; + if (field->in_value) + in_buff = field->in_value; + else + { /* buffer reallocation needed? */ - if (field->num_bits>bitq_in_bufsize*8) { + if (field->num_bits > bitq_in_bufsize * 8) + { /* buffer previously allocated? */ - if (bitq_in_buffer!=NULL) { + if (bitq_in_buffer != NULL) + { /* free it */ free(bitq_in_buffer); - bitq_in_buffer=NULL; + bitq_in_buffer = NULL; } /* double the buffer size until it fits */ - while (field->num_bits>bitq_in_bufsize*8) bitq_in_bufsize*=2; + while (field->num_bits > bitq_in_bufsize * 8) + bitq_in_bufsize *= 2; } - /* if necessary, allocate buffer and check for malloc error */ - if (bitq_in_buffer==NULL && (bitq_in_buffer=malloc(bitq_in_bufsize))==NULL) { - ERROR("malloc error"); - exit(-1); + /* if necessary, allocate buffer and check for malloc error */ + if (bitq_in_buffer == NULL && (bitq_in_buffer = malloc(bitq_in_bufsize)) == NULL) + { + LOG_ERROR("malloc error"); + exit(-1); } - in_buff=(void *)bitq_in_buffer; + in_buff = (void*) bitq_in_buffer; } } /* field scanning */ - while (bitq_in_state.bit_posnum_bits) { - if ((tdo=bitq_interface->in())<0) { + while (bitq_in_state.bit_pos < field->num_bits) + { + if ((tdo = bitq_interface->in()) < 0) + { #ifdef _DEBUG_JTAG_IO_ - DEBUG("bitq in EOF"); + LOG_DEBUG("bitq in EOF"); #endif return; } - if (in_mask==0x01) in_buff[in_idx]=0; - if (tdo) in_buff[in_idx]|=in_mask; - if (in_mask==0x80) { - in_mask=0x01; + if (in_mask == 0x01) + in_buff[in_idx] = 0; + if (tdo) + in_buff[in_idx] |= in_mask; + if (in_mask == 0x80) + { + in_mask = 0x01; in_idx++; } - else in_mask<<=1; + else + in_mask <<= 1; bitq_in_state.bit_pos++; } - - - if (field->in_handler && bitq_in_state.status==ERROR_OK) { - bitq_in_state.status=(*field->in_handler)(in_buff, field->in_handler_priv); - } - } - - bitq_in_state.field_idx++; /* advance to next field */ - bitq_in_state.bit_pos=0; /* start next field from the first bit */ - } + bitq_in_state.field_idx++; /* advance to next field */ + bitq_in_state.bit_pos = 0; /* start next field from the first bit */ + } } - bitq_in_state.cmd=bitq_in_state.cmd->next; /* advance to next command */ - bitq_in_state.field_idx=0; /* preselect first field */ + bitq_in_state.cmd = bitq_in_state.cmd->next; /* advance to next command */ + bitq_in_state.field_idx = 0; /* preselect first field */ } } - void bitq_io(int tms, int tdi, int tdo_req) { bitq_interface->out(tms, tdi, tdo_req); - /* check and process the input queue */ - if (bitq_interface->in_rdy()) bitq_in_proc(); + /* check and process the input queue */ + if (bitq_interface->in_rdy()) + bitq_in_proc(); } -void bitq_end_state(enum tap_state state) +void bitq_end_state(tap_state_t state) { - if (state==-1) return; - if (tap_move_map[state]==-1) { - ERROR("BUG: %i is not a valid end state", state); + if (!tap_is_state_stable(state)) + { + LOG_ERROR("BUG: %i is not a valid end state", state); exit(-1); } - end_state = state; + tap_set_end_state(state); } -void bitq_state_move(enum tap_state new_state) +void bitq_state_move(tap_state_t new_state) { - int i=0; - u8 tms_scan; + int i = 0; + uint8_t tms_scan; - if (tap_move_map[cur_state]==-1 || tap_move_map[new_state]==-1) { - ERROR("TAP move from or to unstable state"); + if (!tap_is_state_stable(tap_get_state()) || !tap_is_state_stable(new_state)) + { + LOG_ERROR("TAP move from or to unstable state"); exit(-1); } - - tms_scan=TAP_MOVE(cur_state, new_state); - for (i=0; i<7; i++) { - bitq_io(tms_scan&1, 0, 0); - tms_scan>>=1; + tms_scan = tap_get_tms_path(tap_get_state(), new_state); + int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); + + for (i = 0; i < tms_count; i++) + { + bitq_io(tms_scan & 1, 0, 0); + tms_scan >>= 1; } - cur_state = new_state; + tap_set_state(new_state); } -void bitq_path_move(pathmove_command_t *cmd) +void bitq_path_move(pathmove_command_t* cmd) { int i; - for (i=0; i<=cmd->num_states; i++) { - if (tap_transitions[cur_state].low == cmd->path[i]) bitq_io(0, 0, 0); - else if (tap_transitions[cur_state].high == cmd->path[i]) bitq_io(1, 0, 0); - else { - ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[i]]); + for (i = 0; i <= cmd->num_states; i++) + { + if (tap_state_transition(tap_get_state(), false) == cmd->path[i]) + bitq_io(0, 0, 0); + else if (tap_state_transition(tap_get_state(), true) == cmd->path[i]) + bitq_io(1, 0, 0); + else + { + LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name( + tap_get_state()), tap_state_name(cmd->path[i])); exit(-1); } - cur_state = cmd->path[i]; + tap_set_state(cmd->path[i]); } - end_state = cur_state; + tap_set_end_state(tap_get_state()); } @@ -197,144 +206,164 @@ void bitq_runtest(int num_cycles) { int i; - /* only do a state_move when we're not already in RTI */ - if (cur_state != TAP_RTI) bitq_state_move(TAP_RTI); + /* only do a state_move when we're not already in IDLE */ + if (tap_get_state() != TAP_IDLE) + bitq_state_move(TAP_IDLE); /* execute num_cycles */ for (i = 0; i < num_cycles; i++) bitq_io(0, 0, 0); /* finish in end_state */ - if (cur_state != end_state) bitq_state_move(end_state); + if (tap_get_state() != tap_get_end_state()) + bitq_state_move(tap_get_end_state()); } -void bitq_scan_field(scan_field_t *field, int pause) +void bitq_scan_field(struct scan_field* field, int pause) { int bit_cnt; int tdo_req; - u8 *out_ptr; - u8 out_mask; - - if ( field->in_value || field->in_handler) tdo_req=1; - else tdo_req=0; + uint8_t* out_ptr; + uint8_t out_mask; - if (field->out_value==NULL) { + if (field->in_value) + tdo_req = 1; + else + tdo_req = 0; + + if (field->out_value == NULL) + { /* just send zeros and request data from TDO */ - for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--) + for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) bitq_io(0, 0, tdo_req); + bitq_io(pause, 0, tdo_req); } - else { + else + { /* send data, and optionally request TDO */ - out_mask=0x01; - out_ptr=field->out_value; - for (bit_cnt=field->num_bits; bit_cnt>1; bit_cnt--) { - bitq_io(0, ((*out_ptr)&out_mask)!=0, tdo_req); - if (out_mask==0x80) { - out_mask=0x01; + out_mask = 0x01; + out_ptr = field->out_value; + for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) + { + bitq_io(0, ((*out_ptr) & out_mask) != 0, tdo_req); + if (out_mask == 0x80) + { + out_mask = 0x01; out_ptr++; } - else out_mask<<=1; + else + out_mask <<= 1; } - bitq_io(pause, ((*out_ptr)&out_mask)!=0, tdo_req); + + bitq_io(pause, ((*out_ptr) & out_mask) != 0, tdo_req); } - if (pause) { - bitq_io(0,0,0); - if (cur_state==TAP_SI) cur_state=TAP_PI; - else if (cur_state==TAP_SD) cur_state=TAP_PD; + if (pause) + { + bitq_io(0, 0, 0); + if (tap_get_state() == TAP_IRSHIFT) + tap_set_state(TAP_IRPAUSE); + else if (tap_get_state() == TAP_DRSHIFT) + tap_set_state(TAP_DRPAUSE); } } -void bitq_scan(scan_command_t *cmd) +void bitq_scan(struct scan_command* cmd) { int i; - if (cmd->ir_scan) bitq_state_move(TAP_SI); - else bitq_state_move(TAP_SD); + if (cmd->ir_scan) + bitq_state_move(TAP_IRSHIFT); + else + bitq_state_move(TAP_DRSHIFT); - for (i=0; i < cmd->num_fields-1; i++) + for (i = 0; i < cmd->num_fields - 1; i++) bitq_scan_field(&cmd->fields[i], 0); + bitq_scan_field(&cmd->fields[i], 1); } int bitq_execute_queue(void) { - jtag_command_t *cmd = jtag_command_queue; /* currently processed command */ - + jtag_command_t* cmd = jtag_command_queue; /* currently processed command */ + bitq_in_state.cmd = jtag_command_queue; bitq_in_state.field_idx = 0; - bitq_in_state.bit_pos = 0; - bitq_in_state.status = ERROR_OK; - - while (cmd) { + bitq_in_state.bit_pos = 0; + bitq_in_state.status = ERROR_OK; - switch (cmd->type) { - - case JTAG_END_STATE: -#ifdef _DEBUG_JTAG_IO_ - DEBUG("end_state: %i", cmd->cmd.end_state->end_state); -#endif - bitq_end_state(cmd->cmd.end_state->end_state); - break; - - case JTAG_RESET: + while (cmd) + { + switch (cmd->type) + { + case JTAG_RESET: #ifdef _DEBUG_JTAG_IO_ - DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); + LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst); #endif - bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); - if (bitq_interface->in_rdy()) bitq_in_proc(); - break; + if ((cmd->cmd.reset->trst == 1) || (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) + { + tap_set_state(TAP_RESET); + } + bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); + if (bitq_interface->in_rdy()) + bitq_in_proc(); + break; - case JTAG_RUNTEST: + case JTAG_RUNTEST: #ifdef _DEBUG_JTAG_IO_ - DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); + LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state); #endif - bitq_end_state(cmd->cmd.runtest->end_state); - bitq_runtest(cmd->cmd.runtest->num_cycles); - break; + bitq_end_state(cmd->cmd.runtest->end_state); + bitq_runtest(cmd->cmd.runtest->num_cycles); + break; - case JTAG_STATEMOVE: + case JTAG_STATEMOVE: #ifdef _DEBUG_JTAG_IO_ - DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); + LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state); #endif - bitq_end_state(cmd->cmd.statemove->end_state); - bitq_state_move(end_state); /* uncoditional TAP move */ - break; + bitq_end_state(cmd->cmd.statemove->end_state); + bitq_state_move(tap_get_end_state()); /* uncoditional TAP move */ + break; - case JTAG_PATHMOVE: + case JTAG_PATHMOVE: #ifdef _DEBUG_JTAG_IO_ - DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); + LOG_DEBUG("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states, + cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]); #endif - bitq_path_move(cmd->cmd.pathmove); - break; + bitq_path_move(cmd->cmd.pathmove); + break; - case JTAG_SCAN: + case JTAG_SCAN: #ifdef _DEBUG_JTAG_IO_ - DEBUG("scan end in %i", cmd->cmd.scan->end_state); - if (cmd->cmd.scan->ir_scan) DEBUG("scan ir"); - else DEBUG("scan dr"); + LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state); + if (cmd->cmd.scan->ir_scan) + LOG_DEBUG("scan ir"); + else + LOG_DEBUG("scan dr"); #endif - bitq_end_state(cmd->cmd.scan->end_state); - bitq_scan(cmd->cmd.scan); - if (cur_state != end_state) bitq_state_move(end_state); - break; + bitq_end_state(cmd->cmd.scan->end_state); + bitq_scan(cmd->cmd.scan); + if (tap_get_state() != tap_get_end_state()) + bitq_state_move(tap_get_end_state()); + break; - case JTAG_SLEEP: + case JTAG_SLEEP: #ifdef _DEBUG_JTAG_IO_ - DEBUG("sleep %i", cmd->cmd.sleep->us); + LOG_DEBUG("sleep %i", cmd->cmd.sleep->us); #endif - bitq_interface->sleep(cmd->cmd.sleep->us); - if (bitq_interface->in_rdy()) bitq_in_proc(); - break; + bitq_interface->sleep(cmd->cmd.sleep->us); + if (bitq_interface->in_rdy()) + bitq_in_proc(); + break; - default: - ERROR("BUG: unknown JTAG command type encountered"); - exit(-1); + default: + LOG_ERROR("BUG: unknown JTAG command type encountered"); + exit(-1); } cmd = cmd->next; @@ -343,12 +372,14 @@ int bitq_execute_queue(void) bitq_interface->flush(); bitq_in_proc(); - if (bitq_in_state.cmd) { - ERROR("missing data from bitq interface"); + if (bitq_in_state.cmd) + { + LOG_ERROR("missing data from bitq interface"); return ERROR_JTAG_QUEUE_FAILED; } - if (bitq_interface->in()>=0) { - ERROR("extra data from bitq interface"); + if (bitq_interface->in() >= 0) + { + LOG_ERROR("extra data from bitq interface"); return ERROR_JTAG_QUEUE_FAILED; } @@ -358,9 +389,9 @@ int bitq_execute_queue(void) void bitq_cleanup(void) { - if (bitq_in_buffer!=NULL) + if (bitq_in_buffer != NULL) { free(bitq_in_buffer); - bitq_in_buffer=NULL; + bitq_in_buffer = NULL; } }