blue1025的个人空间 https://blog.eetop.cn/mj8051 [收藏] [复制] [分享] [RSS]

空间首页 动态 记录 日志 相册 主题 分享 留言板 个人资料

日志

Xilinx Virtex and Spartan JTAG programmer

已有 1372 次阅读| 2008-9-24 11:37 |个人分类:soc leon2.1.30

/*--------------------------------------------------------------------
* Xilinx Virtex and Spartan JTAG programmer, based on
reference doc: XAPP 139 V1.6
Table 7

Rene van Leuken, April 2004

--------------------------------------------------------------------*/

/*--------------------------------------------------------------------

ljp.c: Linux JTAG Xilinx Programmer - version 0.1

Programs Xilinx FPGAs in JTAG mode through a parallel port,
using a Xilinx Parallel Cable III/IV compatible interface by default.
Input bitstream files must be in .bit (binary) format. The parallel
port is used only in 'compatible' mode, so any old hardware will
do. Requires a Linux kernel with ppdev/parport drivers, i.e. 2.4+
or 2.2.17 with the ppdev patch; for more information see
http://people.redhat.com/twaugh/parport/.

You must have r/w permissions for the parport device you want to
use. Typical use:
$ ljp bitstream.bit /dev/parport0
or:
$ gunzip < bitstream.bit.gz | ljp - /dev/parport0

To compile this code use something like: gcc -O2 -o ljp ljp.c

Rudolf Usselmann ASICS World Services rudi(at)asics(dot)ws

Based on original work by:
Reinoud <reinoud@remove.et.tudelft.nl>

--------------------------------------------------------------------

(c) 2003/2004 Rudolf Usselmann
(c) 2001 Reinoud Lamberts

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 <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/ppdev.h>
#include <linux/parport.h>


/*--- interface configuration ---*/

/* Configure the interface/cable with the defines below. Xilinx
parallel cable compatible is the default. If your interface
doesn't use a signal, simply make the corresponding mask all zero.

Note that the mask defines below are named after FPGA signals they
control, and not after names used in the Xilinx parallel cable
schematic. This is because the Xilinx cable is not the only
target, and the names it uses are confusing. */

// select data or control output lines: PPWDATA or PPWCONTROL
#define O_WRITECMD PPWDATA


// output signal masks

#define O_ENABLE 0x10 // Enable TDI, TCK and TSM outputs
#define O_START 0x10 // Pulses TDO (DONE Input to Par. Port) (UNUSED)

#define O_TDI_0 0x00 // TDI Low
#define O_TDI_1 0x01 // TDI High

#define O_TCK_0 0x00 // TCK Low
#define O_TCK_1 0x02 // TCK High

#define O_TMS_0 0x00 // TMS Low
#define O_TMS_1 0x04 // TMS High

// input signal masks; for *_OK give masked expected OK value
#define I_SENSE PARPORT_STATUS_ERROR
#define I_SENSE_OK I_SENSE
#define I_DONE PARPORT_STATUS_SELECT
#define I_DONE_OK I_DONE

// JTAG Commands
#define CMD_CFG 0x05
#define CMD_JSTART 0x0c
#define CMD_IDCODE 0x09

static int d; // descriptor for parport device
unsigned char byte;

// --- print error and clean up if needed ---

void
err (int d, char *s)
{
unsigned char o;
perror (s);

if (d != -1)
{
o = 0x00;
ioctl (d, O_WRITECMD, &o);
ioctl (d, PPRELEASE);
}
exit (1);
}

// Read TDO pin
unsigned char
read_tdo ()
{
unsigned char stat; /* status (input) data from parport */
if (ioctl (d, PPRSTATUS, &stat))
err (d, "read status parport");
if ((stat & I_DONE) == I_DONE_OK)
return (1);
else
return (0);
}

// Read Vcc sense pin
unsigned char
read_vcc ()
{
unsigned char stat; /* status (input) data from parport */
if (ioctl (d, PPRSTATUS, &stat))
err (d, "read status parport");
if ((stat & I_SENSE) == I_SENSE_OK)
return (1);
else
return (0);
}

// Send a single bit to the device (1 clock cycle). 'val' is the
// value for TDI and tms is the value for the TMS pin.
void
send_bit (unsigned char val, unsigned char tms)
{
unsigned char out;
ut = O_TCK_0 | O_ENABLE;
out |= (tms == 0) ? O_TMS_0 : O_TMS_1;
out |= (val == 0) ? O_TDI_0 : O_TDI_1;
ioctl (d, O_WRITECMD, &out);

ut = O_TCK_1 | O_ENABLE;
out |= (tms == 0) ? O_TMS_0 : O_TMS_1;
out |= (val == 0) ? O_TDI_0 : O_TDI_1;
ioctl (d, O_WRITECMD, &out);
}

