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