📄 jp1.c
字号:
/* jp1-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 <stdio.h>#include <ctype.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <stdarg.h>#include <stdint.h>#include "jp.h"#include "mc.h"#define Boolean int#define false 0#define true 1/* Libraries for JTAG proxy server. */#include <sys/stat.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/select.h>#include <sys/poll.h>#include <fcntl.h>#include <netdb.h>#include <netinet/tcp.h>#include <inttypes.h>#include <errno.h>#include "gdb.h" /* partially copied from gdb/config/or1k *//* Selects crc trailer size in bits. Currently supported: 8 */#define CRC_SIZE (8)/* Scan chain size in bits. */#define SC_SIZE (4)#ifndef ULONGEST#define ULONGEST unsigned long#endifint err = 0;int set_pc = 0;int set_step = 0;int waiting = 0;unsigned int serverIP = 0;unsigned int serverPort = 0;unsigned int server_fd = 0;unsigned int gdb_fd = 0;void HandleServerSocket(Boolean block);void JTAGRequest(void);void GDBRequest(void);void ProtocolClean(int,int32_t);static int gdb_read(void*,int);static int gdb_write(void*,int);static void jtag_set_chain (int);/* Scan chain info. *//* *INDENT-OFF* */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};/* *INDENT-OFF* *//* Currently selected scan chain - just to prevent unnecessary transfers. */static int current_chain;/* Designates whether we are in SELECT_DR state, otherwise in RUN TEST/IDLE */static int select_dr = 0;/* 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 intcrc_calc (int crc, uint8_t input_bit){ int c; int new_crc; int d;#if (CRC_SIZE == 8) d = input_bit&1; c = crc; /* Move queue left. */ new_crc = crc << 1; /* Mask upper five bits. */ new_crc &= 0xF8; /* Set lower three bits */ new_crc |= (d ^ ((c >> 7)&1)); new_crc |= (d ^ ((c >> 0)&1) ^ ((c >> 7)&1)) << 1; new_crc |= (d ^ ((c >> 1)&1) ^ ((c >> 7)&1)) << 2; return new_crc;#else return 0;#endif}/* Writes TCLK=0, TRST=1, TMS=bit1, TDI=bit0 and TCLK=1, TRST=1, TMS=bit1, TDI=bit0 */static voidjp1_write_JTAG (packet) 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 uint8_tjp1_read_JTAG (){ uint8_t data; data = jp_in (); crc_r = crc_calc (crc_r, data); return data;}/* Writes bitstream. LS bit first. */static voidjp1_write_stream (stream, len, set_last_bit) ULONGEST stream; int len; int set_last_bit;{ int i; if (len <= 0) return; debug("\nwrite("); for (i = 0; i < len - 1; i++) jp1_write_JTAG ((stream >> i) & 1); if (set_last_bit) jp1_write_JTAG ((stream >> (len - 1))& 1 | TMS); else jp1_write_JTAG ((stream >> (len - 1))& 1); debug(")\n");}/* Gets bitstream. LS bit first. */static ULONGESTjp1_read_stream (stream, len, set_last_bit) unsigned long stream; int len; int set_last_bit;{ int i; ULONGEST data; debug("\nread("); if (len <= 0) return; data = 0; for (i = 0; i < len - 1; i++) { jp1_write_JTAG (stream & 1); /* LSB first */ stream >>= 1; data |= jp1_read_JTAG () << i; /* LSB first */ } if (set_last_bit) jp1_write_JTAG (stream & 1 | TMS); else jp1_write_JTAG (stream & 1); data |= jp1_read_JTAG () << (len - 1); debug(")\n"); return data;}/* Goes into SELECT_IR state. Should be called before every control write. */static voidjp1_prepare_control (){ if (!select_dr) jp1_write_JTAG (TMS); /* SELECT_DR SCAN */ jp1_write_JTAG (TMS); /* SELECT_IR SCAN */ select_dr = 0;}/* Resets JTAG. Writes TRST=0 and TRST=1 */static voidjp1_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++) jp1_write_JTAG (TMS); jp_out (TRST_BIT); JTAG_RETRY_WAIT(); jp1_write_JTAG (0); debug2(")\n"); select_dr = 0;}/* Sets register/memory regno to data. *//* CZ 08/06/01: I am not sure how error checking is intended to be implemented here. It appears that no indication is returned to the caller as you have in standard unix system calls. Therefore, I guess the only way to use these functions when you want to know the exact position of the error is to manually clear err, call the function, and then manually check err. I have also made some changes where necessary because no value was returned at all int jtag_read_reg.*/static voidjtag_write_reg_support (regno, data) int regno; ULONGEST data;{ int crc_read, crc_write, crc_ok, retry; int result; int tmp; debug("\n"); debug2("write_reg %i(%08x) <- %08x \n", regno, regno, data); if (!select_dr) jp1_write_JTAG (TMS); /* SELECT_DR SCAN */ select_dr = 1; /* If we don't have rw bit, we assume chain is read only. */ if (!chain_has_rw[current_chain]) error ("Internal: Chain not writable."); for (retry = 0; retry < NUM_RETRIES; retry++) { jp1_write_JTAG (0); /* CAPTURE_DR */ jp1_write_JTAG (0); /* SHIFT_DR */ crc_w = 0; /* write addr */ jp1_write_stream (regno, chain_addr_size[current_chain], 0); /* write (R/W=1) - we tested that previously. */ jp1_write_JTAG (TDI); if (chain_has_crc[current_chain]) { /* write data */ jp1_write_stream (data, chain_data_size[current_chain], 0); crc_write = crc_w; /* write CRC, EXIT1_DR */ crc_read = jp1_read_stream (crc_write, CRC_SIZE + 1, 1) >> 1; } else { /* write data */ jp1_write_stream (data, chain_data_size[current_chain], 1); } jp1_write_JTAG (TMS); /* UPDATE_DR */ jp1_write_JTAG (TMS); /* SELECT_DR */ /* Did JTAG receive packet correctly? */ if (chain_has_crc[current_chain]) crc_ok = crc_read == crc_write; if (chain_has_crc[current_chain]) { if (crc_ok) return; debug2(", crc failed. read %08x, generated %08x\n", crc_read, crc_write); jp1_reset_JTAG(); jp1_write_JTAG (TMS); /* SELECT_DR SCAN */ select_dr = 1; tmp = current_chain; current_chain = -1; jtag_set_chain(tmp); } else return; } printf ("Invalid CRC\n"); err = ERR_CRC;}/* Reads register/memory from regno. Reading is a bit strange. Data is not available at the time we pass an address, but in successive read instead. Call jtag_read_reg twice to get correct data. */static ULONGESTjtag_read_reg (regno) unsigned int regno;{ ULONGEST data; int crc_read, crc_write, crc_actual_read, retry, crc_ok; int result; int tmp; debug("\n"); debug2("read_reg %i(%08x)", regno, regno); debug (" \n "); if (!select_dr) jp1_write_JTAG (TMS); /* SELECT_DR SCAN */ select_dr = 1; for (retry = 0; retry < NUM_RETRIES; retry++) { jp1_write_JTAG (0); /* CAPTURE_DR */ jp1_write_JTAG (0); /* SHIFT_DR */ crc_w = 0; /* write addr */ jp1_write_stream (regno, chain_addr_size[current_chain], 0); /* read (R/W=0) */ if (chain_has_rw[current_chain]) jp1_write_JTAG (0); if (chain_has_crc[current_chain]) { crc_r = 0; /* data = 0 */ data = jp1_read_stream (0, chain_data_size[current_chain], 0); crc_write = crc_w; crc_actual_read = crc_r; /* Send my crc, EXIT1_DR */ crc_read = jp1_read_stream (crc_write, CRC_SIZE + 1, 1) >> 1; } else { /* data = 0 */ data = jp1_read_stream (0, chain_data_size[current_chain], 1); } jp1_write_JTAG (TMS); /* UPDATE_DR */ jp1_write_JTAG (TMS); /* SELECT_DR */ /* Did JTAG receive packet correctly? */ if (chain_has_crc[current_chain]) crc_ok = jp1_read_JTAG (); if (chain_has_crc[current_chain]) { if ((crc_read == crc_actual_read) && (crc_ok)) { debug2(" , read_reg %i(%08x) = %08x\n", regno, regno, data); prev_regno = regno; return data; } debug2(", crc failed. read %08x, generated %08x\n", crc_read, crc_actual_read); jp1_reset_JTAG(); jp1_write_JTAG (TMS); /* SELECT_DR SCAN */ select_dr = 1; tmp = current_chain; current_chain = -1; jtag_set_chain(tmp); jtag_read_reg (prev_regno); if (err) return -1; } else { debug2(" , read_reg %i(%08x) = %08x\n", regno, regno, data); prev_regno = regno; return data; } } printf ("Invalid CRC\n"); err = ERR_CRC; return -1;}/* Sets scan chain. */static voidjtag_set_chain (chain) int chain;{ int crc_read, crc_write, crc_ok, retry; int result; debug("\n"); debug2("set_chain %i\n", chain); if (current_chain != chain) { if (!chain_is_valid[chain]) error ("Chain not valid."); current_chain = chain; jp1_prepare_control (); while (1) { jp1_write_JTAG (0); /* CAPTURE_IR */ jp1_write_JTAG (0); /* SHIFT_IR */ /* write data, EXIT1_IR */ jp1_write_stream (JI_CHAIN_SELECT, JI_SIZE, 1); jp1_write_JTAG (TMS); /* UPDATE_IR */ jp1_write_JTAG (TMS); /* SELECT_DR */ jp1_write_JTAG (0); /* CAPTURE_DR */ jp1_write_JTAG (0); /* SHIFT_DR */ if (chain_has_crc[current_chain]) { crc_w = 0; /* write data */ jp1_write_stream (chain, SC_SIZE, 0); crc_write = crc_w; /* write CRC, EXIT1_DR */ crc_read = jp1_read_stream (crc_write, CRC_SIZE + 1, 1) >> 1; } else { /* write data, EXIT1_DR */ jp1_write_stream (chain, SC_SIZE, 1); } jp1_write_JTAG (TMS); /* UPDATE_DR */ jp1_write_JTAG (TMS); /* SELECT_DR */ /* Did JTAG receive packet correctly? */ if (chain_has_crc[current_chain]) crc_ok = crc_read == crc_write; if (chain_has_crc[current_chain]) { if (!crc_ok) { debug2(", crc failed.\n"); jp1_reset_JTAG(); jp1_prepare_control (); continue; } } jp1_write_JTAG (TMS); /* SELECT_IR */ jp1_write_JTAG (0); /* CAPTURE_IR */ jp1_write_JTAG (0); /* SHIFT_IR */ crc_w = 0; /* write data, EXIT1_IR */ jp1_write_stream (JI_DEBUG, JI_SIZE, 1); jp1_write_JTAG (TMS); /* UPDATE_IR */ jp1_write_JTAG (TMS); /* SELECT_DR */ select_dr = 1; return; } printf ("Invalid CRC\n"); err = ERR_CRC; } else debug2 ("Already set.\n");}/* Sets register/memory regno to data. */static voidjtag_write_reg (regno, data) int regno; ULONGEST data;{ /* Set PC */// if (current_chain == SC_RISC_DEBUG && regno == 0x10)// data = data - 4; jtag_write_reg_support (regno, data);}/* Stalls the CPU. */static voidor1k_stall (){ int val; jtag_set_chain (SC_REGISTER); val = jtag_read_reg (JTAG_RISCOP); jtag_write_reg (JTAG_RISCOP, val | 1);}/* Unstalls the CPU. */static voidor1k_unstall (){ unsigned int val; jtag_set_chain (SC_REGISTER); val = jtag_read_reg (JTAG_RISCOP); jtag_write_reg (JTAG_RISCOP, val & ~1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -