summaryrefslogblamecommitdiffstats
path: root/cpukit/include/dev/can/can.h
blob: 9e55395039290de4300438d5c9816a415697544a (plain) (tree)



























































































































































































































































































                                                                                                                           
/* SPDX-License-Identifier: BSD-2-Clause */

/**
 * @file
 *
 * @ingroup CANBus
 *
 * @brief Controller Area Network (CAN) Bus Implementation
 *
 */

/*
 * Copyright (C) 2022 Prashanth S (fishesprashanth@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 DEBUG(str, ...)                                                   \
    do {                                                                      \
      printf("CAN: %s:%d ID: %08X ", __FILE__, __LINE__, rtems_task_self());  \
      printf(str, ##__VA_ARGS__);                                             \
    } while (false);

#define CAN_DEBUG(str, ...) DEBUG(str, ##__VA_ARGS__)
#define CAN_DEBUG_BUF(str, ...) CAN_DEBUG(str, ##__VA_ARGS__)
#define CAN_DEBUG_ISR(str, ...) CAN_DEBUG(str, ##__VA_ARGS__)
#define CAN_DEBUG_LOCK(str, ...) CAN_DEBUG(str, ##__VA_ARGS__)
#define CAN_DEBUG_RX(str, ...) CAN_DEBUG(str, ##__VA_ARGS__)
#define CAN_DEBUG_TX(str, ...) CAN_DEBUG(str, ##__VA_ARGS__)
#define CAN_DEBUG_REG(str, ...) //CAN_DEBUG(str, ##__VA_ARGS__)
#define CAN_ERR(str, ...) DEBUG(str, ##__VA_ARGS__)

#define CAN_MSG_LEN(msg) ((char *)(&((struct can_msg *)msg)->data[(uint16_t)((struct can_msg *)msg)->len]) - (char *)(msg))

/* Maximum Bus Reg (255) */
#define CAN_BUS_REG_MAX (255)

/**
 * @defgroup Controller Area Network (CAN) Driver
 *
 * @ingroup RTEMSDeviceDrivers
 *
 * @brief Controller Area Network (CAN) bus and device driver support.
 *
 * @{
 */

/**
 * @defgroup CANBus CAN Bus Driver
 *
 * @ingroup CAN
 *
 * @{
 */

/**
 * @brief CAN tx fifo data structure.
 */
struct ring_buf {
 /**
   * @brief Pointer to array of can_msg structure.
   */
  struct can_msg *pbuf;
 /**
   * @brief Index of the next free buffer.
   */
  uint32_t head;
 /**
   * @brief Index of the produced buffer.
   */
  uint32_t tail;
  /**
   * @brief Number of empty buffers.
   */
  uint32_t empty_count;
};

/**
 * @brief CAN Controller device specific operations.
 * These function pointers are initialized by the CAN device driver while
 * registering (can_bus_register).
 */
typedef struct can_dev_ops {
  /**
   * @brief Transfers CAN messages to device fifo.
   *
   * @param[in] priv device control structure.
   * @param[in] msg can_msg message structure.
   *
   * @retval 0 Successful operation.
   * @retval >0 error number in case of an error.
   */
  int32_t (*dev_tx)(void *priv, struct can_msg *msg);
  /**
   * @brief Check device is ready to transfer a CAN message
   *
   * @param[in] priv device control structure.
   *
   * @retval true device ready.
   * @retval false device not ready.
   */
  bool (*dev_tx_ready)(void *priv);
  /**
   * @brief Enable/Disable CAN interrupts.
   *
   * @param[in] priv device control structure.
   * @param[in] flag true/false to Enable/Disable CAN interrupts.
   *
   */
  void (*dev_int)(void *priv, bool flag);
  /**
   * @brief CAN device specific I/O controls.
   *
   * @param[in] priv device control structure.
   * @param[in] buffer This depends on the cmd.
   * @param[in] cmd Device specific I/O commands.
   *
   * @retval 0 Depends on the cmd.
   */
  int32_t (*dev_ioctl)(void *priv, void *buffer, size_t cmd);
} can_dev_ops;

/**
 * @name CAN bus control
 *
 * @{
 */

/**
 * @brief Obtains the bus.
 *
 * This command has no argument.
 */
typedef struct can_bus {
 /**
   * @brief Device specific control.
   */
  void *priv;
 /**
   * @brief Device controller index.
   */
  uint8_t index;
 /**
   * @brief Device specific operations.
   */
  struct can_dev_ops *can_dev_ops;
 /**
   * @brief tx fifo.
   */
  struct ring_buf tx_fifo;
 /**
   * @brief Counting semaphore id (for fifo sync).
   */
  rtems_id tx_fifo_sem_id;

 /* FIXME: Using only one CAN msg buffer, Should create a ring buffer */
 /**
   * @brief rx fifo.
   */
  struct can_msg can_rx_msg;
 /**
   * @brief Mutex to handle bus concurrency.
   */
  rtems_mutex mutex;
  /**
   * @brief Destroys the bus.
   *
   * @param[in] bus control structure.
   */
  void (*destroy)(struct can_bus *bus);
#ifdef CAN_DEBUG_LOCK

 /**
   * @brief For debugging semaphore obtain/release.
   */
  int sem_count;

#endif /* CAN_DEBUG_LOCK */

} can_bus;

/** @} */

/**
 * @brief Register a CAN node with the CAN bus driver.
 *
 * @param[in] bus bus control structure.
 * @param[in] bus_path path of device node.
 *
 * @retval >=0 rtems status.
 */
rtems_status_code can_bus_register(can_bus *bus, const char *bus_path);

/**
 * @brief Allocate and initilaize bus control structure.
 *
 * @param[in] size Size of the bus control structure.
 *
 * @retval NULL No memory available.
 * @retval Address Pointer to the allocated bus control structure.
 */
can_bus *can_bus_alloc_and_init(size_t size);

/**
 * @brief initilaize bus control structure.
 *
 * @param[in] bus bus control structure.
 *
 * @retval 0 success.
 * @retval >0 error number.
 */
int can_bus_init(can_bus *bus);

/**
 * @brief Initiates CAN message transfer.
 * 
 * Should be called with CAN interrupt disabled.
 *
 * @param[in] bus Bus control structure.
 *
 * @retval 0 success.
 * @retval >0 error number.
 */
int can_tx_done(struct can_bus *bus);

/**
 * @brief Sends the received CAN message to the application.
 * 
 * Should be called by the device when CAN message should be sent to applicaiton.
 * Should be called only with CAN interrupts disabled.
 *
 * @param[in] bus bus control structure.
 * @param[in] msg can_msg structure.
 *
 * @retval 0 success.
 * @retval >0 error number.
 */
int can_receive(struct can_bus *bus, struct can_msg *msg);

/**
 * @brief Prints the can_msg values pointed by msg.
 * 
 * @param[in] msg can_msg structure.
 *
 */
void can_print_msg(struct can_msg const *msg);

/** @} */  /* end of CAN device driver */

/** @} */

#endif /* _DEV_CAN_CAN_H */