XSVF player -- JTAG programming with the Papilio


ben

Recommended Posts

Hi all,

trying to get the CPLD of my C/RAM wing to work without buying an outrageously expensive JTAG cable from XILINX, I made a XSVF player that turns the papilio into a kind of JTAG cable.

More precisely, instead of uploading directly the jedec (resp. bit) file into the cpld (resp. fpga) through a JTAG cable, you ask iMPACT to create a XSVF file. Then you feed this file to the Papilio through UART, which turns it into the proper JTAG signals to program the device.

It's still very beta, but it seems to work: at least the answers from the cpld in the programming phase are correct. Using a 9600 bauds connection (very beta, I said), programming a Xilinx 9572 CPLD (180k XSVF file) takes around 2 minutes, counting the one minute idling to match the erase timings. With a 115200 bauds connection and a finer clock control, it could take 30 seconds or less.

The papilio runs an AVR C program (loosely based on the one Xilinx provides for 8502) and the client is a unix C program. I tried to use a more portable language (python) for the client, but getting the serial port to work properly was too much of a hassle. It's extremely simple though -- it's basically a "read bytes from a file, push them on the serial port" loop -- so getting it to run on windows should be easy.

I'll put the source on github sometime tomorrow (after I've done some more testing and cleaned it up a little)

Link to comment
Share on other sites

Here it is : https://github.com/ben0109/XSVF-Player

To compile it, use your favorite AVR8 bit file -- you only need port A and UART. Update the makefile in "firmware" with the correct paths, and you should get your custom bit file with 'make avr.bit'. To compile the client (unix only, sorry), just run "make" in the "client" directory.

The physical interface is the same as the C/RAM programming side, on port A of the AVR8 (defaults to bits 0-7 of wing A of the Papilio):

0:unused

1:unused

2:unused

3:unused

4:TMS

5:TDO

6:TDI

7:TCK

There is still lots of work to do about the client/papilio interaction. At this point, the client just pushes data to the papilio, and the papilio prints logs. you can set the log level, from insanely verbose (only for debugging) to mute (fatal errors only) The problem is, you cannot really interrupt a programming operation (you can only starve the papilio) and it is a "run once" program: after a programming operation, you need to reset the board to start a new one.

The idea would be to feed the papilio instruction by instruction, with a global "reset" instruction. As the length of the XSVF commands are variable, this is not totally obvious, although not very complicated. It should be a little slower as you send data in smaller chunks, but this should be ok if I can get anything over 9.6k working -- which seems to be an issue at the moment.

Hopefully, I'll have something running along these lines quickly.

Oh, and it's very experimental: I still haven't tried the CPLD after programming...

Ben

Link to comment
Share on other sites

The idea would be to feed the papilio instruction by instruction, with a global "reset" instruction. As the length of the XSVF commands are variable, this is not totally obvious, although not very complicated. It should be a little slower as you send data in smaller chunks, but this should be ok if I can get anything over 9.6k working -- which seems to be an issue at the moment.

Hopefully, I'll have something running along these lines quickly.

Ok, it seems to work, and it's on GitHub. It begins to look like a V1.0.

Using a 57 600 bauds connection (I couldn't get it to work at 115 200), it takes 1'40" to upload the 180kB xsvf file to program a Xilinx 9572 CPLD. Not lightning fast, but not too bad.

Link to comment
Share on other sites

Nice. I'll try to polish the client a bit, at least to remove the hardcoded paths to the xsvf and the serial port...

I believe programming the SPI rom with a similar method should be easy, now that I've got the toolchain working properly. This would at any rate be *way* faster than the boundary scan method used by papilio-prog...

Link to comment
Share on other sites

Sounds great,

On a side note, the boundary scan method used by papilio-prog should only take 3-4 seconds to program the SPI Flash chip. With the Atmel chips it actually does take about 3-4 seconds, but when I added support for SST Flash chips is when the long delay came about. The SST chips have a drastically different internal layout then any other SPI Flash chip. It seems that most chips use pages while the SST doesn't. So the existing code was geared towards programming flash chips using a paging scheme. There also seems to be an issue with difference in the usec delay between windows and linux boxes which required adding a long pause between switching pages to get stability. With the other chips its not noticable because the pages don't switch so much, but with the SST I set a page size of 2 bytes and so the long pauses add up...

So long story short, its been on the task list to fix the support for SST chips to speed SPI Flash programming up to 3-4 seconds but it always seems to make its way to the bottom of the priority list.

Jack.

Link to comment
Share on other sites

Ok,

Everyone that has ever suffered through the Papilio Loader taking a long time to program SPI Flash is going to  love and hate me. :)

First the good news, SST Flash is now programming in 3-5 seconds on my computer.

Now the bad news, the reason it was taking so long was really stupid! I was using two  conflicting methods to detect when a write finished completely. I was reading the status register and then if the status register did not return that the write was done I waited the amount of time that was allocated for a write to take place and then looped through more reads of the status register. That works fine for Atmel chips that allow you to program a full page before reading a status register. The SST chip doesn't require you to program pages, but you can only program 2 bytes at once. Reading the status that often was adding a lot of overhead. I changed the code to simply wait the 10u seconds required for a write and move on and so far it looks good. I'm knocking on wood though, hopefully this works for everyone and not just my machine.

Will post an updated papilio loader app tomorrow.

Jack.

Link to comment
Share on other sites

  • 5 months later...

