+ CLRMOSI;
+ SETTMS;
+ jtag_tcktock(); // Select-DR-Scan
+ jtag_tcktock(); // Select-IR-Scan
+ CLRTMS;
+ jtag_tcktock(); // Capture-IR
+
+ jtag_state = CAPTURE_IR;
+}
+
+//! Get into Capture-DR state
+void jtag_capture_dr()
+{
+ // assumes you're in Run-Test/Idle, Update-DR or Update-IR
+ if (!in_state(RUN_TEST_IDLE | UPDATE_DR | UPDATE_IR))
+ {
+ debugstr("Invalid JTAG state");
+ return;
+ }
+
+ CLRMOSI;
+ SETTMS;
+ jtag_tcktock(); // Select-DR-Scan
+ CLRTMS;
+ jtag_tcktock(); // Capture-IR
+
+ jtag_state = CAPTURE_DR;
+}
+
+//! Gets back to run-test-idle without going through the test-logic-reset
+void jtag_run_test_idle()
+{
+ CLRMOSI;
+
+ if (in_state(SELECT_DR_SCAN | SELECT_IR_SCAN))
+ {
+ CLRTMS;
+ jtag_tcktock();
+ jtag_state <<= 1; //CAPTURE_DR or CAPTURE_IR
+ }
+
+ if (in_state(CAPTURE_DR | CAPTURE_IR))
+ {
+ SETTMS;
+ jtag_tcktock();
+ jtag_state <<= 2; //EXIT1_DR or EXIT1_IR
+ }
+
+ if (in_state(SHIFT_DR | SHIFT_IR))
+ {
+ SETTMS;
+ jtag_tcktock();
+ jtag_state <<= 1; //EXIT1_DR or EXIT1_IR
+ }
+
+ if (in_state(EXIT1_DR | EXIT1_IR))
+ {
+ SETTMS;
+ jtag_tcktock();
+ jtag_state <<=3; //UPDATE_DR or UPDATE_IR
+ }
+
+ if (in_state(PAUSE_DR | PAUSE_IR))
+ {
+ SETTMS;
+ jtag_tcktock();
+ jtag_state <<= 1; // EXIT2_DR or EXIT2_IR
+ }
+
+ if (in_state(EXIT2_DR | EXIT2_IR))
+ {
+ SETTMS;
+ jtag_tcktock();
+ jtag_state <<= 1; // UPDATE_DR or UPDATE_IR
+ }
+
+ if (in_state(UPDATE_DR | UPDATE_IR | TEST_LOGIC_RESET))
+ {
+ CLRTMS;
+ jtag_tcktock();
+ jtag_state = RUN_TEST_IDLE;
+ }
+}
+
+int savedtclk;
+// NOTE: important: THIS MODULE REVOLVES AROUND RETURNING TO RUNTEST/IDLE, OR
+// THE FUNCTIONAL EQUIVALENT
+//! Shift N bits over TDI/TDO. May choose LSB or MSB, and select whether to
+// terminate (TMS-high on last bit) and whether to return to RUNTEST/IDLE
+// flags should be 0 for most uses.
+// for the extreme case, flags should be (NOEND|NORETDLE|LSB)
+// other edge cases can involve a combination of those three flags
+//
+// the max bit-size that can be be shifted is 32-bits.
+// for longer shifts, use the NOEND flag (which infers NORETIDLE so the
+// additional flag is unnecessary)
+//
+// NORETIDLE is used for special cases where (as with arm) the debug
+// subsystem does not want to return to the RUN-TEST/IDLE state between
+// setting IR and DR
+uint32_t jtag_trans_n(uint32_t word,
+ uint8_t bitcount,
+ enum eTransFlags flags)
+{
+ uint8_t bit;
+ uint32_t high = (1L << (bitcount - 1));
+ uint32_t mask = high - 1;
+
+ if (!in_state(SHIFT_IR | SHIFT_DR))
+ {
+ debugstr("jtag_trans_n from invalid TAP state");
+ return 0;
+ }
+
+ SAVETCLK;
+
+ if (flags & LSB)
+ {
+ for (bit = bitcount; bit > 0; bit--)
+ {
+ /* write MOSI on trailing edge of previous clock */
+ if (word & 1)
+ {
+ SETMOSI;
+ }
+ else
+ {
+ CLRMOSI;
+ }
+ word >>= 1;
+
+ if ((bit == 1) && !(flags & NOEND))
+ SETTMS; //TMS high on last bit to exit.
+
+ jtag_tcktock();
+
+ if ((bit == 1) && !(flags & NOEND))
+ jtag_state <<= 1; // Exit1-DR or Exit1-IR
+
+ /* read MISO on trailing edge */
+ if (READMISO)
+ {
+ word += (high);
+ }
+ }
+ }
+ else
+ {
+ for (bit = bitcount; bit > 0; bit--)
+ {
+ /* write MOSI on trailing edge of previous clock */
+ if (word & high)
+ {
+ SETMOSI;
+ }
+ else
+ {
+ CLRMOSI;
+ }
+ word = (word & mask) << 1;
+
+ if ((bit==1) && !(flags & NOEND))
+ SETTMS; //TMS high on last bit to exit.
+
+ jtag_tcktock();
+
+ if ((bit == 1) && !(flags & NOEND))
+ jtag_state <<= 1; // Exit1-DR or Exit1-IR
+
+ /* read MISO on trailing edge */
+ word |= (READMISO);
+ }
+ }
+
+ //This is needed for 20-bit MSP430 chips.
+ //Might break another 20-bit chip, if one exists.
+ if(bitcount==20){
+ word = ((word << 16) | (word >> 4)) & 0x000FFFFF;
+ }
+
+ RESTORETCLK;
+
+ if (!(flags & NOEND))
+ {
+ // exit state
+ jtag_tcktock();
+
+ jtag_state <<= 3; // Update-DR or Update-IR
+
+ // update state
+ if (!(flags & NORETIDLE))
+ {
+ CLRTMS;
+ jtag_tcktock();
+
+ jtag_state = RUN_TEST_IDLE;
+ }
+ }
+
+ return word;
+}
+
+//! Detects the width of the IR register
+uint16_t jtag_detect_ir_width()
+{
+ int i;
+ uint16_t width = 0;
+
+ if (!in_run_test_idle())
+ {
+ debugstr("Not in run-test-idle state");
+ return 0;
+ }
+
+ // get to shift-ir state
+ jtag_capture_ir();
+ jtag_shift_register();
+
+ // first we shift in 1024 zeros
+ CLRMOSI;
+ for(i = 0; i < 1024; i++)
+ {
+ jtag_tcktock();
+ }
+
+ // now we'll clock in ones until we see one
+ SETMOSI;
+ for(i = 0; i < 1024; i++)
+ {
+ jtag_tcktock();
+ if(READMISO)
+ break;
+ width++;
+ }
+
+ // now get back to run-test-idle
+ jtag_run_test_idle();
+
+ return width;
+}
+
+//! Detects how many TAPs are in the JTAG chain
+uint16_t jtag_detect_chain_length()
+{
+ int i;
+ int bit;
+ uint16_t length = 0;
+
+ if (!in_run_test_idle())
+ {
+ debugstr("detect chain length must start from run-test-idle");
+ return 0;
+ }
+
+ // The standard JTAG instruction for "bypass" mode is to set all 1's in the
+ // instruction register. When in "bypass" mode, the DR acts like a 1-bit
+ // shift regiser. So we can use that to detect how many TAPs are in the
+ // chain.
+
+ // first get into shift IR mode
+ jtag_capture_ir();
+ jtag_shift_register();
+
+ // then we flood the IR chain with all 1's to put all device's DRs
+ // into bypass mode
+ CLRTMS;
+ SETMOSI;
+ for (i = 0; i < 1024; i++)
+ {
+ if (i == 1023)
+ SETTMS; // exit on last bit
+ jtag_tcktock();
+ }
+ jtag_state = EXIT1_IR;
+
+ // go to Update-IR
+ CLRMOSI;
+ jtag_tcktock();
+ jtag_state = UPDATE_IR;
+
+ // go to Shift-DR state
+ jtag_capture_dr();
+ jtag_shift_register();
+
+ // flush the DR's with zeros
+ CLRTMS;
+ CLRMOSI;
+ for (i = 0; i < 1024; i++)
+ {
+ jtag_tcktock();
+ }
+
+ // send 1's into the DRs until we see one come out the other side
+ SETMOSI;
+ for (i = 0; i < 1024; i++)
+ {
+ jtag_tcktock();
+ bit = READMISO;
+ if (bit)
+ break;
+ length++;
+ }
+
+ // now get back to run-test-idle
+ jtag_run_test_idle();
+
+ return length;
+}
+
+//! Gets device ID for specified chip in the chain
+uint32_t jtag_get_device_id(int chip)
+{
+ int i;
+ uint16_t chain_length;
+ uint32_t id = 0;
+
+ // reset everything
+ jtag_reset_tap();
+
+ // figure out how many devices are in the chain
+ chain_length = jtag_detect_chain_length();
+
+ if (chip >= chain_length)
+ {
+ debugstr("invalid part index");
+ return 0;
+ }
+
+ // reset everything again because going through test-logic-reset forces
+ // all IR's to have their manufacturer specific instruction for IDCODE
+ // and loads the DR's with the chip's ID code.
+ jtag_reset_tap();
+
+ // get into shift DR state
+ jtag_capture_dr();
+ jtag_shift_register();
+
+ // read out the 32-bit ID codes for each device
+ CLRTMS;
+ CLRMOSI;
+ for (i = 0; i < (chip + 1); i++)
+ {
+ id = jtag_trans_n(0xFFFFFFFF, 32, LSB | NOEND | NORETIDLE);
+ }
+
+ jtag_run_test_idle();
+
+ return id;
+}
+
+//! Shift 8 bits in/out of selected register
+uint8_t jtag_trans_8(uint8_t in)
+{
+ uint32_t out = jtag_trans_n((uint32_t)in, 8, MSB);
+ return (uint8_t)(0x000000FF & out);