// Send an enitre byte to the device. If last is '1', TMS will
// be high for the last bit transmitteda (e.g. force trasnition
// to EXIT1 state).
void
send_data_byte (unsigned char val, unsigned char last)
{
int n;
for (n = 7; n >= 0; n--)
{
send_bit ((val >> n) & 0x01, (n == 0 & last));
}
}

// Identical to send_data_byte, but also reads TDO. Created seperate
// subroutines for write only and write & read mainly for speed-up
// reasons.
void
read_data_byte (unsigned char val, unsigned char last)
{
int n;
unsigned char bit;
byte = 0;
for (n = 7; n >= 0; n--)
{
send_bit ((val >> n) & 0x01, (n == 0 & last));
bit = read_tdo ();
byte |= bit << (7 - n);
}
}

void
decode_id (int id)
{
int manuf, size, family, rev;

if ((id & 0x01) != 1)
{
printf ("Warning: Bit 0 (LSB) of devcice id is not '1' !\n");
}

manuf = (id >> 01) & 0x07ff;
size = (id >> 12) & 0x01ff;
family = (id >> 21) & 0x007f;
rev = (id >> 28) & 0x000f;

printf ("Device ID: %x\n", id);
printf ("Manuf: %x, Part Size: %x, Family Code: %x, Revision: %0d\n", manuf,
size, family, rev);

if (manuf != 0x49)
{
printf ("I can only program Xilinx Virtex and Spartan devices\n");
}
}

