Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

SPI for nios

Altera_Forum
Honored Contributor II
2,878 Views

dear every1,  

i've been stuck with trying to tranfer data out the spi..i just dont know how to use it.i wanna use the alt_avalon_spi_command() but i just cant do it.i'm stuck witthe basic codes of writing it.  

if possible..i just wanna send a 8 bit data out the MISO .. the SCLK pin shows no sign of live at all..  

basically.. i want to transmit a 8 bit data so that a running led light can be dispalyed witt an external protoboard using a shift register. 

If any1 has or can guide me thru this simple program in .c, i would really appriciate it.. 

sincerely, help is needed and fast.. http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/sad.gif  

P/S i dont seem to hv the <altera_avalon_spi.h> and <altera_avalon_spi.h>
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
1,373 Views

Hi edwin, 

 

the main problem, which I encountered with SPI is the SPI enable. Sometimes when trying to send data it goes high or low. Sow it is best to use a dedicated enable PIO for SPI enable. This way it is possible to control it by yourself. It is difficult when you don&#39;t have altera_avalon_spi.h, but you&#39;ve got the control registers I think. Added to this message is my SPI-code, which I rewrote. It is better to use I think http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/smile.gif . Good luck with it.... When you&#39;ve got any questions feel free to ask... 

 

Cheers, 

 

Danny 

# define TMT (1 << 5) //Transmitter shift-register empty# define TRDY (1 << 6) //Transmitter ready# define RRDY (1 << 7) //Receiver ready# define spi_base SPI_0_BASE //Define SPI_base, less typing# define spi_cs SPI_0_CS_BASE //Define SPI_base, less typing 

 

 

void spi_send(alt_u32 base, 

const alt_u8 regBit,  

const alt_u8 subRegBit) 

 

IOWR_ALTERA_AVALON_SPI_CONTROL(base, 0x00); //Clear status register with zero&#39;s 

while(~IORD_ALTERA_AVALON_SPI_STATUS(base) & TRDY); //check if tx data register is empty. If not, keep looping until it is 

IOWR_ALTERA_AVALON_PIO_DATA(spi_cs, 0); //use this SPI-select, the one delivered by Altera doesn&#39;t work!!! 

IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(base, 0x01); //slave select mask enable, slave selection device 0 

IOWR_ALTERA_AVALON_SPI_TXDATA(base, dummyBit); //write dummyBit to tx-buffer, so sending is possible 

usleep(10); //Sleep for 10 useconds. Needed, otherwise SDI2RGB-board will NOT receive any commands 

IOWR_ALTERA_AVALON_SPI_TXDATA(base, regBit); //write to tx-buffer 

IOWR_ALTERA_AVALON_SPI_TXDATA(base, subRegBit); //write to tx-buffer 

while(~IORD_ALTERA_AVALON_SPI_STATUS(base) & RRDY); //check if receiver is ready 

while(~IORD_ALTERA_AVALON_SPI_STATUS(base) & TMT); //check if transmitter shift register is empty 

IOWR_ALTERA_AVALON_PIO_DATA(spi_cs, 1); //use this SPI-select, the one delivered by Altera doesn&#39;t work!!! 

 

 

/* 

* Start of SPI_receive function, 1 parameter is given: 

*  

* Base 

*/ 

 

alt_u8 spi_receive(alt_u32 base) 

alt_u8 data; //Variable for SPI data to be stored in 

IOWR_ALTERA_AVALON_PIO_DATA(spi_cs, 0); //use this SPI-select, the one delivered by Altera doesn&#39;t work!!! 

while(~IORD_ALTERA_AVALON_SPI_STATUS(base) & TRDY); //check if tx data register is empty. If not, keep looping until it is 

while(~IORD_ALTERA_AVALON_SPI_STATUS(base) & TMT); //check if transmitter shift register is empty 

while(~IORD_ALTERA_AVALON_SPI_STATUS(base) & RRDY); //check if receiver is ready 

data = 10; //variable for test-purpose 

IOWR_ALTERA_AVALON_SPI_RXDATA(base, data); //read from RX-register  

IOWR_ALTERA_AVALON_PIO_DATA(spi_cs, 1); //use this SPI-select, the one delivered by Altera doesn&#39;t work!!!  

return data; 

 

}
0 Kudos
Altera_Forum
Honored Contributor II
1,373 Views

firstly.. is there any difference with the nios and niosii coding.. 

is the c coding suppose to be different ?? 

well.. i&#39;m not sure if i&#39;m doing it wrong..  

basically i&#39;m using the nios sdk to compiler the c code(nios-build). 

the changes i made was # define base 00x004A0 //Define SPI_base, less typing# define spi_cs 00x00470 //Define SPI_base, less typing 

 

btw, am i suppose to declare the dummybit,regbit,subregbit? 

and i&#39;m new here.. so is the alt_32 or alt_8* portion of the code ment to be left alone , or changes need to be made.. i kinda dont understand the function of that... 

 

P/S can any1 attach or just copy paste the <altera_avalon_spi.c> and <altera_avalon_spi.h>..i dont know why i dont hv it in my nios installer.. 

i would like to see the content of it...i can hardly imagine how to use the alt_avalon_spi_command() 

