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. '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;
}