[PATCH rtems 5/9] shell: Add i2c and spi commands

Gedare Bloom gedare at rtems.org
Tue Nov 17 17:32:34 UTC 2020


These should be reviewed separately from the BSP addition. I'm not
really that good with the shell, so it would take me some time.

On Tue, Nov 17, 2020 at 4:05 AM Christian Mauderer
<christian.mauderer at embedded-brains.de> wrote:
>
> 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.
> ---
>  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 ++++++++++++++++++++++++++
>  spec/build/cpukit/objshell.yml        |   4 +
>  7 files changed, 569 insertions(+)
>  create mode 100644 cpukit/libmisc/shell/main_i2cdetect.c
>  create mode 100644 cpukit/libmisc/shell/main_i2cget.c
>  create mode 100644 cpukit/libmisc/shell/main_i2cset.c
>  create mode 100644 cpukit/libmisc/shell/main_spi.c
>
> diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am
> index 4e370ae639..2adfcf933f 100644
> --- a/cpukit/Makefile.am
> +++ b/cpukit/Makefile.am
> @@ -1495,6 +1495,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 3e87d472d6..c5fcf4a45e 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 0000000000..e953b4eaef
> --- /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 0000000000..ffa551308b
> --- /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 0000000000..d9025b3b28
> --- /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 0000000000..487a22fc6c
> --- /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,
> +};
> diff --git a/spec/build/cpukit/objshell.yml b/spec/build/cpukit/objshell.yml
> index 2ddcbd3053..dac735a274 100644
> --- a/spec/build/cpukit/objshell.yml
> +++ b/spec/build/cpukit/objshell.yml
> @@ -56,6 +56,9 @@ source:
>  - cpukit/libmisc/shell/main_halt.c
>  - cpukit/libmisc/shell/main_help.c
>  - cpukit/libmisc/shell/main_hexdump.c
> +- cpukit/libmisc/shell/main_i2cdetect.c
> +- cpukit/libmisc/shell/main_i2cget.c
> +- cpukit/libmisc/shell/main_i2cset.c
>  - cpukit/libmisc/shell/main_id.c
>  - cpukit/libmisc/shell/main_ln.c
>  - cpukit/libmisc/shell/main_logoff.c
> @@ -82,6 +85,7 @@ source:
>  - cpukit/libmisc/shell/main_rtrace.c
>  - cpukit/libmisc/shell/main_setenv.c
>  - cpukit/libmisc/shell/main_sleep.c
> +- cpukit/libmisc/shell/main_spi.c
>  - cpukit/libmisc/shell/main_stackuse.c
>  - cpukit/libmisc/shell/main_time.c
>  - cpukit/libmisc/shell/main_top.c
> --
> 2.26.2
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel


More information about the devel mailing list