add jtag_tap logic from luna
authorGreg Davill <greg.davill@gmail.com>
Sat, 18 Apr 2020 11:59:53 +0000 (21:29 +0930)
committerGreg Davill <greg.davill@gmail.com>
Sat, 18 Apr 2020 11:59:53 +0000 (21:29 +0930)
Makefile
iceprog.c
jtag.h [new file with mode: 0644]
jtag_tap.c [new file with mode: 0644]
mpsse.c
mpsse.h

index 664f0a08b47c6f6901fcaa4c7c14c7ee7cacd152..9d3e541394eca33c28bc0370e34a90ac3d794e78 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -50,7 +50,7 @@ endif
 
 all: $(PROGRAM_PREFIX)iceprog$(EXE)
 
-$(PROGRAM_PREFIX)iceprog$(EXE): iceprog.o mpsse.o
+$(PROGRAM_PREFIX)iceprog$(EXE): iceprog.o mpsse.o jtag_tap.o
        $(CC) -o $@ $(LDFLAGS) $^ $(LDLIBS)
 
 install: all
index e0b574146596e80c7741801eb844afe0465e7016..0218f0d2ac566880be97240e73d0a2721ca5406d 100644 (file)
--- a/iceprog.c
+++ b/iceprog.c
@@ -41,6 +41,7 @@
 #endif
 
 #include "mpsse.h"
+#include "jtag.h"
 
 static bool verbose = false;
 
@@ -820,10 +821,24 @@ int main(int argc, char **argv)
 
        mpsse_jtag_init();
 
-       mpsse_jtag_scan_dr();
+       jtag_go_to_state(STATE_SHIFT_IR);
 
-       //fprintf(stderr, "cdone: %s\n", get_cdone() ? "high" : "low");
+       uint8_t data_in[4] = {0,0,0,0};
+       uint8_t data_out[4] = {0,0,0,0};
 
+       data_in[0] = 0xE0;
+       jtag_tap_shift(data_in, data_out, 8, true);
+       fprintf(stderr, " %02x\n", data_out[0]);
+
+       jtag_go_to_state(STATE_SHIFT_DR);
+       jtag_tap_shift(data_in, data_out, 32, true);
+
+
+       fprintf(stderr, "Data: ");
+       for(int i = 0; i< 4; i++)
+               fprintf(stderr, " %02x", data_out[i]);
+       fprintf(stderr, "\n");
+       
        //flash_release_reset();
        usleep(100000);
 
