Forum Discussion
Altera_Forum
Honored Contributor
20 years agoSPI for nios
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 ...
Altera_Forum
Honored Contributor
20 years agoHi,
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. 'base' should * be the base address of your SPI peripheral, while 'slave' 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; }