- flash autoerase <on|off> cmd added, default is off - flash banks are calculated...
[fw/openocd] / src / jtag / bitbang.c
index d6ff289830f77679830c853bd9d527607178f228..19afdbf0b8454397547c71949fde276c144b109e 100644 (file)
@@ -17,6 +17,9 @@
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 
 #include "bitbang.h"
 
@@ -65,6 +68,38 @@ void bitbang_state_move(void) {
        cur_state = end_state;
 }
 
+void bitbang_path_move(pathmove_command_t *cmd)
+{
+       int num_states = cmd->num_states;
+       int state_count;
+
+       state_count = 0;
+       while (num_states)
+       {
+               if (tap_transitions[cur_state].low == cmd->path[state_count])
+               {
+                       bitbang_interface->write(0, 0, 0);
+                       bitbang_interface->write(1, 0, 0);
+               }
+               else if (tap_transitions[cur_state].high == cmd->path[state_count])
+               {
+                       bitbang_interface->write(0, 1, 0);
+                       bitbang_interface->write(1, 1, 0);
+               }                       
+               else
+               {
+                       ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_strings[cur_state], tap_state_strings[cmd->path[state_count]]);
+                       exit(-1);
+               }
+               
+               cur_state = cmd->path[state_count];
+               state_count++;
+               num_states--;
+       }
+       
+       end_state = cur_state;
+}
+
 void bitbang_runtest(int num_cycles)
 {
        int i;
@@ -97,17 +132,35 @@ void bitbang_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
        enum tap_state saved_end_state = end_state;
        int bit_cnt;
        
-       if (ir_scan)
-               bitbang_end_state(TAP_SI);
-       else
-               bitbang_end_state(TAP_SD);
+       if (!((!ir_scan && (cur_state == TAP_SD)) || (ir_scan && (cur_state == TAP_SI))))
+       {
+               if (ir_scan)
+                       bitbang_end_state(TAP_SI);
+               else
+                       bitbang_end_state(TAP_SD);
 
-       bitbang_state_move();
-       bitbang_end_state(saved_end_state);
+               bitbang_state_move();
+               bitbang_end_state(saved_end_state);
+       }
 
        for (bit_cnt = 0; bit_cnt < scan_size; bit_cnt++)
        {
-               if ((buffer[bit_cnt/8] >> (bit_cnt % 8)) & 0x1) {
+               /* set TMS high on the last bit unless we want to end in TAP_SD/SI */
+               int tms;
+               if ((ir_scan && (end_state == TAP_SI)) ||
+                       (!ir_scan && (end_state == TAP_SD)))
+               {
+                       tms = 0;
+               } else {
+                       tms = (bit_cnt==scan_size-1) ? 1 : 0;
+               }
+               
+               /* if we're just reading the scan, but don't care about the output
+                * default to outputting 'low', this also makes valgrind traces more readable,
+                * as it removes the dependency on an uninitialised value
+                */ 
+               if ((type != SCAN_IN) && ((buffer[bit_cnt/8] >> (bit_cnt % 8)) & 0x1))
+               {
                        bitbang_interface->write(0, (bit_cnt==scan_size-1) ? 1 : 0, 1);
                        bitbang_interface->write(1, (bit_cnt==scan_size-1) ? 1 : 0, 1);
                } else {
@@ -143,13 +196,22 @@ int bitbang_execute_queue(void)
        int scan_size;
        enum scan_type type;
        u8 *buffer;
+       int retval;
        
        if (!bitbang_interface)
        {
                ERROR("BUG: Bitbang interface called, but not yet initialized");
                exit(-1);
        }
+       
+       /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
+        * that wasn't handled by a caller-provided error handler
+        */ 
+       retval = ERROR_OK;
                
+       if(bitbang_interface->blink)
+               bitbang_interface->blink(1);
+
        while (cmd)
        {
                switch (cmd->type)
@@ -187,9 +249,15 @@ int bitbang_execute_queue(void)
                                        bitbang_end_state(cmd->cmd.statemove->end_state);
                                bitbang_state_move();
                                break;
+                       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]);
+#endif
+                               bitbang_path_move(cmd->cmd.pathmove);
+                               break;
                        case JTAG_SCAN:
 #ifdef _DEBUG_JTAG_IO_
-                               DEBUG("scan end in %i", cmd->cmd.scan->end_state);
+                               DEBUG("%s scan end in %i",  (cmd->cmd.scan->ir_scan) ? "IR" : "DR", cmd->cmd.scan->end_state);
 #endif
                                if (cmd->cmd.scan->end_state != -1)
                                        bitbang_end_state(cmd->cmd.scan->end_state);
@@ -197,13 +265,13 @@ int bitbang_execute_queue(void)
                                type = jtag_scan_type(cmd->cmd.scan);
                                bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
                                if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
-                                       return ERROR_JTAG_QUEUE_FAILED;
+                                       retval = ERROR_JTAG_QUEUE_FAILED;
                                if (buffer)
                                        free(buffer);
                                break;
                        case JTAG_SLEEP:
 #ifdef _DEBUG_JTAG_IO_
-                               DEBUG("sleep", cmd->cmd.sleep->us);
+                               DEBUG("sleep %i", cmd->cmd.sleep->us);
 #endif
                                jtag_sleep(cmd->cmd.sleep->us);
                                break;
@@ -213,7 +281,9 @@ int bitbang_execute_queue(void)
                }
                cmd = cmd->next;
        }
+       if(bitbang_interface->blink)
+               bitbang_interface->blink(0);
        
-       return ERROR_OK;
+       return retval;
 }