int
main (int argc, char *argv[])
{
char *rbname; /* rbt file name */
char *ppname; /* parport device file name */

FILE *f; /* rbt file ptr */
char c, next; /* char from f */
unsigned char uc;
char *mem;
char mem2[256];

unsigned char o; /* output data for parport */
unsigned char stat; /* status (input) data from parport */
long bitcount; /* bits transferred */
int n, x, len, len2, token;
int devid;

// ====================================================
// ===== get arguments

if (argc != 3)
{
fprintf (stderr,
"usage: %s <BIT file, or - for stdin> <parport device>\n",
argv[0]);
exit (2);
}

rbname = argv[1];
ppname = argv[2];

// ====================================================
// ===== get input file

if (strcmp (rbname, "-"))
f = fopen (rbname, "r");
else
f = stdin;
if (f == NULL)
err (-1, "open bitstream file");


// ====================================================
// ===== Parse binary Header PLEASE REWRITE THIS !

uc = getc (f);
len = uc << 8;
uc = getc (f);
len += uc;
for (x = 0; x < len; x++)
c = getc (f);

uc = getc (f);
len = uc << 8;
uc = getc (f);
len += uc;
//printf("Length: %0d\n",len);

uc = getc (f);
token = uc;
//printf("Token: %x\n",token);

uc = getc (f);
len = uc << 8;
uc = getc (f);
len += uc;
//printf("Length: %0d\n",len);

printf ("Design Name: ");

for (x = 0; x < len; x++)
{
uc = getc (f);
printf ("%c", uc);
}
printf ("\n");

uc = getc (f);
token = uc;
//printf("Token: %x\n",token);

uc = getc (f);
len = uc << 8;
uc = getc (f);
len += uc;
//printf("Length: %0d\n",len);

printf ("Device: ");

for (x = 0; x < len; x++)
{
uc = getc (f);
printf ("%c", uc);
}
printf ("\n");


uc = getc (f);
token = uc;
//printf("Token: %x\n",token);

uc = getc (f);
len = uc << 8;
uc = getc (f);
len += uc;
//printf("Length: %0d\n",len);

printf ("Date: ");

for (x = 0; x < len; x++)
{
uc = getc (f);
printf ("%c", uc);
}
printf ("\n");


uc = getc (f);
token = uc;
//printf("Token: %x\n",token);

uc = getc (f);
len = uc << 8;
uc = getc (f);
len += uc;
//printf("Length: %0d\n",len);

printf ("Time: ");

for (x = 0; x < len; x++)
{
uc = getc (f);
printf ("%c", uc);
}
printf ("\n");

uc = getc (f);
token = uc;
//printf("Token: %x\n",token);

uc = getc (f);
len = uc << 24;
uc = getc (f);
len += uc << 16;
uc = getc (f);
len += uc << 8;
uc = getc (f);
len += uc;
printf ("Bitstream Length: %0d bits\n", len * 8);


// ====================================================
// ===== get parport

d = open (ppname, O_RDWR);
if (d == -1)
err (-1, "open parport");
if (ioctl (d, PPCLAIM))
err (-1, "claim parport");

// ====================================================
// ===== check power
if (!read_vcc ())
{
fprintf (stderr, "ERROR: no power on interface\n");
o = 0x00; // Turn off driver
if (ioctl (d, O_WRITECMD, &o))
err (d, "write parport");
if (ioctl (d, PPRELEASE))
err (-1, "release parport");
exit (-1);
}

// ====================================================
// ########## Start of JTAG Programming sequence

// ====================================================
// ########## RESET Test Logic

for (n = 0; n < 6; n++)
send_bit (0, 1); // Test Logic Reset // 1
// tdi tms
send_bit (0, 0); // 2

// State = IDLE

send_bit (0, 1); // 3
send_bit (0, 1); // 3
send_bit (0, 0); // 4
send_bit (0, 0); // 4

// ====================================================
// ########## IDCODE Instruction
send_bit (1, 0); //
send_bit (0, 0); //
send_bit (0, 0); //
send_bit (1, 0); //
send_bit (0, 1); //


send_bit (0, 1); //
send_bit (0, 1); //

send_bit (0, 0); //
send_bit (0, 0); //

read_data_byte (0x00, 0);
devid = byte;

read_data_byte (0x00, 0);
devid += byte << 8;

read_data_byte (0x00, 0);
devid += byte << 16;

read_data_byte (0x00, 1);
devid += byte << 24;

decode_id (devid);

send_bit (0, 1); //

send_bit (0, 1); //
send_bit (0, 1); //
send_bit (0, 0); //
send_bit (0, 0); //


// END IDCODE



// ====================================================
// ########## CONFIGURE
// CFG_IN 0101
send_bit (1, 0); // 5
send_bit (0, 0); // 5
send_bit (1, 0); // 5
send_bit (0, 0); // 5

send_bit (0, 1); // 6

send_bit (0, 1); // 7
send_bit (0, 1); // 7
send_bit (0, 0); // 8
send_bit (0, 0); // 8

// ====================================================
// SEND DATA

bitcount = 0;
fprintf (stderr, "\nProgramming ... ");

for (n = 0; n < len; n++)
{
uc = getc (f);
send_data_byte (uc, n == (len - 1));
bitcount += 8;
if ((bitcount % (256 * 1024)) == 0)
putc ('*', stderr);
}

fprintf (stderr, "\nProgrammed %0d bits", bitcount);

send_bit (0, 1); // 11
send_bit (0, 1); // 12
send_bit (0, 1); // 12
send_bit (0, 0); // 13
send_bit (0, 0); // 13

// ====================================================
// ########## JSTART 1100

send_bit (0, 0); // 14
send_bit (0, 0); // 14
send_bit (1, 0); // 14
send_bit (1, 0); // 14

send_bit (0, 1); // 15
send_bit (0, 1); // 16
send_bit (0, 1); // 16

for (n = 0; n < 17; n++)
send_bit (0, 0); // Clock-in RUN-TEST sequence

send_bit (0, 1); // 18
send_bit (0, 1); // 18
send_bit (0, 0); // 19
send_bit (0, 0); // 19

// DONE !
// ====================================================

printf ("\n");

o = 0x00; // Turn off driver
if (ioctl (d, O_WRITECMD, &o))
err (d, "write parport");
if (ioctl (d, PPRELEASE))
err (-1, "release parport");
return 0;
}
source html http://ens.ewi.tudelft.nl/~rene/xilinx-jtag.c


点赞

评论 (0 个评论)

facelist

您需要登录后才可以评论 登录 | 注册

  • 关注TA
  • 加好友
  • 联系TA
  • 0

    周排名
  • 0

    月排名
  • 0

    总排名
  • 0

    关注
  • 13

    粉丝
  • 16

    好友
  • 15

    获赞
  • 23

    评论
  • 2824

    访问数
关闭

站长推荐 上一条 /1 下一条

小黑屋| 关于我们| 联系我们| 在线咨询| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2024-4-26 15:49 , Processed in 0.030458 second(s), 14 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
返回顶部