diff --git a/jtag.h b/jtag.h
new file mode 100644 (file)
index 0000000..a752f66
--- /dev/null
+++ b/jtag.h
@@ -0,0 +1,68 @@
+/*
+ * Code for interacting with the FPGA via JTAG.
+ * This file is part of LUNA.
+ *
+ * This JTAG driver is intended to be as simple as possible in order to facilitate
+ * configuration and debugging of the attached FPGA. It is not intended to be a general-
+ * purpose JTAG link.
+ */
+
+#ifndef __JTAG_H__
+#define __JTAG_H__
+
+typedef enum e_TAPState
+{
+       STATE_TEST_LOGIC_RESET =  0,
+       STATE_RUN_TEST_IDLE    =  1,
+       STATE_SELECT_DR_SCAN   =  2,
+       STATE_CAPTURE_DR       =  3,
+       STATE_SHIFT_DR         =  4,
+       STATE_EXIT1_DR         =  5,
+       STATE_PAUSE_DR         =  6,
+       STATE_EXIT2_DR         =  7,
+       STATE_UPDATE_DR        =  8,
+       STATE_SELECT_IR_SCAN   =  9, 
+       STATE_CAPTURE_IR       = 10,
+       STATE_SHIFT_IR         = 11,
+       STATE_EXIT1_IR         = 12,
+       STATE_PAUSE_IR         = 13,
+       STATE_EXIT2_IR         = 14,
+       STATE_UPDATE_IR        = 15
+} jtag_tap_state_t;
+
+
+/**
+ * Performs the start-of-day tasks necessary to talk JTAG to our FPGA.
+ */
+void jtag_init(void);
+
+
+/**
+ * De-inits the JTAG connection, so the JTAG chain. is no longer driven.
+ */
+void jtag_deinit(void);
+
+
+/**
+ * Moves to a given JTAG state.
+ */
+void jtag_goto_state(int state);
+
+
+/**
+ * Performs a raw TAP scan.
+ */
+void jtag_tap_shift(
+       uint8_t *input_data,
+       uint8_t *output_data,
+       uint32_t data_bits,
+       bool must_end);
+
+
+void jtag_wait_time(uint32_t microseconds);
+
+void jtag_go_to_state(unsigned state);
+
+uint8_t jtag_current_state(void);
+
+#endif
diff --git a/jtag_tap.c b/jtag_tap.c
new file mode 100644 (file)
index 0000000..3fcb2d9
--- /dev/null
@@ -0,0 +1,246 @@
+/**
+ * Code adapted from Arduino-JTAG;
+ *    portions copyright (c) 2015 Marcelo Roberto Jimenez <marcelo.jimenez (at) gmail (dot) com>.
+ *    portions copyright (c) 2019 Katherine J. Temkin <kate@ktemkin.com>
+ *    portions copyright (c) 2019 Great Scott Gadgets <ktemkin@greatscottgadgets.com>
+ */
+
+#include <ftdi.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "mpsse.h"
+#include "jtag.h"
+
+void jtag_state_ack(bool tms);
+
+/*
+ * Low nibble : TMS == 0
+ * High nibble: TMS == 1
+ */
+
+#define TMS_T(TMS_HIGH_STATE, TMS_LOW_STATE) (((TMS_HIGH_STATE) << 4) | (TMS_LOW_STATE))
+
+static const uint8_t tms_transitions[] = {
+       /* STATE_TEST_LOGIC_RESET */ TMS_T(STATE_TEST_LOGIC_RESET, STATE_RUN_TEST_IDLE),
+       /* STATE_RUN_TEST_IDLE    */ TMS_T(STATE_SELECT_DR_SCAN,   STATE_RUN_TEST_IDLE),
+       /* STATE_SELECT_DR_SCAN   */ TMS_T(STATE_SELECT_IR_SCAN,   STATE_CAPTURE_DR),
+       /* STATE_CAPTURE_DR       */ TMS_T(STATE_EXIT1_DR,         STATE_SHIFT_DR),
+       /* STATE_SHIFT_DR         */ TMS_T(STATE_EXIT1_DR,         STATE_SHIFT_DR),
+       /* STATE_EXIT1_DR         */ TMS_T(STATE_UPDATE_DR,        STATE_PAUSE_DR),
+       /* STATE_PAUSE_DR         */ TMS_T(STATE_EXIT2_DR,         STATE_PAUSE_DR),
+       /* STATE_EXIT2_DR         */ TMS_T(STATE_UPDATE_DR,        STATE_SHIFT_DR),
+       /* STATE_UPDATE_DR        */ TMS_T(STATE_SELECT_DR_SCAN,   STATE_RUN_TEST_IDLE),
+       /* STATE_SELECT_IR_SCAN   */ TMS_T(STATE_TEST_LOGIC_RESET, STATE_CAPTURE_IR),
+       /* STATE_CAPTURE_IR       */ TMS_T(STATE_EXIT1_IR,         STATE_SHIFT_IR),
+       /* STATE_SHIFT_IR         */ TMS_T(STATE_EXIT1_IR,         STATE_SHIFT_IR),
+       /* STATE_EXIT1_IR         */ TMS_T(STATE_UPDATE_IR,        STATE_PAUSE_IR),
+       /* STATE_PAUSE_IR         */ TMS_T(STATE_EXIT2_IR,         STATE_PAUSE_IR),
+       /* STATE_EXIT2_IR         */ TMS_T(STATE_UPDATE_IR,        STATE_SHIFT_IR),
+       /* STATE_UPDATE_IR        */ TMS_T(STATE_SELECT_DR_SCAN,   STATE_RUN_TEST_IDLE),
+};
+
+#define BITSTR(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) ( \
+       ((uint16_t)(A) << 15) | \
+       ((uint16_t)(B) << 14) | \
+       ((uint16_t)(C) << 13) | \
+       ((uint16_t)(D) << 12) | \
+       ((uint16_t)(E) << 11) | \
+       ((uint16_t)(F) << 10) | \
+       ((uint16_t)(G) <<  9) | \
+       ((uint16_t)(H) <<  8) | \
+       ((uint16_t)(I) <<  7) | \
+       ((uint16_t)(J) <<  6) | \
+       ((uint16_t)(K) <<  5) | \
+       ((uint16_t)(L) <<  4) | \
+       ((uint16_t)(M) <<  3) | \
+       ((uint16_t)(N) <<  2) | \
+       ((uint16_t)(O) <<  1) | \
+       ((uint16_t)(P) <<  0) )
+
+/*
+ * The index of this vector is the current state. The i-th bit tells you the
+ * value TMS must assume in order to go to state "i".
+
+------------------------------------------------------------------------------------------------------------
+|                        |   || F | E | D | C || B | A | 9 | 8 || 7 | 6 | 5 | 4 || 3 | 2 | 1 | 0 ||   HEX  |
+------------------------------------------------------------------------------------------------------------
+| STATE_TEST_LOGIC_RESET | 0 || 0 | 0 | 0 | 0 || 0 | 0 | 0 | 0 || 0 | 0 | 0 | 0 || 0 | 0 | 0 | 1 || 0x0001 |
+| STATE_RUN_TEST_IDLE    | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 0 | 1 || 0xFFFD |
+| STATE_SELECT_DR_SCAN   | 2 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 0 || 0 | 0 | 0 | 0 || 0 | x | 1 | 1 || 0xFE03 |
+| STATE_CAPTURE_DR       | 3 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 0 || x | 1 | 1 | 1 || 0xFFE7 |
+| STATE_SHIFT_DR         | 4 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 0 || 1 | 1 | 1 | 1 || 0xFFEF |
+| STATE_EXIT1_DR         | 5 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0 | 0 | x | 0 || 1 | 1 | 1 | 1 || 0xFF0F |
+| STATE_PAUSE_DR         | 6 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 0 | 1 | 1 || 1 | 1 | 1 | 1 || 0xFFBF |
+| STATE_EXIT2_DR         | 7 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || x | 0 | 0 | 0 || 1 | 1 | 1 | 1 || 0xFF0F |
+| STATE_UPDATE_DR        | 8 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | x || 1 | 1 | 1 | 1 || 1 | 1 | 0 | 1 || 0xFEFD |
+| STATE_SELECT_IR_SCAN   | 9 || 0 | 0 | 0 | 0 || 0 | 0 | x | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0x01FF |
+| STATE_CAPTURE_IR       | A || 1 | 1 | 1 | 1 || 0 | x | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0xF3FF |
+| STATE_SHIFT_IR         | B || 1 | 1 | 1 | 1 || 0 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0xF7FF |
+| STATE_EXIT1_IR         | C || 1 | 0 | 0 | x || 0 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0x87FF |
+| STATE_PAUSE_IR         | D || 1 | 1 | 0 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0xDFFF |
+| STATE_EXIT2_IR         | E || 1 | x | 0 | 0 || 0 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 0x87FF |
+| STATE_UPDATE_IR        | F || x | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 1 | 1 || 1 | 1 | 0 | 1 || 0x7FFD |
+------------------------------------------------------------------------------------------------------------
+
+*/
+static const uint16_t tms_map[] = {
+/* STATE_TEST_LOGIC_RESET */ BITSTR(  0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 1  ),
+/* STATE_RUN_TEST_IDLE    */ BITSTR(  1, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 1,   1, 1, 0, 1  ),
+/* STATE_SELECT_DR_SCAN   */ BITSTR(  1, 1, 1, 1,   1, 1, 1, 0,   0, 0, 0, 0,   0, 0, 1, 1  ),
+/* STATE_CAPTURE_DR       */ BITSTR(  1, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 0,   0, 1, 1, 1  ),
+/* STATE_SHIFT_DR         */ BITSTR(  1, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 0,   1, 1, 1, 1  ),
+/* STATE_EXIT1_DR         */ BITSTR(  1, 1, 1, 1,   1, 1, 1, 1,   0, 0, 0, 0,   1, 1, 1, 1  ),
+/* STATE_PAUSE_DR         */ BITSTR(  1, 1, 1, 1,   1, 1, 1, 1,   1, 0, 1, 1,   1, 1, 1, 1  ),
+/* STATE_EXIT2_DR         */ BITSTR(  1, 1, 1, 1,   1, 1, 1, 1,   0, 0, 0, 0,   1, 1, 1, 1  ),
+/* STATE_UPDATE_DR        */ BITSTR(  1, 1, 1, 1,   1, 1, 1, 0,   1, 1, 1, 1,   1, 1, 0, 1  ),
+/* STATE_SELECT_IR_SCAN   */ BITSTR(  0, 0, 0, 0,   0, 0, 0, 1,   1, 1, 1, 1,   1, 1, 1, 1  ),
+/* STATE_CAPTURE_IR       */ BITSTR(  1, 1, 1, 1,   0, 0, 1, 1,   1, 1, 1, 1,   1, 1, 1, 1  ),
+/* STATE_SHIFT_IR         */ BITSTR(  1, 1, 1, 1,   0, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 1  ),
+/* STATE_EXIT1_IR         */ BITSTR(  1, 0, 0, 0,   0, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 1  ),
+/* STATE_PAUSE_IR         */ BITSTR(  1, 1, 0, 1,   1, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 1  ),
+/* STATE_EXIT2_IR         */ BITSTR(  1, 0, 0, 0,   0, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 1  ),
+/* STATE_UPDATE_IR        */ BITSTR(  0, 1, 1, 1,   1, 1, 1, 1,   1, 1, 1, 1,   1, 1, 0, 1  ),
+};
+
+static uint8_t current_state;
+
+uint8_t jtag_current_state(void)
+{
+       return current_state;
+}
+
+void jtag_set_current_state(uint8_t state)
+{
+       current_state = state;
+}
+
+
+/**
+ * Hook for any per-platform initialization that needs to occur.
+ */
+__attribute__((weak)) void jtag_platform_init(void)
+{
+
+}
+
+
+/**
+ * Performs any start-of-day tasks necessary to talk JTAG to our FPGA.
+ */
+void jtag_init(void)
+{
+       jtag_platform_init();
+       jtag_set_current_state(STATE_TEST_LOGIC_RESET);
+    jtag_go_to_state(STATE_TEST_LOGIC_RESET);
+}
+
+
+static inline void jtag_pulse_clock(void)
+{
+       //mpsse_send_byte(MC_CLK_N);
+       //mpsse_send_byte(0x00);
+    mpsse_send_byte(MC_DATA_TMS | MC_DATA_IN | MC_DATA_LSB | MC_DATA_BITS);
+       mpsse_send_byte(0);
+    mpsse_send_byte(0);
+}
+
+static inline uint8_t jtag_pulse_clock_and_read_tdo(bool tms, bool tdi)
+{
+       uint8_t ret;
+
+    mpsse_send_byte(MC_DATA_TMS | MC_DATA_IN  | MC_DATA_LSB |  MC_DATA_BITS);
+       mpsse_send_byte(0);
+
+    uint8_t data = 0;
+    if(tdi)
+        data |= 0x80;
+    if(tms)
+        data |= 0x01;
+        
+    mpsse_send_byte(data);
+       ret = mpsse_recv_byte();
+    
+       return (ret >> 7) & 1;
+}
+
+
+void jtag_tap_shift(
+       uint8_t *input_data,
+       uint8_t *output_data,
+       uint32_t data_bits,
+       bool must_end)
+{
+       uint32_t bit_count = data_bits;
+       uint32_t byte_count = (data_bits + 7) / 8;
+
+       for (uint32_t i = 0; i < byte_count; ++i) {
+               uint8_t byte_out = input_data[i];
+               uint8_t tdo_byte = 0;
+               for (int j = 0; j < 8 && bit_count-- > 0; ++j) {
+            bool tms = false;
+            bool tdi = false;
+                       if (bit_count == 0 && must_end) {
+                tms = true;
+                               jtag_state_ack(1);
+                       }
+                       if (byte_out & 1) {
+                               tdi = true;
+                       } else {
+                               tdi = false;
+                       }
+                       byte_out >>= 1;
+                       bool tdo = jtag_pulse_clock_and_read_tdo(tms, tdi);
+                       tdo_byte |= tdo << j;
+               }
+               output_data[i] = tdo_byte;
+       }
+}
+
+void jtag_state_ack(bool tms)
+{
+       if (tms) {
+               jtag_set_current_state((tms_transitions[jtag_current_state()] >> 4) & 0xf);
+       } else {
+               jtag_set_current_state(tms_transitions[jtag_current_state()] & 0xf);
+       }
+}
+
+void jtag_state_step(bool tms)
+{
+    
+    mpsse_send_byte(MC_DATA_TMS | MC_DATA_LSB | MC_DATA_BITS);
+       mpsse_send_byte(0);
+       if (tms) {
+       mpsse_send_byte(1);
+       } else {
+        mpsse_send_byte(0);
+       }
+    
+       jtag_state_ack(tms);
+}
+
+void jtag_go_to_state(unsigned state)
+{
+    fprintf(stderr, " (%u) > (%u)\n", jtag_current_state() ,state);
+       if (state == STATE_TEST_LOGIC_RESET) {
+               for (int i = 0; i < 5; ++i) {
+                       jtag_state_step(true);
+               }
+       } else {
+               while (jtag_current_state() != state) {
+                       jtag_state_step((tms_map[jtag_current_state()] >> state) & 1);
+               }
+       }
+}
+
+void jtag_wait_time(uint32_t microseconds)
+{
+       while (microseconds--) {
+               jtag_pulse_clock();
+       }
+}
+
diff --git a/mpsse.c b/mpsse.c
index 34a73f1b0831de55b8f7ea28b6989dc5599ef2a1..5090d7447654287fe1dc58d5d06acb4c0685e40a 100644 (file)
--- a/mpsse.c
+++ b/mpsse.c
@@ -54,102 +54,49 @@ bool mpsse_ftdic_open = false;
 bool mpsse_ftdic_latency_set = false;
 unsigned char mpsse_ftdi_latency;
 
