• 0
daeroro

petalinux pmodCAN

Question

Posted (edited)

Hi, 

I'm using zybo-z7 10 and pmod CAN.

Now I'm trying to build pmod CAN petalinux user app.

But first of all, I want to handle spi transfer, so I build spi example code.

 

I'm using petalinux 2017.4 and vivado 2018.2. 

And hardware design referenced from here :

https://reference.digilentinc.com/learn/programmable-logic/tutorials/pmod-ips/start

 

and device tree (in ~/CAN_fpga/project-spec/meta-user/recipes-bsp/device-tree/files/system_user.dtsi) :

/include/ "system-conf.dtsi"
/ {
};

&spi0 {
  is-decoded-cs = <0>;
  num-cs = <1>;
  status = "okay";

  spidev@0x00 {
    compatible = "spidev";
    spi-max-frequency = <10000000>;
    reg = <0>;
  };
};

 

and the user app code:

-------------------------------------------------------------------------------

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>

#define SPI_DEV    "/dev/spidev32766.0"

int main(void)
{
    int fd, i;
    int rbuf[128];
    const char * name = SPI_DEV;
    int readcount = 8;
    int msglen = 8;

    if((fd = open(SPI_DEV, O_RDWR))<0)
    {
        perror("Open error: ");
        exit(-1);
    }
    printf("Open success\n");

    dumpstat(name, fd);

    printf("before do_msg\n");

    if (msglen)
        do_msg(fd, msglen);

    printf("after do_msg\n");

    if (readcount)
        do_read(fd, readcount);


    return 0;
}
 

static void do_read(int fd, int len)
{
    unsigned char    buf[32], *bp;
    int        status;

    /* read at least 2 bytes, no more than 32 */
    if (len < 2)
        len = 2;
    else if (len > sizeof(buf))
        len = sizeof(buf);
    memset(buf, 0, sizeof buf);

    status = read(fd, buf, len);
    if (status < 0) {
        perror("read");
        return;
    }
    if (status != len) {
        fprintf(stderr, "short read\n");
        return;
    }

    printf("read(%2d, %2d): %02x %02x,", len, status, buf[0], buf[1]);


    status -= 2;
    bp = buf + 2;
    while (status-- > 0)
        printf(" %02x", *bp++);


    printf("\n");
}

static void do_msg(int fd, int len)
{
    struct spi_ioc_transfer    xfer[2];
    unsigned char        buf[32], *bp;
    int            status;

    memset(xfer, 0, sizeof xfer);
    memset(buf, 0, sizeof buf);

    if (len > sizeof buf)
        len = sizeof buf;

    buf[0] = 0xaa;
    xfer[0].tx_buf = (unsigned long)buf;
    xfer[0].len = 1;

    xfer[1].rx_buf = (unsigned long) buf;
    xfer[1].len = len;

    printf("before do_msg ioctl\n");

    status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);

    printf("after do_msg ioctl\n");
    if (status < 0) {

        printf("status : %d\n", status);
        perror("SPI_IOC_MESSAGE");
        return;
    }

    printf("response(%2d, %2d): ", len, status);
    for (bp = buf; len; len--)
        printf(" %02x", *bp++);
    printf("\n");
}

static void dumpstat(const char *name, int fd)
{
    __u8    lsb, bits;
    __u32    mode, speed;

    if (ioctl(fd, SPI_IOC_RD_MODE32, &mode) < 0) {
        perror("SPI rd_mode");
        return;
    }
    if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) {
        perror("SPI rd_lsb_fist");
        return;
    }
    if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) {
        perror("SPI bits_per_word");
        return;
    }
    if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) {
        perror("SPI max_speed_hz");
        return;
    }
    
    printf("%s: spi read mode 0x%x, %d bits %sper word, %d Hz max\n",
        name, mode, bits, lsb ? "(lsb first) " : "", speed);

}

------------------------------------------------------------------------------------------------------------------------------

I want to control spi in duplex mode using ioctl() bolded above code.

 

But the result is :

1161170300_2019-05-3114-18-41.png.8086dc0934326d9d38aa52534ae5cffa.png

- SPI transfer timed out   -> ioctl() function doesn't work properly, I think.

 

Could you give me some advice?

Edited by daeroro

Share this post


Link to post
Share on other sites

1 answer to this question

Recommended Posts

  • 0

Hi @daeroro,

#define SPI_DEV    "/dev/spidev32766.0" 

Judging by the .dtsi this should be something else... probably something like spidev1.0. You will need to change to the right device name. To determine which is the right name please run

ls /dev/ | grep spi

on the running petalinux target.

-Ciprian

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now