Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
20 years ago

SPI 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 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>

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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;

    }
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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;

    }
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Edwin,

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

    cheers,

    Danny