-
-enum jtag_states 
+/* Not sure if all of these are applicable to the JTAG interface */
+enum lattice_cmd
 {
-       JTAG_INVALID = 0,
-       JTAG_TEST_LOGIC_RESET,
-       JTAG_RUN_TEST_IDLE,
-       JTAG_SELECT_DR_SCAN,
-       JTAG_CAPTURE_DR,
-       JTAG_SHIFT_DR,
-       JTAG_EXIT_1_DR,
-       JTAG_PAUSE_DR,
-       JTAG_EXIT_2_DR,
-       JTAG_UPDATE_DR,
-       JTAG_SELECT_IR_SCAN,
-       JTAG_CAPTURE_IR,
-       JTAG_SHIFT_IR,
-       JTAG_EXIT_1_IR,
-       JTAG_PAUSE_IR,
-       JTAG_EXIT_2_IR,
-       JTAG_UPDATE_IR,
+       ISC_NOOP = 0xFF, /* 0 bits - Non-operation */
+       READ_ID = 0xE0, /* 24 bits - Read out the 32-bit IDCODE of the device */
+       USERCODE = 0xC0, /* 24 bits - Read 32-bit usercode */
+       LSC_READ_STATUS = 0x3C, /* 24 bits - Read out internal status */
+       LSC_CHECK_BUSY = 0xF0, /* 24 bits - Read 1 bit busy flag to check the command execution status */
+       LSC_REFRESH = 0x79, /* 24 bits - Equivalent to toggle PROGRAMN pin */
+       ISC_ENABLE = 0xC6, /* 24 bits - Enable the Offline configuration mode */
+       ISC_ENABLE_X = 0x74, /* 24 bits - Enable the Transparent configuration mode */
+       ISC_DISABLE = 0x26, /* 24 bits - Disable the configuration operation */
+       ISC_PROGRAM_USERCODE = 0xC2, /* 24 bits - Write the 32-bit new USERCODE data to USERCODE register */
+       ISC_ERASE = 0x0E, /* 24 bits - Bulk erase the memory array base on the access mode and array selection */
+       ISC_PROGRAM_DONE = 0x5E, /* 24 bits - Program the DONE bit if the device is in Configuration state. */
+       ISC_PROGRAM_SECURITY = 0xCE, /* 24 bits - Program the Security bit if the device is in Configuration state */
+       LSC_INIT_ADDRESS = 0x46, /* 24 bits - Initialize the Address Shift Register */
+       LSC_WRITE_ADDRESS = 0xB4, /* 24 bits - Write the 16 bit Address Register to move the address quickly */
+       LSC_BITSTREAM_BURST = 0x7A, /* 24 bits - Program the device the whole bitstream sent in as the command operand */
+       LSC_PROG_INCR_RTI = 0x82, /* 24 bits - Write configuration data to the configuration memory frame at current address and post increment the address, Byte 2~0 of the opcode indicate number of the frames included in the operand field */
+       LSC_PROG_INCR_ENC = 0xB6, /* 24 bits - Encrypt the configuration data then write */
+       LSC_PROG_INCR_CMP = 0xB8, /* 24 bits - Decompress the configuration data, then write */
+       LSC_PROG_INCR_CNE = 0xBA, /* 24 bits - Decompress and Encrypt the configuration data, then write */
+       LSC_VERIFY_INCR_RTI = 0x6A, /* 24 bits - Read back the configuration memory frame selected by the address register and post increment the address */
+       LSC_PROG_CTRL0 = 0x22, /* 24 bits - Modify the Control Register 0 */
+       LSC_READ_CTRL0 = 0x20, /* 24 bits - Read the Control Register 0 */
+       LSC_RESET_CRC = 0x3B, /* 24 bits - Reset 16-bit frame CRC register to 0x0000 */
+       LSC_READ_CRC = 0x60, /* 24 bits - Read 16-bit frame CRC register content */
+       LSC_PROG_SED_CRC = 0xA2, /* 24 bits - Program the calculated 32-bit CRC based on configuration bit values only into overall CRC register */
+       LSC_READ_SED_CRC = 0xA4, /* 24 bits - Read the 32-bit SED CRC */
+       LSC_PROG_PASSWORD = 0xF1, /* 24 bits - Program 64-bit password into the non-volatile memory (Efuse) */
+       LSC_READ_PASSWORD = 0xF2, /* 24 bits - Read out the 64-bit password before activated for verification */
+       LSC_SHIFT_PASSWORD = 0xBC, /* 24 bits - Shift in the password to unlock for re-configuration (necessary when password protection feature is active). */
+       LSC_PROG_CIPHER_KEY = 0xF3, /* 24 bits - Program the 128-bit cipher key into Efuse */
+       LSC_READ_CIPHER_KEY = 0xF4, /* 24 bits - Read out the 128-bit cipher key before activated for verification */
+       LSC_PROG_FEATURE = 0xE4, /* 24 bits - Program User Feature, such as Customer ID, I2C Slave Address, Unique ID Header */
+       LSC_READ_FEATURE = 0xE7, /* 24 bits - Read User Feature, such as Customer ID, I2C Slave Address, Unique ID Header */
+       LSC_PROG_FEABITS = 0xF8, /* 24 bits - Program User Feature Bits, such as CFG port and pin persistence, PWD_EN, PWD_ALL, DEC_ONLY, Feature Row Lock etc. */
+       LSC_READ_FEABITS = 0xFB, /* 24 bits - Read User Feature Bits, such as CFH port and pin persistence, PWD_EN, PWD_ALL, DEC_ONLY, Feature Row Lock etc. */
+       LSC_PROG_OTP = 0xF9, /* 24 bits - Program OTP bits, to set Memory Sectors One Time Programmable */
+       LSC_READ_OTP = 0xFA, /* 24 bits - Read OTP bits setting */
 };
