The core of this is a TCP server written in C++ known as jtagd. So far I have tested it on Debian 7 on both x86_64-linux-gnu and arm-linux-gnueabihf architectures (laptop computer and Beaglebone Black).
The main jtagd executable connects to a JtagInterface object and bridges it out to a TCP socket using my custom protocol. The protocol is not 100% finalized at this point, several features (like a magic-number banner to verify the client is actually talking to a valid jtagd and not a mistyped port number) will be added before a public release.
Starting a jtagd is quite simple: run "jtagd --list" to see what interfaces are available, then connect to one of them.
azonenberg@mars$ jtagd --list
JTAG server daemon [SVN rev 1230M] by Andrew D. Zonenberg.
License: 3-clause ("new" or "modified") BSD.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Digilent API version: 2.9.3
Enumerating interfaces... 2 found
Interface 0: JtagSmt1
Serial number: SN:210203825011
User ID: JtagSmt1
Default clock: 10.00 MHz
Interface 1: JtagHs1
Serial number: SN:210205812611
User ID: JtagHs1
Default clock: 10.00 MHz
FTDI API version: libftd2xx 1.1.4
Enumerating interfaces... 16 found
Interface 0: Digilent Adept USB Device A
Serial number: 210203825011A
User ID: 210203825011A
Default clock: 10.00 MHz
[[ Output trimmed for brevity ]]
Interface 10: Dev Board JTAG
Serial number: FTWB6M0W
User ID: FTWB6M0W
Default clock: 10.00 MHz
azonenberg@mars$ jtagd --api ftdi --serial 210203825011A --port 50200
JTAG server daemon [SVN rev 1230M] by Andrew D. Zonenberg.
License: 3-clause ("new" or "modified") BSD.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Connected to interface "Digilent Adept USB Device A (2232H)" (serial number "210203825011A")
Once the jtagd is running, you can connect to it using command-line tools such as jtagclient, or directly from C code using libjtaghal. The example here connects to a Digilent Atlys and verifies the device ID of the XC6SLX45 FPGA.
NetworkedJtagInterface iface;
iface.Connect(server, port);
//note use of RAII-style mutexing
//since jtagd is multi-client capable
JtagLock lock(m_iface);
m_iface->InitializeChain();
int ndev = m_iface->GetDeviceCount();
if(ndev == 0)
{
throw JtagExceptionWrapper(
"No devices found - invalid scan chain?",
"",
JtagException::EXCEPTION_TYPE_BOARD_FAULT);
}
//Verify that the board is an Atlys
//Should have a single XC6SLX45
XilinxSpartan6Device* pfpga = dynamic_cast<XilinxSpartan6Device*>(m_iface->GetDevice(0));
if(pfpga == NULL)
{
throw JtagExceptionWrapper(
"Device does not appear to be a Spartan-6",
"",
JtagException::EXCEPTION_TYPE_BOARD_FAULT);
}
if(pfpga->GetArraySize() != XilinxSpartan6Device::SPARTAN6_LX45)
{
throw JtagExceptionWrapper(
"Device is not an XC6SLX45",
"",
JtagException::EXCEPTION_TYPE_BOARD_FAULT);
}
The library internally uses low-level chain operations in order to talk to the device. The code below retrieves the "Device DNA" die serial number from a Spartan-6.
void XilinxSpartan6Device::GetSerialNumber(unsigned char* data)
{
JtagLock lock(m_iface);
Erase();
//Enter ISC mode (wipes configuration)
ResetToIdle();
SetIR(INST_ISC_ENABLE);
//Read the DNA value
SetIR(INST_ISC_DNA);
unsigned char zeros[8] = {0x00};
ScanDR(zeros, data, 57);
//Done
SetIR(INST_ISC_DISABLE);
}
Stay tuned for my next post on nocswitch and the NoC-to-JTAG debug bridge :)
Thanks for sharing.
ReplyDeleteJTAG