Forum Discussion
Altera_Forum
Honored Contributor
14 years agoSPI Problems
Hi,
I'm trying to get handle with the SPI on a Nios II Core but I don't get it. I have a SPI master and a SPI Slave that I can try to transmit some data from the master to the slave. I connected them with the "loopback board". My Code is://Write some data to the Slave
IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(SPI_SLAVE_BASE,0x04);
//Check the TRDY bit if data is written(TRDY=0 means it is writing and
//TRDY=1 again means the data was written)
trdyNumber=(IORD_ALTERA_AVALON_SPI_STATUS(SPI_SLAVE_BASE)& ALTERA_AVALON_SPI_STATUS_TRDY_MSK)>>6;
//Read from the register
int data=(IORD_ALTERA_AVALON_SPI_RXDATA(SPI_SLAVE_BASE)&0xFF);
printf("%d",data); I also read the manuel for the SPI Core but it doesn't work. Can somebody help my with an exsample or give me an advice? Regards22 Replies
- Altera_Forum
Honored Contributor
Your code contains several mistakes:
IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(SPI_SLAVE_BASE,0x04) This doesn't write data to the slave, but it selects (enables) slave whose address is 4 for receiving data SPI slave is not supposed to transmit data autonomously. It sends data upon reception of a master request. You both send and receive data on slave. I think you meant send with master and receive with slave. - Altera_Forum
Honored Contributor
First thanks!
And yes I want to send some data from Master to Slave but how? Thats what I don't understand precicely. May you can bring light in the dark. - Altera_Forum
Honored Contributor
The correct procedure is something like this:
// select slave (not required in single slave system) IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(master_base, n_slave); // assert CS IOWR_ALTERA_AVALON_SPI_CONTROL(master_base, ALTERA_AVALON_SPI_CONTROL_SSO_MSK); // wait tx channel ready do { status = IORD_ALTERA_AVALON_SPI_STATUS(master_base); } while (((status & ALTERA_AVALON_SPI_STATUS_TRDY_MSK) == 0) && (status & ALTERA_AVALON_SPI_STATUS_RRDY_MSK) == 0); // (optional) data possibly to be transmitted back from slave to master upon request IOWR_ALTERA_AVALON_SPI_TXDATA(slave_base, data_answer); // tx data IOWR_ALTERA_AVALON_SPI_TXDATA(master_base, data_tx); // this will initiate the transfer; in the same time the slave sends out on miso pin // the data ready in its tx register // Wait until the interface has finished transmitting do { status = IORD_ALTERA_AVALON_SPI_STATUS(master_base); } while ((status & ALTERA_AVALON_SPI_STATUS_TMT_MSK) == 0); // release CS IOWR_ALTERA_AVALON_SPI_CONTROL(master_base, 0); // read received data from slave data_rx = IORD_ALTERA_AVALON_SPI_RXDATA(slave_base); // data_rx must match data_tx // (optional) read answer from master recvd_answer = IORD_ALTERA_AVALON_SPI_RXDATA(master_base); // recvd_answer must match data_answer Please note that I wrote this code by heart. I'm not sure this it will compile without errors. - Altera_Forum
Honored Contributor
Thanks again!
I just tried your code and it is compileable but it doesen't work complitly correct. The Code looks like: --- Quote Start --- int status=0; int countTMT; // select slave (not required in single slave system) IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(SPI_MASTER_BASE, SPI_SLAVE_BASE); // assert CS IOWR_ALTERA_AVALON_SPI_CONTROL(SPI_MASTER_BASE, ALTERA_AVALON_SPI_CONTROL_SSO_MSK); // wait tx channel ready do { status = IORD_ALTERA_AVALON_SPI_STATUS(SPI_MASTER_BASE); } while (((status & ALTERA_AVALON_SPI_STATUS_TRDY_MSK) == 0) && (status & ALTERA_AVALON_SPI_STATUS_RRDY_MSK) == 0); // (optional) data possibly to be transmitted back from slave to master upon request IOWR_ALTERA_AVALON_SPI_TXDATA(SPI_SLAVE_BASE, 0x01); // tx data IOWR_ALTERA_AVALON_SPI_TXDATA(SPI_MASTER_BASE, 0x10); // this will initiate the transfer; in the same time the slave sends out on miso pin // the data ready in its tx register // Wait until the interface has finished transmitting do{ status = IORD_ALTERA_AVALON_SPI_STATUS(SPI_MASTER_BASE); IOWR_ALTERA_AVALON_PIO_DATA(LED_PIO_BASE,countTMT & 0x01); usleep(50000); countTMT++; } while((status & ALTERA_AVALON_SPI_STATUS_TMT_MSK) == 0); // release CS IOWR_ALTERA_AVALON_SPI_CONTROL(SPI_MASTER_BASE, 0); // read received data from slave int data_rx = IORD_ALTERA_AVALON_SPI_RXDATA(SPI_SLAVE_BASE); // data_rx must match data_tx printf("Daten aus dem Slave:%d\n",data_rx); // (optional) read answer from master int recvd_answer = IORD_ALTERA_AVALON_SPI_RXDATA(SPI_MASTER_BASE); // recvd_answer must match data_answer printf("Daten aus dem Master:%d\n",recvd_answer); --- Quote End --- The result is: --- Quote Start --- Daten aus dem Slave:0 Daten aus dem Master:0 --- Quote End --- I don't understand why it doesn't work because it should. Maybe you can help me one more time. Thanks for your helt! Regards - Altera_Forum
Honored Contributor
I presume you already checked the loopback connections:
- mosi output from master connected to mosi input pin to slave - miso output from slave connected to miso input to master - sclk from master feeds sclk slave input - slave select output from master drives ss input pin on slave What's your master sclk frequency? Can you test the mosi signal? Also check the status and control register on both master and slave, both before and after the execution of the above code. If you don't find anything wrong, post their values and I'll take a look. For similar spi example, you can also refer to the alt_avalon_spi_command() function in HAL driver library. - Altera_Forum
Honored Contributor
Hi chris 72,
thanks for your support! I tried what you`ve told me and also control the pin assignment for the loopback board. For this I used the loopback_test_lowcost.pdf from Altera. My assignment looks like it is benife: spi_master_MISO,Input,PIN_Y4 spi_master_MOSI,Output,PIN_R6 spi_master_SCLK,Output,PIN_R7 spi_master_SS_n,Output,PIN_V3 spi_slave_MISO,Output,PIN_V4 spi_slave_MOSI,Input,PIN_AB1 spi_slave_SCLK,Input,PIN_AB2 spi_slave_SS_n,Input,PIN_Y3 I also tested to connect the MOSI of the Master to a LED on the board but I can't see anything. Maybe it is because of the frequency:). The frequency of my system is 50MHZ and the frequency for the SPI is 128kHZ. could this be a problem? I also looked through the Controlregs and the Statusregs of the Spi: Befor transmitting data: Statusregister of the Master: 0x260.(1001100000) Controlregister of the Master: 0x400.(10000000000) Statusregister of the Slave: 0x310.(1100010000) Controlregister of the Slave: 0x0(0) After transmitting and reading data: Statusregister of the Master: 0x260.(1001100000) Controlregister of the Master: 0x0.(0) Statusregister of the Slave: 0x310.(1100010000) Controlregister of the Slave: 0x0.(0) I thank you in advance for your help! - Altera_Forum
Honored Contributor
I don't know about your board schematics, so I can't check your signal to pin connections.
Routing mosi signal to a LED is useless: you would never be able to see it (or maybe are you kind of guy sensitive to kryptonite? are you? :D) You must use an oscilloscope to test it. If you do, test especially the sclk signal. If you can't afford an oscilloscope, you can SignalTap the design. Focus on sclk and ss signals, not on mosi. SPI registers seems to indicate that the master has correctly transmitted data, but the slave has received nothing. Moreover, slave status shows an overrun error. This is usually due to a missing sclk or unasserted ss on slave side. Writing anything to slave status register should clear the overrun error. Clear it and verify if your spi command code set this error again. - Altera_Forum
Honored Contributor
Unfortunately I'm not sensitive to kryptonite;-)
I tried like you told to use the SignalTap II but it didn't work. The triggering didn't appear. So I tried to read and write the registers by my on. I started my code with writing in the statusreg of the master and the slave and i recognized that I'm not bale to write data in the slave statusreg. Why? Maybe you can help my. You also said that the overrun error accure because of missing sclk, could this be related with a false pin assignment? Do I need to turn on something on the cyclon III developement board if I useing the HSMCA port? Thanks in advance! - Altera_Forum
Honored Contributor
Hi,
I tried the SignalTap II again whith some other adjustmens and it worked. It is shown in the diagram that the data transmission from the master is ok but how to understand the spi_master_SS_n signal i don't understand exactly. Now my question is how could it be that the data is transmitted correct but can't be read correct? Could it be that it is something wrong with the slave or its pin assignment? Thanks in advance! - Altera_Forum
Honored Contributor
--- Quote Start --- Unfortunately I'm not sensitive to kryptonite;-) I started my code with writing in the statusreg of the master and the slave and i recognized that I'm not bale to write data in the slave statusreg. Why? --- Quote End --- You are not supposed to write to the status reg and read back data. The write command is fake and is only used to instruct the spi core to reset the error bits, as stated in the spi datasheet, page 7-11.