📄 jp2.c
字号:
/* jp2-linux.c -- JTAG protocol via parallel port for linux Copyright(C) 2001 Marko Mlinar, markom@opencores.org Code for TCP/IP copied from gdb, by Chris ZiomkowskiThis file is part of OpenRISC 1000 Architectural Simulator.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *//* Establishes jtag proxy server and communicates with parallel port directly. Requires root access. */#include <assert.h>#include <stdio.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <stdarg.h>#include <sys/stat.h>#include <sys/types.h>#include "mc.h"#include "gdb.h"#include "jp2.h"#include "jp.h"#define TC_RESET 0#define TC_BRIGHT 1#define TC_DIM 2#define TC_UNDERLINE 3#define TC_BLINK 4#define TC_REVERSE 7#define TC_HIDDEN 8#define TC_BLACK 0#define TC_RED 1#define TC_GREEN 2#define TC_YELLOW 3#define TC_BLUE 4#define TC_MAGENTA 5#define TC_CYAN 6#define TC_WHITE 7#define SDRAM_BASE 0x00000000#define SDRAM_SIZE 0x04000000#define SRAM_BASE 0x40000000#define SRAM_SIZE 0x04000000 // This is not okint err = 0;int set_pc = 0;int set_step = 0;int waiting = 0;/* Scan chain info. */static int chain_addr_size[] = { 0, 32, 0, 0, 5, 32, 32};static int chain_data_size[] = { 0, 32, 0, 32, 32, 32, 32};static int chain_is_valid[] = { 0, 1, 0, 1, 1, 1, 1};static int chain_has_crc[] = { 0, 1, 0, 1, 1, 1, 1};static int chain_has_rw[] = { 0, 1, 0, 0, 1, 1, 1};/* Currently selected scan chain - just to prevent unnecessary transfers. */static int current_chain = -1;/* The chain that should be currently selected. */static int dbg_chain = -1;/* Crc of current read or written data. */static int crc_r, crc_w = 0;/* Address of previous read */static unsigned long prev_regno = 0;/* Generates new crc, sending in new bit input_bit */static unsigned long crc_calc(unsigned long crc, int input_bit) { unsigned long d = (input_bit&1) ? 0xfffffff : 0x0000000; unsigned long crc_32 = ((crc >> 31)&1) ? 0xfffffff : 0x0000000; crc <<= 1; return crc ^ (d ^ crc_32) & DBG_CRC_POLY;}/* Writes TCLK=0, TRST=1, TMS=bit1, TDI=bit0 and TCLK=1, TRST=1, TMS=bit1, TDI=bit0 */static void jp2_write_JTAG(uint8_t packet) { uint8_t data = TRST_BIT; if(packet & 1) data |= TDI_BIT; if(packet & 2) data |= TMS_BIT; jp_out(data); jp_wait(); crc_w = crc_calc(crc_w, packet&1); /* rise clock */ jp_out(data | TCLK_BIT); jp_wait();}/* Reads TDI. */static int jp2_read_JTAG() { uint8_t data; data = jp_in(); crc_r = crc_calc(crc_r, data); return data;}/* Writes bitstream. LS bit first if len < 0, MS bit first if len > 0. */static void jp2_write_stream(ULONGEST stream, int len, int set_last_bit) { int i; if (len < 0) { len = -len; debug("writeL%d(", len); for(i = 0; i < len - 1; i++) jp2_write_JTAG((stream >> i) & 1); if(set_last_bit) jp2_write_JTAG((stream >>(len - 1))& 1 | TMS); else jp2_write_JTAG((stream >>(len - 1))& 1); } else { debug("write%d(", len); for(i = 0; i < len - 1; i++) jp2_write_JTAG((stream >> (len - 1 - i)) & 1); if(set_last_bit) jp2_write_JTAG((stream >> 0) & 1 | TMS); else jp2_write_JTAG((stream >> 0)& 1); } debug(")\n");}/* Gets bitstream. LS bit first if len < 0, MS bit first if len > 0. */static ULONGEST jp2_read_stream(unsigned long stream, int len, int set_last_bit) { int i; ULONGEST data = 0; if (len < 0) { debug("readL("); for(i = 0; i < len - 1; i++) { jp2_write_JTAG((stream >> i) & 1); /* LSB first */ data |= jp2_read_JTAG() << i; /* LSB first */ } if (set_last_bit) jp2_write_JTAG((stream >> (len - 1)) & 1 | TMS); else jp2_write_JTAG((stream >> (len - 1)) & 1); data |= jp2_read_JTAG() << (len - 1); } else { debug("read("); for(i = 0; i < len - 1; i++) { jp2_write_JTAG((stream >> (len - 1 - i)) & 1); /* MSB first */ data |= jp2_read_JTAG() << (len - 1 - i); /* MSB first */ } if (set_last_bit) jp2_write_JTAG((stream >> 0) & 1 | TMS); else jp2_write_JTAG((stream >> 0) & 1); data |= jp2_read_JTAG() << 0; } debug(")\n"); return data;}/* Sets scan chain. */void jtag_set_ir(int ir) { jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ jp2_write_JTAG(TMS); /* SELECT_IR SCAN */ jp2_write_JTAG(0); /* CAPTURE_IR */ jp2_write_JTAG(0); /* SHIFT_IR */ /* write data, EXIT1_IR */ jp2_write_stream(ir, -JI_SIZE, 1); jp2_write_JTAG(TMS); /* UPDATE_IR */ jp2_write_JTAG(0); /* IDLE */ current_chain = -1;}/* Resets JTAG Writes TRST=0 and TRST=1 */static void jp2_reset_JTAG() { int i; debug2("\nreset("); jp_out(0); JTAG_RETRY_WAIT(); /* In case we don't have TRST reset it manually */ for(i = 0; i < 8; i++) jp2_write_JTAG(TMS); jp_out(TRST_BIT); JTAG_RETRY_WAIT(); jp2_write_JTAG(0); debug2(")\n");}/* Resets JTAG, and sets DEBUG scan chain */static int dbg_reset() { int err; unsigned long id; jp2_reset_JTAG(); /* read ID */ jtag_set_ir(JI_IDCODE); jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ jp2_write_JTAG(0); /* CAPTURE_DR */ jp2_write_JTAG(0); /* SHIFT_DR */ /* read ID, EXIT1_DR */ crc_w = 0xffffffff; id = jp2_read_stream(0, 32, 1); jp2_write_JTAG(TMS); /* UPDATE_DR */ jp2_write_JTAG(0); /* IDLE */ printf("JTAG ID = %08x\n", id); /* select debug scan chain and stay in it forever */ jtag_set_ir(JI_DEBUG); current_chain = -1; return DBG_ERR_OK;}/* counts retries and returns zero if we should abort *//* TODO: dinamically adjust timings for jp2 */static int retry_no = 0;int retry_do() { int i, err; printf("RETRY\n"); //exit(2); if (retry_no >= NUM_SOFT_RETRIES) { if ((err = dbg_reset())) return err; } else { /* quick reset */ for(i = 0; i < 8; i++) jp2_write_JTAG(TMS); jp2_write_JTAG(0); /* go into IDLE state */ } if (retry_no >= NUM_SOFT_RETRIES + NUM_HARD_RETRIES) { retry_no = 0; return 0; } retry_no++; return 1;}/* resets retry counter */void retry_ok() { retry_no = 0;}/* Sets scan chain. */int dbg_set_chain(int chain) { int status, crc_generated, crc_read; dbg_chain = chain;try_again: if (current_chain == chain) return DBG_ERR_OK; current_chain = -1; debug("\n"); debug2("set_chain %i\n", chain); jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ jp2_write_JTAG(0); /* CAPTURE_DR */ jp2_write_JTAG(0); /* SHIFT_DR */ /* write data, EXIT1_DR */ crc_w = 0xffffffff; jp2_write_stream((chain & 0xf | (1<<DC_SIZE)), DC_SIZE + 1, 0); jp2_write_stream(crc_w, DBG_CRC_SIZE, 0); crc_r = 0xffffffff; status = jp2_read_stream(0, DC_STATUS_SIZE, 0); crc_generated = crc_r; crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1); //printf("%x %x %x\n", status, crc_read, crc_generated); /* CRCs must match, otherwise retry */ if (crc_read != crc_generated) { if (retry_do()) goto try_again; else return DBG_ERR_CRC; } /* we should read expected status value, otherwise retry */ if (status != 0) { if (retry_do()) goto try_again; else return status; } /* reset retry counter */ retry_ok(); jp2_write_JTAG(TMS); /* UPDATE_DR */ jp2_write_JTAG(0); /* IDLE */ current_chain = chain; return DBG_ERR_OK;}/* sends out a command with 32bit address and 16bit length, if len >= 0 */int dbg_command(int type, unsigned long adr, int len) { int status, crc_generated, crc_read;try_again: dbg_set_chain(dbg_chain); debug("\n"); debug2("comm %i\n", type); /***** WRITEx *****/ jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ jp2_write_JTAG(0); /* CAPTURE_DR */ jp2_write_JTAG(0); /* SHIFT_DR */ /* write data, EXIT1_DR */ crc_w = 0xffffffff; jp2_write_stream((DI_WRITE_CMD & 0xf | (0<<DC_SIZE)), DC_SIZE + 1, 0); jp2_write_stream(type, 4, 0); jp2_write_stream(adr, 32, 0); assert(len > 0); jp2_write_stream(len - 1, 16, 0); jp2_write_stream(crc_w, DBG_CRC_SIZE, 0); crc_r = 0xffffffff; status = jp2_read_stream(0, DC_STATUS_SIZE, 0); crc_generated = crc_r; crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1); /* CRCs must match, otherwise retry */ if (crc_read != crc_generated) { if (retry_do()) goto try_again; else return DBG_ERR_CRC; } /* we should read expected status value, otherwise retry */ if (status != 0) { if (retry_do()) goto try_again; else return status; } jp2_write_JTAG(TMS); /* UPDATE_DR */ jp2_write_JTAG(0); /* IDLE */ /* reset retry counter */ retry_ok(); return DBG_ERR_OK;}/* writes a ctrl reg */int dbg_ctrl(int reset, int stall) { int status, crc_generated, crc_read;try_again: dbg_set_chain(dbg_chain); debug("\n"); debug2("ctrl\n"); /***** WRITEx *****/ jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ jp2_write_JTAG(0); /* CAPTURE_DR */ jp2_write_JTAG(0); /* SHIFT_DR */ /* write data, EXIT1_DR */ crc_w = 0xffffffff; jp2_write_stream((DI_WRITE_CTRL & 0xf | (0<<DC_SIZE)), DC_SIZE + 1, 0); jp2_write_stream(reset, 1, 0); jp2_write_stream(stall, 1, 0); jp2_write_stream(0, 50, 0); jp2_write_stream(crc_w, DBG_CRC_SIZE, 0); crc_r = 0xffffffff; status = jp2_read_stream(0, DC_STATUS_SIZE, 0); crc_generated = crc_r; crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1); /* CRCs must match, otherwise retry */ //printf("%x %x %x\n", status, crc_read, crc_generated); if (crc_read != crc_generated) { if (retry_do()) goto try_again; else return DBG_ERR_CRC; } /* we should read expected status value, otherwise retry */ if (status != 0) { if (retry_do()) goto try_again; else return status; } jp2_write_JTAG(TMS); /* UPDATE_DR */ jp2_write_JTAG(0); /* IDLE */ /* reset retry counter */ retry_ok(); return DBG_ERR_OK;}/* reads control register */int dbg_ctrl_read(int *reset, int *stall) { int status, crc_generated, crc_read;try_again: dbg_set_chain(dbg_chain); debug("\n"); debug2("ctrl_read\n"); jp2_write_JTAG(TMS); /* SELECT_DR SCAN */ jp2_write_JTAG(0); /* CAPTURE_DR */ jp2_write_JTAG(0); /* SHIFT_DR */ /* write data, EXIT1_DR */ crc_w = 0xffffffff; jp2_write_stream(DI_READ_CTRL | (0<<DC_SIZE), DC_SIZE + 1, 0); jp2_write_stream(crc_w, DBG_CRC_SIZE, 0); crc_r = 0xffffffff; *reset = jp2_read_stream(0, 1, 0); *stall = jp2_read_stream(0, 1, 0); jp2_read_stream(0, 50, 0); status = jp2_read_stream(0, DC_STATUS_SIZE, 0); crc_generated = crc_r; crc_read = jp2_read_stream(0, DBG_CRC_SIZE, 1); /* CRCs must match, otherwise retry */ //printf("%x %x %x\n", status, crc_read, crc_generated);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -