Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 177 additions & 6 deletions components/drivers/include/drivers/dev_can.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2023, RT-Thread Development Team
* Copyright (c) 2006-2024 RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
Expand Down Expand Up @@ -66,16 +66,153 @@ enum CANBAUD
/**
* @addtogroup Drivers RTTHREAD Driver
* @defgroup CAN_Device CAN Driver
*
* @brief CAN driver api
*
* <b>Example</b>
* @code {.c}
* #include <rtthread.h>
* #include "rtdevice.h"
*
* #define CAN_DEV_NAME "can1" // CAN 设备名称
*
* static struct rt_semaphore rx_sem; // 用于接收消息的信号量
* static rt_device_t can_dev; // CAN 设备句柄
*
* // 接收数据回调函数
* static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size)
* {
* // CAN 接收到数据后产生中断,调用此回调函数,然后发送接收信号量
* rt_sem_release(&rx_sem);
*
* return RT_EOK;
* }
*
* static void can_rx_thread(void *parameter)
* {
* int i;
* rt_err_t res;
* struct rt_can_msg rxmsg = {0};
*
* // 设置接收回调函数
* rt_device_set_rx_indicate(can_dev, can_rx_call);
*
* #ifdef RT_CAN_USING_HDR
* struct rt_can_filter_item items[5] =
* {
* RT_CAN_FILTER_ITEM_INIT(0x100, 0, 0, 0, 0x700, RT_NULL, RT_NULL), // std,match ID:0x100~0x1ff,hdr 为 - 1,设置默认过滤表
* RT_CAN_FILTER_ITEM_INIT(0x300, 0, 0, 0, 0x700, RT_NULL, RT_NULL), // std,match ID:0x300~0x3ff,hdr 为 - 1
* RT_CAN_FILTER_ITEM_INIT(0x211, 0, 0, 0, 0x7ff, RT_NULL, RT_NULL), // std,match ID:0x211,hdr 为 - 1
* RT_CAN_FILTER_STD_INIT(0x486, RT_NULL, RT_NULL), // std,match ID:0x486,hdr 为 - 1
* {0x555, 0, 0, 0, 0x7ff, 7,} // std,match ID:0x555,hdr 为 7,指定设置 7 号过滤表
* };
* struct rt_can_filter_config cfg = {5, 1, items}; // 一共有 5 个过滤表
* // 设置硬件过滤表
* res = rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
* RT_ASSERT(res == RT_EOK);
* #endif
*
* while (1)
* {
* // hdr 值为 - 1,表示直接从 uselist 链表读取数据
* rxmsg.hdr = -1;
* // 阻塞等待接收信号量
* rt_sem_take(&rx_sem, RT_WAITING_FOREVER);
* // 从 CAN 读取一帧数据
* rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
* // 打印数据 ID 及内容
* rt_kprintf("ID:%x", rxmsg.id);
* for (i = 0; i < 8; i++)
* {
* rt_kprintf("%2x", rxmsg.data[i]);
* }
*
* rt_kprintf("\n");
* }
* }
*
* int can_sample(int argc, char *argv[])
* {
* struct rt_can_msg msg = {0};
* rt_err_t res;
* rt_size_t size;
* rt_thread_t thread;
* char can_name[RT_NAME_MAX];
*
* if (argc == 2)
* {
* rt_strncpy(can_name, argv[1], RT_NAME_MAX);
* }
* else
* {
* rt_strncpy(can_name, CAN_DEV_NAME, RT_NAME_MAX);
* }
* // 查找 CAN 设备
* can_dev = rt_device_find(can_name);
* if (!can_dev)
* {
* rt_kprintf("find %s failed!\n", can_name);
* return -RT_ERROR;
* }
*
* // 初始化 CAN 接收信号量
* rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
*
* // 以中断接收及发送方式打开 CAN 设备
* res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
* RT_ASSERT(res == RT_EOK);
* // 创建数据接收线程
* thread = rt_thread_create("can_rx", can_rx_thread, RT_NULL, 1024, 25, 10);
* if (thread != RT_NULL)
* {
* rt_thread_startup(thread);
* }
* else
* {
* rt_kprintf("create can_rx thread failed!\n");
* }
*
* msg.id = 0x78; // ID 为 0x78
* msg.ide = RT_CAN_STDID; // 标准格式
* msg.rtr = RT_CAN_DTR; // 数据帧
* msg.len = 8; // 数据长度为 8
* // 待发送的 8 字节数据
* msg.data[0] = 0x00;
* msg.data[1] = 0x11;
* msg.data[2] = 0x22;
* msg.data[3] = 0x33;
* msg.data[4] = 0x44;
* msg.data[5] = 0x55;
* msg.data[6] = 0x66;
* msg.data[7] = 0x77;
* // 发送一帧 CAN 数据
* size = rt_device_write(can_dev, 0, &msg, sizeof(msg));
* if (size == 0)
* {
* rt_kprintf("can dev write data failed!\n");
* }
*
* return res;
* }
* // 导出到 msh 命令列表中
* MSH_CMD_EXPORT(can_sample, can device sample);
* @endcode
*
* @ingroup Drivers
*
*/