-enum jtag_states jtag_state = JTAG_INVALID;
-
-/* MPSSE engine command definitions */
-enum mpsse_cmd
-{
-       /* Mode commands */
-       MC_SETB_LOW = 0x80, /* Set Data bits LowByte */
-       MC_READB_LOW = 0x81, /* Read Data bits LowByte */
-       MC_SETB_HIGH = 0x82, /* Set Data bits HighByte */
-       MC_READB_HIGH = 0x83, /* Read data bits HighByte */
-       MC_LOOPBACK_EN = 0x84, /* Enable loopback */
-       MC_LOOPBACK_DIS = 0x85, /* Disable loopback */
-       MC_SET_CLK_DIV = 0x86, /* Set clock divisor */
-       MC_FLUSH = 0x87, /* Flush buffer fifos to the PC. */
-       MC_WAIT_H = 0x88, /* Wait on GPIOL1 to go high. */
-       MC_WAIT_L = 0x89, /* Wait on GPIOL1 to go low. */
-       MC_TCK_X5 = 0x8A, /* Disable /5 div, enables 60MHz master clock */
-       MC_TCK_D5 = 0x8B, /* Enable /5 div, backward compat to FT2232D */
-       MC_EN_3PH_CLK = 0x8C, /* Enable 3 phase clk, DDR I2C */
-       MC_DIS_3PH_CLK = 0x8D, /* Disable 3 phase clk */
-       MC_CLK_N = 0x8E, /* Clock every bit, used for JTAG */
-       MC_CLK_N8 = 0x8F, /* Clock every byte, used for JTAG */
-       MC_CLK_TO_H = 0x94, /* Clock until GPIOL1 goes high */
-       MC_CLK_TO_L = 0x95, /* Clock until GPIOL1 goes low */
-       MC_EN_ADPT_CLK = 0x96, /* Enable adaptive clocking */
-       MC_DIS_ADPT_CLK = 0x97, /* Disable adaptive clocking */
-       MC_CLK8_TO_H = 0x9C, /* Clock until GPIOL1 goes high, count bytes */
-       MC_CLK8_TO_L = 0x9D, /* Clock until GPIOL1 goes low, count bytes */
-       MC_TRI = 0x9E, /* Set IO to only drive on 0 and tristate on 1 */
-       /* CPU mode commands */
-       MC_CPU_RS = 0x90, /* CPUMode read short address */
-       MC_CPU_RE = 0x91, /* CPUMode read extended address */
-       MC_CPU_WS = 0x92, /* CPUMode write short address */
-       MC_CPU_WE = 0x93, /* CPUMode write extended address */
-};
-
-/* Transfer Command bits */
-
-/* All byte based commands consist of:
- * - Command byte
- * - Length lsb
- * - Length msb
- *
- * If data out is enabled the data follows after the above command bytes,
- * otherwise no additional data is needed.
- * - Data * n
- *
- * All bit based commands consist of:
- * - Command byte
- * - Length
- *
- * If data out is enabled a byte containing bitst to transfer follows.
- * Otherwise no additional data is needed. Only up to 8 bits can be transferred
- * per transaction when in bit mode.
- */
-
-/* b 0000 0000
- *   |||| |||`- Data out negative enable. Update DO on negative clock edge.
- *   |||| ||`-- Bit count enable. When reset count represents bytes.
- *   |||| |`--- Data in negative enable. Latch DI on negative clock edge.
- *   |||| `---- LSB enable. When set clock data out LSB first.
- *   ||||
- *   |||`------ Data out enable
- *   ||`------- Data in enable
- *   |`-------- TMS mode enable
- *   `--------- Special command mode enable. See mpsse_cmd enum.
- */
 
