I am using a Linux board called NanoPi Neo based on the H3 chipset. I got the spidev driver working and it appears as /dev/spidev0.0
I am trying to use a SPI module called RF24L01. However, I was not able to read the register values properly. So I hooked up a logic analyzer and found strange peaks in the clock signal which are not supposed to be there.
The SPI is configured as follows
Bits: 8 Speed: 5kHz Mode: 0 (CPOL=0, CPHA=0)
How can I fix this? Kernel version is 4.14 ($uname -r)
I have used different spidev based programs for SPI and all their waveforms exhibit this behaviour. I think there is something in the driver which is causing this weird behaviour. Can anyone point me in a direction?
This is the code using spidev driver
#include "spi.h"
#include <fcntl.h>
#include <linux/spi/spidev.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <unistd.h>
#define RF24_SPIDEV_BITS 8
SPI::SPI():fd(-1) {
}
void SPI::begin(int busNo){
/* set spidev accordingly to busNo like:
* busNo = 23 -> /dev/spidev2.3
*
* a bit messy but simple
* */
char device[] = "/dev/spidev0.0";
device[11] += (busNo / 10) % 10;
device[13] += busNo % 10;
if (this->fd < 0) // check whether spi is already open
{
this->fd = open(device, O_RDWR);
if (this->fd < 0)
{
perror("can't open device");
abort();
}
}
init();
}
void SPI::init()
{
uint8_t bits = RF24_SPIDEV_BITS;
uint32_t speed = RF24_SPIDEV_SPEED;
uint8_t mode = SPI_MODE_0;
int ret;
/*
* spi mode
*/
ret = ioctl(this->fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
{
perror("can't set spi mode");
abort();
}
ret = ioctl(this->fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
{
perror("can't set spi mode");
abort();
}
/*
* bits per word
*/
ret = ioctl(this->fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
{
perror("can't set bits per word");
abort();
}
ret = ioctl(this->fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
{
perror("can't set bits per word");
abort();
}
/*
* max speed hz
*/
ret = ioctl(this->fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
{
perror("can't set max speed hz");
abort();
}
ret = ioctl(this->fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
{
perror("can't set max speed hz");
abort();
}
}
uint8_t SPI::transfer(uint8_t tx)
{
struct spi_ioc_transfer tr;
memset(&tr, 0, sizeof(tr));
tr.tx_buf = (unsigned long)&tx;
uint8_t rx;
tr.rx_buf = (unsigned long)℞
tr.len = sizeof(tx);
tr.speed_hz = RF24_SPIDEV_SPEED;
tr.delay_usecs = 0;
tr.bits_per_word = RF24_SPIDEV_BITS;
tr.cs_change = 0;
int ret;
ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
{
perror("can't send spi message");
abort();
}
return rx;
}
void SPI::transfernb(char* tbuf, char* rbuf, uint32_t len)
{
struct spi_ioc_transfer tr;
memset(&tr, 0, sizeof(tr));
tr.tx_buf = (unsigned long)tbuf;
tr.rx_buf = (unsigned long)rbuf;
tr.len = len;
tr.speed_hz = RF24_SPIDEV_SPEED;
tr.delay_usecs = 0;
tr.bits_per_word = RF24_SPIDEV_BITS;
tr.cs_change = 0;
int ret;
ret = ioctl(this->fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
{
perror("can't send spi message");
abort();
}
}
SPI::~SPI() {
if (!(this->fd < 0))
close(this->fd);
}