[PATCH] cpukit/dev/can: Added CAN support (Prashanth S)

Prashanth S fishesprashanth at gmail.com
Sun Jul 31 11:58:52 UTC 2022


Hi All,

This is a review request for CAN support. I have addressed the review
comments.

The files are work in progress, I need to add few more comments
in the include (*.h) files.

Regards
Prashanth S

On Sun, 31 Jul 2022 at 17:24, <devel-request at rtems.org> wrote:

> Send devel mailing list submissions to
>         devel at rtems.org
>
> To subscribe or unsubscribe via the World Wide Web, visit
>         http://lists.rtems.org/mailman/listinfo/devel
> or, via email, send a message with subject or body 'help' to
>         devel-request at rtems.org
>
> You can reach the person managing the list at
>         devel-owner at rtems.org
>
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of devel digest..."
>
>
> Today's Topics:
>
>    1. Re: [PATCH v5 1/4] bsps/stm32f4 Include STM32F4 HAL (Karel Gardas)
>    2. Re: [PATCH v5 1/4] bsps/stm32f4 Include STM32F4 HAL
>       (oss at c-mauderer.de)
>    3. [PATCH] cpukit/dev/can: Added CAN support (Prashanth S)
>
>
> ----------------------------------------------------------------------
>
> Message: 1
> Date: Sat, 30 Jul 2022 21:41:19 +0200
> From: Karel Gardas <karel at functional.vision>
> To: oss at c-mauderer.de, Duc Doan <dtbpkmte at gmail.com>, devel at rtems.org
> Subject: Re: [PATCH v5 1/4] bsps/stm32f4 Include STM32F4 HAL
> Message-ID: <2af4f901-b157-c0b0-cc75-45921bf788eb at functional.vision>
> Content-Type: text/plain; charset=UTF-8; format=flowed
>
> On 7/30/22 16:32, oss at c-mauderer.de wrote:
> >> ? bsps/arm/include/cmsis_compiler.h???????????? |?? 266 +
> >> ? bsps/arm/include/cmsis_gcc.h????????????????? |? 3460 +--
> >> ? bsps/arm/include/cmsis_version.h????????????? |??? 39 +
> >> ? bsps/arm/include/core_cm4.h?????????????????? |?? 524 +-
> >> ? bsps/arm/include/core_cm7.h?????????????????? |? 5186 ++--
> >> ? bsps/arm/include/mpu_armv7.h????????????????? |?? 270 +
> >
> > Are the cmsis files from the same source or directly from ARM?
> >
> > The cmsis_gcc.h has a lot of changes compared to the earlier version
> > that has been present in RTEMS. A lot of the changes seem to be
> > whitespace changes. Can these be avoided somehow (for example by using
> > dos2unix before overwriting the file)?
> >
> > In the discord chat there was one suggestion from Ho Kaido to move the
> > files one level down and make them BSP specific. I'm not sure whether
> > I'm for or against that idea. Advantage is that it makes BSPs
> > independant from each other. Disadvantage is that it duplicates code.
> >
> > I think I would try to avoid moving them down due to the code
> > duplication but it raises the question: Which BSPs use the files too and
> > did you try whether they still compile after the upgrade?
>
> We have had this dicussion with Duc on discord IIRC when he started. He
> needed new CMSIS (v5) version due to new HAL which Duc claims depends on
> them. I have not verified that claim personally.
>
> New CMSIS v5 brings obviously:
>
> - by ARM maintained code (v4 is unmaintained IIRC)
>
> but also:
>
> - license change from BSD to Apache-2
>
> At that time I've told Duc to continue with the code and not to worry
> about license changes -- as this would be longer discussion anyway. Not
> sure, but IIRC he also wrote to Sebastian asking for clarification --
> well, not sure about that. Certainly IIRC I suggested that.
>
> Anyway, I took Duc code and try H7 BSPs and to my surprise they compiles
> more or less all without any compilation related issue. Well, I've not
> tried M4 variants. So far I've not run full tester on this. I'll, but
> first I'd like to test his API if it's possible to also use with H7.
>
> BTW: if RTEMS prefer old unmaintained BSD-3 ARM CSMIS code, then it's
> perhaps possible to go in F4 HAL history back and grab just the three
> with the v4 dependency. On the other hand, for ARM Apache-2 seems to be
> the way forward and for some ST.com depended code too -- so I guess
> RTEMS project will need to live with that fact somehow.
>
> Thanks,
> Karel
>
>
> ------------------------------
>
> Message: 2
> Date: Sat, 30 Jul 2022 22:19:54 +0200
> From: oss at c-mauderer.de
> To: Karel Gardas <karel at functional.vision>, Duc Doan
>         <dtbpkmte at gmail.com>, devel at rtems.org
> Subject: Re: [PATCH v5 1/4] bsps/stm32f4 Include STM32F4 HAL
> Message-ID: <3628b5b2-0848-304f-9738-f6d64e9bb05a at c-mauderer.de>
> Content-Type: text/plain; charset=UTF-8; format=flowed
>
>
>
>
> Am 30.07.22 um 21:41 schrieb Karel Gardas:
> > On 7/30/22 16:32, oss at c-mauderer.de wrote:
> >>> ? bsps/arm/include/cmsis_compiler.h???????????? |?? 266 +
> >>> ? bsps/arm/include/cmsis_gcc.h????????????????? |? 3460 +--
> >>> ? bsps/arm/include/cmsis_version.h????????????? |??? 39 +
> >>> ? bsps/arm/include/core_cm4.h?????????????????? |?? 524 +-
> >>> ? bsps/arm/include/core_cm7.h?????????????????? |? 5186 ++--
> >>> ? bsps/arm/include/mpu_armv7.h????????????????? |?? 270 +
> >>
> >> Are the cmsis files from the same source or directly from ARM?
> >>
> >> The cmsis_gcc.h has a lot of changes compared to the earlier version
> >> that has been present in RTEMS. A lot of the changes seem to be
> >> whitespace changes. Can these be avoided somehow (for example by using
> >> dos2unix before overwriting the file)?
> >>
> >> In the discord chat there was one suggestion from Ho Kaido to move the
> >> files one level down and make them BSP specific. I'm not sure whether
> >> I'm for or against that idea. Advantage is that it makes BSPs
> >> independant from each other. Disadvantage is that it duplicates code.
> >>
> >> I think I would try to avoid moving them down due to the code
> >> duplication but it raises the question: Which BSPs use the files too
> >> and did you try whether they still compile after the upgrade?
> >
> > We have had this dicussion with Duc on discord IIRC when he started. He
> > needed new CMSIS (v5) version due to new HAL which Duc claims depends on
> > them. I have not verified that claim personally.
> >
> > New CMSIS v5 brings obviously:
> >
> > - by ARM maintained code (v4 is unmaintained IIRC)
> >
> > but also:
> >
> > - license change from BSD to Apache-2
> >
> > At that time I've told Duc to continue with the code and not to worry
> > about license changes -- as this would be longer discussion anyway. Not
> > sure, but IIRC he also wrote to Sebastian asking for clarification --
> > well, not sure about that. Certainly IIRC I suggested that.
> >
> > Anyway, I took Duc code and try H7 BSPs and to my surprise they compiles
> > more or less all without any compilation related issue. Well, I've not
> > tried M4 variants. So far I've not run full tester on this. I'll, but
> > first I'd like to test his API if it's possible to also use with H7.
> >
> > BTW: if RTEMS prefer old unmaintained BSD-3 ARM CSMIS code, then it's
> > perhaps possible to go in F4 HAL history back and grab just the three
> > with the v4 dependency. On the other hand, for ARM Apache-2 seems to be
> > the way forward and for some ST.com depended code too -- so I guess
> > RTEMS project will need to live with that fact somehow.
> >
> > Thanks,
> > Karel
> >
>
> Hello Karel,
>
> thanks for the clarification. I have to be honest: I missed the license
> change. That is a bit of a difficult one and will cause a discussion.
> @Duc: We need a new LICENSE.... file in the top level that represents
> that. Maybe split the CMSIS update into a separate patch so that it is
> clear why there is a new license file (if the license is only for the
> CMSIS and not for the STM HAL too).
>
> But my main concern was another one: Which BSPs use the CMSIS files?
> Beneath the stm32 variants, that's at least the atsam and imxrt. Maybe I
> missed some more. We should at least make sure that these BSPs are
> compile-clean with the updated cmsis headers.
>
> Best regards
>
> Christian
>
>
> ------------------------------
>
> Message: 3
> Date: Sun, 31 Jul 2022 17:23:51 +0530
> From: Prashanth S <fishesprashanth at gmail.com>
> To: devel at rtems.org
> Cc: Prashanth S <fishesprashanth at gmail.com>
> Subject: [PATCH] cpukit/dev/can: Added CAN support
> Message-ID: <20220731115351.23992-1-fishesprashanth at gmail.com>
>
> ---
>  cpukit/dev/can/can.c               | 514 +++++++++++++++++++++++++++++
>  cpukit/include/dev/can/can-msg.h   |  55 +++
>  cpukit/include/dev/can/can-queue.h | 127 +++++++
>  cpukit/include/dev/can/can.h       | 102 ++++++
>  spec/build/cpukit/librtemscpu.yml  |   6 +
>  5 files changed, 804 insertions(+)
>  create mode 100644 cpukit/dev/can/can.c
>  create mode 100644 cpukit/include/dev/can/can-msg.h
>  create mode 100644 cpukit/include/dev/can/can-queue.h
>  create mode 100644 cpukit/include/dev/can/can.h
>
> diff --git a/cpukit/dev/can/can.c b/cpukit/dev/can/can.c
> new file mode 100644
> index 0000000000..8feec8800b
> --- /dev/null
> +++ b/cpukit/dev/can/can.c
> @@ -0,0 +1,514 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +
> +/**
> + * @file
> + *
> + * @ingroup CANBus
> + *
> + * @brief Controller Area Network (CAN) Bus Implementation
> + *
> + */
> +
> +/*
> + * Copyright (C) 2022 Prashanth S (fishesprashanth at gmail.com)
> + *
> + * 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 <rtems/imfs.h>
> +#include <rtems/thread.h>
> +
> +#include <dev/can/can-queue.h>
> +#include <dev/can/can.h>
> +
> +#include <string.h>
> +#include <stdlib.h>
> +
> +#include <fcntl.h>
> +
> +static ssize_t
> +can_bus_open(rtems_libio_t *iop, const char *path, int oflag, mode_t
> mode);
> +static ssize_t
> +can_bus_read(rtems_libio_t *iop, void *buffer, size_t count);
> +static ssize_t
> +can_bus_write(rtems_libio_t *iop, const void *buffer, size_t count);
> +static ssize_t
> +can_bus_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer);
> +
> +static int can_xmit(struct can_bus *bus);
> +
> +static int can_create_sem(struct can_bus *);
> +static int try_sem(struct can_bus *);
> +static int take_sem(struct can_bus *);
> +static int give_sem(struct can_bus *);
> +
> +/* sem_count this is for debug purpose, for debugging
> +the take_sem and give_sem
> +*/
> +static int sem_count = 0;
> +
> +static void can_bus_obtain(can_bus *bus)
> +{
> +  rtems_recursive_mutex_lock(&bus->mutex);
> +}
> +
> +static void can_bus_release(can_bus *bus)
> +{
> +  rtems_recursive_mutex_unlock(&bus->mutex);
> +}
> +
> +int can_create_sem(struct can_bus *bus)
> +{
> +  int ret = 0;
> +
> +  ret = rtems_semaphore_create(rtems_build_name('c', 'a', 'n',
> bus->index),
> +      CAN_TX_BUF_COUNT, RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE |
> RTEMS_LOCAL,
> +      0, &bus->tx_fifo_sem_id);
> +
> +  if (ret != 0) {
> +    printf("can_create_sem: rtems_semaphore_create failed %d\n", ret);
> +  }
> +
> +  return ret;
> +}
> +
> +static void can_interrupt_lock_acquire(struct can_bus *bus)
> +{
> +  can_bus_obtain(bus);
> +  bus->can_dev_ops->dev_int(bus->priv, false);
> +}
> +
> +static void can_interrupt_lock_release(struct can_bus *bus)
> +{
> +  bus->can_dev_ops->dev_int(bus->priv, true);
> +  can_bus_release(bus);
> +}
> +
> +static int take_sem(struct can_bus *bus)
> +{
> +  int ret = rtems_semaphore_obtain(bus->tx_fifo_sem_id, RTEMS_WAIT,
> +                                RTEMS_NO_TIMEOUT);
> +  if (ret == RTEMS_SUCCESSFUL) {
> +    CAN_DEBUG_LOCK("take_sem: Counting semaphore count = %d\n",
> ++sem_count);
> +    if (sem_count > CAN_TX_BUF_COUNT) {
> +      printf("take_sem error: sem_count is misleading\n");
> +      while (1);
> +    }
> +  }
> +
> +  return ret;
> +}
> +
> +static int give_sem(struct can_bus *bus)
> +{
> +  int ret = rtems_semaphore_release(bus->tx_fifo_sem_id);
> +  if (ret == RTEMS_SUCCESSFUL) {
> +    CAN_DEBUG_LOCK("give_sem: Counting semaphore count = %d\n",
> --sem_count);
> +    if (sem_count < 0) {
> +      printf("give_sem error: sem_count is misleading\n");
> +      while (1);
> +    }
> +  }
> +
> +  return ret;
> +}
> +
> +static int try_sem(struct can_bus *bus)
> +{
> +  int ret = rtems_semaphore_obtain(bus->tx_fifo_sem_id, RTEMS_NO_WAIT,
> +                                RTEMS_NO_TIMEOUT);
> +  if (ret == RTEMS_SUCCESSFUL) {
> +    CAN_DEBUG_LOCK("take_sem: Counting semaphore count = %d\n",
> ++sem_count);
> +    if (sem_count > CAN_TX_BUF_COUNT) {
> +      printf("take_sem error: sem_count is misleading\n");
> +      while (1);
> +    }
> +  }
> +
> +  return ret;
> +}
> +
> +static ssize_t
> +can_bus_open(rtems_libio_t *iop, const char *path, int oflag, mode_t mode)
> +{
> +/*
> +  can_bus *bus = IMFS_generic_get_context_by_iop(iop);
> +
> +  if (bus == NULL) {
> +    return -RTEMS_NOT_DEFINED;
> +  }
> +*/
> +  return 0;
> +}
> +
> +int can_receive(struct can_bus *bus, struct can_msg *msg)
> +{
> +  int32_t ret = 0;
> +
> +  uint32_t count = 0;
> +
> +  ret = rtems_message_queue_broadcast(bus->rx_queue_id, msg,
> CAN_MSGLEN(msg),
> +                                                              &count);
> +  if (ret != RTEMS_SUCCESSFUL) {
> +    CAN_DEBUG_RX("rtems_message_queue_send failed\n");
> +  }
> +
> +  CAN_DEBUG_RX("rtems_message_queue_broadcast = %u\n", count);
> +
> +  return ret;
> +}
> +
> +/* count argument is not used here as struct can_msg has the dlc member */
> +static ssize_t can_bus_read(rtems_libio_t *iop, void *buffer, size_t
> count)
> +{
> +  int32_t ret = 0;
> +  uint32_t flags = 0;
> +
> +  can_bus *bus = IMFS_generic_get_context_by_iop(iop);
> +
> +  if (bus == NULL || bus->can_dev_ops->dev_rx == NULL) {
> +    return -RTEMS_NOT_DEFINED;
> +  }
> +
> +  struct can_msg *msg = (struct can_msg *)buffer;
> +
> +  if ((iop->flags & O_NONBLOCK) != 0) {
> +    flags = RTEMS_NO_WAIT;
> +  }
> +
> +  ret = rtems_message_queue_receive(bus->rx_queue_id, (void *)msg, &count,
> +                                    flags, 0);
> +  if (ret != RTEMS_SUCCESSFUL) {
> +    return ret;
> +  }
> +
> +  return count;
> +}
> +
> +static int can_xmit(struct can_bus *bus)
> +{
> +  int ret = RTEMS_SUCCESSFUL;
> +
> +  struct can_msg *msg = NULL;
> +
> +  while (1) {
> +    CAN_DEBUG_LOCK("can_xmit: acquiring lock\n");
> +    can_interrupt_lock_acquire(bus);
> +
> +    ret = bus->can_dev_ops->dev_tx_ready(bus->priv);
> +    if (ret != true) {
> +      goto return_with_lock_release;
> +    }
> +
> +    msg = can_tx_get_data_buf(bus);
> +    if (msg == NULL) {
> +      goto return_with_lock_release;
> +    }
> +
> +    ret = bus->can_dev_ops->dev_tx(bus->priv, msg);
> +    if (ret != RTEMS_SUCCESSFUL) {
> +        printf("can_xmit: dev_send failed\n");
> +    }
> +
> +    ret = give_sem(bus);
> +    if (ret != RTEMS_SUCCESSFUL) {
> +      printf("can_tx_done: rtems_semaphore_release failed = %d\n", ret);
> +    }
> +
> +    CAN_DEBUG_LOCK("can_xmit: releasing lock\n");
> +    can_interrupt_lock_release(bus);
> +
> +    //can_tx_done(bus);
> +  }
> +
> +  return ret;
> +
> +return_with_lock_release:
> +
> +  CAN_DEBUG_LOCK("can_xmit: releasing lock\n");
> +  can_interrupt_lock_release(bus);
> +
> +  return ret;
> +}
> +
> +void can_print_msg(struct can_msg const *msg)
> +{
> +
> printf("\n----------------------------------------------------------------\n");
> +  printf("id = %d len = %d flags = 0x%08X\n", msg->id, msg->len,
> msg->flags);
> +
> +  for (int i = 0; i < msg->len; i++) {
> +    printf("%02x ", msg->data[i]);
> +  }
> +
> +
> printf("\n-----------------------------------------------------------------\n");
> +}
> +
> +/* can_tx_done should be called only with interrupts disabled */
> +int can_tx_done(struct can_bus *bus)
> +{
> +  int ret = 0;
> +
> +  if (bus->can_dev_ops->dev_tx_ready(bus->priv) == true) {
> +    can_xmit(bus);
> +  }
> +
> +  return ret;
> +}
> +
> +static ssize_t
> +can_bus_write(rtems_libio_t *iop, const void *buffer, size_t count)
> +{
> +  can_bus *bus = IMFS_generic_get_context_by_iop(iop);
> +
> +  if (bus == NULL || bus->can_dev_ops->dev_tx == NULL) {
> +    return -RTEMS_NOT_DEFINED;
> +  }
> +
> +  int32_t ret = 0;
> +
> +  struct can_msg const *msg = buffer;
> +  struct can_msg *fifo_buf = NULL;
> +
> +  CAN_DEBUG_LOCK("can_bus_write: acquiring lock tx_fifo.empty_count\n");
> +  can_interrupt_lock_acquire(bus);
> +  CAN_DEBUG_TX("can_bus_write: empty_count = %u\n",
> bus->tx_fifo.empty_count);
> +  CAN_DEBUG_LOCK("can_bus_write: release lock tx_fifo.empty_count\n");
> +  can_interrupt_lock_release(bus);
> +
> +  if ((iop->flags & O_NONBLOCK) != 0) {
> +    ret = try_sem(bus);
> +    if (ret != RTEMS_SUCCESSFUL) {
> +      return -RTEMS_NO_MEMORY;
> +    }
> +  } else {
> +    CAN_DEBUG_LOCK("can_bus_write: acquiring lock
> can_tx_buf_waiters++\n");
> +    can_interrupt_lock_acquire(bus);
> +    bus->can_tx_buf_waiters++;
> +    CAN_DEBUG_LOCK("can_bus_write: release lock can_tx_buf_waiters++\n");
> +    can_interrupt_lock_release(bus);
> +
> +    ret = take_sem(bus);
> +
> +    CAN_DEBUG_LOCK("can_bus_write: acquiring lock
> can_tx_buf_waiters--\n");
> +    can_interrupt_lock_acquire(bus);
> +    bus->can_tx_buf_waiters--;
> +    CAN_DEBUG_LOCK("can_bus_write: release lock can_tx_buf_waiters--\n");
> +    can_interrupt_lock_release(bus);
> +
> +    if (ret != RTEMS_SUCCESSFUL) {
> +      printf("can_bus_write: cannot take semaphore\n");
> +      ret = -RTEMS_INTERNAL_ERROR;
> +      goto return_from_func;
> +    }
> +  }
> +
> +  /* sleep is for debug purpose to test concurrency issues */
> +  printf("can_bus_write: calling sleep\n");
> +  sleep(1);
> +  printf("can_bus_write: coming out sleep\n");
> +
> +  CAN_DEBUG_LOCK("can_bus_write: acquiring lock can_tx_get_empty_buf\n");
> +  can_interrupt_lock_acquire(bus);
> +  fifo_buf = can_tx_get_empty_buf(bus);
> +  CAN_DEBUG_LOCK("can_bus_write: releasing lock can_tx_get_empty_buf\n");
> +  can_interrupt_lock_release(bus);
> +
> +  if (fifo_buf == NULL) {
> +    printf("can_bus_write: Buffer counts are not synchronized with
> semaphore count\n");
> +    return -RTEMS_INTERNAL_ERROR;
> +  }
> +
> +  /* sleep is for debug purpose to test concurrency issues */
> +  printf("can_bus_write: calling sleep\n");
> +  sleep(1);
> +  printf("can_bus_write: coming out sleep\n");
> +
> +  uint32_t msg_size = (char *)&msg->data[msg->len] - (char *)msg;
> +
> +  CAN_DEBUG_TX("can_bus_write: can_msg_size = %u\n", msg_size);
> +  if (msg_size > sizeof(struct can_msg)) {
> +    printf("can_bus_write:"
> +          "can message len error msg_size = %u struct can_msg = %u\n",
> +          msg_size, sizeof(struct can_msg));
> +    return -RTEMS_INVALID_SIZE;
> +  }
> +
> +  CAN_DEBUG_TX("can_bus_write: copying msg from application to driver
> buffer\n");
> +  memcpy(fifo_buf, msg, msg_size);
> +  ret = msg_size;
> +
> +  /* sleep is for debug purpose to test concurrency issues */
> +  printf("can_bus_write: calling sleep\n");
> +  sleep(1);
> +  printf("can_bus_write: coming out sleep\n");
> +
> +  if (bus->can_dev_ops->dev_tx_ready(bus->priv) == true) {
> +    can_xmit(bus);
> +  }
> +
> +return_from_func:
> +  return ret;
> +}
> +
> +static ssize_t
> +can_bus_ioctl(rtems_libio_t *iop, ioctl_command_t request, void *buffer)
> +{
> +  can_bus *bus = IMFS_generic_get_context_by_iop(iop);
> +
> +  if (bus == NULL || bus->can_dev_ops->dev_ioctl == NULL) {
> +    return -RTEMS_NOT_DEFINED;
> +  }
> +
> +  can_bus_obtain(bus);
> +
> +  bus->can_dev_ops->dev_ioctl(bus->priv, NULL, 0);
> +
> +  can_bus_release(bus);
> +
> +  return RTEMS_SUCCESSFUL;
> +}
> +
> +static const rtems_filesystem_file_handlers_r can_bus_handler = {
> +  .open_h = can_bus_open,
> +  .close_h = rtems_filesystem_default_close,
> +  .read_h = can_bus_read,
> +  .write_h = can_bus_write,
> +  .ioctl_h = can_bus_ioctl,
> +  .lseek_h = rtems_filesystem_default_lseek,
> +  .fstat_h = IMFS_stat,
> +  .ftruncate_h = rtems_filesystem_default_ftruncate,
> +  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
> +  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
> +  .fcntl_h = rtems_filesystem_default_fcntl,
> +  .kqfilter_h = rtems_filesystem_default_kqfilter,
> +  .mmap_h = rtems_filesystem_default_mmap,
> +  .poll_h = rtems_filesystem_default_poll,
> +  .readv_h = rtems_filesystem_default_readv,
> +  .writev_h = rtems_filesystem_default_writev
> +};
> +
> +static void can_bus_node_destroy(IMFS_jnode_t *node)
> +{
> +  can_bus *bus;
> +
> +  bus = IMFS_generic_get_context_by_node(node);
> +  (*bus->destroy)(bus);
> +
> +  IMFS_node_destroy_default(node);
> +}
> +
> +static const
> +IMFS_node_control can_bus_node_control =
> IMFS_GENERIC_INITIALIZER(&can_bus_handler,
> +                    IMFS_node_initialize_generic, can_bus_node_destroy);
> +
> +rtems_status_code can_bus_register(can_bus *bus, const char *bus_path)
> +{
> +  int ret = RTEMS_SUCCESSFUL;
> +
> +  static uint8_t index = 0;
> +
> +  if (index == 255) {
> +    printf("can_bus_register: can bus registration limit reached\n");
> +    return RTEMS_TOO_MANY;
> +  }
> +
> +  bus->index = index++;
> +  CAN_DEBUG("Registering CAN bus index = %u\n", bus->index);
> +
> +  ret = IMFS_make_generic_node(bus_path, S_IFCHR | S_IRWXU | S_IRWXG |
> S_IRWXO,
> +                              &can_bus_node_control, bus);
> +  if (ret != RTEMS_SUCCESSFUL) {
> +    printf("can_bus_register: Creating node failed = %d\n", ret);
> +    goto fail;
> +  }
> +
> +  if ((ret = can_create_sem(bus)) != RTEMS_SUCCESSFUL) {
> +    printf("can_bus_register: can_create_sem failed = %d\n", ret);
> +    goto fail;
> +  }
> +
> +  if ((ret = can_create_tx_buffers(bus)) != RTEMS_SUCCESSFUL) {
> +    printf("can_bus_register: can_create_tx_buffers failed = %d\n", ret);
> +    goto fail;
> +  }
> +
> +  if ((ret = can_create_rx_buffers(bus)) != RTEMS_SUCCESSFUL) {
> +    printf("can_bus_register: can_create_rx_buffers failed = %d\n", ret);
> +    goto free_tx_buffers_return;
> +  }
> +
> +  return ret;
> +
> +free_tx_buffers_return:
> +  free(bus->tx_fifo.pbuf);
> +
> +fail:
> +  (*bus->destroy)(bus);
> +  return ret;
> +
> +}
> +
> +static void can_bus_destroy(can_bus *bus)
> +{
> +  rtems_recursive_mutex_destroy(&bus->mutex);
> +}
> +
> +static int can_bus_do_init(can_bus *bus, void (*destroy)(can_bus *bus))
> +{
> +  rtems_recursive_mutex_init(&bus->mutex, "CAN Bus");
> +  bus->destroy = can_bus_destroy;
> +
> +  return RTEMS_SUCCESSFUL;
> +}
> +
> +static void can_bus_destroy_and_free(can_bus *bus)
> +{
> +  can_bus_destroy(bus);
> +  free(bus);
> +}
> +
> +int can_bus_init(can_bus *bus)
> +{
> +  memset(bus, 0, sizeof(*bus));
> +
> +  return can_bus_do_init(bus, can_bus_destroy);
> +}
> +
> +can_bus *can_bus_alloc_and_init(size_t size)
> +{
> +  can_bus *bus = NULL;
> +
> +  if (size >= sizeof(*bus)) {
> +    bus = calloc(1, size);
> +    if (bus == NULL) {
> +      printf("can_bus_alloc_and_init: calloc failed\b");
> +      return NULL;
> +    }
> +
> +    int rv = can_bus_do_init(bus, can_bus_destroy_and_free);
> +    if (rv != 0) {
> +      printf("can_bus_alloc_and_init: can_bus_do_init failed\n");
> +      return NULL;
> +    }
> +  }
> +  return bus;
> +}
> diff --git a/cpukit/include/dev/can/can-msg.h
> b/cpukit/include/dev/can/can-msg.h
> new file mode 100644
> index 0000000000..5c79b91600
> --- /dev/null
> +++ b/cpukit/include/dev/can/can-msg.h
> @@ -0,0 +1,55 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +
> +/**
> + * @file
> + *
> + * @ingroup CANBus
> + *
> + * @brief Controller Area Network (CAN) Bus Implementation
> + *
> + */
> +
> +/*
> + * Copyright (C) 2022 Prashanth S <fishesprashanth at gmail.com>
> + *
> + * 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.
> + */
> +
> +#ifndef _DEV_CAN_CAN_MSG_H
> +#define _DEV_CAN_CAN_MSG_H
> +
> +#define CAN_MSG_MAX_SIZE  (8u)
> +
> +#define CAN_TX_BUF_COUNT  (2u)
> +#define CAN_RX_BUF_COUNT  (2u)
> +
> +#define CAN_MSGLEN(msg) (sizeof(struct can_msg) - (CAN_MSG_MAX_SIZE -
> msg->len))
> +
> +struct can_msg {
> +  uint32_t id;                              // 32 bits to support
> extended id (29 bits).
> +  uint32_t timestamp;
> +  uint16_t flags;                           // RTR | BRS | EXT ...
> +  uint16_t len;
> +  uint8_t data[CAN_MSG_MAX_SIZE];           // For supporting data
> transfer up to 64 bytes.
> +};
> +
> +#endif /* _DEV_CAN_CAN_MSG_H */
> diff --git a/cpukit/include/dev/can/can-queue.h
> b/cpukit/include/dev/can/can-queue.h
> new file mode 100644
> index 0000000000..c018441320
> --- /dev/null
> +++ b/cpukit/include/dev/can/can-queue.h
> @@ -0,0 +1,127 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +
> +/**
> + * @file
> + *
> + * @ingroup CANBus
> + *
> + * @brief Controller Area Network (CAN) Bus Implementation
> + *
> + */
> +
> +/*
> + * Copyright (C) 2022 Prashanth S <fishesprashanth at gmail.com>
> + *
> + * 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.
> + */
> +
> +#ifndef _DEV_CAN_CAN_QUEUE_H
> +#define _DEV_CAN_CAN_QUEUE_H
> +
> +#include <rtems/imfs.h>
> +#include <rtems/thread.h>
> +
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#include <dev/can/can-msg.h>
> +#include <dev/can/can.h>
> +
> +static rtems_status_code can_create_tx_buffers(struct can_bus *bus);
> +static rtems_status_code can_create_rx_buffers(struct can_bus *bus);
> +static bool can_tx_buf_isempty(struct can_bus *bus);
> +static struct can_msg *can_tx_get_data_buf(struct can_bus *bus);
> +static struct can_msg *can_tx_get_empty_buf(struct can_bus *bus);
> +
> +static rtems_status_code can_create_rx_buffers(struct can_bus *bus)
> +{
> +  return rtems_message_queue_create(rtems_build_name('c', 'a', 'n',
> bus->index),
> +           CAN_RX_BUF_COUNT, sizeof(struct can_msg),
> +           RTEMS_FIFO | RTEMS_LOCAL, &bus->rx_queue_id);
> +}
> +
> +static rtems_status_code can_create_tx_buffers(struct can_bus *bus)
> +{
> +  bus->tx_fifo.pbuf = (struct can_msg *)malloc(CAN_TX_BUF_COUNT *
> +                              sizeof(struct can_msg));
> +  if (bus->tx_fifo.pbuf == NULL) {
> +    printf("can_create_tx_buffers: malloc failed\n");
> +    return RTEMS_NO_MEMORY;
> +  }
> +
> +  bus->tx_fifo.empty_count = CAN_TX_BUF_COUNT;
> +
> +  return RTEMS_SUCCESSFUL;
> +}
> +
> +static bool can_tx_buf_isempty(struct can_bus *bus)
> +{
> +  if (bus->tx_fifo.empty_count == 0) {
> +    return false;
> +  }
> +
> +  return true;
> +}
> +
> +// TODO: free the given data buf is done in the same function
> +// SO the returned buffer should be consumed before releasing the
> +// lock acquired while calling this function.
> +static struct can_msg *can_tx_get_data_buf(struct can_bus *bus)
> +{
> +  struct can_msg *msg = NULL;
> +
> +  if (bus->tx_fifo.empty_count == CAN_TX_BUF_COUNT) {
> +    CAN_DEBUG_BUF("can_tx_get_data_buf: All buffers are empty\n");
> +    return NULL;
> +  }
> +
> +  msg = &bus->tx_fifo.pbuf[bus->tx_fifo.tail];
> +  bus->tx_fifo.empty_count++;
> +  bus->tx_fifo.tail = (bus->tx_fifo.tail + 1) % CAN_TX_BUF_COUNT;
> +
> +  return msg;
> +}
> +
> +// TODO: marking the given buf as produced is done in the same function
> +// So the returned buffer should be produced before releasing the
> +// lock acquired while calling this function.
> +static struct can_msg *can_tx_get_empty_buf(struct can_bus *bus)
> +{
> +  struct can_msg *msg = NULL;
> +
> +  /* Check whether there is a empty CAN msg buffer */
> +  if (can_tx_buf_isempty(bus) == false) {
> +    CAN_DEBUG_BUF("can_tx_get_empty_buf: No empty buffer\n");
> +    return NULL;
> +  }
> +
> +  bus->tx_fifo.empty_count--;
> +
> +  /* tx_fifo.head always points to a empty buffer if there is atleast one
> */
> +  msg = &bus->tx_fifo.pbuf[bus->tx_fifo.head];
> +  bus->tx_fifo.head = (bus->tx_fifo.head + 1) % CAN_TX_BUF_COUNT;
> +
> +  return msg;
> +}
> +
> +#endif /*_DEV_CAN_CAN_QUEUE_H */
> diff --git a/cpukit/include/dev/can/can.h b/cpukit/include/dev/can/can.h
> new file mode 100644
> index 0000000000..eeb2eb2c0b
> --- /dev/null
> +++ b/cpukit/include/dev/can/can.h
> @@ -0,0 +1,102 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +
> +/**
> + * @file
> + *
> + * @ingroup CANBus
> + *
> + * @brief Controller Area Network (CAN) Bus Implementation
> + *
> + */
> +
> +/*
> + * Copyright (C) 2022 Prashanth S (fishesprashanth at gmail.com)
> + *
> + * 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.
> + */
> +
> +#ifndef _DEV_CAN_CAN_H
> +#define _DEV_CAN_CAN_H
> +
> +#include <rtems/imfs.h>
> +#include <rtems/thread.h>
> +#include <semaphore.h>
> +
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdio.h>
> +
> +#include <dev/can/can-msg.h>
> +
> +#define CAN_DEBUG(str, ...) printf(str, ##__VA_ARGS__)
> +#define CAN_DEBUG_BUF(str, ...) printf(str, ##__VA_ARGS__)
> +#define CAN_DEBUG_ISR(str, ...) printf(str, ##__VA_ARGS__)
> +#define CAN_DEBUG_LOCK(str, ...) printf(str, ##__VA_ARGS__)
> +#define CAN_DEBUG_RX(str, ...) printf(str, ##__VA_ARGS__)
> +#define CAN_DEBUG_TX(str, ...) printf(str, ##__VA_ARGS__)
> +
> +struct ring_buf {
> +  struct can_msg *pbuf;
> +  uint32_t head;
> +  uint32_t tail;
> +  uint32_t empty_count;
> +};
> +
> +typedef struct can_dev_ops {
> +  int32_t (*dev_rx)(void *priv, void *buffer);
> +  int32_t (*dev_tx)(void *priv, void *buffer);
> +  bool (*dev_tx_ready)(void *priv);
> +  void (*dev_int)(void *priv, bool);
> +  int32_t (*dev_ioctl)(void *priv, void *buffer, size_t cmd);
> +} can_dev_ops;
> +
> +typedef struct can_bus {
> +  void *priv;                               // CAN controller specific
> struct.
> +  uint8_t index;
> +  struct can_dev_ops *can_dev_ops;          // CAN controller operations.
> +
> +  struct ring_buf tx_fifo;                  // TX fifo
> +  rtems_id tx_fifo_sem_id;                  // TX fifo counting semaphore
> id
> +  uint32_t can_tx_buf_waiters;
> +
> +  rtems_id rx_queue_id;
> +  uint32_t rx_queue_name;
> +
> +  rtems_recursive_mutex mutex;              // For handling driver
> concurrency.
> +  RTEMS_INTERRUPT_LOCK_MEMBER(can_bus_lock);
> +
> +  void (*destroy)(struct can_bus *bus);     // Clean the CAN controller
> specific resources.
> +} can_bus;
> +
> +extern rtems_status_code can_bus_register(can_bus *bus, const char
> *bus_path);
> +
> +extern can_bus *can_bus_alloc_and_init(size_t size);
> +extern int can_bus_init(can_bus *bus);
> +extern int can_tx_done(struct can_bus *);
> +extern int can_receive(struct can_bus *, struct can_msg *);
> +
> +extern uint16_t can_len_to_dlc(uint16_t len);
> +extern uint16_t can_dlc_to_len(uint16_t dlc);
> +
> +extern void can_print_msg(struct can_msg const *);
> +
> +#endif /* _DEV_CAN_CAN_H */
> diff --git a/spec/build/cpukit/librtemscpu.yml
> b/spec/build/cpukit/librtemscpu.yml
> index 31a68cf85a..b7f6c0457c 100644
> --- a/spec/build/cpukit/librtemscpu.yml
> +++ b/spec/build/cpukit/librtemscpu.yml
> @@ -50,6 +50,11 @@ install:
>  - destination: ${BSP_INCLUDEDIR}/dev/spi
>    source:
>    - cpukit/include/dev/spi/spi.h
> +- destination: ${BSP_INCLUDEDIR}/dev/can
> +  source:
> +  - cpukit/include/dev/can/can.h
> +  - cpukit/include/dev/can/can-msg.h
> +  - cpukit/include/dev/can/can-queue.h
>  - destination: ${BSP_INCLUDEDIR}/linux
>    source:
>    - cpukit/include/linux/i2c-dev.h
> @@ -530,6 +535,7 @@ source:
>  - cpukit/dev/serial/sc16is752-spi.c
>  - cpukit/dev/serial/sc16is752.c
>  - cpukit/dev/spi/spi-bus.c
> +- cpukit/dev/can/can.c
>  - cpukit/dtc/libfdt/fdt.c
>  - cpukit/dtc/libfdt/fdt_addresses.c
>  - cpukit/dtc/libfdt/fdt_empty_tree.c
> --
> 2.25.1
>
>
>
> ------------------------------
>
> Subject: Digest Footer
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
>
> ------------------------------
>
> End of devel Digest, Vol 128, Issue 178
> ***************************************
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.rtems.org/pipermail/devel/attachments/20220731/08844683/attachment-0001.htm>


More information about the devel mailing list