/* 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 #include #include #include #include #include #include #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 */