123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271 |
- /*
- * Copyright (c) 2006-2021, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2021-05-11 Carl the first version
- */
- #include "drv_can.h"
- #include "interrupt.h"
- #include <string.h>
- #ifdef BSP_USE_CAN
- #define LOG_TAG "drv_can"
- #include <drv_log.h>
- #define _CAN0_NAME "can0"
- #define _CAN1_NAME "can1"
- #define RTHW_CAN_WAIT(_can) rt_sem_take(&_can->recv_semaphore, RT_WAITING_FOREVER);
- #define RTHW_CAN_SEND(_can) rt_sem_release(&_can->recv_semaphore);
- #ifdef BSP_USING_CAN0
- struct ft2004_can drv_can0 =
- {
- .name = _CAN0_NAME,
- .can_handle.Config.InstanceId = 0};
- #endif
- #ifdef BSP_USING_CAN1
- struct ft2004_can drv_can1 =
- {
- .name = _CAN1_NAME,
- .can_handle.Config.InstanceId = 1};
- #endif
- static void _can_recv_irq(void *args)
- {
- struct ft2004_can *drv_can = (struct ft2004_can *)args;
- RTHW_CAN_SEND(drv_can);
- }
- static void rt_hw_inner_can_isr(int irqno, void *param)
- {
- FCan_IntrHandler(param);
- }
- static rt_err_t _can_config(struct rt_can_device *can, struct can_configure *cfg)
- {
- struct FCan_Bittiming bit_timing = {0};
- struct ft2004_can *drv_can;
- RT_ASSERT(can);
- RT_ASSERT(cfg);
- drv_can = (struct ft2004_can *)can->parent.user_data;
- RT_ASSERT(drv_can);
- FCan_CfgInitialize(&drv_can->can_handle, FCan_LookupConfig(drv_can->can_handle.Config.InstanceId));
- FCan_SetHandler(&drv_can->can_handle, FCAN_HANDLER_RECV, _can_recv_irq, drv_can);
- bit_timing.bitrate = cfg->baud_rate;
- if (FCan_CalcBittiming(&bit_timing) != FCAN_SUCCESS)
- {
- LOG_E("Setting baud rate %x is not valid \r\n", bit_timing.bitrate);
- return -RT_ERROR;
- }
- FCan_SetTiming(&drv_can->can_handle, &bit_timing);
- rt_hw_interrupt_set_priority(drv_can->can_handle.Config.IrqNum, 16);
- rt_hw_interrupt_install(drv_can->can_handle.Config.IrqNum, rt_hw_inner_can_isr, &drv_can->can_handle, drv_can->name);
- rt_hw_interrupt_umask(drv_can->can_handle.Config.IrqNum);
- FCan_Enable(&drv_can->can_handle);
- return RT_EOK;
- }
- static rt_err_t _can_control(struct rt_can_device *can, int cmd, void *arg)
- {
- return RT_EOK;
- }
- static int _can_sendmsg(struct rt_can_device *can, const void *buf, rt_uint32_t box_num)
- {
- struct ft2004_can *drv_can;
- struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
- struct FCan_Frame can_frame = {0};
- RT_ASSERT(can);
- drv_can = (struct ft2004_can *)can->parent.user_data;
- RT_ASSERT(drv_can);
- /* Check the parameters */
- RT_ASSERT(pmsg->len <= 8U);
- if (RT_CAN_STDID == pmsg->ide)
- {
- can_frame.CanId = pmsg->id;
- }
- else
- {
- can_frame.CanId = pmsg->id;
- can_frame.CanId |= CAN_EFF_FLAG;
- }
- if (RT_CAN_DTR == pmsg->rtr)
- {
- }
- else
- {
- can_frame.CanId |= CAN_RTR_FLAG;
- }
- can_frame.CanDlc = pmsg->len & 0x0FU;
- memcpy(can_frame.data, pmsg->data, 8);
- return (FCan_SendByIrq(&drv_can->can_handle, &can_frame, 1, RT_NULL) == 1) ? RT_EOK : -RT_ERROR;
- }
- static int _can_recvmsg(struct rt_can_device *can, void *buf, rt_uint32_t fifo)
- {
- struct ft2004_can *drv_can;
- struct rt_can_msg *pmsg = (struct rt_can_msg *)buf;
- RT_ASSERT(can);
- struct FCan_Frame recv_frame = {0};
- drv_can = (struct ft2004_can *)can->parent.user_data;
- RT_ASSERT(drv_can);
- RTHW_CAN_WAIT(drv_can);
- if (FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1) == 0)
- {
- LOG_E("rx msg is error");
- return -RT_ERROR;
- }
- if (CAN_EFF_FLAG & recv_frame.CanId)
- {
- pmsg->ide = RT_CAN_EXTID;
- pmsg->id = (recv_frame.CanId & ~(RT_CAN_EXTID));
- }
- else
- {
- pmsg->ide = RT_CAN_STDID;
- pmsg->id = recv_frame.CanId;
- }
- if (CAN_RTR_FLAG & recv_frame.CanId)
- {
- pmsg->id &= ~CAN_RTR_FLAG;
- pmsg->rtr = RT_CAN_RTR;
- }
- else
- {
- pmsg->rtr = RT_CAN_DTR;
- }
- /* get len */
- pmsg->len = recv_frame.CanDlc;
- return RT_EOK;
- }
- static const struct rt_can_ops _can_ops =
- {
- _can_config,
- _can_control,
- _can_sendmsg,
- _can_recvmsg,
- };
- int rt_hw_can_init(void)
- {
- #ifdef BSP_USING_CAN0
- drv_can0.can_handle.Config.InstanceId = 0;
- rt_sem_init(&drv_can0.recv_semaphore, "can0_recv", 0, RT_IPC_FLAG_FIFO);
- drv_can0.device.config.ticks = 20000;
- drv_can0.device.config.baud_rate = 1000000;
- rt_hw_can_register(&drv_can0.device,
- drv_can0.name,
- &_can_ops,
- &drv_can0);
- #endif
- #ifdef BSP_USING_CAN1
- drv_can1.can_handle.Config.InstanceId = 1;
- drv_can1.device.config.ticks = 20000;
- drv_can1.device.config.baud_rate = 1000000;
- rt_sem_init(&drv_can1.recv_semaphore, "can1_recv", 0, RT_IPC_FLAG_FIFO);
- rt_hw_can_register(&drv_can1.device,
- drv_can1.name,
- &_can_ops,
- &drv_can1);
- #endif
- return 0;
- }
- INIT_BOARD_EXPORT(rt_hw_can_init);
- #ifdef BSP_USING_CAN0_DEBUG
- struct can_test_struct
- {
- const char *name;
- struct rt_can_filter_config *filter;
- rt_device_t candev;
- struct rt_semaphore _sem;
- };
- static struct can_test_struct can0_test_obj = {
- .name = _CAN0_NAME};
- void can_recv_irq(void *param)
- {
- struct can_test_struct *_can_obj = (struct can_test_struct *)param;
- rt_kprintf("can_recv_iqr \r\n");
- rt_sem_release(&_can_obj->_sem);
- }
- static void rt_can_test_loopback_thread_entry(void *param)
- {
- struct can_test_struct *_can_obj = (struct can_test_struct *)param;
- struct FCan_Frame recv_frame;
- struct ft2004_can *drv_can;
- rt_uint32_t i;
- _can_obj->candev = rt_device_find(_can_obj->name);
- RT_ASSERT(_can_obj->candev);
- drv_can = (struct ft2004_can *)_can_obj->candev->user_data;
- rt_sem_init(&_can_obj->_sem, "canrx_wait", 0, RT_IPC_FLAG_FIFO);
- rt_device_open(_can_obj->candev, RT_DEVICE_OFLAG_RDWR);
- while (1)
- {
- rt_kprintf(" start to wait loopback \r\n");
- RTHW_CAN_WAIT(drv_can);
- while (0 != FCan_RecvByIrq(&drv_can->can_handle, &recv_frame, 1))
- {
- rt_kprintf("CanId %x \r\n", recv_frame.CanId);
- rt_kprintf("CanDlc %x \r\n", recv_frame.CanDlc);
- for (i = 0; i < recv_frame.CanDlc; i++)
- {
- rt_kprintf("data [%d] %x \r\n", i, recv_frame.data[i]);
- }
- FCan_SendByIrq(&drv_can->can_handle, &recv_frame, 1, RT_NULL);
- }
- }
- }
- int rt_can0_test(void)
- {
- rt_thread_t tid;
- tid = rt_thread_create("can0_loopback",
- rt_can_test_loopback_thread_entry, &can0_test_obj,
- 1024, 16, 20);
- if (tid != RT_NULL)
- rt_thread_startup(tid);
- return 0;
- }
- INIT_APP_EXPORT(rt_can0_test);
- #endif
- #endif
|