LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Embedded & Single-board computer (https://www.linuxquestions.org/questions/linux-embedded-and-single-board-computer-78/)
-   -   ICM-20948 issues using ioctl and spi_ioc_message (https://www.linuxquestions.org/questions/linux-embedded-and-single-board-computer-78/icm-20948-issues-using-ioctl-and-spi_ioc_message-4175656569/)

chickenwing101 06-28-2019 08:01 PM

ICM-20948 issues using ioctl and spi_ioc_message
 
I am using a DM3730 Torpedo and trying to use SPI to grab information from an ICM-20948 IMU sensor.

I am using the spidev framework and am having issues actually grabbing information. I am able to retriever the WHO_AM_I register at 0h by sending 0x80 (1 at the MSB to say read) but am unable to get access to any other registers. Below is attached code that return 00 EA (EA is the who_am_i value). Does anybody have suggestions on what I need to change in order to read other registers?

Thanks

Code:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <stdint.h>


#include <linux/types.h>
#include <linux/ioctl.h>
#include <linux/spi/spidev.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

static void pabort(const char *s)
{
perror(s);
abort();
}

static const char *device = "/dev/spidev1.1";
static uint8_t mode = 0;
static uint8_t bits = 8;
static uint32_t speed = 100000;
static uint16_t delay = 100;

static void transfer(int fd)
{
int ret;
uint8_t tx[] = {
 0x80, 0x00,
};
uint8_t rx[ARRAY_SIZE(tx)] = {0, };
struct spi_ioc_transfer tr = {
 .tx_buf = (unsigned long)tx,
 .rx_buf = (unsigned long)rx,
 .len = 3,
 .delay_usecs = delay,
 .speed_hz = speed,
 .bits_per_word = bits,
};

ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1)
 pabort("can't send spi message");

for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
 if (!(ret % 6))
  puts("");
 printf("%.2X ", rx[ret]);
}
puts("");
}

static void print_usage(const char *prog)
{
printf("Usage: %s [-DsbdlHOLC3]\n", prog);
puts("  -D --device  device to use (default /dev/spidev1.1)\n"
    "  -s --speed    max speed (Hz)\n"
    "  -d --delay    delay (usec)\n"
    "  -b --bpw      bits per word \n"
    "  -l --loop    loopback\n"
    "  -H --cpha    clock phase\n"
    "  -O --cpol    clock polarity\n"
    "  -L --lsb      least significant bit first\n"
    "  -C --cs-high  chip select active high\n"
    "  -3 --3wire    SI/SO signals shared\n");
exit(1);
}

static void parse_opts(int argc, char *argv[])
{
while (1) {

 static const struct option lopts[] = {
  { "device",  1, 0, 'D' },
  { "speed",  1, 0, 's' },
  { "delay",  1, 0, 'd' },
  { "bpw",    1, 0, 'b' },
  { "loop",    0, 0, 'l' },
  { "cpha",    0, 0, 'H' },
  { "cpol",    0, 0, 'O' },
  { "lsb",    0, 0, 'L' },
  { "cs-high", 0, 0, 'C' },
  { "3wire",  0, 0, '3' },
  { "no-cs",  0, 0, 'N' },
  { "ready",  0, 0, 'R' },
  { NULL, 0, 0, 0 },
 };
 
 int c;
 
 c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
 
 if (c == -1)
  break;
 
 switch (c) {
 case 'D':
  device = optarg;
  break;
 
 case 's':
  speed = atoi(optarg);
  break;
 case 'd':
  delay = atoi(optarg);
  break;
 case 'b':
  bits = atoi(optarg);
  break;
 case 'l':
  mode |= SPI_LOOP;
  break;
 case 'H':
  mode |= SPI_CPHA;
  break;
 case 'O':
  mode |= SPI_CPOL;
  break;
 case 'L':
  mode |= SPI_LSB_FIRST;
  break;
 case 'C':
  mode |= SPI_CS_HIGH;
  break;
 case '3':
  mode |= SPI_3WIRE;
  break;

 case 'N':
  //mode |= SPI_NO_CS;
  break;

 case 'R':
  //mode |= SPI_READY;
  break;
 default:
  print_usage(argv[0]);
  break;
 }
}
}

int main(int argc, char *argv[])
{
int ret = 0;
int fd;

parse_opts(argc, argv);

fd = open(device, O_RDWR);
if (fd < 0)
 pabort("can't open device");

/*
 * spi mode
 */
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
 pabort("can't set spi mode");

ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
 pabort("can't get spi mode");

/*
 * bits per word
 */
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
 pabort("can't set bits per word");

ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
 pabort("can't get bits per word");

/*
 * max speed hz
 */
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
 pabort("can't set max speed hz");

ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
 pabort("can't get max speed hz");

printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);

transfer(fd);

close(fd);

return ret;
}


pippalla 12-21-2023 02:27 AM

Hi @chickenwing101 ,

Good Day!

I am also trying to grab information from an ICM-20948 IMU sensor Using SPI.

In my case i used the same code you used for reading the WHO_AM_I register.MISO Always returing the 0xFF 0xFFF

I hope you had an improvement in your side , please help on this same or if you share the piece of code also find


Thanks regards
Pippalla


All times are GMT -5. The time now is 09:03 PM.