0

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) enter image description here

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)&rx;
    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);
}
  • I have not heard of any such behaviour. I suggest it is down to incorrect use of the software or possibly poor wiring. – joan Jan 5 '18 at 9:20
  • I've tried with two different modules and checked wiring. When I try with SPI Mode 3 or 2 (CPOL = 1) the waveform is perfect. But my module only supports SPI Mode 0, so I am stuck here. Also, I tested kernel 4.10.0, 4.11.0, 4.11.2, 4.14.0 and the behaviour is same! For RF24 SPI i am using the library here github.com/nRF24/RF24 – azmath Jan 5 '18 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.