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++
12606 Discussions

NIOS II SPI HAL driver open code

Altera_Forum
Honored Contributor II
2,554 Views

#ifndef __ALT_AVALON_SPI_H__# define __ALT_AVALON_SPI_H__ 

 

/****************************************************************************** 

* File: quartus60\sopc_builder\components\altera_avalon_spi\ * 

* HAL\inc\altera_avalon_spi.h *  

* Auth: lvjian (lvjian75@126.com) * 

* date: 2006.8.1 * 

* version: 0.1 * 

******************************************************************************/ 

# include <stddef.h> 

# include "sys/alt_dev.h"# include "sys/alt_alarm.h"# include "sys/alt_warning.h" 

# include "os/alt_sem.h"# include "os/alt_flag.h" 

 

/* If the user wants all drivers to be small rather than fast then make sure 

* this one is marked as needing to be small. 

*/# define ALT_AVALON_SPI_BUF_LEN (16) 

 

/* 

* Device structure definition. This is needed by alt_sys_init in order to reserve memory 

* for the device instance. 

*/ 

 

typedef struct  

int pos; 

int datalen; 

alt_u8 buf[ALT_AVALON_SPI_BUF_LEN];  

}spi_data_buf; 

 

typedef struct 

alt_dev dev; /* The device callback structure */ 

void* base; /* The base address of the device */ 

alt_u32 irq_enable; 

alt_u32 ctrl; /* Shadow value of the control register */ 

spi_data_buf rx_data; /* Start of the pending receive data */ 

spi_data_buf tx_data; /* End of the pending receive data */ 

alt_u8 ismaster; /* master or slave work mode */ 

alt_u8 databits; /* the number of the interface bits */ 

ALT_FLAG_GRP (events) /* Event flags used for  

* foreground/background in mult-threaded 

* mode */  

ALT_SEM (rx_wait) /* interrupt isr notify the reader */ 

ALT_SEM (tx_wait) /* interrupt isr notify the writer */ 

} alt_avalon_spi_dev; 

 

 

 

extern int alt_avalon_spi_read (alt_fd* fd, char* ptr, int len); 

extern int alt_avalon_spi_write (alt_fd* fd, const char* ptr, int len); 

 

 

extern void alt_avalon_spi_init (alt_avalon_spi_dev* dev, int base, int irq); 

extern int alt_avalon_spi_ioctl (alt_fd* fd, int req, void* arg); 

# define SPI_MASTER_IOCTL_SELECT_SLAVE 0x01 

 

 

/* 

* Macros used by alt_sys_init 

*/ 

 

 

# define ALTERA_AVALON_SPI_INSTANCE(name, device)  

static alt_avalon_spi_dev device =  