-#define MC_DATA_TMS  (0x40) /* When set use TMS mode */
-#define MC_DATA_IN   (0x20) /* When set read data (Data IN) */
-#define MC_DATA_OUT  (0x10) /* When set write data (Data OUT) */
-#define MC_DATA_LSB  (0x08) /* When set input/output data LSB first. */
-#define MC_DATA_ICN  (0x04) /* When set receive data on negative clock edge */
-#define MC_DATA_BITS (0x02) /* When set count bits not bytes */
-#define MC_DATA_OCN  (0x01) /* When set update data on negative clock edge */
 
 // ---------------------------------------------------------
 // MPSSE / FTDI function implementations
@@ -299,66 +246,15 @@ void mpsse_jtag_init(){
        mpsse_send_byte(0x0B); /* Direction */
 
        /* Reset JTAG State machine */
-       mpsse_jtag_tms(6, 0b111111);
-
-       jtag_state = JTAG_TEST_LOGIC_RESET;
+       jtag_init();
 }
 
 void mpsse_jtag_tms(uint8_t bits, uint8_t pattern){
-       mpsse_send_byte(MC_DATA_TMS | MC_DATA_IN | MC_DATA_LSB | MC_DATA_BITS);
+       mpsse_send_byte(MC_DATA_TMS | MC_DATA_LSB | MC_DATA_BITS);
        mpsse_send_byte(bits-1);
        mpsse_send_byte(pattern);
 }
 
