- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Has anybody used the SPI core as a slave device in a NIOS II implementation? If so, have you had relatively frequent data errors?
There is no HAL for the SPI as slave, so I'm just using the IORD... and IOWR... macros defined in altera_avalon_spi_regs.h. I've tried both polling and ISR implementations, yet I keep getting data errors. I originally suspected noise on the SCLK or MOSI lines, but they look golden -- no glitches. Example: the SPI master sends 3 bytes -- 0xF1, 0x41, 0xF6. Most times, that's what I get, but over 10% of the time (!) I see examples such as: 0xF1 0x20 0xF6, or 0xF1 0xA8 0x81 0xF6 (and there are only 3 bytes sent, looking at the SCLK and MOSI lines), or 0xF1 0x41 0xBD. Here's my interrupt handler (the protocol stuff isn't relevant): void SpiSlave::InterruptHandler(void) { U_INT32 irq_flag_reg; U_INT32 irq_mask_reg; U_BYTE RxChar; static U_BYTE GotHeader = FALSE; IsrCount++; // read register to determine which flags are set irq_flag_reg = IORD_ALTERA_AVALON_SPI_STATUS(BaseAddress); // read the interrupt mask register irq_mask_reg = IORD_ALTERA_AVALON_SPI_CONTROL(BaseAddress); while (irq_flag_reg &= irq_mask_reg) { // Check for Rxed character if (irq_flag_reg & ALTERA_AVALON_SPI_STATUS_RRDY_MSK) { RxIsrCount++; if (RxMsgSize >= SPI_SLAVE_RX_BUFFER_SIZE) { // buffer overflow // queue an event RxMsgSize = 0; GotHeader = FALSE; } RxChar = IORD_ALTERA_AVALON_SPI_RXDATA(BaseAddress); if (GotHeader) { RxDataBuffer[RxMsgSize++] = RxChar; // store char in temp buffer if (RxChar == (U_BYTE)0xF6) { // ETX char received GotHeader = 0; DisableInterrupt(ALTERA_AVALON_SPI_CONTROL_ITRDY_MSK); // no more TRDY if (NewMsgRxed) { // app hasn't processed the last msg yet! // queue event } else { // ready to give msg to application // copy data to app buffer while (RxMsgSize--) { AppRxBuffer[RxMsgSize] = RxDataBuffer[RxMsgSize]; } NewMsgRxed = TRUE; RxMsgSize = 0; } } // end if ETX else { // not ETX if (RxChar > (U_BYTE)0xF0) { // unexpected header // start msg all over, beginning with the new header // note that GotHeader is already TRUE RxMsgSize = 0; RxDataBuffer[RxMsgSize++] = RxChar; } // end if unexpected header } // end if not ETX } // end if GotHeader else if ((RxChar > (U_BYTE)0xF0) && (RxChar != (U_BYTE)0xF6)) { // Header rxed GotHeader = TRUE; RxMsgSize = 0; RxDataBuffer[RxMsgSize++] = RxChar; } } // end if Rx Rdy interrupt if (irq_flag_reg & ALTERA_AVALON_SPI_STATUS_TRDY_MSK) { TxIsrCount++; if ((BytesToSend) && (TxData)) { // data to tx IOWR_ALTERA_AVALON_SPI_TXDATA(BaseAddress, *TxData++); BytesToSend--; } else { // nothing more to send, so disable ints to avoid infinite ints DisableInterrupt(ALTERA_AVALON_SPI_CONTROL_ITRDY_MSK); } } if (irq_flag_reg & ALTERA_AVALON_SPI_STATUS_ROE_MSK) { // Rx overrun error -- queue event? } if (irq_flag_reg & ALTERA_AVALON_SPI_STATUS_TOE_MSK) { // Tx overrun error -- queue event? } // re-read register to determine which flags are set irq_flag_reg = IORD_ALTERA_AVALON_SPI_STATUS(BaseAddress); // Clear status bits by writing anything to the status register //IOWR_ALTERA_AVALON_SPI_STATUS(BaseAddress, 0); // read the interrupt mask register irq_mask_reg = IORD_ALTERA_AVALON_SPI_CONTROL(BaseAddress); } // end while } // end SpiSlave::InterruptHandler()Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
What version of the tools and speeds (Avalon clock and sclk) are you using?
Enhancements to the SPI component have reduced the maximum speed of the SPI slave device (so don't run it at speeds up to half the Avalon clock rate anymore). I do not recommend exceeding 1/10th the Avalon speed. Also I didn't look at the code but in case you were not aware, this is important: If the SPI slave is selected and it has not readied it's TX register, when data is recieved (via RX) it will be looped around and sent back through the TX signal (SPI is fully duplex so it has to send something back).- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm using Quartus II v5.0 Build 168, NIOS II v5.0 Build 73c. The clock speed is 65 MHz, and the SCLK is currently about 1MHz, though we've tried a range from about 44 KHz to about 2 MHz, with no difference in results.
I've found that if I have never loaded the TX register, the master reads back 0xFF, and that if I have loaded it with some byte, that same byte will be read out until I re-load the TX register. Thanks for the interest. You've gotten the SPI slave to work reliably? I haven't seen anything on this or the Altera forums about anybody using the SPI core as a slave. Everybody's always talking about it as a master. I have no problems at all with my SPI master, which makes this seem kinda weird.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Doug,
I have the same issues submitted to Altera's "MySupport". In addition to what Doug has stated, the Status register error bits also do not clear after a write operation, like they are supposed to. Does anyone know why Altera provides a Master SPI driver but not a slave one? Granted, it's not that hard to implement, but nonetheless it would seem that if they had actually written a driver, these things would have fallen out during test and verification...??? John- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Email me if you are not up and running and I can give you some code I made for a slave device (it's not interupt based but it may point out what's failing in your design).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Any news here?
I'm experiencing similar problems. My Cyclone III is configured as Slave another controller as Master. For testing I set up the master to send 0x5555 and the slave to send 0xffff all the time. As I did not receive the right values in both direction I took a look at the bus. You may want to have a look at the screenshots: yellow - clock green - slave select blue - MOSI red - MISO The data the code of the master shows are exactly the same I can see on an oscilloscope. So there cant be a problem on masters side. The data I want to send from slave's side varies on the bus (as shown on the screenshots). And the data I receive on slave's side seems to be totally random. I've never received valid data in slave. I've not tried yet to interchange master-slave to see if this is caused by a faulty slave driver. I anyway prefer it to have it the way it is and to solve the problems. Any hints are appreciated. Kind Regards.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Just testet to switch master and slave.
The FPGA is working flawless as master. I only have problems if I use it as slave. Any idea how to solve the slave bug?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Are you using a recent (V9.0 or V9.1) sopc IP? There have been changes to the SPI slave code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm using Quartus II V9.1.
IP-Details: SPI (3 Wire Serial) Class: altera_avalon_spi Version: 9.1- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Recently upgraded to 91sp1 but still the same. As master everthing is flawless as slave everthing seems to be random.
I just noticed that the signal from slave also toggles sometimes at the wrong clock edges. On the screenshot: yellow:clock blue: slave select green: MISO (here is the problem) red: MOSI The settings ( Clock Polarity and Clock Phase ) in SOPC-Builder are both set to 1. So the data should only toggle on negative clock edges. Does anyone of you got the SPI Slave running without errors? Perhaps someone can send me his code?! Thanks.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I use the SOPC-Builder to build my project. You can find that module in the SOPC-Builder Library under "Interface Protocols" -> "Serial" -> "SPI (3 Wire Serial)".
Or, you may find it in your install directory: <root>/altera/<version>/ip/altera/sopc_builder_ip/altera_avalon_spi/- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Not the SPI (as in Serial Periperal Interface), I wrote SP1 (as in QII 9.1 Service Pack1). Where did you get it from ?
Update: Nevermind, I found it now. It was not announced in the front page as I expected it to be.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ah, I missunderstood this.
Go to altera.com --> "Products" --> "Design Software" --> on the right side "Download Software" There you can choose to download the latest Version of QuartusII. It includes this SP1. I think there is no small SP1 installer, you need to install the whole QuartusII.- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
SOPC bilder generates, as seems, wrong verilog code for SPI slave, at SS_n rise edge rx register shifted one more time, and ROE bit is set to 1. To avoid this, you should read RX register before SS_n rise edge or delay SS_n edge, if it possible.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
--- Quote Start --- SOPC bilder generates, as seems, wrong verilog code for SPI slave, at SS_n rise edge rx register shifted one more time, and ROE bit is set to 1. To avoid this, you should read RX register before SS_n rise edge or delay SS_n edge, if it possible. --- Quote End --- Could you elaborate on this? Also, is Altera going to fix this bug?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe I found the solution to this problem. I had my SPI slave running from a 40MHz source. The data rate I was using was <1MHz. I found that the lower data rate I would run my master at, the worse these errors became. I changed my SPI slave to run at a 1MHz rate. The errors went away. So it seems that your SPI slave clock should be close to the data rate you intend to run at. I'm not sure how close it has to be or what the upper limit on the SPI slaves data rate is.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, you said if the clock rate over 1MHz the transmission error went away. I tried it, and it had a little effect, the errors reduced ,but sometimes it still came. Would you please provide some code for the slave and master program ?I just want to implement transmitting 32bit data from master side to slave one and then read back. I have paste some of my code and post it, the link is alteraforum.com/forum/showthread.php?t=36274
Thanks a lot!:)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page