mirror of
git://projects.qi-hardware.com/nn-usb-fpga.git
synced 2025-01-08 14:50:15 +02:00
a7c692d3f0
Adding FPGA sram hdl code and user space code Fixing some errors: LCD's pinout connector is swapped FPGA TDI SIGNAL must be routed to another pin (C14), right now is DQMH Remove R11 Check JZ4725 symbol's component (PORTD is wrong) Adding PB2 and PB3 wiring ADC's vref to external connector Adding power LED Adding CPU Led
353 lines
6.9 KiB
C++
353 lines
6.9 KiB
C++
/* JTAG low level functions and base class for cables
|
|
|
|
Copyright (C) 2004 Andrew Rogers
|
|
|
|
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 */
|
|
|
|
|
|
|
|
#include "iobase.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
using namespace std;
|
|
|
|
IOBase::IOBase()
|
|
{
|
|
current_state=UNKNOWN;
|
|
}
|
|
|
|
int IOBase::shiftTDITDO(const unsigned char *tdi, unsigned char *tdo, int length, bool last)
|
|
{
|
|
if(length==0)return 0;
|
|
int i=0;
|
|
int j=0;
|
|
unsigned char tdo_byte=0;
|
|
unsigned char tdi_byte=tdi[j];
|
|
while(i<length-1){
|
|
tdo_byte=tdo_byte+(txrx(false, (tdi_byte&1)==1)<<(i%8));
|
|
tdi_byte=tdi_byte>>1;
|
|
i++;
|
|
if((i%8)==0){ // Next byte
|
|
tdo[j]=tdo_byte; // Save the TDO byte
|
|
tdo_byte=0;
|
|
j++;
|
|
tdi_byte=tdi[j]; // Get the next TDI byte
|
|
}
|
|
};
|
|
tdo_byte=tdo_byte+(txrx(last, (tdi_byte&1)==1)<<(i%8)); // TMS set if last=true
|
|
tdo[j]=tdo_byte;
|
|
nextTapState(last); // If TMS is set the the state of the tap changes
|
|
}
|
|
|
|
int IOBase::shiftTDI(const unsigned char *tdi, int length, bool last)
|
|
{
|
|
if(length==0)return 0;
|
|
int i=0;
|
|
int j=0;
|
|
unsigned char tdi_byte=tdi[j];
|
|
while(i<length-1){
|
|
tx(false, (tdi_byte&1)==1);
|
|
tdi_byte=tdi_byte>>1;
|
|
i++;
|
|
if((i%8)==0){ // Next byte
|
|
j++;
|
|
tdi_byte=tdi[j]; //Get the next TDI byte
|
|
}
|
|
};
|
|
tx(last, (tdi_byte&1)==1); // TMS set if last=true
|
|
nextTapState(last); // If TMS is set the the state of the tap changes
|
|
}
|
|
|
|
// TDI gets a load of zeros, we just record TDO.
|
|
int IOBase::shiftTDO(unsigned char *tdo, int length, bool last)
|
|
{
|
|
if(length==0)return 0;
|
|
int i=0;
|
|
int j=0;
|
|
unsigned char tdo_byte=0;
|
|
while(i<length-1){
|
|
tdo_byte=tdo_byte+(txrx(false, false)<<(i%8));
|
|
i++;
|
|
if((i%8)==0){ // Next byte
|
|
tdo[j]=tdo_byte; // Save the TDO byte
|
|
tdo_byte=0;
|
|
j++;
|
|
}
|
|
};
|
|
tdo_byte=tdo_byte+(txrx(last, false)<<(i%8)); // TMS set if last=true
|
|
tdo[j]=tdo_byte;
|
|
nextTapState(last); // If TMS is set the the state of the tap changes
|
|
}
|
|
|
|
// TDI gets a load of zeros or ones, and we ignore TDO
|
|
int IOBase::shift(bool tdi, int length, bool last)
|
|
{
|
|
if(length==0)return 0;
|
|
int i=0;
|
|
while(i<length-1){
|
|
tx(false, tdi);
|
|
i++;
|
|
};
|
|
tx(last, tdi); // TMS set if last=true
|
|
nextTapState(last); // If TMS is set the the state of the tap changes
|
|
}
|
|
|
|
int IOBase::setTapState(tapState_t state)
|
|
{
|
|
bool tms;
|
|
while(current_state!=state){
|
|
switch(current_state){
|
|
|
|
case TEST_LOGIC_RESET:
|
|
switch(state){
|
|
case TEST_LOGIC_RESET:
|
|
tms=true;
|
|
break;
|
|
default:
|
|
tms=false;
|
|
current_state=RUN_TEST_IDLE;
|
|
};
|
|
break;
|
|
|
|
case RUN_TEST_IDLE:
|
|
switch(state){
|
|
case RUN_TEST_IDLE:
|
|
tms=false;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=SELECT_DR_SCAN;
|
|
};
|
|
break;
|
|
|
|
case SELECT_DR_SCAN:
|
|
switch(state){
|
|
case CAPTURE_DR:
|
|
case SHIFT_DR:
|
|
case EXIT1_DR:
|
|
case PAUSE_DR:
|
|
case EXIT2_DR:
|
|
case UPDATE_DR:
|
|
tms=false;
|
|
current_state=CAPTURE_DR;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=SELECT_IR_SCAN;
|
|
};
|
|
break;
|
|
|
|
case CAPTURE_DR:
|
|
switch(state){
|
|
case SHIFT_DR:
|
|
tms=false;
|
|
current_state=SHIFT_DR;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=EXIT1_DR;
|
|
};
|
|
break;
|
|
|
|
case SHIFT_DR:
|
|
switch(state){
|
|
case SHIFT_DR:
|
|
tms=false;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=EXIT1_DR;
|
|
};
|
|
break;
|
|
|
|
case EXIT1_DR:
|
|
switch(state){
|
|
case PAUSE_DR:
|
|
case EXIT2_DR:
|
|
case SHIFT_DR:
|
|
case EXIT1_DR:
|
|
tms=false;
|
|
current_state=PAUSE_DR;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=UPDATE_DR;
|
|
};
|
|
break;
|
|
|
|
case PAUSE_DR:
|
|
switch(state){
|
|
case PAUSE_DR:
|
|
tms=false;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=EXIT2_DR;
|
|
};
|
|
break;
|
|
|
|
case EXIT2_DR:
|
|
switch(state){
|
|
case SHIFT_DR:
|
|
case EXIT1_DR:
|
|
case PAUSE_DR:
|
|
tms=false;
|
|
current_state=SHIFT_DR;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=UPDATE_DR;
|
|
};
|
|
break;
|
|
|
|
case UPDATE_DR:
|
|
switch(state){
|
|
case RUN_TEST_IDLE:
|
|
tms=false;
|
|
current_state=RUN_TEST_IDLE;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=SELECT_DR_SCAN;
|
|
};
|
|
break;
|
|
|
|
case SELECT_IR_SCAN:
|
|
switch(state){
|
|
case CAPTURE_IR:
|
|
case SHIFT_IR:
|
|
case EXIT1_IR:
|
|
case PAUSE_IR:
|
|
case EXIT2_IR:
|
|
case UPDATE_IR:
|
|
tms=false;
|
|
current_state=CAPTURE_IR;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=TEST_LOGIC_RESET;
|
|
};
|
|
break;
|
|
|
|
case CAPTURE_IR:
|
|
switch(state){
|
|
case SHIFT_IR:
|
|
tms=false;
|
|
current_state=SHIFT_IR;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=EXIT1_IR;
|
|
};
|
|
break;
|
|
|
|
case SHIFT_IR:
|
|
switch(state){
|
|
case SHIFT_IR:
|
|
tms=false;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=EXIT1_IR;
|
|
};
|
|
break;
|
|
|
|
case EXIT1_IR:
|
|
switch(state){
|
|
case PAUSE_IR:
|
|
case EXIT2_IR:
|
|
case SHIFT_IR:
|
|
case EXIT1_IR:
|
|
tms=false;
|
|
current_state=PAUSE_IR;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=UPDATE_IR;
|
|
};
|
|
break;
|
|
|
|
case PAUSE_IR:
|
|
switch(state){
|
|
case PAUSE_IR:
|
|
tms=false;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=EXIT2_IR;
|
|
};
|
|
break;
|
|
|
|
case EXIT2_IR:
|
|
switch(state){
|
|
case SHIFT_IR:
|
|
case EXIT1_IR:
|
|
case PAUSE_IR:
|
|
tms=false;
|
|
current_state=SHIFT_IR;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=UPDATE_IR;
|
|
};
|
|
break;
|
|
|
|
case UPDATE_IR:
|
|
switch(state){
|
|
case RUN_TEST_IDLE:
|
|
tms=false;
|
|
current_state=RUN_TEST_IDLE;
|
|
break;
|
|
default:
|
|
tms=true;
|
|
current_state=SELECT_DR_SCAN;
|
|
};
|
|
break;
|
|
|
|
default:
|
|
tapTestLogicReset();
|
|
tms=true;
|
|
};
|
|
tx(tms,false);
|
|
};
|
|
}
|
|
|
|
// After shift data into the DR or IR we goto the next state
|
|
// This function should only be called from the end of a shift function
|
|
int IOBase::nextTapState(bool tms)
|
|
{
|
|
if(current_state==SHIFT_DR){
|
|
if(tms)current_state=EXIT1_DR; // If TMS was set then goto next state
|
|
}
|
|
else if(current_state==SHIFT_IR){
|
|
if(tms)current_state=EXIT1_IR; // If TMS was set then goto next state
|
|
}
|
|
else tapTestLogicReset(); // We were in an unexpected state
|
|
}
|
|
|
|
void IOBase::tapTestLogicReset()
|
|
{
|
|
for(int i=0; i<5; i++)tx(true,false);
|
|
current_state=TEST_LOGIC_RESET;
|
|
}
|
|
|
|
void IOBase::cycleTCK(int n, bool tdi)
|
|
{
|
|
bool tms=false;
|
|
if(current_state==TEST_LOGIC_RESET)tms=true;
|
|
for(int i=0; i<n; i++)tx(tms,tdi);
|
|
}
|