From 2a11e31052521c25f0f1c75e472465e73fc3c906 Mon Sep 17 00:00:00 2001 From: Kurt Eckhardt Date: Sat, 18 Oct 2014 09:25:19 -0700 Subject: [PATCH] spi: Add SPI transfer function that pass in RX/TX When using SPI, I prefer to not have to do malloc/free functions for each transfer, so why not have a transfer function that you can pass in both buffers. With my ILI9341 TFT display code that gave some perf wins, also more of a win, you can pass in NULL for recv buffer and the underlying device driver does not have to copy the data. Signed-off-by: Kurt Eckhardt Signed-off-by: Brendan Le Foll --- api/mraa/spi.h | 11 +++++++++++ api/mraa/spi.hpp | 15 ++++++++++++++- examples/c++/Spi-pot.cpp | 13 +++++++++---- src/spi/spi.c | 19 +++++++++++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/api/mraa/spi.h b/api/mraa/spi.h index afc785d..b2ca81c 100644 --- a/api/mraa/spi.h +++ b/api/mraa/spi.h @@ -105,6 +105,17 @@ uint8_t mraa_spi_write(mraa_spi_context dev, uint8_t data); */ uint8_t* mraa_spi_write_buf(mraa_spi_context dev, uint8_t* data, int length); +/** Transfer Buffer of bytes to the SPI device. Both send and recv buffers + * are passed in + * + * @param dev The Spi context + * @param data to send + * @param rxbuf buffer to recv data back, may be NULL + * @param length elements within buffer, Max 4096 + * @return Result of operation + */ +mraa_result_t mraa_spi_transfer_buf(mraa_spi_context dev, uint8_t* data, uint8_t* rxbuf, int length); + /** * Change the SPI lsb mode * diff --git a/api/mraa/spi.hpp b/api/mraa/spi.hpp index 6153051..941f3e8 100644 --- a/api/mraa/spi.hpp +++ b/api/mraa/spi.hpp @@ -84,7 +84,8 @@ class Spi { return (char) mraa_spi_write(m_spi, (uint8_t) data); } /** - * Write buffer of bytes to SPI device + * Write buffer of bytes to SPI device The pointer return has to be + * free'd by the caller. * * @param data buffer to send * @param length size of buffer to send @@ -93,6 +94,18 @@ class Spi { char* write(char* data, size_t length) { return (char*) mraa_spi_write_buf(m_spi, (uint8_t *) data, (int) length); } + /** + * Transfer data to and from SPI device Receive pointer may be null if return + * data is not needed. + * + * @param data buffer to send + * @param rxBuf buffer to optionally receive data from spi device + * @param length size of buffer to send + * @return Result of operation + */ + mraa_result_t transfer(char* data, char* rxBuf, size_t length) { + return mraa_spi_transfer_buf(m_spi, (uint8_t *) data, (uint8_t *)rxBuf, (int) length); + } /** * Change the SPI lsb mode * diff --git a/examples/c++/Spi-pot.cpp b/examples/c++/Spi-pot.cpp index b86f5f2..b622996 100644 --- a/examples/c++/Spi-pot.cpp +++ b/examples/c++/Spi-pot.cpp @@ -49,6 +49,7 @@ int main () spi = new mraa::Spi(0); char data[] = {0x00, 100}; + char rxBuf[2]; char *recv; while (running == 0) { int i; @@ -56,14 +57,18 @@ int main () data[1] = i; recv = spi->write(data, 2); printf("Writing -%i",i); - printf("RECIVED-%i-%i\n",recv[0],recv[1]); + if (recv) { + printf("RECIVED-%i-%i\n",recv[0],recv[1]); + free(recv); + } usleep(100000); } for (i = 130; i > 90; i--) { data[1] = i; - recv = spi->write(data, 2); - printf("Writing -%i",i); - printf("RECIVED-%i-%i\n",recv[0],recv[1]); + if (spi->transfer(data, rxBuf, 2) == MRAA_SUCCESS) { + printf("Writing -%i",i); + printf("RECIVED-%i-%i\n",rxBuf[0],rxBuf[1]); + } usleep(100000); } diff --git a/src/spi/spi.c b/src/spi/spi.c index 78611ac..6589eaf 100644 --- a/src/spi/spi.c +++ b/src/spi/spi.c @@ -193,6 +193,25 @@ mraa_spi_write_buf(mraa_spi_context dev, uint8_t* data, int length) return recv; } +mraa_result_t +mraa_spi_transfer_buf(mraa_spi_context dev, uint8_t* data, uint8_t* rxbuf, int length) +{ + struct spi_ioc_transfer msg; + memset(&msg, 0, sizeof(msg)); + + msg.tx_buf = (unsigned long) data; + msg.rx_buf = (unsigned long) rxbuf; + msg.speed_hz = dev->clock; + msg.bits_per_word = dev->bpw; + msg.delay_usecs = 0; + msg.len = length; + if (ioctl(dev->devfd, SPI_IOC_MESSAGE(1), &msg) < 0) { + syslog(LOG_ERR, "Failed to perform dev transfer"); + return MRAA_ERROR_INVALID_RESOURCE; + } + return MRAA_SUCCESS; +} + mraa_result_t mraa_spi_stop(mraa_spi_context dev) {