📄 ft2232.c
字号:
/* * $Id: ft2232.c 1295 2008-07-02 18:59:24Z jiez $ * * Generic cable driver for FTDI's FT2232C chip in MPSSE mode. * Copyright (C) 2007 A. Laeuger * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA. * * Written by Arnim Laeuger, 2007-2008. * Support for JTAGkey submitted by Laurent Gauch, 2008. * */#include <stdlib.h>#include <string.h>#include "sysdep.h"#include <cable.h>#include <chain.h>#include <cmd.h>#include "generic.h"#include "generic_usbconn.h"#include "usbconn.h"#include "usbconn/libftdx.h"#include "cmd_xfer.h"/* Maximum TCK frequency of FT2232 */#define FT2232_MAX_TCK_FREQ 6000000/* The default driver if not specified otherwise during connect */#ifdef ENABLE_LOWLEVEL_FTD2XX#define DEFAULT_DRIVER "ftd2xx-mpsse"#else#define DEFAULT_DRIVER "ftdi-mpsse"#endif/* repeat the definitions for MPSSE command processor here since we cannot rely on the existence of ftdih. even though they're defined there *//* Shifting commands IN MPSSE Mode*/#define MPSSE_WRITE_NEG 0x01 /* Write TDI/DO on negative TCK/SK edge*/#define MPSSE_BITMODE 0x02 /* Write bits, not bytes */#define MPSSE_READ_NEG 0x04 /* Sample TDO/DI on negative TCK/SK edge */#define MPSSE_LSB 0x08 /* LSB first */#define MPSSE_DO_WRITE 0x10 /* Write TDI/DO */#define MPSSE_DO_READ 0x20 /* Read TDO/DI */#define MPSSE_WRITE_TMS 0x40 /* Write TMS/CS *//* FTDI MPSSE commands */#define SET_BITS_LOW 0x80/*BYTE DATA*//*BYTE Direction*/#define SET_BITS_HIGH 0x82/*BYTE DATA*//*BYTE Direction*/#define GET_BITS_LOW 0x81#define GET_BITS_HIGH 0x83#define LOOPBACK_START 0x84#define LOOPBACK_END 0x85#define TCK_DIVISOR 0x86#define SEND_IMMEDIATE 0x87/* bit and bitmask definitions for GPIO commands */#define BIT_TCK 0#define BIT_TDI 1#define BIT_TDO 2#define BIT_TMS 3#define BITMASK_TDO (1 << BIT_TDO)#define BITMASK_TDI (1 << BIT_TDI)#define BITMASK_TCK (1 << BIT_TCK)#define BITMASK_TMS (1 << BIT_TMS)/* bit and bitmask definitions for Amontec JTAGkey */#define BIT_JTAGKEY_nOE 4#define BIT_JTAGKEY_TRST_N_OUT 0#define BIT_JTAGKEY_SRST_N_OUT 1#define BIT_JTAGKEY_TRST_N_OE_N 2#define BIT_JTAGKEY_SRST_N_OE_N 3#define BITMASK_JTAGKEY_nOE (1 << BIT_JTAGKEY_nOE)#define BITMASK_JTAGKEY_TRST_N_OUT (1 << BIT_JTAGKEY_TRST_N_OUT)#define BITMASK_JTAGKEY_SRST_N_OUT (1 << BIT_JTAGKEY_SRST_N_OUT)#define BITMASK_JTAGKEY_TRST_N_OE_N (1 << BIT_JTAGKEY_TRST_N_OE_N)#define BITMASK_JTAGKEY_SRST_N_OE_N (1 << BIT_JTAGKEY_SRST_N_OE_N)/* bit and bitmask definitions for Olimex ARM-USB-OCD */#define BIT_ARMUSBOCD_nOE 4#define BIT_ARMUSBOCD_nTRST 0#define BIT_ARMUSBOCD_nTSRST 1#define BIT_ARMUSBOCD_nTRST_nOE 2#define BIT_ARMUSBOCD_RED_LED 3#define BITMASK_ARMUSBOCD_nOE (1 << BIT_ARMUSBOCD_nOE)#define BITMASK_ARMUSBOCD_nTRST (1 << BIT_ARMUSBOCD_nTRST)#define BITMASK_ARMUSBOCD_nTSRST (1 << BIT_ARMUSBOCD_nTRST)#define BITMASK_ARMUSBOCD_nTRST_nOE (1 << BIT_ARMUSBOCD_nTRST_nOE)#define BITMASK_ARMUSBOCD_RED_LED (1 << BIT_ARMUSBOCD_RED_LED)/* bit and bitmask definitions for Blackfin gnICE */#define BIT_GNICE_nTRST 1#define BIT_GNICE_nLED 3 #define BITMASK_GNICE_nTRST (1 << BIT_GNICE_nTRST)#define BITMASK_GNICE_nLED (1 << BIT_GNICE_nLED)/* bit and bitmask definitions for OOCDLink-s */#define BIT_OOCDLINKS_nTRST_nOE 0#define BIT_OOCDLINKS_nTRST 1#define BIT_OOCDLINKS_nSRST_nOE 2#define BIT_OOCDLINKS_nSRST 3#define BITMASK_OOCDLINKS_nTRST_nOE (1 << BIT_OOCDLINKS_nTRST_nOE)#define BITMASK_OOCDLINKS_nTRST (1 << BIT_OOCDLINKS_nTRST)#define BITMASK_OOCDLINKS_nSRST_nOE (1 << BIT_OOCDLINKS_nSRST_nOE)#define BITMASK_OOCDLINKS_nSRST (1 << BIT_OOCDLINKS_nSRST)/* bit and bitmask definitions for Turtelizer 2 */#define BIT_TURTELIZER2_nJTAGOE 4#define BIT_TURTELIZER2_RST 6#define BIT_TURTELIZER2_nTX1LED 2#define BIT_TURTELIZER2_nRX1LED 3#define BITMASK_TURTELIZER2_nJTAGOE (1 << BIT_TURTELIZER2_nJTAGOE)#define BITMASK_TURTELIZER2_RST (1 << BIT_TURTELIZER2_RST)#define BITMASK_TURTELIZER2_nTX1LED (1 << BIT_TURTELIZER2_nTX1LED)#define BITMASK_TURTELIZER2_nRX1LED (1 << BIT_TURTELIZER2_nRX1LED)/* bit and bitmask definitions for USB to JTAG Interface */#define BIT_USBTOJTAGIF_nTRST 4#define BIT_USBTOJTAGIF_RST 6#define BIT_USBTOJTAGIF_DBGRQ 7#define BIT_USBTOJTAGIF_nRxLED 2#define BIT_USBTOJTAGIF_nTxLED 3#define BITMASK_USBTOJTAGIF_nTRST (1 << BIT_USBTOJTAGIF_nTRST)#define BITMASK_USBTOJTAGIF_RST (1 << BIT_USBTOJTAGIF_RST)#define BITMASK_USBTOJTAGIF_DBGRQ (1 << BIT_USBTOJTAGIF_DBGRQ)#define BITMASK_USBTOJTAGIF_nRxLED (1 << BIT_USBTOJTAGIF_nRxLED)#define BITMASK_USBTOJTAGIF_nTxLED (1 << BIT_USBTOJTAGIF_nTxLED)/* bit and bitmask definitions for Xverve DT-USB-ST Signalyzer Tool */#define BIT_SIGNALYZER_nTRST 4#define BIT_SIGNALYZER_nSRST 5#define BITMASK_SIGNALYZER_nTRST (1 << BIT_SIGNALYZER_nTRST)#define BITMASK_SIGNALYZER_nSRST (1 << BIT_SIGNALYZER_nSRST)typedef struct { uint32_t mpsse_frequency; /* this driver issues several "Set Data Bits Low Byte" commands here is the place where cable specific values can be stored that are used each time this command is issued */ uint8_t low_byte_value; uint8_t low_byte_dir; /* this driver supports TRST control on high byte only set the variables below with value/direction for active and inactive TRST line static settings for other high byte signals must be entered here as well */ uint8_t high_byte_value_trst_active; uint8_t high_byte_value_trst_inactive; uint8_t high_byte_dir; /* variables to save last TDO value this acts as a cache to prevent multiple "Read Data Bits Low" transfer over USB for ft2232_get_tdo */ unsigned int last_tdo_valid; unsigned int last_tdo; cx_cmd_root_t cmd_root;} params_t;static const uint8_t imm_buf[1] = {SEND_IMMEDIATE};static const cx_cmd_t imm_cmd = {NULL, 1, 1, (uint8_t *)imm_buf, 0};static voidft2232_set_frequency( cable_t *cable, uint32_t new_frequency ){ params_t *params = (params_t *)cable->params; cx_cmd_root_t *cmd_root = &(params->cmd_root); if (!new_frequency || new_frequency > FT2232_MAX_TCK_FREQ) new_frequency = FT2232_MAX_TCK_FREQ; cable->frequency = new_frequency; /* update ft2232 frequency if cable setting changed */ if (new_frequency != params->mpsse_frequency) { uint32_t div; div = FT2232_MAX_TCK_FREQ / new_frequency; if (FT2232_MAX_TCK_FREQ % new_frequency) div++; if (div >= (1 << 16)) { div = (1 << 16) - 1; printf( _("Warning: Setting lowest supported frequency for FT2232: %d\n"), FT2232_MAX_TCK_FREQ/div ); } /* send new divisor to device */ div -= 1; cx_cmd_queue( cmd_root, 0 ); cx_cmd_push( cmd_root, TCK_DIVISOR ); cx_cmd_push( cmd_root, div & 0xff ); cx_cmd_push( cmd_root, (div >> 8) & 0xff ); cx_xfer( cmd_root, &imm_cmd, cable, COMPLETELY ); params->mpsse_frequency = FT2232_MAX_TCK_FREQ / (div + 1); }}static intft2232_generic_init( cable_t *cable ){ params_t *params = (params_t *)cable->params; cx_cmd_root_t *cmd_root = &(params->cmd_root); if (usbconn_open( cable->link.usb )) return -1; /* safe default values */ params->low_byte_value = 0; params->low_byte_dir = 0; /* Set Data Bits Low Byte TCK = 0, TMS = 1, TDI = 0 */ cx_cmd_queue( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_LOW ); cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); /* Set Data Bits High Byte */ params->high_byte_value_trst_active = 0; params->high_byte_value_trst_inactive = 0; params->high_byte_dir = 0; cx_cmd_push( cmd_root, SET_BITS_HIGH ); cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); params->last_tdo_valid = 0; return 0;}static intft2232_jtagkey_init( cable_t *cable ){ params_t *params = (params_t *)cable->params; cx_cmd_root_t *cmd_root = &(params->cmd_root); if (usbconn_open( cable->link.usb )) return -1; /* static low byte value and direction: set nOE to '0' -> activate output enables */ params->low_byte_value = 0; params->low_byte_dir = BITMASK_JTAGKEY_nOE; /* Set Data Bits Low Byte TCK = 0, TMS = 1, TDI = 0, nOE = 0 */ cx_cmd_queue( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_LOW ); cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); /* Set Data Bits High Byte default: TRST_N_OUT = 1 TRST_N_OE_N = 0 SRST_N_OUT = 1 SRST_N_OE_N = 0 */ params->high_byte_value_trst_active = BITMASK_JTAGKEY_SRST_N_OUT; params->high_byte_value_trst_inactive = BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OUT; params->high_byte_dir = BITMASK_JTAGKEY_TRST_N_OUT | BITMASK_JTAGKEY_TRST_N_OE_N | BITMASK_JTAGKEY_SRST_N_OUT | BITMASK_JTAGKEY_SRST_N_OE_N; cx_cmd_push( cmd_root, SET_BITS_HIGH ); cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); cx_cmd_push( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_HIGH ); cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); params->last_tdo_valid = 0; return 0;}static intft2232_armusbocd_init( cable_t *cable ){ params_t *params = (params_t *)cable->params; cx_cmd_root_t *cmd_root = &(params->cmd_root); if (usbconn_open( cable->link.usb )) return -1; /* static low byte value and direction: set nOE to '0' -> activate output enables */ params->low_byte_value = 0; params->low_byte_dir = BITMASK_ARMUSBOCD_nOE; /* Set Data Bits Low Byte TCK = 0, TMS = 1, TDI = 0, nOE = 0 */ cx_cmd_queue( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_LOW ); cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); /* Set Data Bits High Byte default: TRST = 1 TRST buffer enable = 0 TSRST = 1 RED LED on */ params->high_byte_value_trst_active = BITMASK_ARMUSBOCD_nTSRST | BITMASK_ARMUSBOCD_RED_LED; params->high_byte_value_trst_inactive = BITMASK_ARMUSBOCD_nTRST | BITMASK_ARMUSBOCD_nTSRST | BITMASK_ARMUSBOCD_RED_LED; params->high_byte_dir = BITMASK_ARMUSBOCD_nTRST | BITMASK_ARMUSBOCD_nTRST_nOE | BITMASK_ARMUSBOCD_nTSRST | BITMASK_ARMUSBOCD_RED_LED; cx_cmd_push( cmd_root, SET_BITS_HIGH ); cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); cx_cmd_push( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_HIGH ); cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); params->last_tdo_valid = 0; return 0;}static intft2232_gnice_init( cable_t *cable ){ params_t *params = (params_t *)cable->params; cx_cmd_root_t *cmd_root = &(params->cmd_root); if (usbconn_open( cable->link.usb )) return -1; /* safe default values */ params->low_byte_value = 0; params->low_byte_dir = 0; /* Set Data Bits Low Byte TCK = 0, TMS = 1, TDI = 0 */ cx_cmd_queue( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_LOW ); cx_cmd_push( cmd_root, params->low_byte_value | BITMASK_TMS ); cx_cmd_push( cmd_root, params->low_byte_dir | BITMASK_TCK | BITMASK_TDI | BITMASK_TMS ); /* Set Data Bits High Byte */ params->high_byte_value_trst_active = BITMASK_GNICE_nLED; params->high_byte_value_trst_inactive = BITMASK_GNICE_nTRST; params->high_byte_dir = BITMASK_GNICE_nTRST | BITMASK_GNICE_nLED; cx_cmd_push( cmd_root, SET_BITS_HIGH ); cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); cx_cmd_push( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_HIGH ); cx_cmd_push( cmd_root, params->high_byte_value_trst_inactive ); cx_cmd_push( cmd_root, params->high_byte_dir ); ft2232_set_frequency( cable, FT2232_MAX_TCK_FREQ ); params->last_tdo_valid = 0; return 0;}static intft2232_oocdlinks_init( cable_t *cable ){ params_t *params = (params_t *)cable->params; cx_cmd_root_t *cmd_root = &(params->cmd_root); if (usbconn_open( cable->link.usb )) return -1; /* static low byte value and direction */ params->low_byte_value = 0; params->low_byte_dir = 0; /* Set Data Bits Low Byte TCK = 0, TMS = 1, TDI = 0 */ cx_cmd_queue( cmd_root, 0 ); cx_cmd_push( cmd_root, SET_BITS_LOW );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -