WiringPi/wiringPi/wiringPiSPI.c
Gordon Henderson b1dfc186ef A new version of wiringPi. Added in more stuff and fixed it up
for kernels 4.8 onwards.

Some very old stuff might break.

Additional fixes for the ISR code and some tweaks here and
there. I've removed the checks for some operations that might
fail when using the gpiomem interface - which is now the default
way of doing things - if your program segfaults, then you
may need to use sudo on it.
2016-12-12 14:19:55 +00:00

138 lines
3.9 KiB
C

/*
* wiringPiSPI.c:
* Simplified SPI access routines
* Copyright (c) 2012-2015 Gordon Henderson
***********************************************************************
* This file is part of wiringPi:
* https://projects.drogon.net/raspberry-pi/wiringpi/
*
* wiringPi is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* wiringPi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with wiringPi.
* If not, see <http://www.gnu.org/licenses/>.
***********************************************************************
*/
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <sys/ioctl.h>
#include <asm/ioctl.h>
#include <linux/spi/spidev.h>
#include "wiringPi.h"
#include "wiringPiSPI.h"
// The SPI bus parameters
// Variables as they need to be passed as pointers later on
static const char *spiDev0 = "/dev/spidev0.0" ;
static const char *spiDev1 = "/dev/spidev0.1" ;
static const uint8_t spiBPW = 8 ;
static const uint16_t spiDelay = 0 ;
static uint32_t spiSpeeds [2] ;
static int spiFds [2] ;
/*
* wiringPiSPIGetFd:
* Return the file-descriptor for the given channel
*********************************************************************************
*/
int wiringPiSPIGetFd (int channel)
{
return spiFds [channel & 1] ;
}
/*
* wiringPiSPIDataRW:
* Write and Read a block of data over the SPI bus.
* Note the data ia being read into the transmit buffer, so will
* overwrite it!
* This is also a full-duplex operation.
*********************************************************************************
*/
int wiringPiSPIDataRW (int channel, unsigned char *data, int len)
{
struct spi_ioc_transfer spi ;
channel &= 1 ;
// Mentioned in spidev.h but not used in the original kernel documentation
// test program )-:
memset (&spi, 0, sizeof (spi)) ;
spi.tx_buf = (unsigned long)data ;
spi.rx_buf = (unsigned long)data ;
spi.len = len ;
spi.delay_usecs = spiDelay ;
spi.speed_hz = spiSpeeds [channel] ;
spi.bits_per_word = spiBPW ;
return ioctl (spiFds [channel], SPI_IOC_MESSAGE(1), &spi) ;
}
/*
* wiringPiSPISetupMode:
* Open the SPI device, and set it up, with the mode, etc.
*********************************************************************************
*/
int wiringPiSPISetupMode (int channel, int speed, int mode)
{
int fd ;
mode &= 3 ; // Mode is 0, 1, 2 or 3
channel &= 1 ; // Channel is 0 or 1
if ((fd = open (channel == 0 ? spiDev0 : spiDev1, O_RDWR)) < 0)
return wiringPiFailure (WPI_ALMOST, "Unable to open SPI device: %s\n", strerror (errno)) ;
spiSpeeds [channel] = speed ;
spiFds [channel] = fd ;
// Set SPI parameters.
if (ioctl (fd, SPI_IOC_WR_MODE, &mode) < 0)
return wiringPiFailure (WPI_ALMOST, "SPI Mode Change failure: %s\n", strerror (errno)) ;
if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0)
return wiringPiFailure (WPI_ALMOST, "SPI BPW Change failure: %s\n", strerror (errno)) ;
if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0)
return wiringPiFailure (WPI_ALMOST, "SPI Speed Change failure: %s\n", strerror (errno)) ;
return fd ;
}
/*
* wiringPiSPISetup:
* Open the SPI device, and set it up, etc. in the default MODE 0
*********************************************************************************
*/
int wiringPiSPISetup (int channel, int speed)
{
return wiringPiSPISetupMode (channel, speed, 0) ;
}