Jump to content
  • 0

FPGA SPI transfer timed out



Hi all,

I'm having an issue with the FPGA SPI interface I programmed onto my microzed. The issue is that the interface cannot read the data sent back from my slave device! I'm using a SAMA5d3-xplained devboard, and an oscilloscope to measure signals. I made the SAMA return the same buffer it received, only with every byte shifted. So it's a semi-loopback routine. The oscilloscope captures both the correct signal back from the SAMA (every byte divided by 2), AND the signal going into it (out of the MicroZed). However, the spidev_test.c (that seemingly famous SPI testing utility on the torvalds repository (https://github.com/torvalds/linux/blob/master/tools/spi/spidev_test.c) program that I'm using shows one of two things:

1. Either the result is always an error of "SPI transfer timed out"

2. or the value in rx is the same as in tx. That is, even though the SAMA slave is demonstrably (via oscilloscope) returning something else, all the RX buffer gets is the same as was sent via the TX buffer. In fact, I can even disconnect the header that plugs the master to the slave, and this behavior becomes no different.

The difference between these two results is simply a matter of removing the 1050th line in drivers/spi/spi.c when building the kernel. It's the call to wait_for_completion_timeout() in the function static int spi_transfer_one_message(struct spi_controller *ctlr, struct spi_message *msg). What I get from this is basically that the spi-xilinx.c driver does not know where to look for the output from the slave (MISO), and it either waits eternally for that output (if the call to wait_for_completion is left intact) OR it doesn't care to look for the data and just fills the rx buffer with the tx buffer.

Now I have a very limited understanding of hardware and driver programming, so I'm basically like a blind man in the dark here. I'm adding printk() statements to spi-xilinx.c and spi.c everywhere, and checking their results with dmesg and there's just nothing enlightening (I'm using PetaLinux, and the devices all show up correctly in /dev and /sys). I'm hoping someone more experienced can shine a light on what I'm doing wrong here, or at least point me in the right direction.

Attached is my device tree file, plus a screenshot of the hardware design. (the relevant node in the DT is highlighted below)

amba_pl {
		#address-cells = <0x1>;
		#size-cells = <0x1>;
		compatible = "simple-bus";

		axi_quad_spi@41e00000 {
			bits-per-word = <0x8>;
			compatible = "xlnx,xps-spi-2.00.a";
			clock-names = "axi_clk", "spi_clk";
			clocks = <0x1 0xf>, <0x1 0xf>;
			fifo-size = <0x10>;
			interrupt-parent = <0x4>;
			interrupts = <0x0 0x1d 0x1>;
			num-cs = <0x1>;
			reg = <0x41e00000 0x10000>;
			xlnx,num-ss-bits = <0x1>;
			xlnx,spi-mode = <0x0>;

			spidev@0 {
				compatible = "spidev";
				reg = <0x0>;
				spi-max-frequency = <0x17d7840>;


digilent final hw design.png


Link to comment
Share on other sites

3 answers to this question

Recommended Posts

@morsucci I'm using Petalinux, yeah. The problem went away by (seemingly) magic, however, and brought another problem in its stead. I now can't set the SPI frequency via the ioctl() call. Currently working on that by digging into the spi-xilinx.c driver, putting up printk() calls everywhere. The only way I can calibrate frequency is via regenerating the design and exporting it to Petalinux via Vivado. And anything above 20MHz incurs in data loss. But I'll update the forum on anything I find!

Link to comment
Share on other sites


I may be totally wrong about this, but I think that if you are using Axi Quad Spi as your spi controller, the frequency will be locked at whatever you set it to in your Vivado design. That is, you wouldnt be able to change the frequency of the transfer from software or in Linux. 

Link to comment
Share on other sites


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

  • Create New...