{  

{  

ALT_LLIST_ENTRY,  

name##_NAME,  

NULL, /* open */  

NULL, /* close */  

alt_avalon_spi_read,  

alt_avalon_spi_write,  

NULL, /* lseek */  

NULL, /* fstat */  

alt_avalon_spi_ioctl,  

},  

# define ALTERA_AVALON_SPI_INIT(name, dev)  

{  

if (name##_ISMASTER)  

dev.ismaster = 1;  

else  

dev.ismaster = 0;  

dev.databits = name##_DATABITS;  

if (name##_IRQ == ALT_IRQ_NOT_CONNECTED)  

{  

ALT_LINK_ERROR ("Error: Interrupt not connected for "# dev ". "  

"You have selected the interrupt driven version of "  

"the ALTERA Avalon JTAG UART driver, but the "  

"interrupt is not connected for this device. You can "  

"select a polled mode driver by checking the &#39;small "  

"driver&#39; option in the HAL configuration window, or "  

"by using the -DALTERA_AVALON_JTAG_UART_SMALL "  

"preprocessor flag.");  

}  

else  

alt_avalon_spi_init (&dev, name##_BASE, name##_IRQ);  

 

 

 

/* 

*/ 

# endif /* __ALT_AVALON_SPI_H__ */
0 Kudos
8 Replies
Altera_Forum
Honored Contributor II
791 Views

/****************************************************************************** 

* File: quartus60\sopc_builder\components\altera_avalon_spi\ * 

* HAL\inc\altera_avalon_spi.c *  

* Auth: lvjian (lvjian75@126.com) * 

* date: 2006.8.1 * 

* version: 0.1 * 

******************************************************************************/ 

# include <string.h># include <fcntl.h># include <errno.h># include <limits.h> 

# include <sys/stat.h># include <os/alt_sem.h># include "sys/alt_dev.h"# include "sys/alt_irq.h"# include "sys/alt_alarm.h"# include "sys/ioctl.h"# include "alt_types.h" 

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

# include "sys/alt_log_printf.h" 

 

 

/* ----------------------------------------------------------------------- */ 

/* ---------------------- ROUTINES FOR FAST DRIVER ----------------------- */ 

 

int alt_avalon_spi_read(alt_fd* fd, char * buffer, int space) 

alt_avalon_spi_dev* dev = (alt_avalon_spi_dev*) fd->dev;  

 

spi_data_buf *pbuf; 

int copylen; 

int copypos; 

int i; 

 

pbuf = &(dev->rx_data);  

ALT_SEM_PEND(dev->rx_wait,0); 

copylen = space>pbuf->datalen?pbuf->datalen:space; 

copypos = pbuf->pos; 

for(i=0;i<copylen;i++){ 

*(buffer+i) = *(pbuf->buf+copypos); 

copypos = (copypos+1)%ALT_AVALON_SPI_BUF_LEN; 

pbuf->datalen -= copylen; 

pbuf->pos = copypos; 

return copylen;  

 

int alt_avalon_spi_write(alt_fd* fd, const char * ptr, int count) 

int copylen; 

int copypos; 

int alltxlen; 

spi_data_buf *pbuf; 

 

alt_avalon_spi_dev* dev = (alt_avalon_spi_dev*) fd->dev; 

pbuf = &(dev->tx_data); 

alltxlen = count; 

 

while(count){ 

ALT_SEM_PEND(dev->tx_wait,0);  

copylen = ALT_AVALON_SPI_BUF_LEN-pbuf->datalen; 

copylen = copylen>count?count:copylen; 

copypos = (pbuf->pos+pbuf->datalen)%ALT_AVALON_SPI_BUF_LEN; 

count -= copylen; 

pbuf->datalen+=copylen; 

while(copylen){ 

pbuf->buf[copypos] = *(ptr++); 

copypos = (copypos+1)%ALT_AVALON_SPI_BUF_LEN; 

copylen--; 

dev->irq_enable |= ALTERA_AVALON_SPI_CONTROL_ITRDY_MSK;  

IOWR_ALTERA_AVALON_SPI_CONTROL(dev->base,dev->irq_enable); 

 

return alltxlen; 

 

static void alt_avalon_spi_hw_tx_data(alt_avalon_spi_dev* dev) 

spi_data_buf *pbuf; 

pbuf = &(dev->tx_data); 

if(pbuf->datalen==0){ 

dev->irq_enable &= ~ALTERA_AVALON_SPI_CONTROL_ITRDY_MSK; 

IOWR_ALTERA_AVALON_SPI_CONTROL(dev->base,dev->irq_enable); 

ALT_SEM_POST(dev->tx_wait); 

else{ 

if(dev->databits==8){ 

IOWR_ALTERA_AVALON_SPI_TXDATA(dev->base,pbuf->buf[pbuf->pos]); 

pbuf->pos = (pbuf->pos+1)%ALT_AVALON_SPI_BUF_LEN; 

pbuf->datalen--; 

else if(dev->databits==16){ 

IOWR_ALTERA_AVALON_SPI_TXDATA(dev->base,*(alt_u16*)(pbuf->buf+pbuf->pos)); 

pbuf->pos = (pbuf->pos+2)%ALT_AVALON_SPI_BUF_LEN; 

pbuf->datalen-=2;  

}  

 

/* 

* Interrupt routine 

*/  

 

static void alt_avalon_spi_hw_rx_data (alt_avalon_spi_dev* dev) 

spi_data_buf *pbuf; 

int copypos; 

pbuf = &(dev->rx_data); 

copypos = (pbuf->pos+pbuf->datalen)%ALT_AVALON_SPI_BUF_LEN;  

if(dev->databits==8){ 

*(pbuf->buf+copypos) = IORD_ALTERA_AVALON_SPI_RXDATA(dev->base); 

pbuf->datalen++; 

else if(dev->databits==16){ 

*(alt_u16*)(pbuf->buf+copypos)=IORD_ALTERA_AVALON_SPI_RXDATA(dev->base); 

pbuf->datalen+=2;  

ALT_SEM_POST(dev->rx_wait); 

 

static void alt_avalon_spi_irq(void* context, alt_u32 id) 

alt_u16 status; 

alt_avalon_spi_dev* dev = (alt_avalon_spi_dev*) context; 

status = IORD_ALTERA_AVALON_SPI_STATUS(dev->base); 

if(status & ALTERA_AVALON_SPI_STATUS_TRDY_MSK){ 

alt_avalon_spi_hw_tx_data(dev); 

if(status & ALTERA_AVALON_SPI_STATUS_RRDY_MSK){ 

alt_avalon_spi_hw_rx_data(dev); 

}# if 0  

case ALTERA_AVALON_SPI_STATUS_ROE_MSK: 

case ALTERA_AVALON_SPI_STATUS_TOE_MSK: 

case ALTERA_AVALON_SPI_STATUS_TMT_MSK: 

case ALTERA_AVALON_SPI_STATUS_E_MSK:# endif  

 

int alt_avalon_spi_ioctl (alt_fd* fd, int req, void* arg) 

alt_avalon_spi_dev* dev = (alt_avalon_spi_dev*) fd->dev; 

int rc = -ENOTTY; 

switch (req) 

case SPI_MASTER_IOCTL_SELECT_SLAVE: 

if(dev->ismaster){ 

IOWR_ALTERA_AVALON_SPI_SLAVE_SEL(dev->base,1<<(*(alt_u8*)arg)); 

 

break; 

 

default: 

break; 

}  

 

return rc; 

 

/* Driver initialisation code. Register interrupts and start a timer 

* which we can use to check whether the host is there. 

*/ 

 

void alt_avalon_spi_init(alt_avalon_spi_dev* dev, int base, int irq) 

ALT_FLAG_CREATE(&dev->events, 0); 

ALT_SEM_CREATE(&dev->rx_wait, 0); 

ALT_SEM_CREATE(&dev->tx_wait, 1); 

memset(&(dev->tx_data),0,sizeof(spi_data_buf)); 

memset(&(dev->rx_data),0,sizeof(spi_data_buf)); 

dev->base = (void *)base; 

/* enable read interrupts at the device */ 

 

 

dev->irq_enable = ALTERA_AVALON_SPI_CONTROL_IRRDY_MSK; 

 

IOWR_ALTERA_AVALON_SPI_CONTROL(dev->base,dev->irq_enable); 

 

/* register the interrupt handler */ 

if (alt_irq_register(irq, dev, alt_avalon_spi_irq) >= 0) 

/* make the device available to the system */ 

alt_dev_reg(&dev->dev); 

}
0 Kudos
Altera_Forum
Honored Contributor II
791 Views

examples application code: 

/************************************************************************* 

* Copyright ? 2004 Altera Corporation, San Jose, California, USA. * 

* All rights reserved. All use of this software and documentation is * 

* subject to the License Agreement located at the end of this file below.* 

************************************************************************** 

* Description: * 

* The following is a simple hello world program running MicroC/OS-II.The *  

* purpose of the design is to be a very simple application that just * 

* demonstrates MicroC/OS-II running on NIOS II.The design doesn&#39;t account* 

* for issues such as checking system call return codes. etc. * 

* * 

* Requirements: * 

* -Supported Example Hardware Platforms * 

* Standard * 

* Full Featured * 

* Low Cost * 

* -Supported Development Boards * 

* Nios II Development Board, Stratix II Edition * 

* Nios Development Board, Stratix Professional Edition * 

* Nios Development Board, Stratix Edition * 

* Nios Development Board, Cyclone Edition * 

* -System Library Settings * 

* RTOS Type - MicroC/OS-II * 

* Periodic System Timer * 

* -Know Issues * 

* If this design is run on the ISS, terminal output will take several* 

* minutes per iteration. * 

**************************************************************************/ 

 

# include <stdio.h># include <io.h># include <sys/types.h># include <sys/stat.h># include <fcntl.h># include <unistd.h># include "includes.h"# include "altera_avalon_spi_regs.h" /*&#36825;&#20004;&#20010;&#22836;&#25991;&#20214;&#24517;&#19981;&#21487;&#23569;*/# include "altera_avalon_spi.h"  

 

/* Definition of Task Stacks */# define TASK_STACKSIZE 2048 

OS_STK task1_stk[TASK_STACKSIZE]; 

OS_STK task2_stk[TASK_STACKSIZE]; 

OS_STK task3_stk[TASK_STACKSIZE]; 

 

/* Definition of Task Priorities */ 

# define TASK1_PRIORITY 1# define TASK2_PRIORITY 2# define TASK3_PRIORITY 3# define BUFLEN 256  

 

int master_fd; 

 

/* Prints "Hello World" and sleeps for three seconds */ 

void task1(void* pdata) 

 

alt_u8 sendbuf[BUFLEN]; 

 

alt_u16 writelen,i; 

for(i=0;i<BUFLEN;i++) 

sendbuf = i; 

alt_u16 value=0; 

ioctl(master_fd,spi_master_ioctl_select_slave,&value); 

// return; 

while (1) 

{  

writelen = write(master_fd,sendbuf,sizeof(sendbuf)); 

// printf("write %d\n",writelen); 

ostimedlyhmsm(0, 0, 0, 50); 

 

 

void task3(void* pdata) 

alt_u8 recvbuf[buflen];  

alt_u16 readlen,i,wi; 

wi = 0; 

while (1) 

{  

readlen = read(master_fd,recvbuf,sizeof(recvbuf)); 

for(i=0;i<readlen;i++){ 

printf("%2.2x ",recvbuf); 

wi = (wi+1)%16; 

if(wi==0) 

printf("\n"); 

 

void task2(void* pdata) 

alt_u8 recvbuf[BUFLEN]; 

alt_u16 readlen,i,wi; 

printf("Hello from task2\n");  

int fd; 

if ((fd=open(SPI_SLAVE_NAME, O_RDWR, 0)) < 0) 

perror("open spi"); 

return; 

printf("fd=%d\n",fd); 

wi=0; 

while (1) 

{  

readlen = read(fd,recvbuf,sizeof(recvbuf)); 

write(fd,recvbuf,readlen);# if 0 

for(i=0;i<readlen;i++){ 

printf("%2.2x ",recvbuf[i]); 

wi = (wi+1)%16; 

if(wi==0) 

printf("\n"); 

}# endif 

close(fd); 

 

 

/* The main function creates two task and starts multi-tasking */ 

int main(void) 

 

if ((master_fd=open(SPI_MASTER_NAME, O_RDWR, 0)) < 0) 

perror("open spi"); 

return; 

 

OSTaskCreateExt(task1, 

NULL, 

(void *)&task1_stk[TASK_STACKSIZE], 

TASK1_PRIORITY, 

TASK1_PRIORITY, 

task1_stk, 

TASK_STACKSIZE, 

NULL, 

0); 

OSTaskCreateExt(task3, 

NULL, 

(void *)&task3_stk[TASK_STACKSIZE], 

TASK3_PRIORITY, 

TASK3_PRIORITY, 

task3_stk, 

TASK_STACKSIZE, 

NULL, 

0); 

 

 

OSTaskCreateExt(task2, 

NULL, 

(void *)&task2_stk[TASK_STACKSIZE], 

TASK2_PRIORITY, 

TASK2_PRIORITY, 

task2_stk, 

TASK_STACKSIZE, 

NULL, 

0); 

OSStart(); 

return 0; 

}
0 Kudos
Altera_Forum
Honored Contributor II
791 Views

Just replace the previous spi hal files with the above two files,then you can use  

open read write ioctl close to operator the spi device.  

The driver does support master and slave spi device.
0 Kudos
Altera_Forum
Honored Contributor II
791 Views

Hi, I have troubles using the RS232 functions defined in "altera_up_avalon_rs232.h". It should be similar to SPI, I guess... 

I need to know how the device should be initialized in order to work with the functions defined in "altera_up_avalon_rs232.h". 

Thank you
0 Kudos
Altera_Forum
Honored Contributor II
791 Views

 

--- Quote Start ---  

Hi, I have troubles using the RS232 functions defined in "altera_up_avalon_rs232.h". It should be similar to SPI, I guess... 

I need to know how the device should be initialized in order to work with the functions defined in "altera_up_avalon_rs232.h". 

Thank you 

--- Quote End ---  

 

 

add this module in sopc first and then ----> open it in your eclipse code like FILE *fp, look in to system.h for path of RS232 /dev/rs3232, and use function fopen fwrite etc.
0 Kudos
Altera_Forum
Honored Contributor II
791 Views

 

--- Quote Start ---  

add this module in sopc first and then ----> open it in your eclipse code like FILE *fp, look in to system.h for path of RS232 /dev/rs3232, and use function fopen fwrite etc. 

--- Quote End ---  

 

 

Thank you kaushal, 

I followed your tip, I wrote this code on NIOSII IDE. Build is ok but it doesn't seem to work... 

# include "alt_types.h"# include "altera_up_avalon_parallel_port.h" //university program# include "sys/alt_irq.h"# include "system.h"# include "binary.h"# include "altera_up_avalon_rs232.h"# include "altera_avalon_spi.h"# include <string.h># include <stdlib.h># include <stdio.h># include <unistd.h> 

# define CLOCK 50000000; 

 

void delay_us(int us); 

 

/*****************MAIN**********************/ 

int main() 

{  

char* msg = "a"; 

FILE* fp; 

fp = fopen (RS232_NAME, "w"); //RS232_NAME defined in system.h 

if (fp!=NULL) 

fprintf(fp, "%s",msg); 

fclose (fp); 

return 0; 

 

What is wrong in your opinion? 

Thank you 

 

rollingringhio
0 Kudos
Altera_Forum
Honored Contributor II
791 Views

i think your path "fp=fopen(RS3232_name,"w")" is not correct it may be something like "/dev/RS232_NAME" you may found exact path from your system.h and just copy past that path to your fopen function

0 Kudos
Altera_Forum
Honored Contributor II
791 Views

 

--- Quote Start ---  

i think your path "fp=fopen(RS3232_name,"w")" is not correct it may be something like "/dev/RS232_NAME" you may found exact path from your system.h and just copy past that path to your fopen function 

--- Quote End ---  

 

 

I finally solved it, I used the functions defined in altera_up_avalon_rs232.h. The main problem however was the clock frequency: switching from 50MHz to 27MHz solved all my problems. I red on other threads that other people experienced the same problem. 

Thank you Kaushal for your time. 

 

happy coding 

 

rollingringhio
0 Kudos
Reply