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
#endif
#include "mpsse.h"
+#include "jtag.h"
static bool verbose = false;
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);
--- /dev/null
+/*
+ * 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
--- /dev/null
+/**
+ * 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();
+ }
+}
+
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
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;
#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);