-void mpsse_jtag_idcode(){
-       mpsse_send_byte(MC_SETB_LOW);
-       mpsse_send_byte(0x08); /* Value */
-       mpsse_send_byte(0x0B); /* Direction */
-
-       /* Reset JTAG State machine */
-       mpsse_jtag_tms(6, 0b000000);
-       mpsse_jtag_tms(6, 0b000000);
-
-       jtag_state = JTAG_TEST_LOGIC_RESET;
-}
-
-void mpsse_jtag_scan_dr(uint16_t len, uint8_t* data_out){
-       uint8_t data;
-       enter_jtag_state_shift_dr();
-
-       mpsse_send_byte(MC_DATA_IN | MC_DATA_LSB);
-       mpsse_send_byte(4);
-               data = mpsse_recv_byte();
-               data = mpsse_recv_byte();
-       
-       uint32_t idcode = 0;
-
-       for(int i = 0; i < 4; i++)
-       {
-               mpsse_send_byte(0);
-               idcode = mpsse_recv_byte() << 24 | idcode >> 8;
-       }       
-
-       fprintf(stderr, "idcode: 0x%08x\n", idcode);
-
-       mpsse_jtag_tms(6, 0b111111);
-
-       
-}
-
-void enter_jtag_state_shift_dr(){
-       switch(jtag_state){
-               case JTAG_TEST_LOGIC_RESET:
-                       mpsse_jtag_tms(4, 0b0010);
-                       break;
-
-               default:
-               case JTAG_INVALID:
-                       fprintf(stderr, "JTAG statemachine in INVALID State\n");
-                       break;
-       }
-}
-
 void mpsse_init(int ifnum, const char *devstr, bool slow_clock)
 {
        enum ftdi_interface ftdi_ifnum = INTERFACE_A;
diff --git a/mpsse.h b/mpsse.h
index b64b076b9b47db6b29dc6bfbef7b5d9d63f196ce..d71761c1edbb0e00438628261f5260289d13a06c 100644 (file)
--- a/mpsse.h
+++ b/mpsse.h
 
 #include <stdint.h>
 
+
+
+/* MPSSE engine command definitions */
+enum mpsse_cmd
+{
+       /* Mode commands */
+       MC_SETB_LOW = 0x80, /* Set Data bits LowByte */
+       MC_READB_LOW = 0x81, /* Read Data bits LowByte */
+       MC_SETB_HIGH = 0x82, /* Set Data bits HighByte */
+       MC_READB_HIGH = 0x83, /* Read data bits HighByte */
+       MC_LOOPBACK_EN = 0x84, /* Enable loopback */
+       MC_LOOPBACK_DIS = 0x85, /* Disable loopback */
+       MC_SET_CLK_DIV = 0x86, /* Set clock divisor */
+       MC_FLUSH = 0x87, /* Flush buffer fifos to the PC. */
+       MC_WAIT_H = 0x88, /* Wait on GPIOL1 to go high. */
+       MC_WAIT_L = 0x89, /* Wait on GPIOL1 to go low. */
+       MC_TCK_X5 = 0x8A, /* Disable /5 div, enables 60MHz master clock */
+       MC_TCK_D5 = 0x8B, /* Enable /5 div, backward compat to FT2232D */
+       MC_EN_3PH_CLK = 0x8C, /* Enable 3 phase clk, DDR I2C */
+       MC_DIS_3PH_CLK = 0x8D, /* Disable 3 phase clk */
+       MC_CLK_N = 0x8E, /* Clock every bit, used for JTAG */
+       MC_CLK_N8 = 0x8F, /* Clock every byte, used for JTAG */
+       MC_CLK_TO_H = 0x94, /* Clock until GPIOL1 goes high */
+       MC_CLK_TO_L = 0x95, /* Clock until GPIOL1 goes low */
+       MC_EN_ADPT_CLK = 0x96, /* Enable adaptive clocking */
+       MC_DIS_ADPT_CLK = 0x97, /* Disable adaptive clocking */
+       MC_CLK8_TO_H = 0x9C, /* Clock until GPIOL1 goes high, count bytes */
+       MC_CLK8_TO_L = 0x9D, /* Clock until GPIOL1 goes low, count bytes */
+       MC_TRI = 0x9E, /* Set IO to only drive on 0 and tristate on 1 */
+       /* CPU mode commands */
+       MC_CPU_RS = 0x90, /* CPUMode read short address */
+       MC_CPU_RE = 0x91, /* CPUMode read extended address */
+       MC_CPU_WS = 0x92, /* CPUMode write short address */
+       MC_CPU_WE = 0x93, /* CPUMode write extended address */
+};
+
+
+/* Transfer Command bits */
+
+/* All byte based commands consist of:
+ * - Command byte
+ * - Length lsb
+ * - Length msb
+ *
+ * If data out is enabled the data follows after the above command bytes,
+ * otherwise no additional data is needed.
+ * - Data * n
+ *
+ * All bit based commands consist of:
+ * - Command byte
+ * - Length
+ *
+ * If data out is enabled a byte containing bitst to transfer follows.
+ * Otherwise no additional data is needed. Only up to 8 bits can be transferred
+ * per transaction when in bit mode.
+ */
+
+/* b 0000 0000
+ *   |||| |||`- Data out negative enable. Update DO on negative clock edge.
+ *   |||| ||`-- Bit count enable. When reset count represents bytes.
+ *   |||| |`--- Data in negative enable. Latch DI on negative clock edge.
+ *   |||| `---- LSB enable. When set clock data out LSB first.
+ *   ||||
+ *   |||`------ Data out enable
+ *   ||`------- Data in enable
+ *   |`-------- TMS mode enable
+ *   `--------- Special command mode enable. See mpsse_cmd enum.
+ */
+
+#define MC_DATA_TMS  (0x40) /* When set use TMS mode */
+#define MC_DATA_IN   (0x20) /* When set read data (Data IN) */
+#define MC_DATA_OUT  (0x10) /* When set write data (Data OUT) */
+#define MC_DATA_LSB  (0x08) /* When set input/output data LSB first. */
+#define MC_DATA_ICN  (0x04) /* When set receive data on negative clock edge */
+#define MC_DATA_BITS (0x02) /* When set count bits not bytes */
+#define MC_DATA_OCN  (0x01) /* When set update data on negative clock edge */
+
+
 void mpsse_check_rx(void);
 void mpsse_error(int status);
 uint8_t mpsse_recv_byte(void);