/*!
* @addtogroup CAN_Device
* @{
*/
#define CAN_RX_FIFO0 (0x00000000U) /*!< CAN receive FIFO 0 */
#define CAN_RX_FIFO1 (0x00000001U) /*!< CAN receive FIFO 1 */

/**
* @brief CAN filter item
*/
struct rt_can_filter_item
{
rt_uint32_t id : 29;
Expand Down Expand Up @@ -125,13 +262,20 @@ struct rt_can_filter_item
RT_CAN_FILTER_ITEM_INIT(id,1,0,1,0xFFFFFFFF)
#endif


/**
* @brief CAN filter configuration
*/
struct rt_can_filter_config
{
rt_uint32_t count;
rt_uint32_t actived;
struct rt_can_filter_item *items;
};

/**
* @brief CAN timing configuration
*/
struct rt_can_bit_timing
{
rt_uint16_t prescaler; /* Pre-scaler */
Expand All @@ -142,8 +286,8 @@ struct rt_can_bit_timing
};

/**
* CAN bit timing configuration list
* NOTE:
* @brief CAN bit timing configuration list
* @note
* items[0] always for CAN2.0/CANFD Arbitration Phase
* items[1] always for CANFD (if it exists)
*/
Expand All @@ -153,6 +297,10 @@ struct rt_can_bit_timing_config
struct rt_can_bit_timing *items;
};


/**
* @brief CAN configuration
*/
struct can_configure
{
rt_uint32_t baud_rate;
Expand Down Expand Up @@ -218,6 +366,9 @@ enum RT_CAN_BUS_ERR
RT_CAN_BUS_CRC_ERR = 6,
};

/**
* @brief CAN status
*/
struct rt_can_status
{
rt_uint32_t rcverrcnt;
Expand Down Expand Up @@ -248,6 +399,7 @@ struct rt_can_hdr
#endif
struct rt_can_device;
typedef rt_err_t (*rt_canstatus_ind)(struct rt_can_device *, void *);

typedef struct rt_can_status_ind_type
{
rt_canstatus_ind ind;
Expand Down Expand Up @@ -354,6 +506,9 @@ struct rt_can_tx_fifo
struct rt_list_node freelist;
};

/**
* @brief CAN operators
*/
struct rt_can_ops
{
rt_err_t (*configure)(struct rt_can_device *can, struct can_configure *cfg);
Expand All @@ -362,13 +517,29 @@ struct rt_can_ops
rt_ssize_t (*recvmsg)(struct rt_can_device *can, void *buf, rt_uint32_t boxno);
};

/**
* @brief Register a CAN device to device list
*
* @param can the CAN device object
* @param name the name of CAN device
* @param ops the CAN device operators
* @param data the private data of CAN device
*
* @return the error code, RT_EOK on successfully
*/
rt_err_t rt_hw_can_register(struct rt_can_device *can,
const char *name,
const struct rt_can_ops *ops,
void *data);

/**
* @brief CAN interrupt service routine
*
* @param can the CAN device
* @param event the event mask
*/
void rt_hw_can_isr(struct rt_can_device *can, int event);

/*! @}
*/
/*! @}*/

#endif /*__DEV_CAN_H*/
#endif /*__DEV_CAN_H*/
Loading