Skip to content

Commit

Permalink
Fix SPIDEV using Armbian Stretch
Browse files Browse the repository at this point in the history
  • Loading branch information
marceloaqno committed Sep 2, 2018
1 parent 0b51d5c commit 46efbe5
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 44 deletions.
28 changes: 14 additions & 14 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -193,51 +193,51 @@ function detect_machine {
soc="BCM2837"
fi
;;
sun4i|Sun4iw1p1)
*sun4i*|*Sun4iw1p1*)
soc="A10"
;;
sun5i|Sun4iw2p1)
*sun5i*|*Sun4iw2p1*)
soc="A13"
;;
Sun4iw2p2)
*Sun4iw2p2*)
soc="A12"
;;
Sun4iw2p3)
*Sun4iw2p3*)
soc="A10s"
;;
sun6i|Sun8iw1p1)
*sun6i*|*Sun8iw1p1*)
soc="A31"
;;
Sun8iw1p2)
*Sun8iw1p2*)
soc="A31s"
;;
sun7i|Sun8iw2p1)
*sun7i*|*Sun8iw2p1*)
soc="A20"
if [[ $machine == "Banana Pi"* ]]; then
tp="BananaPi"
elif [[ $machine == "Banana Pro"* ]]; then
tp="BananaPro"
fi
;;
sun8i|Sun8iw7p1)
*sun8i*|*Sun8iw7p1*)
soc="H3"
;;
Sun8iw3p1)
*Sun8iw3p1*)
soc="A23"
;;
Sun8iw5p1)
*Sun8iw5p1*)
soc="A33"
;;
Sun8iw6p1)
*Sun8iw6p1*)
soc="A83t"
;;
sun9i|Sun9iw1p1)
*sun9i*|*Sun9iw1p1*)
soc="A80"
;;
Sun9iw1p2)
*Sun9iw1p2*)
soc="A80t"
;;
sun50i|Sun50iw1p1)
*sun50i*|*Sun50iw1p1*)
soc="A64"
;;
'Generic AM33XX'*)
Expand Down
189 changes: 166 additions & 23 deletions drivers/Linux/SPIDEV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ SPIDEVClass SPIDEV = SPIDEVClass();
uint8_t SPIDEVClass::initialized = 0;
int SPIDEVClass::fd = -1;
std::string SPIDEVClass::device = SPI_SPIDEV_DEVICE;
uint8_t SPIDEVClass::mode = SPI_MODE0;
uint8_t SPIDEVClass::mode_temp = SPI_MODE0;
uint32_t SPIDEVClass::speed = SPI_CLOCK_BASE;
uint32_t SPIDEVClass::speed_temp = SPI_CLOCK_BASE;
struct spi_ioc_transfer SPIDEVClass::tr = {0,0,0,0,0,8,1,0,0,0}; // 8 bits_per_word, 1 cs_change
uint8_t SPIDEVClass::bit_order = MSBFIRST;
uint8_t SPIDEVClass::bit_order_temp = MSBFIRST;
struct spi_ioc_transfer SPIDEVClass::tr = {0,0,0,0,0,8,0,0,0,0}; // 8 bits_per_word, 0 cs_change

SPIDEVClass::SPIDEVClass()
{
Expand Down Expand Up @@ -78,15 +82,21 @@ void SPIDEVClass::end()
}
}

