libftdi Archives

Subject: JTAG IDCODE

From: Røunnus <rounnus@xxxxxxxxx>
To: libftdi@xxxxxxxxxxxxxxxxxxxxxxx
Date: Thu, 20 Feb 2025 18:52:14 +0200
Hello!,

Lately I have been trying to read the IDCODE register contents from the JTAG interface of an ARTIX-7 FPGA (name: BASYS-3).  The procedure i know is the following:
     reset the TAP controller > navigate to IR-SHIFT-STATE > store the value 0x09 which to the IR > navigate to DR-SHIFT-STATE > read the contents that corresponds to the value of the IDCODE register.

While I do the procedure above, I can't retrieve the data I'm seeking.
Following, this is the code I have developed. I don't really know where i'm wrong, but i guess, it is something to do with TAP.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <libftdi1/ftdi.h>

#define BASYS_3_VENDOR 0x0403
#define BASYS_3_VERSION  0x6010


int main()
{
struct ftdi_context *ftdi;

if ((ftdi = ftdi_new()) == 0) {
(void) printf("ftdi new failed]\n");
return EXIT_FAILURE;
}

if (ftdi_usb_open(ftdi, BASYS_3_VENDOR, BASYS_3_VERSION) < 0) {
(void) printf("Unable to open ftdi device\n");
return EXIT_FAILURE;
}

if (ftdi_set_interface(ftdi, INTERFACE_A) < 0) {
(void) printf("Unable to set the interface\n");
return EXIT_FAILURE;
}


// Set the mode in such mode to have access to tap controller.
if (ftdi_set_bitmode(ftdi, 0xfb, BITMODE_MPSSE) < 0) {
(void) printf("Unable to set bitmode\n");
return EXIT_FAILURE;
}
if (ftdi_tcioflush(ftdi) < 0) {
(void) printf("Unable to purge the buffers\n");
}

sleep(2);

unsigned char buff[3] = {
0xAA,
0x00,
0x00
};

unsigned char buff_tmp;

// Send bogus command.
ftdi_write_data(ftdi, buff, 1);

// Read the data (bogus from the device)
ftdi_read_data(ftdi, &buff_tmp, sizeof(buff_tmp));

// CONFIGURE THE CLOCK DIVIDER.
buff[0] = 0x8A;
buff[1] = 0x97;
buff[2] = 0x8D;

ftdi_write_data(ftdi, buff, sizeof(buff));

buff[0] = 0x80;
buff[1] = 0x08;
buff[2] = 0x0B;

ftdi_write_data(ftdi, buff, sizeof(buff));

buff[0] = 0x82;
buff[1] = 0x00;
buff[2] = 0x00;

ftdi_write_data(ftdi, buff, sizeof(buff));

buff[0] = '\x86';
buff[1] = 0x05DB & 0xFF;
buff[2] = (0x05DB >> 8) & 0xFF;

ftdi_write_data(ftdi, buff, sizeof(buff));

buff[0] = 0x85;

ftdi_write_data(ftdi, buff, 1);

// JTAG RELATED STEPS

// Clock in 6 bits, to reset the state of the TAP.
// After that, TAP is set to LOW.
buff[0] = 0x4B;
buff[1] = 0x06;
buff[2] = 0x7f;

ftdi_write_data(ftdi, buff, sizeof(buff));

// Navigate the TAP to the shift IR state.
buff[0] = 0x4B;
buff[1] = 0x06;
buff[2] = 0x0D;

ftdi_write_data(ftdi, buff, sizeof(buff));

// Until this point were are correct.

// Store the value 0x09 to the IR register.
buff[0] = 0x1B;
buff[1] = 0x04;
buff[2] = 0x09;

ftdi_write_data(ftdi, buff, sizeof(buff));

// Navigate to the DR-SHIFT STATE.
buff[0] = 0x4B;
buff[1] = 0x03;
buff[2] = 0x83;

ftdi_write_data(ftdi, buff, sizeof(buff));

// Push out the 32-bit contents of the DR (IDCODE).
buff[0] = 0x2E;
buff[1] = 0x1F;
buff[2] = 0x01;

ftdi_write_data(ftdi, buff, 2);

unsigned char idcode[3] = {0};

// Read the contents from the FTDI.
ftdi_read_data(ftdi, idcode, 4);

(void) printf("%X%X%X%X\n", idcode[3], idcode[2], idcode[1], idcode[0]);

ftdi_free(ftdi);
(void) printf("SUCCESS\n");
return EXIT_SUCCESS;
}

Thanks!





libftdi - see http://www.intra2net.com/en/developer/libftdi for details.
To unsubscribe send a mail to libftdi+unsubscribe@xxxxxxxxxxxxxxxxxxxxxxx


Current Thread