thanks..urgent reply is gratefully appriciated..the deadline is killing me..http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/sad.gif  

eddie
0 Kudos
Altera_Forum
Honored Contributor II
1,373 Views

Hi, 

 

here is the code 

 

# include <stddef.h> 

# include "alt_types.h" 

 

/* 

* Macros used by alt_sys_init 

*/ 

# define ALTERA_AVALON_SPI_INSTANCE(name, device) extern int alt_no_storage# define ALTERA_AVALON_SPI_INIT(name, device) while (0) 

 

/* 

* Use this function to perform one SPI access on your target. &#39;base&#39; should 

* be the base address of your SPI peripheral, while &#39;slave&#39; indicates which 

* bit in the slave select register should be set. 

*/ 

 

/* If you need to make multiple accesses to the same slave then you should  

* set the merge bit in the flags for all of them except the first. 

*/# define ALT_AVALON_SPI_COMMAND_MERGE (0x01) 

 

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); 

# endif /* __ALT_AVALON_SPI_H__ */ 

 

 

# include "alt_types.h" 

# include "altera_avalon_spi_regs.h"# include "altera_avalon_spi.h" 

 

/* This is a very simple routine which performs one SPI master transaction. 

* It would be possible to implement a more efficient version using interrupts 

* and sleeping threads but this is probably not worthwhile initially. 

*/ 

 

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) 

const alt_u8 * write_end = write_data + write_length; 

alt_u8 * read_end = read_data + read_length; 

 

alt_u32 write_zeros = read_length; 

alt_u32 read_ignore = write_length; 

alt_u32 status; 

 

/* We must not send more than two bytes to the target before it has 

* returned any as otherwise it will overflow. */ 

/* Unfortunately the hardware does not seem to work with credits > 1, 

* leave it at 1 for now. */ 

alt_32 credits = 1; 

 

/* Warning: this function is not currently safe if called in a multi-threaded 

* environment, something above must perform locking to make it safe if more 

* than one thread intends to use it. 

*/ 

 

IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(base, 1 << slave); 

 

/* Set the SSO bit (force chipselect) */ 

IOWR_ALTERA_AVALON_SPI_CONTROL(base, ALTERA_AVALON_SPI_CONTROL_SSO_MSK); 

 

/* Keep clocking until all the data has been processed. */ 

for ( ; ; ) 

do 

status = IORD_ALTERA_AVALON_SPI_STATUS(base); 

while (((status & ALTERA_AVALON_SPI_STATUS_TRDY_MSK) == 0 || credits == 0) && 

(status & ALTERA_AVALON_SPI_STATUS_RRDY_MSK) == 0); 

 

if ((status & ALTERA_AVALON_SPI_STATUS_TRDY_MSK) != 0 && credits > 0) 

credits--; 

 

if (write_data < write_end) 

IOWR_ALTERA_AVALON_SPI_TXDATA(base, *write_data++); 

else if (write_zeros > 0) 

write_zeros--; 

IOWR_ALTERA_AVALON_SPI_TXDATA(base, 0); 

else 

credits = -1024; 

}; 

 

if ((status & ALTERA_AVALON_SPI_STATUS_RRDY_MSK) != 0) 

alt_u32 rxdata = IORD_ALTERA_AVALON_SPI_RXDATA(base); 

 

if (read_ignore > 0) 

read_ignore--; 

else 

*read_data++ = (alt_u8)rxdata; 

credits++; 

 

if (read_ignore == 0 && read_data == read_end) 

break; 

 

/* Wait until the interface has finished transmitting */ 

do 

status = IORD_ALTERA_AVALON_SPI_STATUS(base); 

while ((status & ALTERA_AVALON_SPI_STATUS_TMT_MSK) == 0); 

 

/* Clear SSO (release chipselect) unless the caller is going to 

* keep using this chip 

*/ 

if ((flags & ALT_AVALON_SPI_COMMAND_MERGE) == 0) 

IOWR_ALTERA_AVALON_SPI_CONTROL(base, 0); 

 

return read_length; 

}
0 Kudos
Altera_Forum
Honored Contributor II
1,373 Views

thanks for the altera_avalon_spi.c files.. 

if u dont mind can u copy paste the alt_types.h and altera_avalon__spi_regs.h files.. 

the thing is i&#39;m dealing with the nios1.. so the method of c programing is also rather different.. 

there&#39;s no usage of IOWR...etc.. 

currently i can understand the functions.. so if i can at least translate the programing method it would really help..trying to model the sequence of relevent events in the program..  

btw.. when i tried interfacing the fpga with and extenal hardware [74MH595 shift register]... the SCLK signal from the FPGA doesn&#39;t seem to generate a clockin signal..any comments.. and the MISO is always high.. i&#39;ve re-checked the pin assignment and no change.. i can only suspect the programin code has something to do wit it.... 

any issues or advise regarding the SPI core for nios(I) is gladly welcomed.. 

 

deeply thankful for any sharing, 

eddie http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/blink.gif
0 Kudos
Altera_Forum
Honored Contributor II
1,373 Views

Hi Edwin, 

 

some variables as dummybit etc was needed in my project... So just forget about those 

 

cheers, 

 

Danny
0 Kudos
Reply