fpgatools/mini-jtag/jtag.c
minux ea5ad1478a libs, mini-jtag: fix two typos
Signed-off-by: minux <minux.ma@gmail.com>
2013-01-16 10:06:36 +08:00

195 lines
3.7 KiB
C

//
// Author: Xiangfu Liu
//
// This is free and unencumbered software released into the public domain.
// For details see the UNLICENSE file at the root of the source tree.
//
#include <ftdi.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "jtag.h"
int tap_tms(struct ftdi_context *ftdi, int tms, uint8_t bit7)
{
uint8_t buf[3];
buf[0] = MPSSE_WRITE_TMS|MPSSE_LSB|MPSSE_BITMODE|MPSSE_WRITE_NEG;
buf[1] = 0; /* value = length - 1 */
buf[2] = (tms ? 0x01 : 0x00) | ((bit7 & 0x01) << 7);
if (ftdi_write_data(ftdi, buf, 3) != 3)
return -1;
return 0;
}
void tap_reset_rti(struct ftdi_context *ftdi)
{
int i;
for(i = 0; i < 5; i++)
tap_tms(ftdi, 1, 0);
tap_tms(ftdi, 0, 0); /* Goto RTI */
}
int tap_shift_ir_only(struct ftdi_context *ftdi, uint8_t ir)
{
int ret = 0;
uint8_t buf[3] = {0, 0, 0};
buf[0] = MPSSE_DO_WRITE|MPSSE_LSB|
MPSSE_BITMODE|MPSSE_WRITE_NEG;
buf[1] = 4;
buf[2] = ir;
if (ftdi_write_data(ftdi,buf, 3) != 3) {
fprintf(stderr, "Write loop failed\n");
ret = -1;
}
tap_tms(ftdi, 1, (ir >> 5));
return ret;
}
int tap_shift_ir(struct ftdi_context *ftdi, uint8_t ir)
{
int ret;
tap_tms(ftdi, 1, 0); /* RTI status */
tap_tms(ftdi, 1, 0);
tap_tms(ftdi, 0, 0);
tap_tms(ftdi, 0, 0); /* Goto shift IR */
ret = tap_shift_ir_only(ftdi, ir);
tap_tms(ftdi, 1, 0);
tap_tms(ftdi, 0, 0); /* Goto RTI */
return ret;
}
static int shift_last_bits(struct ftdi_context *ftdi,
uint8_t *in, uint8_t len, uint8_t *out)
{
uint8_t buf[3];
if (!len)
return -1;
buf[0] = MPSSE_LSB|MPSSE_BITMODE|MPSSE_WRITE_NEG;
if (in)
buf[0] |= MPSSE_DO_WRITE;
if (out)
buf[0] |= MPSSE_DO_READ;
buf[1] = len - 1;
if (in)
buf[2] = *in;
if (ftdi_write_data(ftdi, buf, 3) != 3) {
fprintf(stderr,
"Ftdi write failed\n");
return -1;
}
if (out)
ftdi_read_data(ftdi, out, 1);
return 0;
}
int tap_shift_dr_bits_only(struct ftdi_context *ftdi,
uint8_t *in, uint32_t in_bits,
uint8_t *out)
{
/* Have to be at RTI status before call this function */
uint8_t buf_bytes[FTDI_MAX_RW_SIZE + 3];
uint32_t in_bytes = 0;
uint32_t last_bits = 0;
uint16_t last_bytes, len;
int i, t;
in_bytes = in_bits / 8;
last_bits = in_bits % 8;
/* If last_bits == 0, the last bit of last byte should send out with TMS */
if (in_bytes) {
t = in_bytes / FTDI_MAX_RW_SIZE;
last_bytes = in_bytes % FTDI_MAX_RW_SIZE;
for (i = 0; i <= t; i++) {
len = (i == t) ? last_bytes : FTDI_MAX_RW_SIZE;
buf_bytes[0] = MPSSE_LSB|MPSSE_WRITE_NEG;
if (in)
buf_bytes[0] |= MPSSE_DO_WRITE;
if (out)
buf_bytes[0] |= MPSSE_DO_READ;
buf_bytes[1] = (len - 1) & 0xff;
buf_bytes[2] = ((len - 1) >> 8) & 0xff;
if (in)
memcpy(&buf_bytes[3], (in + i * FTDI_MAX_RW_SIZE), len);
if (ftdi_write_data(ftdi, buf_bytes, len + 3) != len + 3) {
fprintf(stderr,
"Ftdi write failed\n");
return -1;
}
if (out)
ftdi_read_data(ftdi, (out + i * FTDI_MAX_RW_SIZE), len);
}
}
if (last_bits) {
/* Send last few bits */
shift_last_bits(ftdi, &in[in_bytes], last_bits - 1, out);
tap_tms(ftdi, 1, (in[in_bytes] >> (last_bits - 1)));
} else
tap_tms(ftdi, 1, 0);
return 0;
}
int tap_shift_dr_bits(struct ftdi_context *ftdi,
uint8_t *in, uint32_t in_bits,
uint8_t *out)
{
int ret;
/* Send 3 Clocks with TMS = 1 0 0 to reach SHIFTDR*/
tap_tms(ftdi, 1, 0);
tap_tms(ftdi, 0, 0);
tap_tms(ftdi, 0, 0);
ret = tap_shift_dr_bits_only(ftdi, in, in_bits, out);
tap_tms(ftdi, 1, 0);
tap_tms(ftdi, 0, 0); /* Goto RTI */
return ret;
}
int ft232_flush(struct ftdi_context *ftdi)
{
uint8_t buf[1] = { SEND_IMMEDIATE };
if (ftdi_write_data(ftdi, buf, 1) != 1) {
fprintf(stderr,
"Can't SEND_IMMEDIATE\n");
return -1;
}
return 0;
}