Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
20688 Discussions

Problem with SPI (Cyclone II)

Altera_Forum
Honored Contributor II
1,751 Views

Hello, 

 

It is my first message in the forum but I tend to visit it when I have problems in my designs. I always get good information in this forum but in this case, I haven't been able to solve my problem. I don't have a great deal of experience using altera devices and my doubt might be a little simple.  

 

I am using the SPI core of SOPC Builder in the NIOS II EDS. Particularly, I am doing a communication using SPI between a cyclone II FPGA and a flash SPI memory. I have checked clock polarity, clock pahse and data direction are suitable for the memory and I have defined a 8bits width data. The communication is very easy: firstly I send the write enable, then I write 0xAA in the address memory 0x0000F0 and finally I read and display it in a LED's array. In my first attempt I used the function... 

 

int alt_avalon_spi_command(alt_u32 base, alt_u32 slave, 

alt_u32 write_length, const alt_u8 * write_data, 

alt_u32 read_length, alt_u8 * read_data, 

alt_u32 flags); 

 

and the program was ok, so the system definition is ok. However, now I want/need to develop my own driver to use a SPI communication but my attemps end up in failure. I don't know which the mistake is and I will be completely grateful if anyone can give me any tip about my problem. 

 

Many thanks! 

 

My code is (it is a little long but it is very easy to understand): 

# include "system.h"# include "altera_avalon_pio_regs.h" //iord & iowr led's# include "altera_avalon_spi_regs.h" //definition of status spi# include "altera_avalon_spi.h" //alt_avalon_spi_command# include "unistd.h" //sleep/usleep# include "os_cpu.h" //definition of int8u type 

 

int main(void){ 

 

int8u wdata,slave=0x01,write_en=0x06,page_program=0x02,read_mem=0x03,led_val=0x55; 

 

// initial state led's (01010101) 

iowr_altera_avalon_pio_data(led_base,led_val); 

usleep(1000000); 

 

// select slave  

iowr_altera_avalon_spi_slave_sel(spi_base,slave); 

 

// clean receiver buffer  

iord_altera_avalon_spi_rxdata(spi_base); 

 

////////////////////// write enable ////////////////////// 

// enable chip select selected slave 

iowr_altera_avalon_spi_control(spi_base,altera_avalon_spi_control_sso_msk); 

wdata=write_en; 

// wait until spi bus is empty to transmit 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

// wait until data has been sent 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

// disable chip select of selected slave 

iowr_altera_avalon_spi_control(spi_base,0x00); 

 

 

////////// write byte 0xaa in address memory 0x0000f0 ////////// 

// enable chip select selected slave 

iowr_altera_avalon_spi_control(spi_base,altera_avalon_spi_control_sso_msk); 

wdata=page_program; 

// wait until spi bus is empty to transmit 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

// wait until data has been sent 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

wdata=0x00; 

// wait until spi bus is empty to transmit 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

// wait until data has been sent 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

wdata=0x00; 

// wait until spi bus is empty to transmit 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

// wait until data has been sent 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

wdata=0xf0; 

// wait until spi bus is empty to transmit 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

// wait until data has been sent 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

wdata=0xaa; 

// wait until spi bus is empty to transmit 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

// disable chip select of selected slave 

iowr_altera_avalon_spi_control(spi_base,0x00); 

 

 

///////// read address memory 0x0000f0///////// 

iowr_altera_avalon_spi_control(spi_base,altera_avalon_spi_control_sso_msk); 

// realizo la comunicación 

wdata=read_mem; 

// wait until spi bus is empty to transmit 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

// wait until data has been sent 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

wdata=0x00; 

// wait until spi bus is empty to transmit 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

// wait until data has been sent 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

wdata=0x00; 

// wait until spi bus is empty to transmit 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

// wait until data has been sent 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

wdata=0xf0; 

// wait until spi bus is empty 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

// wait until data has been sent 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

// wait until spi bus is empty to receive 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_rrdy_msk)==0); 

// read data from spi bus 

led_val=iord_altera_avalon_spi_rxdata(spi_base); 

 

// disable chip select of selected slave 

iowr_altera_avalon_spi_control(spi_base,0x00); 

 

// display data of memory address 0x0000f0 in led's  

// if everything was ok, it is supposed to be 10101010 

iowr_altera_avalon_pio_data(led_base,led_val); 

 

return(0);  

 

0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
651 Views

Does it freeze somewhere or does it execute all the code? 

I suggest to put some signaltap probes on the SPI signals and check the differences on the resulting signals when you use your version and the driver. It will help you find where the difference comes from.
0 Kudos
Altera_Forum
Honored Contributor II
651 Views

Hello, 

 

First of all, many thanks for your reply Daixiwen and I am sorry for my delay to answer. 

 

I have got an oscilloscope and could see the spi signals. The mistake must make in this reception part of my code. This part is: 

 

// last byte of spi memory address 

 

// wait to transmit  

wdata=0xf0; 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

 

// send data 

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

 

////////////// wait the end of transmission ////////////// 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

// wait to receive  

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_rrdy_msk)==0); 

 

// clean data  

iord_altera_avalon_spi_rxdata(spi_base);  

iowr_altera_avalon_spi_status(spi_base,0x00); 

 

////// dummy bite to read the spi memory ifnormation  

 

// wait to transmit  

wdata=0x00;  

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_trdy_msk)==0); 

 

// send data  

iowr_altera_avalon_spi_txdata(spi_base,wdata); 

 

// wait the end of transmission 

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_tmt_msk)==0); 

 

// wait to receive  

while ((iord_altera_avalon_spi_status(spi_base) & altera_avalon_spi_status_rrdy_msk)==0); 

 

// read data  

led_val=iord_altera_avalon_spi_rxdata(spi_base);  

iowr_altera_avalon_spi_status(spi_base,0x00); 

 

//disable cs  

iowr_altera_avalon_spi_control(spi_base,~altera_avalon_spi_control_sso_msk); 

usleep(25); 

 

// display data 

iowr_altera_avalon_pio_data(led_base,led_val); 

 

The problem is when I send to the spi memory the last byte of the address which I want to read (emphasized in bold). The MOSI signal appears in the oscilloscopi such as I expected. By contrast, the MISO signal is not working when the spi memory, in principle, is sending the data of the desired address (0x0000F0). I have already checked the hardware connection several time, so I think the mistake must be by software. 

 

I would be very grateful if anyone could give a piece of advice about my problem.  

 

Many thanks,
0 Kudos
Altera_Forum
Honored Contributor II
651 Views

But it does work with the standard driver, doesn't it? Are you sure all the signals are the same between the two runs? Check especially the timing between the clock signal and the chip select and MOSI.

0 Kudos
Altera_Forum
Honored Contributor II
651 Views

First of all, thank you for your reply. 

 

The code works well, the problem was that the spi memory was not working... It is natural my driver did not receive anything. I used other device and everything worked perfect.  

 

Anyway, thank you for your interest to help me :o
0 Kudos
Altera_Forum
Honored Contributor II
651 Views

 

--- Quote Start ---  

First of all, thank you for your reply. 

 

The code works well, the problem was that the spi memory was not working... It is natural my driver did not receive anything. I used other device and everything worked perfect.  

 

Anyway, thank you for your interest to help me :o 

--- Quote End ---  

 

 

Can you share your original implementation when you used the alt_avalon_spi_command function? There isn't a lot of help on how to use this function properly. Thanks in advance.
0 Kudos
Reply