📄 pp_jtag.cpp
字号:
/* * This file is part of Jelie, * (c) 2002 Julien Pilet <julien.pilet@epfl.ch> and * Stephane Magnenat <stephane.magnenat@epfl.ch> * * Jelie 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. * * Jelie 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 Foobar; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//*! \file * \brief Parallel port JTAG controller. * * This file contains support for the Macraigor Systems OCDemon, connected on a * parallel port. Unfortunatly it's for x86/linux only. * * \author Julien Pilet <julien.pilet@epfl.ch> * \author Stephane Magnenat <stephane.magnenat@epfl.ch> */#include <unistd.h> /* for libc5 */#include <sys/io.h> /* for glibc */#include <stdio.h>#include "pp_jtag.h"#include <assert.h>//#define ALTERAPROG#define OCDEMON_WIGGLER#ifdef OCDEMON_WIGGLER/* output */#define JTAG_TMS (0x2)#define JTAG_CLK (0x4)#define JTAG_TDI (0x8)#define JTAG_PWR (0x80)#define JTAG_TRST (0x10)/* input */#define JTAG_TDO (1<<7)#define JTAG_CPURESET (1)#endif#ifdef ALTERAPROG/* output */#define JTAG_TMS (1 << 1)#define JTAG_CLK (1 << 0)#define JTAG_TDI (1 << 6)#define JTAG_PWR (0)#define JTAG_TRST (0)/* input */#define JTAG_TDO (1<<7)#define JTAG_CPURESET (0)#endif PPJTAG::PPJTAG() : port(0x378), permBits(0x80), jtagRestarted(0) { }bool PPJTAG::init(int argc, char **argv) { static bool first=true; assert(first); first=false; int r = ioperm(port, 3, 1)==0;#ifdef ALTERAPROG // activate autofeed to enable output. if (r>=0) { outb(2, port + 2); } else { perror("ioperm"); }#endif //trst(true); return r;}unsigned char PPJTAG::readJTAG() { return ~inb(port+1); }void PPJTAG::writeJTAG(unsigned char data) { portVal = data; outb(data | permBits, port); }void PPJTAG::jtagReg(unsigned char *_data, unsigned char length){ unsigned char *input_pointer; unsigned char *output_pointer; unsigned char count; unsigned char input=0, value; unsigned char output = 0; input_pointer = _data; output_pointer = _data; /* select -> capture */ writeJTAG(JTAG_PWR); writeJTAG(JTAG_PWR | JTAG_CLK); /* capture -> shift */ writeJTAG(JTAG_PWR); writeJTAG(JTAG_PWR | JTAG_CLK); /* read/writing */ for (count = 0; count < length; count ++) { if ((count & 0x7) == 0) { /* fetch next word of data */ input = *input_pointer; input_pointer ++; } value = JTAG_PWR; if (input & 0x01) value = value | JTAG_TDI; if (count == (length -1)) { /* shift -> exit, as it's the last bit */ value = value | JTAG_TMS; } writeJTAG(value); writeJTAG(value | JTAG_CLK); if ((readJTAG() & JTAG_TDO) != 0) output = output | (1 << (count & 0x7)); input = input >> 1; if ((count & 0x7) == 0x7) { /* store recieved word of data */ *output_pointer = output; output_pointer ++; output = 0; } } /* ensure that the output is captured if less than whole long word */ if (length & 0x7) *output_pointer = output; /* exit -> update */ writeJTAG(JTAG_PWR | JTAG_TMS); writeJTAG(JTAG_PWR | JTAG_TMS | JTAG_CLK);#ifdef _FORCE_IDLE_RUN_ if (jtagRestarted) {#endif /* update -> Idle/Run */ writeJTAG(JTAG_PWR); writeJTAG(JTAG_PWR | JTAG_CLK); writeJTAG(JTAG_PWR);#ifdef _FORCE_IDLE_RUN_ } else { /* update -> select DR */ writeJTAG(JTAG_PWR | JTAG_TMS); writeJTAG(JTAG_PWR | JTAG_TMS | JTAG_CLK); writeJTAG(JTAG_PWR | JTAG_TMS); }#endif}void PPJTAG::ireg(unsigned char *_data){#ifdef _FORCE_IDLE_RUN_ if (jtagRestarted == 1) { /* this is only output if you have come from IDLE/RUN */ jtagRestarted = 0;#endif /* idle -> select DR */ writeJTAG(JTAG_PWR | JTAG_TMS); writeJTAG(JTAG_PWR | JTAG_TMS | JTAG_CLK);#ifdef _FORCE_IDLE_RUN_ }#endif /* select DR -> select IR */ writeJTAG(JTAG_PWR | JTAG_TMS); writeJTAG(JTAG_PWR | JTAG_TMS | JTAG_CLK); jtagReg(_data, JTAG_IRLENGTH);}void PPJTAG::dreg(unsigned char *data, unsigned char length, bool wonly){#ifdef _FORCE_IDLE_RUN_ if (jtagRestarted == 1) { /* this is only output if you have come from IDLE/RUN */ jtagRestarted = 0;#endif /* idle -> select DR */ writeJTAG(JTAG_PWR | JTAG_TMS); writeJTAG(JTAG_PWR | JTAG_TMS | JTAG_CLK);#ifdef _FORCE_IDLE_RUN_ }#endif /* we always go via Idle/Run for data register stuff */ jtagRestarted = 1; jtagReg(data, length); // state is now run test / Idle.}void PPJTAG::jtagReset(void){ unsigned char loop_count; trst(true); trst(false); /* Go out of nTRST if in it */ writeJTAG(JTAG_PWR); writeJTAG(JTAG_PWR | JTAG_CLK); for(loop_count = 0; loop_count < 5; loop_count++) { /* goto Test Logic Reset and stay there */ writeJTAG(JTAG_PWR | JTAG_TMS); writeJTAG(JTAG_PWR | JTAG_TMS | JTAG_CLK); } /* Test Logic Reset -> Idle */ writeJTAG(JTAG_PWR); writeJTAG(JTAG_PWR | JTAG_CLK); writeJTAG(JTAG_PWR); writeJTAG(JTAG_PWR | JTAG_CLK); writeJTAG(JTAG_PWR); jtagRestarted = 1;}void PPJTAG::cpuReset(bool state) { if (state) { /* put cpu_reset line to 0 (ouput and zero) */ permBits |= JTAG_CPURESET; writeJTAG(portVal); } else { /* put cpu_reset line high Z (input) */ permBits &= ~JTAG_CPURESET; writeJTAG(portVal); }}void PPJTAG::trst(bool state) { if (!state) { /* put trst line to 0 (ouput and zero) */ //OUTB&=~JTAG_TRST; permBits|=JTAG_TRST; writeJTAG(portVal); } else { /* put trst line high Z (input) */ permBits&=~JTAG_TRST; writeJTAG(portVal); }}void PPJTAG::idle(unsigned int nbTCK){ unsigned int i; for (i=0; i<nbTCK; i++) { writeJTAG(JTAG_PWR); writeJTAG(JTAG_PWR | JTAG_CLK); } writeJTAG(JTAG_PWR);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -