SPI interface with Nios II
Please give me example code for Nios II of MAX10 FPGA for making SPI interface.
Nios II SPI (Master ) to be interfaced with slave devices.
I tried this example code in embedded peripheral user guide but it didn't work.
CODE:
/*
* "Small Hello World" example.
*
* This example prints 'Hello from Nios II' to the STDOUT stream. It runs on
* the Nios II 'standard', 'full_featured', 'fast', and 'low_cost' example
* designs. It requires a STDOUT device in your system's hardware.
*
* The purpose of this example is to demonstrate the smallest possible Hello
* World application, using the Nios II HAL library. The memory footprint
* of this hosted application is ~332 bytes by default using the standard
* reference design. For a more fully featured Hello World application
* example, see the example titled "Hello World".
*
* The memory footprint of this example has been reduced by making the
* following changes to the normal "Hello World" example.
* Check in the Nios II Software Developers Manual for a more complete
* description.
*
* In the SW Application project (small_hello_world):
*
* - In the C/C++ Build page
*
* - Set the Optimization Level to -Os
*
* In System Library project (small_hello_world_syslib):
* - In the C/C++ Build page
*
* - Set the Optimization Level to -Os
*
* - Define the preprocessor option ALT_NO_INSTRUCTION_EMULATION
* This removes software exception handling, which means that you cannot
* run code compiled for Nios II cpu with a hardware multiplier on a core
* without a the multiply unit. Check the Nios II Software Developers
* Manual for more details.
*
* - In the System Library page:
* - Set Periodic system timer and Timestamp timer to none
* This prevents the automatic inclusion of the timer driver.
*
* - Set Max file descriptors to 4
* This reduces the size of the file handle pool.
*
* - Check Main function does not exit
* - Uncheck Clean exit (flush buffers)
* This removes the unneeded call to exit when main returns, since it
* won't.
*
* - Check Don't use C++
* This builds without the C++ support code.
*
* - Check Small C library
* This uses a reduced functionality C library, which lacks
* support for buffering, file IO, floating point and getch(), etc.
* Check the Nios II Software Developers Manual for a complete list.
*
* - Check Reduced device drivers
* This uses reduced functionality drivers if they're available. For the
* standard design this means you get polled UART and JTAG UART drivers,
* no support for the LCD driver and you lose the ability to program
* CFI compliant flash devices.
*
* - Check Access device drivers directly
* This bypasses the device file system to access device drivers directly.
* This eliminates the space required for the device file system services.
* It also provides a HAL version of libc services that access the drivers
* directly, further reducing space. Only a limited number of libc
* functions are available in this configuration.
*
* - Use ALT versions of stdio routines:
*
* Function Description
* =============== =====================================
* alt_printf Only supports %s, %x, and %c ( < 1 Kbyte)
* alt_putstr Smaller overhead than puts with direct drivers
* Note this function doesn't add a newline.
* alt_putchar Smaller overhead than putchar with direct drivers
* alt_getchar Smaller overhead than getchar with direct drivers
*
*/
#include "alt_types.h"
#include "sys/alt_stdio.h"
#include "io.h"
#include "system.h"
#include "sys/alt_cache.h"
#include "altera_avalon_spi.h"
#include "altera_avalon_spi_regs.h"
#include "sys/alt_irq.h"
//This is the ISR that runs when the SPI Slave receives data
static void spi_rx_isr(void* isr_context){
alt_printf("ISR
//This resets the IRQ flag. Otherwise the IRQ will continuously run.
IOWR_ALTERA_AVALON_SPI_STATUS(SPI_SLAVE_BASE, 0x0);
}
int main()
{
alt_printf("Hello from Nios II!\n");
int return_code,ret;
char spi_command_string_tx[10] = "$HELLOABC*";
char spi_command_string_rx[10] = "$HELLOABC*";
//This registers the Slave IRQ with NIOS
ret = alt_ic_isr_register(SPI_SLAVE_IRQ_INTERRUPT_CONTROLLER_ID,SPI_SLAVE_IRQ,spi_rx_isr,(void *)spi_command_string_tx,0x0);
alt_printf("IRQ register return %x \n", ret);
//You need to enable the IRQ in the IP core control register as well.
IOWR_ALTERA_AVALON_SPI_CONTROL(SPI_SLAVE_BASE,ALTERA_AVALON_SPI_CONTROL_SSO_MSK | ALTERA_AVALON_SPI_CONTROL_IRRDY_MSK);
//Just calling the ISR to see if the function is OK.
spi_rx_isr(NULL);
return_code = alt_avalon_spi_command(SPI_MASTER_BASE,0 ,1, spi_command_string_tx, 0, spi_command_string_rx,0);
return_code = alt_avalon_spi_command(SPI_MASTER_BASE,0 ,1, &spi_command_string_tx[1],0, spi_command_string_rx,0);
return_code = alt_avalon_spi_command(SPI_MASTER_BASE,0 ,1, &spi_command_string_tx[2],0, spi_command_string_rx,0);
return_code = alt_avalon_spi_command(SPI_MASTER_BASE,0 ,1, &spi_command_string_tx[3],0, spi_command_string_rx,0);
if(return_code < 0)
alt_printf("ERROR SPI TX RET = %x \n" , return_code);
alt_printf("Transmit done. RET = %x spi_rx %x\n",return_code,spi_command_string_rx[0]);
//RX is done via interrupts.
alt_printf("Rx done \n");
return 0;
}
Error:
12:24:17 **** Incremental Build of configuration Nios II for project nios_spiv1 ****
wsl make all
Info: Building /mnt/e/nios_spiv1/software/nios_spiv1_bsp/
make --no-print-directory -C /mnt/e/nios_spiv1/software/nios_spiv1_bsp/
[BSP build complete]
Info: Compiling hello_world_small.c to obj/default/hello_world_small.o
nios2-elf-gcc.exe -xc -MP -MMD -c -Ie:/nios_spiv1/software/nios_spiv1_bsp//HAL/inc -Ie:/nios_spiv1/software/nios_spiv1_bsp/ -Ie:/nios_spiv1/software/nios_spiv1_bsp//drivers/inc -pipe -D__hal__ -DALT_NO_C_PLUS_PLUS -DALT_NO_CLEAN_EXIT -D'exit(a)=_exit(a)' -DALT_NO_EXIT -DALT_USE_DIRECT_DRIVERS -DALT_NO_INSTRUCTION_EMULATION -DALT_USE_SMALL_DRIVERS -DSMALL_C_LIB -DALT_SINGLE_THREADED -Os -g -Wall -mno-hw-div -mno-hw-mul -mno-hw-mulx -mgpopt=global -o obj/default/hello_world_small.o hello_world_small.c
In file included from hello_world_small.c:83:
hello_world_small.c: In function 'spi_rx_isr':
hello_world_small.c:92:31: error: 'SPI_SLAVE_BASE' undeclared (first use in this function); did you mean 'SPI_0_BASE'?
92 | IORD_ALTERA_AVALON_SPI_RXDATA(SPI_SLAVE_BASE));
| ^~~~~~~~~~~~~~
e:\nios_spiv1\software\nios_spiv1_bsp\hal\inc\io.h:70:23: note: in definition of macro '__IO_CALC_ADDRESS_NATIVE'
70 | ((void *)(((alt_u8*)BASE) + ((REGNUM) * (SYSTEM_BUS_WIDTH/8))))
| ^~~~
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi_regs.h:38:55: note: in expansion of macro 'IORD'
38 | #define IORD_ALTERA_AVALON_SPI_RXDATA(base) IORD(base, ALTERA_AVALON_SPI_RXDATA_REG)
| ^~~~
hello_world_small.c:92:1: note: in expansion of macro 'IORD_ALTERA_AVALON_SPI_RXDATA'
92 | IORD_ALTERA_AVALON_SPI_RXDATA(SPI_SLAVE_BASE));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hello_world_small.c:92:31: note: each undeclared identifier is reported only once for each function it appears in
92 | IORD_ALTERA_AVALON_SPI_RXDATA(SPI_SLAVE_BASE));
| ^~~~~~~~~~~~~~
e:\nios_spiv1\software\nios_spiv1_bsp\hal\inc\io.h:70:23: note: in definition of macro '__IO_CALC_ADDRESS_NATIVE'
70 | ((void *)(((alt_u8*)BASE) + ((REGNUM) * (SYSTEM_BUS_WIDTH/8))))
| ^~~~
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi_regs.h:38:55: note: in expansion of macro 'IORD'
38 | #define IORD_ALTERA_AVALON_SPI_RXDATA(base) IORD(base, ALTERA_AVALON_SPI_RXDATA_REG)
| ^~~~
hello_world_small.c:92:1: note: in expansion of macro 'IORD_ALTERA_AVALON_SPI_RXDATA'
92 | IORD_ALTERA_AVALON_SPI_RXDATA(SPI_SLAVE_BASE));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hello_world_small.c: In function 'main':
hello_world_small.c:104:21: error: 'SPI_SLAVE_IRQ_INTERRUPT_CONTROLLER_ID' undeclared (first use in this function); did you mean 'SPI_0_IRQ_INTERRUPT_CONTROLLER_ID'?
104 | alt_ic_isr_register(SPI_SLAVE_IRQ_INTERRUPT_CONTROLLER_ID,SPI_SLAVE_IRQ,spi_rx_i
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| SPI_0_IRQ_INTERRUPT_CONTROLLER_ID
hello_world_small.c:104:59: error: 'SPI_SLAVE_IRQ' undeclared (first use in this function); did you mean 'SPI_0_IRQ'?
104 | alt_ic_isr_register(SPI_SLAVE_IRQ_INTERRUPT_CONTROLLER_ID,SPI_SLAVE_IRQ,spi_rx_i
| ^~~~~~~~~~~~~
| SPI_0_IRQ
hello_world_small.c:104:73: error: 'spi_rx_i' undeclared (first use in this function); did you mean 'spi_rx_isr'?
104 | alt_ic_isr_register(SPI_SLAVE_IRQ_INTERRUPT_CONTROLLER_ID,SPI_SLAVE_IRQ,spi_rx_i
| ^~~~~~~~
| spi_rx_isr
hello_world_small.c:104:81: error: expected ')' before 'sr'
104 | alt_ic_isr_register(SPI_SLAVE_IRQ_INTERRUPT_CONTROLLER_ID,SPI_SLAVE_IRQ,spi_rx_i
| ^
| )
105 | sr,(void *)spi_command_string_tx,0x0);
| ~~
hello_world_small.c:104:1: error: too few arguments to function 'alt_ic_isr_register'
104 | alt_ic_isr_register(SPI_SLAVE_IRQ_INTERRUPT_CONTROLLER_ID,SPI_SLAVE_IRQ,spi_rx_i
| ^~~~~~~~~~~~~~~~~~~
In file included from hello_world_small.c:88:
e:\nios_spiv1\software\nios_spiv1_bsp\hal\inc\sys\alt_irq.h:195:12: note: declared here
195 | extern int alt_ic_isr_register(alt_u32 ic_id,
| ^~~~~~~~~~~~~~~~~~~
In file included from hello_world_small.c:83:
hello_world_small.c:108:32: error: 'SPI_SLAVE_BASE' undeclared (first use in this function); did you mean 'SPI_0_BASE'?
108 | IOWR_ALTERA_AVALON_SPI_CONTROL(SPI_SLAVE_BASE,ALTERA_AVALON_SPI_CONTROL_SSO_MSK
| ^~~~~~~~~~~~~~
e:\nios_spiv1\software\nios_spiv1_bsp\hal\inc\io.h:70:23: note: in definition of macro '__IO_CALC_ADDRESS_NATIVE'
70 | ((void *)(((alt_u8*)BASE) + ((REGNUM) * (SYSTEM_BUS_WIDTH/8))))
| ^~~~
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi_regs.h:67:55: note: in expansion of macro 'IOWR'
67 | #define IOWR_ALTERA_AVALON_SPI_CONTROL(base, data) IOWR(base, ALTERA_AVALON_SPI_CONTROL_REG, data)
| ^~~~
hello_world_small.c:108:1: note: in expansion of macro 'IOWR_ALTERA_AVALON_SPI_CONTROL'
108 | IOWR_ALTERA_AVALON_SPI_CONTROL(SPI_SLAVE_BASE,ALTERA_AVALON_SPI_CONTROL_SSO_MSK
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hello_world_small.c:112:38: error: 'SPI_MASTER_BASE' undeclared (first use in this function)
Makefile:724: recipe for target 'obj/default/hello_world_small.o' failed
112 | return_code = alt_avalon_spi_command(SPI_MASTER_BASE,0 ,
| ^~~~~~~~~~~~~~~
hello_world_small.c:113:4: warning: pointer targets in passing argument 4 of 'alt_avalon_spi_command' differ in signedness [-Wpointer-sign]
113 | 1, spi_command_string_tx,
| ^~~~~~~~~~~~~~~~~~~~~
| |
| char *
In file included from hello_world_small.c:86:
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi.h:68:65: note: expected 'const alt_u8 *' {aka 'const unsigned char *'} but argument is of type 'char *'
68 | alt_u32 write_length, const alt_u8 * write_data,
| ~~~~~~~~~~~~~~~^~~~~~~~~~
hello_world_small.c:114:4: warning: pointer targets in passing argument 6 of 'alt_avalon_spi_command' differ in signedness [-Wpointer-sign]
114 | 0, spi_command_string_rx,
| ^~~~~~~~~~~~~~~~~~~~~
| |
| char *
In file included from hello_world_small.c:86:
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi.h:69:58: note: expected 'alt_u8 *' {aka 'unsigned char *'} but argument is of type 'char *'
69 | alt_u32 read_length, alt_u8 * read_data,
| ~~~~~~~~~^~~~~~~~~
hello_world_small.c:117:4: warning: pointer targets in passing argument 4 of 'alt_avalon_spi_command' differ in signedness [-Wpointer-sign]
117 | 1, &spi_command_string_tx[1],
| ^~~~~~~~~~~~~~~~~~~~~~~~~
| |
| char *
In file included from hello_world_small.c:86:
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi.h:68:65: note: expected 'const alt_u8 *' {aka 'const unsigned char *'} but argument is of type 'char *'
68 | alt_u32 write_length, const alt_u8 * write_data,
| ~~~~~~~~~~~~~~~^~~~~~~~~~
hello_world_small.c:118:4: warning: pointer targets in passing argument 6 of 'alt_avalon_spi_command' differ in signedness [-Wpointer-sign]
118 | 0, spi_command_string_rx,
| ^~~~~~~~~~~~~~~~~~~~~
| |
| char *
In file included from hello_world_small.c:86:
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi.h:69:58: note: expected 'alt_u8 *' {aka 'unsigned char *'} but argument is of type 'char *'
69 | alt_u32 read_length, alt_u8 * read_data,
| ~~~~~~~~~^~~~~~~~~
hello_world_small.c:121:4: warning: pointer targets in passing argument 4 of 'alt_avalon_spi_command' differ in signedness [-Wpointer-sign]
121 | 1, &spi_command_string_tx[2],
| ^~~~~~~~~~~~~~~~~~~~~~~~~
| |
| char *
In file included from hello_world_small.c:86:
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi.h:68:65: note: expected 'const alt_u8 *' {aka 'const unsigned char *'} but argument is of type 'char *'
68 | alt_u32 write_length, const alt_u8 * write_data,
| ~~~~~~~~~~~~~~~^~~~~~~~~~
hello_world_small.c:122:4: warning: pointer targets in passing argument 6 of 'alt_avalon_spi_command' differ in signedness [-Wpointer-sign]
122 | 0, spi_command_string_rx,0);
| ^~~~~~~~~~~~~~~~~~~~~
| |
| char *
In file included from hello_world_small.c:86:
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi.h:69:58: note: expected 'alt_u8 *' {aka 'unsigned char *'} but argument is of type 'char *'
69 | alt_u32 read_length, alt_u8 * read_data,
| ~~~~~~~~~^~~~~~~~~
hello_world_small.c:124:4: warning: pointer targets in passing argument 4 of 'alt_avalon_spi_command' differ in signedness [-Wpointer-sign]
124 | 1, &spi_command_string_tx[3],
| ^~~~~~~~~~~~~~~~~~~~~~~~~
| |
| char *
In file included from hello_world_small.c:86:
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi.h:68:65: note: expected 'const alt_u8 *' {aka 'const unsigned char *'} but argument is of type 'char *'
68 | alt_u32 write_length, const alt_u8 * write_data,
| ~~~~~~~~~~~~~~~^~~~~~~~~~
hello_world_small.c:125:4: warning: pointer targets in passing argument 6 of 'alt_avalon_spi_command' differ in signedness [-Wpointer-sign]
125 | 0, spi_command_string_rx,
| ^~~~~~~~~~~~~~~~~~~~~
| |
| char *
In file included from hello_world_small.c:86:
e:\nios_spiv1\software\nios_spiv1_bsp\drivers\inc\altera_avalon_spi.h:69:58: note: expected 'alt_u8 *' {aka 'unsigned char *'} but argument is of type 'char *'
69 | alt_u32 read_length, alt_u8 * read_data,
| ~~~~~~~~~^~~~~~~~~
hello_world_small.c:129:12: warning: missing terminating " character
129 | alt_printf("Transmit done. RET = %x spi_rx %x
| ^
hello_world_small.c:129:12: error: missing terminating " character
129 | alt_printf("Transmit done. RET = %x spi_rx %x
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hello_world_small.c:130:1: error: stray '\' in program
130 | \n",return_code,spi_command_string_rx[0]);
| ^
hello_world_small.c:130:3: warning: missing terminating " character
130 | \n",return_code,spi_command_string_rx[0]);
| ^
hello_world_small.c:130:3: error: missing terminating " character
130 | \n",return_code,spi_command_string_rx[0]);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
hello_world_small.c:130:2: error: 'n' undeclared (first use in this function)
130 | \n",return_code,spi_command_string_rx[0]);
| ^
hello_world_small.c:130:3: error: expected ')' before 'alt_printf'
130 | \n",return_code,spi_command_string_rx[0]);
| ^
| )
131 | //RX is done via interrupts.
132 | alt_printf("Rx done \n");
| ~~~~~~~~~~
hello_world_small.c:133:10: error: expected ';' before '}' token
133 | return 0;
| ^
| ;
134 | }
| ~
12:24:18 Build Finished (took 737ms)