[rtems commit] shell: Add i2c and spi commands

Joel Sherrill joel at rtems.org
Tue Apr 6 13:24:48 UTC 2021


Just a reminder that there is a Shell Manual and these commands should be
in there.

--joel

On Tue, Apr 6, 2021 at 8:16 AM Jan Sommer <jan at rtems.org> wrote:

> Module:    rtems
> Branch:    5
> Commit:    a274b6fdcb7b39b3d67aad33dba0360a47f20204
> Changeset:
> http://git.rtems.org/rtems/commit/?id=a274b6fdcb7b39b3d67aad33dba0360a47f20204
>
> Author:    Christian Mauderer <christian.mauderer at embedded-brains.de>
> Date:      Wed Nov 18 08:36:48 2020 +0100
>
> shell: Add i2c and spi commands
>
> This adds some commands that are usefull for debugging simple serial
> interfaces.
>
> Even if they are a complete re-implementation, the i2c* commands use a
> simmilar call like the Linux i2c tools.
>
> Closes #4371
>
> ---
>
>  cpukit/Makefile.am                    |   4 +
>  cpukit/include/rtems/shellconfig.h    |  28 ++++++
>  cpukit/libmisc/shell/main_i2cdetect.c | 107 +++++++++++++++++++++++
>  cpukit/libmisc/shell/main_i2cget.c    | 145
> +++++++++++++++++++++++++++++++
>  cpukit/libmisc/shell/main_i2cset.c    | 124 +++++++++++++++++++++++++++
>  cpukit/libmisc/shell/main_spi.c       | 157
> ++++++++++++++++++++++++++++++++++
>  6 files changed, 565 insertions(+)
>
> diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
> index 51f38c8..18eda95 100644
> --- a/cpukit/Makefile.am
> +++ b/cpukit/Makefile.am
> @@ -1483,6 +1483,10 @@ librtemscpu_a_SOURCES +=
> libmisc/shell/login_prompt.c
>  librtemscpu_a_SOURCES += libmisc/shell/login_check.c
>  librtemscpu_a_SOURCES += libmisc/shell/fdisk.c
>  librtemscpu_a_SOURCES += libmisc/shell/main_rtc.c
> +librtemscpu_a_SOURCES += libmisc/shell/main_spi.c
> +librtemscpu_a_SOURCES += libmisc/shell/main_i2cdetect.c
> +librtemscpu_a_SOURCES += libmisc/shell/main_i2cset.c
> +librtemscpu_a_SOURCES += libmisc/shell/main_i2cget.c
>  librtemscpu_a_SOURCES += libmisc/shell/dd-args.c
>  librtemscpu_a_SOURCES += libmisc/shell/main_dd.c
>  librtemscpu_a_SOURCES += libmisc/shell/dd-conv.c
> diff --git a/cpukit/include/rtems/shellconfig.h
> b/cpukit/include/rtems/shellconfig.h
> index 3e87d47..c5fcf4a 100644
> --- a/cpukit/include/rtems/shellconfig.h
> +++ b/cpukit/include/rtems/shellconfig.h
> @@ -78,6 +78,10 @@ extern rtems_shell_cmd_t rtems_shell_DF_Command;
>  extern rtems_shell_cmd_t rtems_shell_MD5_Command;
>
>  extern rtems_shell_cmd_t rtems_shell_RTC_Command;
> +extern rtems_shell_cmd_t rtems_shell_SPI_Command;
> +extern rtems_shell_cmd_t rtems_shell_I2CDETECT_Command;
> +extern rtems_shell_cmd_t rtems_shell_I2CGET_Command;
> +extern rtems_shell_cmd_t rtems_shell_I2CSET_Command;
>
>  extern rtems_shell_cmd_t rtems_shell_SHUTDOWN_Command;
>  extern rtems_shell_cmd_t rtems_shell_CPUINFO_Command;
> @@ -521,6 +525,30 @@ extern rtems_shell_alias_t * const
> rtems_shell_Initial_aliases[];
>        &rtems_shell_RTC_Command,
>      #endif
>
> +    #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) \
> +          && !defined(CONFIGURE_SHELL_NO_COMMAND_SPI)) \
> +        || defined(CONFIGURE_SHELL_COMMAND_SPI)
> +      &rtems_shell_SPI_Command,
> +    #endif
> +
> +    #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) \
> +          && !defined(CONFIGURE_SHELL_NO_COMMAND_I2CDETECT)) \
> +        || defined(CONFIGURE_SHELL_COMMAND_I2CDETECT)
> +      &rtems_shell_I2CDETECT_Command,
> +    #endif
> +
> +    #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) \
> +          && !defined(CONFIGURE_SHELL_NO_COMMAND_I2CGET)) \
> +        || defined(CONFIGURE_SHELL_COMMAND_I2CGET)
> +      &rtems_shell_I2CGET_Command,
> +    #endif
> +
> +    #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) \
> +          && !defined(CONFIGURE_SHELL_NO_COMMAND_I2CSET)) \
> +        || defined(CONFIGURE_SHELL_COMMAND_I2CSET)
> +      &rtems_shell_I2CSET_Command,
> +    #endif
> +
>      /*
>       *  System related commands
>       */
> diff --git a/cpukit/libmisc/shell/main_i2cdetect.c
> b/cpukit/libmisc/shell/main_i2cdetect.c
> new file mode 100644
> index 0000000..e953b4e
> --- /dev/null
> +++ b/cpukit/libmisc/shell/main_i2cdetect.c
> @@ -0,0 +1,107 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (C) 2020 embedded brains GmbH.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +/*
> + * The command implemented here has a similar interface like the one from
> Linux
> + * i2c tools. Think of it as a heavily simplified version of them.
> Instead of
> + * the bus number they expect a bus path.
> + */
> +
> +#include <dev/i2c/i2c.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +#include <rtems/shell.h>
> +
> +static const char rtems_i2cdetect_shell_usage [] =
> +  "i2cdetect <I2C_BUS>\n"
> +  "\ttry to detect i2c devices on the given bus\n";
> +
> +static int rtems_i2cdetect_shell_main(int argc, char *argv[])
> +{
> +  int fd;
> +  int rv;
> +  const char *bus;
> +  const uint16_t first = 1;
> +  const uint16_t last = 0x7f;
> +  uint16_t current;
> +
> +  if (argc != 2 || strcmp(argv[1], "-h") == 0) {
> +    printf(rtems_i2cdetect_shell_usage);
> +    return 1;
> +  }
> +
> +  bus = argv[1];
> +  fd = open(bus, O_RDWR);
> +  if (fd < 0) {
> +    perror("Couldn't open bus");
> +    return 1;
> +  }
> +
> +  printf("    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF\n"
> +         "0x    ");
> +  for (current = first; current <= last; ++current) {
> +    i2c_msg msg = {
> +      .addr = current,
> +      .flags = 0,
> +      .len = 0,
> +      .buf = NULL,
> +    };
> +
> +    struct i2c_rdwr_ioctl_data payload = {
> +      .msgs = &msg,
> +      .nmsgs = 1,
> +    };
> +
> +    if ((current & 0x0F) == 0) {
> +      printf("\n%1xx ", current >> 4);
> +    }
> +
> +    rv = ioctl(fd, I2C_RDWR, &payload);
> +    if (rv < 0) {
> +      if (errno != EIO) {
> +        perror("ioctl failed");
> +      }
> +      printf(" --");
> +    } else {
> +      printf(" %02x", current);
> +    }
> +  }
> +  printf("\n");
> +  close(fd);
> +
> +  return 0;
> +}
> +
> +rtems_shell_cmd_t rtems_shell_I2CDETECT_Command = {
> +  .name = "i2cdetect",
> +  .usage = rtems_i2cdetect_shell_usage,
> +  .topic = "misc",
> +  .command = rtems_i2cdetect_shell_main,
> +};
> diff --git a/cpukit/libmisc/shell/main_i2cget.c
> b/cpukit/libmisc/shell/main_i2cget.c
> new file mode 100644
> index 0000000..ffa5513
> --- /dev/null
> +++ b/cpukit/libmisc/shell/main_i2cget.c
> @@ -0,0 +1,145 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (C) 2020 embedded brains GmbH.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +/*
> + * The command implemented here has a similar interface like the one from
> Linux
> + * i2c tools. Think of it as a heavily simplified version of them.
> Instead of
> + * the bus number they expect a bus path.
> + *
> + * Additionally the i2cget has a continuous read mode that isn't
> available on
> + * Linux but does something similar to i2cdump.
> + */
> +
> +#include <dev/i2c/i2c.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +#include <rtems/shell.h>
> +
> +static const char rtems_i2cget_shell_usage [] =
> +  "i2cget <I2C_BUS> <CHIP-ADDRESS> <DATA-ADDRESS> [<NR-BYTES>]\n"
> +  "\tGet one or more bytes from an EEPROM like i2c device.\n"
> +  "\tNote that multiple bytes will be read in continuous mode.\n";
> +
> +static int read_bytes(
> +  int fd,
> +  uint16_t i2c_address,
> +  uint8_t data_address,
> +  uint16_t nr_bytes
> +)
> +{
> +  int rv;
> +  uint8_t value[nr_bytes];
> +  i2c_msg msgs[] = {{
> +    .addr = i2c_address,
> +    .flags = 0,
> +    .buf = &data_address,
> +    .len = 1,
> +  }, {
> +    .addr = i2c_address,
> +    .flags = I2C_M_RD,
> +    .buf = value,
> +    .len = nr_bytes,
> +  }};
> +  struct i2c_rdwr_ioctl_data payload = {
> +    .msgs = msgs,
> +    .nmsgs = sizeof(msgs)/sizeof(msgs[0]),
> +  };
> +  uint16_t i;
> +
> +  rv = ioctl(fd, I2C_RDWR, &payload);
> +  if (rv < 0) {
> +    perror("ioctl failed");
> +  } else {
> +    for (i = 0; i < nr_bytes; ++i) {
> +      printf("0x%02x ", value[i]);
> +    }
> +    printf("\n");
> +  }
> +
> +  return rv;
> +}
> +
> +static int rtems_i2cget_shell_main(int argc, char *argv[])
> +{
> +  int fd;
> +  int rv;
> +  const char *bus;
> +  uint16_t chip_address;
> +  uint8_t data_address;
> +  uint16_t nr_bytes;
> +
> +  if (argc < 4 || argc > 5) {
> +    printf(rtems_i2cget_shell_usage);
> +    return 1;
> +  }
> +
> +  errno = 0;
> +  chip_address = (uint16_t) strtoul(argv[2], NULL, 0);
> +  if (errno != 0) {
> +    perror("Couldn't read chip address");
> +    return 1;
> +  }
> +
> +  errno = 0;
> +  data_address = (uint8_t) strtoul(argv[3], NULL, 0);
> +  if (errno != 0) {
> +    perror("Couldn't read data address");
> +    return 1;
> +  }
> +
> +  nr_bytes = 1;
> +  if (argc == 5) {
> +    errno = 0;
> +    nr_bytes = (uint16_t) strtoul(argv[4], NULL, 0);
> +    if (errno != 0) {
> +      perror("Couldn't read number of bytes");
> +      return 1;
> +    }
> +  }
> +
> +  bus = argv[1];
> +  fd = open(bus, O_RDWR);
> +  if (fd < 0) {
> +    perror("Couldn't open bus");
> +    return 1;
> +  }
> +
> +  rv = read_bytes(fd, chip_address, data_address, nr_bytes);
> +
> +  close(fd);
> +
> +  return rv;
> +}
> +
> +rtems_shell_cmd_t rtems_shell_I2CGET_Command = {
> +  .name = "i2cget",
> +  .usage = rtems_i2cget_shell_usage,
> +  .topic = "misc",
> +  .command = rtems_i2cget_shell_main,
> +};
> diff --git a/cpukit/libmisc/shell/main_i2cset.c
> b/cpukit/libmisc/shell/main_i2cset.c
> new file mode 100644
> index 0000000..d9025b3
> --- /dev/null
> +++ b/cpukit/libmisc/shell/main_i2cset.c
> @@ -0,0 +1,124 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (C) 2020 embedded brains GmbH.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +/*
> + * The command implemented here has a similar interface like the one from
> Linux
> + * i2c tools. Think of it as a heavily simplified version of them.
> Instead of
> + * the bus number they expect a bus path.
> + *
> + * Additionally it is possible to write multiple values as a continuous
> write.
> + */
> +
> +#include <dev/i2c/i2c.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +#include <rtems/shell.h>
> +
> +static const char rtems_i2cset_shell_usage [] =
> +  "i2cset <I2C_BUS> <CHIP-ADDRESS> <DATA-ADDRESS> <VALUE> [<VALUE>
> [...]]\n"
> +  "\tset one byte of an EEPROM like i2c device\n";
> +
> +static int
> +rtems_i2cset_shell_main(int argc, char *argv[])
> +{
> +  int fd;
> +  int rv;
> +  const char *bus;
> +  uint16_t chip_address;
> +  /* Necessary: data-address and values. This will be a bit more. */
> +  uint8_t writebuff[argc];
> +  size_t len;
> +  size_t i;
> +  i2c_msg msgs[] = {{
> +    .flags = 0,
> +    .buf = writebuff,
> +    .len = 0,
> +  }};
> +  struct i2c_rdwr_ioctl_data payload = {
> +    .msgs = msgs,
> +    .nmsgs = sizeof(msgs)/sizeof(msgs[0]),
> +  };
> +
> +  if (argc < 5) {
> +    printf(rtems_i2cset_shell_usage);
> +    return 1;
> +  }
> +
> +  errno = 0;
> +  chip_address = (uint16_t) strtoul(argv[2], NULL, 0);
> +  if (errno != 0) {
> +    perror("Couldn't read CHIP_ADDRESS");
> +    return 1;
> +  }
> +  msgs[0].addr = chip_address;
> +
> +  errno = 0;
> +  writebuff[0] = (uint8_t) strtoul(argv[3], NULL, 0);
> +  if (errno != 0) {
> +    perror("Couldn't read DATA_ADDRESS");
> +    return 1;
> +  }
> +
> +  /* Read values starting from the fifth argument (index 4) */
> +  i = 4;
> +  len = 0;
> +  while (i < argc) {
> +    errno = 0;
> +    writebuff[len + 1] = (uint8_t) strtoul(argv[i], NULL, 0);
> +    if (errno != 0) {
> +      perror("Couldn't read VALUE");
> +      return 1;
> +    }
> +    ++i;
> +    ++len;
> +  }
> +  msgs[0].len = len + 1; /* Don't forget address */
> +
> +  bus = argv[1];
> +  fd = open(bus, O_RDWR);
> +  if (fd < 0) {
> +    perror("Couldn't open bus");
> +    return 1;
> +  }
> +
> +  rv = ioctl(fd, I2C_RDWR, &payload);
> +  if (rv < 0) {
> +    perror("ioctl failed");
> +  }
> +  close(fd);
> +
> +  return rv;
> +}
> +
> +rtems_shell_cmd_t rtems_shell_I2CSET_Command = {
> +  .name = "i2cset",
> +  .usage = rtems_i2cset_shell_usage,
> +  .topic = "misc",
> +  .command = rtems_i2cset_shell_main,
> +};
> diff --git a/cpukit/libmisc/shell/main_spi.c
> b/cpukit/libmisc/shell/main_spi.c
> new file mode 100644
> index 0000000..487a22f
> --- /dev/null
> +++ b/cpukit/libmisc/shell/main_spi.c
> @@ -0,0 +1,157 @@
> +/*
> + * SPDX-License-Identifier: BSD-2-Clause
> + *
> + * Copyright (C) 2020 embedded brains GmbH.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
> THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
> BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
> BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
> THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#include <dev/spi/spi.h>
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +
> +#include <rtems/shell.h>
> +
> +static const char rtems_spi_shell_usage [] =
> +  "simple SPI read / write\n"
> +  "\n"
> +  "spi [-loh] [-c <cs>] [-s <speed>] [-m <mode>] <SPI_BUS> xx [xx [..]]\n"
> +  "    <SPI_BUS>  Bus device to use\n"
> +  "    xx         Hex value of a byte to send\n"
> +  "    -c <cs>    Use chip select <cs> (default: None)\n"
> +  "    -m <mode>  Use SPI mode <mode> (default: 0)\n"
> +  "    -l         Send LSB first\n"
> +  "    -o         Use loopback mode\n"
> +  "    -s <speed> Bus speed in hz\n"
> +  "    -h         Print this help\n";
> +
> +static int rtems_spi_shell_main(int argc, char *argv[])
> +{
> +  uint8_t buffer[argc - 1];
> +  size_t len = 0;
> +  int i;
> +  size_t j;
> +  int rv;
> +  int fd;
> +  char *bus = NULL;
> +  unsigned long mode;
> +  spi_ioc_transfer msg = {
> +    .len = 0,
> +    .rx_buf = buffer,
> +    .tx_buf = buffer,
> +    .speed_hz = 100000,
> +    .bits_per_word = 8,
> +    .cs_change = true,
> +    .mode = SPI_MODE_0 | SPI_NO_CS,
> +  };
> +
> +  for (i = 1; i < argc; ++i) {
> +    if (argv[i][0] == '-') {
> +      switch (argv[i][1]) {
> +      case ('c'):
> +        errno = 0;
> +        msg.mode &= ~SPI_NO_CS;
> +        msg.cs = (uint8_t) strtoul(argv[i+1], NULL, 0);
> +        ++i;
> +        if (errno != 0) {
> +          printf("Couldn't process chip select\n");
> +          return 1;
> +        }
> +        break;
> +      case ('m'):
> +        errno = 0;
> +        mode = strtoul(argv[i+1], NULL, 0);
> +        ++i;
> +        if (errno != 0 || mode > 3) {
> +          printf("Couldn't process mode\n");
> +          return 1;
> +        }
> +        msg.mode &= ~(SPI_CPOL | SPI_CPHA);
> +        msg.mode |= mode;
> +        break;
> +      case ('s'):
> +        errno = 0;
> +        msg.speed_hz = (uint32_t) strtoul(argv[i+1], NULL, 0);
> +        ++i;
> +        if (errno != 0) {
> +          printf("Couldn't process speed\n");
> +          return 1;
> +        }
> +        break;
> +      case ('l'):
> +        msg.mode |= SPI_LSB_FIRST;
> +        break;
> +      case ('o'):
> +        msg.mode |= SPI_LOOP;
> +        break;
> +      case ('h'):
> +        /* fallthrough */
> +      default:
> +        printf(rtems_spi_shell_usage);
> +        return 1;
> +      }
> +    } else if (bus == NULL) {
> +      bus = argv[i];
> +    } else {
> +      errno = 0;
> +      buffer[len] = (uint8_t) strtol(argv[i], NULL, 16);
> +      if (errno != 0) {
> +        printf("Couldn't process '%s'\n", argv[i]);
> +        return 1;
> +      }
> +      ++len;
> +    }
> +  }
> +
> +  if (len == 0) {
> +    printf("Nothing to do\n");
> +    return 0;
> +  }
> +
> +  fd = open(bus, O_RDWR);
> +  if (fd < 0) {
> +    perror("Couldn't open bus");
> +    return 1;
> +  }
> +  msg.len = len;
> +  rv = ioctl(fd, SPI_IOC_MESSAGE(1), &msg);
> +  if (rv == -1) {
> +    perror("Couldn't send the message");
> +  } else {
> +    printf("received:");
> +    for (j = 0; j < len; ++j) {
> +      printf(" %02x", buffer[j]);
> +    }
> +    printf("\n");
> +  }
> +  close(fd);
> +
> +  return 0;
> +}
> +
> +rtems_shell_cmd_t rtems_shell_SPI_Command = {
> +  .name = "spi",
> +  .usage = rtems_spi_shell_usage,
> +  .topic = "misc",
> +  .command = rtems_spi_shell_main,
> +};
>
> _______________________________________________
> vc mailing list
> vc at rtems.org
> http://lists.rtems.org/mailman/listinfo/vc
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20210406/4b458436/attachment-0001.html>


More information about the devel mailing list