2.3.6.8.4. SPI
2.3.6.8.4.1. Description
This example shows communication with the Red Pitaya SPI Micron flash chip. The code below simulates a simple loop back by writing and then getting the flash ID of the Red Pitaya SPI flash chip operation.
2.3.6.8.4.3. Code - C
Note
Although the C code examples don’t require the use of the SCPI server, we have included them here to demonstrate how the same functionality can be achieved with different programming languages. Instructions on how to compile the code are here.
/* @brief This is a simple application for testing SPI communication on a RedPitaya
* @Author Luka Golinar <luka.golinar@redpitaya.com>
*
* (c) Red Pitaya http://www.redpitaya.com
*
* This part of code is written in C programming language.
* Please visit http://en.wikipedia.org/wiki/C_(programming_language)
* for more details on the language used herein.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <linux/spi/spidev.h>
#include <linux/types.h>
/* Inline functions definition */
static int init_spi();
static int release_spi();
static int read_flash_id(int fd);
static int write_spi(char *write_data, int size);
/* Constants definition */
int spi_fd = -1;
int main(void){
/* Sample data */
char *data = "REDPITAYA SPI TEST";
/* Init the spi resources */
if(init_spi() < 0){
printf("Initialization of SPI failed. Error: %s\n", strerror(errno));
return -1;
}
/* Write some sample data */
if(write_spi(data, strlen(data)) < 0){
printf("Write to SPI failed. Error: %s\n", strerror(errno));
return -1;
}
/* Read flash ID and some sample loopback data */
if(read_flash_id(spi_fd) < 0){
printf("Error reading from SPI bus : %s\n", strerror(errno));
return -1;
}
/* Release resources */
if(release_spi() < 0){
printf("Relase of SPI resources failed, Error: %s\n", strerror(errno));
return -1;
}
return 0;
}
static int init_spi(){
/* MODES: mode |= SPI_LOOP;
* mode |= SPI_CPHA;
* mode |= SPI_CPOL;
* mode |= SPI_LSB_FIRST;
* mode |= SPI_CS_HIGH;
* mode |= SPI_3WIRE;
* mode |= SPI_NO_CS;
* mode |= SPI_READY;
*
* multiple possibilities possible using | */
int mode = 0;
/* Opening file stream */
spi_fd = open("/dev/spidev1.0", O_RDWR | O_NOCTTY);
if(spi_fd < 0){
printf("Error opening spidev0.1. Error: %s\n", strerror(errno));
return -1;
}
/* Setting mode (CPHA, CPOL) */
if(ioctl(spi_fd, SPI_IOC_WR_MODE, &mode) < 0){
printf("Error setting SPI_IOC_RD_MODE. Error: %s\n", strerror(errno));
return -1;
}
/* Setting SPI bus speed */
int spi_speed = 1000000;
if(ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) < 0){
printf("Error setting SPI_IOC_WR_MAX_SPEED_HZ. Error: %s\n", strerror(errno));
return -1;
}
return 0;
}
static int release_spi(){
/* Release the spi resources */
close(spi_fd);
return 0;
}
/* Read data from the SPI bus */
static int read_flash_id(int fd){
int size = 2;
/*struct spi_ioc_transfer {
__u64 tx_buf;
__u64 rx_buf;
__u32 len;
__u32 speed_hz;
__u16 delay_usecs;
__u8 bits_per_word;
__u8 cs_change;
__u32 pad;
}*/
/* If the contents of 'struct spi_ioc_transfer' ever change
* incompatibly, then the ioctl number (currently 0) must change;
* ioctls with constant size fields get a bit more in the way of
* error checking than ones (like this) where that field varies.
*
* NOTE: struct layout is the same in 64bit and 32bit userspace.*/
struct spi_ioc_transfer xfer[size];
unsigned char buf0[1];
unsigned char buf1[3];
int status;
memset(xfer, 0, sizeof xfer);
/* RDID command */
buf0[0] = 0x9f;
/* Some sample data */
buf1[0] = 0x01;
buf1[1] = 0x23;
buf1[2] = 0x45;
/* RDID buffer */
xfer[0].tx_buf = (__u64)((__u32)buf0);
xfer[0].rx_buf = (__u64)((__u32)buf0);
xfer[0].len = 1;
/* Sample loopback buffer */
xfer[1].tx_buf = (__u64)((__u32)buf1);
xfer[1].rx_buf = (__u64)((__u32)buf1);
xfer[1].len = 3;
/* ioctl function arguments
* arg[0] - file descriptor
* arg[1] - message number
* arg[2] - spi_ioc_transfer structure
*/
status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
if (status < 0) {
perror("SPI_IOC_MESSAGE");
return -1;
}
/* Print read buffer */
for(int i = 0; i < 3; i++){
printf("Buffer: %d\n", buf1[i]);
}
return 0;
}
/* Write data to the SPI bus */
static int write_spi(char *write_buffer, int size){
int write_spi = write(spi_fd, write_buffer, strlen(write_buffer));
if(write_spi < 0){
printf("Failed to write to SPI. Error: %s\n", strerror(errno));
return -1;
}
return 0;
}