tap_state_transition() calculates the next state given a current
state and a TMS setting.

The attached function jtag_move_to() calulates the TMS bits given
a *ANY* current state and a *ANY* goal state. It could be used in
OpenOCD to replace the tms_seqs[][] table.

Currently, OpenOCD always sends down 7 TMS bit transitions to go
from a stable state to another stable state. However, with my
function it's possible to just send down the needed bits. For
this I wrote my own 

void ft2232_tms(int bits, char tms)
{
        MYTRACE("ft2232_tms(%d, 0x%02x)", bits, (quint8)tms);
        for (int i=0; i<bits; i++) {
                bool t = tms & (1 << i);
                current_state = tap_state_transition(current_state, t);
                MYVERBOSE("  tms %d, advance to %s %d", t, 
tap_state_name(current_state), current_state);
        }
        ft2232_buffer.append(0x4b);
        ft2232_buffer.append(bits-1);
        ft2232_buffer.append(tms);
}


I'm currently using both the jtag_move_to() and the jtag_tms()
functions in a project that is outside OpenOCD, so it might need
slight massaging if you think that this is helpful. For me, it's
helpful, because it allows me to easily do any state transition
the hardware wants.
void jtag_move_to(enum tap_state goal)
{
        LOG_DEBUG("jtag_move_to(%s)", tap_state_name(goal));
        if (current_state == goal)
                return;

        enum tap_state s = current_state;
        char bit[7];
        int bits = 0;

        for (int loop=0; loop<2; loop++) {
                if (s == TAP_RESET) {
                        bit[bits++] = 0;
                        s = TAP_IDLE;
                }
                if (s==goal) break;

                if (s == TAP_IDLE) {
                        bit[bits++] = 1;
                        s = TAP_DRSELECT;
                }
                if (s==goal) break;

                if (s == TAP_DRSELECT && ((goal >= TAP_IRSELECT) || (goal == 
TAP_RESET))) {
                        bit[bits++] = 1;
                        s = TAP_IRSELECT;
                } else
                if (s == TAP_DRSELECT) {
                        bit[bits++] = 0;
                        s = TAP_DRCAPTURE;
                } 
                if (s==goal) break;

                if (s == TAP_IRSELECT && (goal == TAP_RESET)) {
                        bit[bits++] = 1;
                        s = TAP_RESET;
                } else
                if (s == TAP_IRSELECT) {
                        bit[bits++] = 0;
                        s = TAP_IRCAPTURE;
                }
                if (s==goal) break;

                if (s == TAP_DRCAPTURE && goal==TAP_DRSHIFT) {
                        bit[bits++] = 0;
                        s = TAP_DRSHIFT;
                } else
                if (s == TAP_DRCAPTURE) {
                        bit[bits++] = 1;
                        s = TAP_DREXIT1;
                } else
                if (s == TAP_IRCAPTURE && goal==TAP_IRSHIFT) {
                        bit[bits++] = 0;
                        s = TAP_IRSHIFT;
                } else
                if (s == TAP_IRCAPTURE) {
                        bit[bits++] = 1;
                        s = TAP_IREXIT1;
                }
                if (s==goal) break;

                if (s == TAP_DRSHIFT) {
                        bit[bits++] = 1;
                        s = TAP_DREXIT1;
                } else
                if (s == TAP_IRSHIFT) {
                        bit[bits++] = 1;
                        s = TAP_IREXIT1;
                }
                if (s==goal) break;

                if (s == TAP_DREXIT1 && (goal == TAP_DRPAUSE || goal == 
TAP_DREXIT2)) {
                        bit[bits++] = 0;
                        s = TAP_DRPAUSE;
                } else
                if (s == TAP_DREXIT1) {
                        bit[bits++] = 1;
                        s = TAP_DRUPDATE;
                } else
                if (s == TAP_IREXIT1 && (goal == TAP_IRPAUSE || goal == 
TAP_IREXIT2)) {
                        bit[bits++] = 0;
                        s = TAP_IRPAUSE;
                } else
                if (s == TAP_IREXIT1) {
                        bit[bits++] = 1;
                        s = TAP_IRUPDATE;
                }
                if (s==goal) break;

                if (s == TAP_DRPAUSE) {
                        bit[bits++] = 1;
                        s = TAP_DREXIT2;
                } else
                if (s == TAP_IRPAUSE) {
                        bit[bits++] = 1;
                        s = TAP_IREXIT2;
                }
                if (s==goal) break;

                if (s == TAP_DREXIT2 && goal >= TAP_DRSHIFT && goal <= 
TAP_DRPAUSE) {
                        bit[bits++] = 0;
                        s = TAP_DRSHIFT;
                } else
                if (s == TAP_DREXIT2) {
                        bit[bits++] = 1;
                        s = TAP_DRUPDATE;
                } else
                if (s == TAP_IREXIT2 && goal >= TAP_IRSHIFT && goal <= 
TAP_IRPAUSE) {
                        bit[bits++] = 0;
                        s = TAP_IRSHIFT;
                } else
                if (s == TAP_IREXIT2) {
                        bit[bits++] = 1;
                        s = TAP_IRUPDATE;
                }
                if (s==goal) break;

                if (s == TAP_DRUPDATE || s == TAP_IRUPDATE) {
                        if (goal == TAP_IDLE) {
                                bit[bits++] = 0;
                                s = TAP_IDLE;
                        } else {
                                bit[bits++] = 1;
                                s = TAP_DRSELECT;
                        }
                }
                if (s==goal) break;
                
                if (s == TAP_IDLE) {
                        bit[bits++] = 1;
                        s = TAP_DRSELECT;
                }
                if (s==goal) break;

                if (bits > sizeof(bit)) {
                        LOG_ERROR("not enougth bits");
                        break;
                }
        }

        char trans = 0;
        for (int i=0; i<bits; i++) {
                trans |= (bit[i] << i);
        }
        jtag_tms(bits, trans);
}

/* Some test code:

void test_move()
{
        enum tap_state from;
        enum tap_state to;
        for (from=TAP_RESET; from <= TAP_IRUPDATE; from++) {
                for (to=TAP_RESET; to <= TAP_IRUPDATE; to++) {
                        LOG_DEBUG("\n%s %d -> %s %d",
                                tap_state_name(from), from,
                                tap_state_name(to), to);
                        current_state = (enum tap_state)from;
                        jtag_move_to(to);
                        if (current_state != to) {
                                LOG_ERROR("dit not reach goal, now at %d, not 
%d",
                                        current_state,
                                        to);
                                exit(1);
                        }
                }
                LOG_DEBUG("%s","");
        }
}
_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to