void SPIDEVClass::setBitOrder(uint8_t bit_order)
void SPIDEVClass::setBitOrder(uint8_t border)
{
pthread_mutex_lock(&spiMutex);

/*
* bit order
*/
int lsb_setting = bit_order;
int ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_setting);
bit_order = bit_order_temp = border;
int ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order);
if (ret == -1) {
logError("Can't set SPI bit order.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order);
if (ret == -1) {
logError("Can't set SPI bit order.\n");
abort();
Expand All @@ -102,7 +112,14 @@ void SPIDEVClass::setDataMode(uint8_t data_mode)
/*
* spi mode
*/
int ret = ioctl(fd, SPI_IOC_WR_MODE, &data_mode);
mode = mode_temp = data_mode;
int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1) {
logError("Can't set SPI mode.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1) {
logError("Can't set SPI mode.\n");
abort();
Expand All @@ -118,13 +135,19 @@ void SPIDEVClass::setClockDivider(uint16_t divider)
/*
* max speed hz
*/
speed = SPI_CLOCK_BASE / divider;
speed = speed_temp = SPI_CLOCK_BASE / divider;
int ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1) {
logError("Can't set SPI max speed hz.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1) {
logError("Can't set SPI max speed hz.\n");
abort();
}

pthread_mutex_unlock(&spiMutex);
}

Expand Down Expand Up @@ -195,29 +218,128 @@ void SPIDEVClass::beginTransaction(SPISettings settings)
/*
* spi mode
*/
ret = ioctl(fd, SPI_IOC_WR_MODE, &settings.dmode);
if (ret == -1) {
logError("Can't set spi mode.\n");
abort();
if (settings.dmode != mode) {
// Save the current mode
mode_temp = mode;
mode = settings.dmode;

ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1) {
logError("Can't set spi mode.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1) {
logError("Can't set spi mode.\n");
abort();
}
}

// Save the current speed
speed_temp = speed;
speed = settings.clock;
/*
* speed
*/
if (settings.clock != speed) {
// Save the current speed
speed_temp = speed;
speed = settings.clock;

ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1) {
logError("Can't set spi mode.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1) {
logError("Can't set spi mode.\n");
abort();
}
}

/*
* bit order
*/
ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &settings.border);
if (ret == -1) {
logError("Can't set bits per word.\n");
abort();
if (settings.border != bit_order) {
// Save the current bit order
bit_order_temp = bit_order;
bit_order = settings.border;

ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order);
if (ret == -1) {
logError("Can't set bits per word.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order);
if (ret == -1) {
logError("Can't set bits per word.\n");
abort();
}
}
}

void SPIDEVClass::endTransaction()
{
speed = speed_temp;
int ret;

/*
* spi mode
*/
if (mode != mode_temp) {
mode = mode_temp;

ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1) {
logError("Can't set spi mode.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1) {
logError("Can't set spi mode.\n");
abort();
}
}

/*
* speed
*/
if (speed != speed_temp) {
speed = speed_temp;

ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1) {
logError("Can't set spi mode.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1) {
logError("Can't set spi mode.\n");
abort();
}
}

/*
* bit order
*/
if (bit_order != bit_order_temp) {
bit_order = bit_order_temp;

ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order);
if (ret == -1) {
logError("Can't set bits per word.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order);
if (ret == -1) {
logError("Can't set bits per word.\n");
abort();
}
}

pthread_mutex_unlock(&spiMutex);
}

Expand Down Expand Up @@ -248,38 +370,59 @@ void SPIDEVClass::init()
/*
* spi mode
*/
uint8_t mode = SPI_MODE0;
int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1) {
logError("Can't set SPI mode.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1) {
logError("Can't set SPI mode.\n");
abort();
}

/*
* bits per word
*/
uint8_t bits = 0; // 0 corresponds to 8 bits per word
uint8_t bits = 8; // 8 bits per word
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1) {
logError("Can't set SPI bits per word.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1) {
logError("Can't set SPI bits per word.\n");
abort();
}

/*
* max speed hz
*/
speed = SPI_CLOCK_BASE;
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1) {
logError("Can't set SPI max speed hz.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1) {
logError("Can't set SPI max speed hz.\n");
abort();
}

/*
* bit order
*/
int lsb_setting = MSBFIRST;
ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &lsb_setting);
ret = ioctl(fd, SPI_IOC_WR_LSB_FIRST, &bit_order);
if (ret == -1) {
logError("Can't set SPI bit order.\n");
abort();
}

ret = ioctl(fd, SPI_IOC_RD_LSB_FIRST, &bit_order);
if (ret == -1) {
logError("Can't set SPI bit order.\n");
abort();
Expand Down
4 changes: 4 additions & 0 deletions drivers/Linux/SPIDEV.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,12 @@ class SPIDEVClass
static uint8_t initialized; //!< @brief SPI initialized flag.
static int fd; //!< @brief SPI device file descriptor.
static std::string device; //!< @brief Default SPI device.
static uint8_t mode; //!< @brief SPI mode.
static uint8_t mode_temp; //!< @brief Used when doing transaction.
static uint32_t speed; //!< @brief SPI speed.
static uint32_t speed_temp; //!< @brief Used when doing transaction.
static uint8_t bit_order; //!< @brief SPI bit order.
static uint8_t bit_order_temp; //!< @brief Used when doing transaction.
static struct spi_ioc_transfer tr; //!< @brief Auxiliar struct for data transfer.

static void init();
Expand Down
Loading

0 comments on commit 46efbe5

Please sign in to comment.