|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2005 by Mark Six *
|
|
|
|
* marksix@xs4all.nl *
|
|
|
|
* *
|
|
|
|
* 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., *
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/* FIXME
|
|
|
|
*
|
|
|
|
* This source is still a mess.
|
|
|
|
* I will clean it in the (near?) future.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "jtagprogrammer.h"
|
|
|
|
#include <iostream>
|
|
|
|
#include <tqapplication.h>
|
|
|
|
#include <tqeventloop.h>
|
|
|
|
|
|
|
|
bool IDCODE_PROM[] = { 0, 1, 1, 1, 1, 1, 1, 1 } ;
|
|
|
|
bool BYPASS_PROM[] = { 1, 1, 1, 1, 1, 1, 1, 1 } ;
|
|
|
|
bool IDCODE[] = { 1, 0, 0, 1, 0, 0 } ;
|
|
|
|
bool CFG_IN[] = { 1, 0, 1, 0, 0, 0 } ;
|
|
|
|
bool JSTART[] = { 0, 0, 1, 1, 0, 0 } ;
|
|
|
|
bool JPROGRAM[] = { 1, 1, 0, 1, 0, 0 } ;
|
|
|
|
bool JSHUTDOWN[] = { 1, 0, 1, 1, 0, 0 } ;
|
|
|
|
bool USER1[] = { 0, 1, 0, 0, 0, 0 } ;
|
|
|
|
bool USER2[] = { 1, 1, 0, 0, 0, 0 } ;
|
|
|
|
|
|
|
|
#define XCF02S 0x05045093
|
|
|
|
#define XC3S50 0x0140C093
|
|
|
|
#define XC3S200 0x01414093
|
|
|
|
#define XC3S400 0x0141C093
|
|
|
|
#define XC3S1000 0x01428093
|
|
|
|
#define XC3S1500 0x01434093
|
|
|
|
#define XC3S2000 0x01440093
|
|
|
|
#define XC3S4000 0x01448093
|
|
|
|
#define XC3S5000 0x01450093
|
|
|
|
|
|
|
|
#define ID_LEN 32
|
|
|
|
|
|
|
|
const char *id_string[] =
|
|
|
|
{
|
|
|
|
"XS3S50", "XS3S200", "XS3S400", "XS3S1000", "XS3S1500", "XS3S2000", "XS3S4000", "XS3S5000",
|
|
|
|
"XCF02S"
|
|
|
|
} ;
|
|
|
|
|
|
|
|
const unsigned int id_code[] =
|
|
|
|
{
|
|
|
|
XC3S50, XC3S200, XC3S400, XC3S1000, XC3S1500, XC3S2000, XC3S4000, XC3S5000,
|
|
|
|
XCF02S
|
|
|
|
} ;
|
|
|
|
|
|
|
|
#define MAX_IDS ( sizeof( id_code ) / sizeof( int ) )
|
|
|
|
|
|
|
|
JTAGProgrammer::JTAGProgrammer( TQObject *parent )
|
|
|
|
{
|
|
|
|
m_parent = parent ;
|
|
|
|
m_bitFilename = "" ;
|
|
|
|
|
|
|
|
m_dev = new CJTAG ;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
JTAGProgrammer::~JTAGProgrammer()
|
|
|
|
{
|
|
|
|
m_dev->close() ;
|
|
|
|
delete m_dev ;
|
|
|
|
}
|
|
|
|
|
|
|
|
int JTAGProgrammer::getDevice( bool *id ) {
|
|
|
|
unsigned int j, dev_id ;
|
|
|
|
|
|
|
|
for ( j = 0, dev_id = 0 ; j < ID_LEN ; j++ ) {
|
|
|
|
dev_id |= id[ j ] << j ;
|
|
|
|
}
|
|
|
|
|
|
|
|
for ( j = 0 ; j < MAX_IDS ; j++ ) {
|
|
|
|
if ( id_code[j] == dev_id ) {
|
|
|
|
std::string s ;
|
|
|
|
s = std::string( "Found Device : ") + id_string[j] + std::string( "\n" );
|
|
|
|
emit message( s.c_str() ) ;
|
|
|
|
return dev_id ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << "Unknown ID: " << std::hex << dev_id << "\n" ;
|
|
|
|
|
|
|
|
return 0 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JTAGProgrammer::program()
|
|
|
|
{
|
|
|
|
if ( m_bitFilename == "" ) {
|
|
|
|
emit message( "No filename given\n" ) ;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool id[ ID_LEN], ones[ ID_LEN ], dummy[ 32 ] ;
|
|
|
|
int device0, device1 ;
|
|
|
|
bool prom_present = true ;
|
|
|
|
|
|
|
|
for ( int i = 0 ; i < ID_LEN ; i++ )
|
|
|
|
ones[i] = 1 ;
|
|
|
|
|
|
|
|
if ( m_dev->isOpen() )
|
|
|
|
return ;
|
|
|
|
|
|
|
|
if ( !m_dev->open( (char*) "/dev/parport0" ) ) {
|
|
|
|
emit message( "/dev/parport0 could not be opened; check permissions\n" ) ;
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
/* ...Get device(s)... */
|
|
|
|
m_dev->selectIR() ;
|
|
|
|
m_dev->setIR( IDCODE_PROM, 8 ) ;
|
|
|
|
m_dev->setIR( IDCODE, 5 ) ;
|
|
|
|
m_dev->exitIR( IDCODE[5] ) ;
|
|
|
|
|
|
|
|
m_dev->selectDR() ;
|
|
|
|
m_dev->setDR( ones, id, ID_LEN ) ;
|
|
|
|
|
|
|
|
device0 = getDevice( id ) ;
|
|
|
|
|
|
|
|
if ( !device0 ) {
|
|
|
|
emit message( "Unknown device in JTAG chain\n" ) ;
|
|
|
|
goto exit ;
|
|
|
|
}
|
|
|
|
m_dev->setDR( ones, id, ID_LEN-1 ) ;
|
|
|
|
id[ 31 ] = m_dev->exitDR( 1 ) ;
|
|
|
|
|
|
|
|
device1 = getDevice( id ) ;
|
|
|
|
if ( !device1 ) {
|
|
|
|
emit message( "Second device is unknown (I will try to continue)\n" ) ;
|
|
|
|
prom_present = false ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ....Setup for configuration..... */
|
|
|
|
m_dev->selectIR() ;
|
|
|
|
m_dev->setIR( JPROGRAM, 5 ) ; /* Clear configuration memory */
|
|
|
|
m_dev->exitIR( JPROGRAM[5] ) ; /* Although this is not documented?? */
|
|
|
|
|
|
|
|
m_dev->selectIR();
|
|
|
|
if ( prom_present ) m_dev->setIR( BYPASS_PROM, 8 ) ;
|
|
|
|
m_dev->setIR( JSHUTDOWN, 5 ) ;
|
|
|
|
m_dev->exitIR( JSHUTDOWN[5] ) ;
|
|
|
|
|
|
|
|
m_dev->selectRunTestIdle() ;
|
|
|
|
for ( int i = 0 ; i < 20 ; i++ ) /* Shutdown sequence */
|
|
|
|
m_dev->execute( 0, 0 ) ;
|
|
|
|
|
|
|
|
m_dev->selectIR() ;
|
|
|
|
if ( prom_present ) m_dev->setIR( BYPASS_PROM, 8 ) ;
|
|
|
|
m_dev->setIR( CFG_IN, 5 ) ;
|
|
|
|
m_dev->exitIR( CFG_IN[5] ) ;
|
|
|
|
|
|
|
|
/* ....Send bit file.....*/
|
|
|
|
FILE *bit_file ;
|
|
|
|
bit_file = fopen( m_bitFilename.c_str(), "r" ) ;
|
|
|
|
if ( bit_file == NULL ) {
|
|
|
|
emit message( "Could not read bit file\n" ) ;
|
|
|
|
goto exit ;
|
|
|
|
}
|
|
|
|
|
|
|
|
int size ;
|
|
|
|
bool frame[ 8 ] ;
|
|
|
|
unsigned int cur, next ;
|
|
|
|
size = 0 ;
|
|
|
|
|
|
|
|
m_dev->selectDR() ;
|
|
|
|
fread( &cur, 1, 1, bit_file ) ;
|
|
|
|
|
|
|
|
int prog, prev_prog, total ;
|
|
|
|
fseek( bit_file, 0, SEEK_END ) ;
|
|
|
|
total = ftell( bit_file ) ;
|
|
|
|
rewind( bit_file ) ;
|
|
|
|
|
|
|
|
emit message( "Programming..." ) ;
|
|
|
|
for (prog=prev_prog=0;;) {
|
|
|
|
for ( int i = 0 ; i < 8; i++, cur <<= 1 )
|
|
|
|
frame[i] = (cur & 0x80 ) != 0 ;
|
|
|
|
|
|
|
|
size += 1;
|
|
|
|
|
|
|
|
emit progress( size*100/total ) ;
|
|
|
|
|
|
|
|
if ( fread( &next, 1, 1, bit_file ) == 0 )
|
|
|
|
break ;
|
|
|
|
m_dev->setDR( frame, dummy, 8 ) ;
|
|
|
|
cur = next ;
|
|
|
|
|
|
|
|
TQApplication::eventLoop()->processEvents( TQEventLoop::AllEvents ) ;
|
|
|
|
}
|
|
|
|
std::cout << std::endl ;
|
|
|
|
|
|
|
|
m_dev->setDR( frame, dummy, 7 ) ;
|
|
|
|
m_dev->exitDR( frame[7] ) ;
|
|
|
|
fclose( bit_file ) ;
|
|
|
|
|
|
|
|
/*....Start FPGA.....*/
|
|
|
|
m_dev->selectTestLogicReset() ;
|
|
|
|
|
|
|
|
m_dev->selectIR() ;
|
|
|
|
if ( prom_present ) m_dev->setIR( BYPASS_PROM, 8 ) ;
|
|
|
|
m_dev->setIR( JSTART, 5 ) ;
|
|
|
|
m_dev->exitIR( JSTART[5] ) ;
|
|
|
|
|
|
|
|
m_dev->selectRunTestIdle() ;
|
|
|
|
for ( int i = 0 ; i < 20 ; i++ ) /* Start up sequence */
|
|
|
|
m_dev->execute( 0, 0 ) ;
|
|
|
|
|
|
|
|
emit message( "done.\n" ) ;
|
|
|
|
exit:
|
|
|
|
m_dev->close() ;
|
|
|
|
}
|
|
|
|
|
|
|
|
void JTAGProgrammer::setBitFile( std::string filename )
|
|
|
|
{
|
|
|
|
m_bitFilename = filename ;
|
|
|
|
}
|
|
|
|
|