Using a 57 600 bauds connection (I couldn't get it to work at 115 200), it takes 1'40" to upload the 180kB xsvf file to program a Xilinx 9572 CPLD. Not lightning fast, but not too bad.

Ben, this looks like great work; thanks for doing it. I have exactly the same motivations as you -- have XC9572XL, refuse to buy $50 cable -- but would like to solve the problem slightly differently. The hardware platform to do the bit-banging will be an Arduino, and the PC program driving the Arduino sketch will be written in Python, so it'll work out of the box on any desktop machine. Except for a YouTube video posted by someone who hasn't shared his code, I am not aware of anyone else pursuing this lowest-common-denominator approach to playing XSVF.

I'll report my progress as it happens.

Link to comment
Share on other sites

The hardware platform to do the bit-banging will be an Arduino, and the PC program driving the Arduino sketch will be written in Python, so it'll work out of the box on any desktop machine.

Nice. I guess you can reuse the avr part with no or little changes.

And I'll sure enjoy a reasonable client, at last : c was both overkill and cumbersome...

Link to comment
Share on other sites

Made a lot of progress last night, Ben. With moderate changes your AVR code mostly works as an Arduino sketch (changing pin assignments, messing around with the delay functions, and ripping out the Serial debug statements before discovering they were fairly essential and then putting them all back in again).

The client requires a little more work, at least on OSX. I had to switch to a nonblocking file descriptor, or else it hangs on the open() function. So this is requiring some rearchitecting of the main loop. But I haven't seen anything other than a small matter of debugging that stands between here and a working version.

After I have your C code working, I'll port the client to Python, and then we'll have a nice clean implementation that should work on virtually any desktop platform and a very widely available device platform.

Link to comment
Share on other sites

Still cranking away. I can see evidence of a lot of hard work in your code to get this finicky protocol working on the Papilio. After reading XAPP058 a few dozen times, I'm starting to understand it. This weekend I plan to get back to basics and follow the building-block tests in the "ports_c_waittime_calibration" directory that I enjoyed pretending didn't exist. I can now see how helpful those test cases will be.

Link to comment
Share on other sites

Nice. I guess you can reuse the avr part with no or little changes.

And I'll sure enjoy a reasonable client, at last : c was both overkill and cumbersome...

I'm going down exactly the same path you did -- starting with a Python client and running into trouble with the serial port. At the moment (see what I have here) it'll successfully read the DeviceID off a JTAG device (tested only with an XC9572XL breakout board from DP), but it chokes if I try to send anything more substantial. The choking is desktop-to-Arduino communication; I haven't even finished implementing all the JTAG commands yet.

I also have trouble with the Arduino-to-target communication; frequently the XSDRTDO command shifts in all FFs, requiring a successful retry. I know the protocol allows for this, but it shouldn't flake on a Device ID get command.

Anyway, fire up your Arduino and see The JTAG Whisperer speak JTAG to a CPLD!

Link to comment
Share on other sites

The choking is desktop-to-Arduino communication; I haven't even finished implementing all the JTAG commands yet.

You might be interested in my SerPro library.

https://github.com/alvieboy/arduino-serpro/tree/v3

Although it requires C++ on PC side. Although you can implement the protocol in any language (Java was once supported)

And yes, I did implement a JTAG programmer once using SerPro. :)

Álvaro

Link to comment
Share on other sites

Thanks, Álvaro. I seem to have worked out the bugs with the serial communication, and it's now quite reliable. There were two problems: (1) leftover junk from the previous session in the serial buffer, and (2) the Arduino appears to have absolutely no flow control. So I implemented my own ring buffer, and the device now requests a packet of data when it reaches the end of the buffer, rather than the desktop pushing it all to the device and hoping that flow control takes care of it.

Link to comment
Share on other sites

The JTAG Whisperer is looking better, but it still chokes on a certain 'fpga'-mode value in my test file. I fixed some silly bugs, examined the code carefully, and now like any good (lazy) software engineer am starting to suspect the hardware. I wonder whether I've fried my '9572. I'm going to try to find a friend with a v3 Bus Pirate, and if I can program the CPLD with that, then I'll return to bug-hunting.

If anyone reading has an Arduino and a '9572, please report whether it works for you.

Link to comment
Share on other sites

The project is ready for action! It has a simple Python script that sends XSVFs from the desktop to your Arduino (or Papilio-based Arduino compatible environment), and the Arduino executes the script, sending the JTAG commands over pins 8-11. I've tested several times with the single XC9572XL breakout board that I have, so it's hardly battle-hardened, but it oughta work elsewhere. By the way, the reason it wasn't working as early as Saturday was that I had my CPLD hooked up to 5 volts instead of the required 3.3. Doh.

Thanks again to Ben for his initial project, and particularly for his concise, economical state-transition logic that I haven't seen in any other XSVF/JTAG code on the web. Cool stuff, good engineering.

Link to comment
Share on other sites

The project is ready for action! It has a simple Python script that sends XSVFs from the desktop to your Arduino (or Papilio-based Arduino compatible environment), and the Arduino executes the script, sending the JTAG commands over pins 8-11.

Thanks again to Ben for his initial project, and particularly for his concise, economical state-transition logic that I haven't seen in any other XSVF/JTAG code on the web. Cool stuff, good engineering.

Great. Reading your code, I can't see what I was doing wrong with pyserial... must have been something stupid, really.

And I'm glad you enjoyed the state-transition logic :)

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.