|
@@ -11,11 +11,18 @@
|
|
|
/*------------------------------- 头文件 --------------------------------------
|
|
/*------------------------------- 头文件 --------------------------------------
|
|
|
*/
|
|
*/
|
|
|
#include "bspconfig.h"
|
|
#include "bspconfig.h"
|
|
|
|
|
+#include "rt_printf.h"
|
|
|
#include "ustimer.h"
|
|
#include "ustimer.h"
|
|
|
#include "rt.h"
|
|
#include "rt.h"
|
|
|
#include "flexcan.h"
|
|
#include "flexcan.h"
|
|
|
#include <string.h>
|
|
#include <string.h>
|
|
|
#include <sys/mman.h>
|
|
#include <sys/mman.h>
|
|
|
|
|
+#include <sys/socket.h>
|
|
|
|
|
+#include <sys/ioctl.h>
|
|
|
|
|
+#include <linux/can.h>
|
|
|
|
|
+#include <linux/can/raw.h>
|
|
|
|
|
+#include <sys/prctl.h>
|
|
|
|
|
+#include <unistd.h>
|
|
|
|
|
|
|
|
#ifdef BSP_CAN_ENABLE
|
|
#ifdef BSP_CAN_ENABLE
|
|
|
|
|
|
|
@@ -93,6 +100,13 @@
|
|
|
|
|
|
|
|
/*------------------------------ 类型结构 -------------------------------------
|
|
/*------------------------------ 类型结构 -------------------------------------
|
|
|
*/
|
|
*/
|
|
|
|
|
+typedef enum
|
|
|
|
|
+{
|
|
|
|
|
+ CAN_1,
|
|
|
|
|
+ CAN_2,
|
|
|
|
|
+ CAN_RES
|
|
|
|
|
+}can_type;
|
|
|
|
|
+
|
|
|
//CANFD 基地址
|
|
//CANFD 基地址
|
|
|
static unsigned int g_rt_canfd_baseaddr[RT_CAN_NUM][RT_CAN_DEV_TYPE]=
|
|
static unsigned int g_rt_canfd_baseaddr[RT_CAN_NUM][RT_CAN_DEV_TYPE]=
|
|
|
{
|
|
{
|
|
@@ -164,6 +178,7 @@ struct can_timestamp
|
|
|
//flexcan 设备数据结构
|
|
//flexcan 设备数据结构
|
|
|
struct can_dev
|
|
struct can_dev
|
|
|
{
|
|
{
|
|
|
|
|
+ int can_sock;
|
|
|
uint32_t no;
|
|
uint32_t no;
|
|
|
uint32_t base_addr;
|
|
uint32_t base_addr;
|
|
|
|
|
|
|
@@ -229,6 +244,10 @@ struct can_platform_data
|
|
|
*/
|
|
*/
|
|
|
//flexcan设备
|
|
//flexcan设备
|
|
|
int g_can_fd = -1;
|
|
int g_can_fd = -1;
|
|
|
|
|
+static int bexit = 0;
|
|
|
|
|
+static u8 g_can_tx_call[CAN_BUS_NUM] = {0};
|
|
|
|
|
+pthread_t can_tid[CAN_BUS_NUM];
|
|
|
|
|
+pthread_t can_tid_s[CAN_BUS_NUM];
|
|
|
unsigned g_can_mapped_size;
|
|
unsigned g_can_mapped_size;
|
|
|
void *g_can_map_base[CAN_BUS_NUM], *g_can_virt_addr[CAN_BUS_NUM];
|
|
void *g_can_map_base[CAN_BUS_NUM], *g_can_virt_addr[CAN_BUS_NUM];
|
|
|
|
|
|
|
@@ -243,6 +262,7 @@ extern int g_print_can_monitor;
|
|
|
|
|
|
|
|
/*------------------------------ 函数声明 -------------------------------------
|
|
/*------------------------------ 函数声明 -------------------------------------
|
|
|
*/
|
|
*/
|
|
|
|
|
+static void can_soft_recv_data(int sock);
|
|
|
static int _can_set_reset_mode(struct can_dev *dev);
|
|
static int _can_set_reset_mode(struct can_dev *dev);
|
|
|
static int _can_set_normal_mode(struct can_dev *dev);
|
|
static int _can_set_normal_mode(struct can_dev *dev);
|
|
|
static int _can_set_bittiming(struct can_dev *dev);
|
|
static int _can_set_bittiming(struct can_dev *dev);
|
|
@@ -256,6 +276,244 @@ int _can_irq_force(int no);
|
|
|
int _can_irq_clear(int no);
|
|
int _can_irq_clear(int no);
|
|
|
int _can_irq_is_force(int no);
|
|
int _can_irq_is_force(int no);
|
|
|
|
|
|
|
|
|
|
+/*------------------------------ 内部函数 -------------------------------------
|
|
|
|
|
+*/
|
|
|
|
|
+static int can_soft_send(int sock, struct can_frame frame)
|
|
|
|
|
+{
|
|
|
|
|
+ int nbytes;
|
|
|
|
|
+ int wlen = sizeof(struct can_frame);
|
|
|
|
|
+ int times = 2;
|
|
|
|
|
+
|
|
|
|
|
+ while(times --)
|
|
|
|
|
+ {
|
|
|
|
|
+ nbytes = write(sock, &frame, wlen);
|
|
|
|
|
+ if (nbytes != wlen)
|
|
|
|
|
+ {
|
|
|
|
|
+ rt_printf("Send Error frame(nbytes:%d, wlen:%d)\n", nbytes, wlen);
|
|
|
|
|
+ usleep(200);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ //printf("Send frame(nbytes:%d, wlen:%d)\n", nbytes, wlen);
|
|
|
|
|
+ return (0);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return -1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int can_send_data(can_type type, unsigned char *buf, int len)
|
|
|
|
|
+{
|
|
|
|
|
+ int i, j;
|
|
|
|
|
+ int cnt;
|
|
|
|
|
+ int sock;
|
|
|
|
|
+ int ret = 0;
|
|
|
|
|
+ struct can_frame frame;
|
|
|
|
|
+
|
|
|
|
|
+ if(type == CAN_1)
|
|
|
|
|
+ {
|
|
|
|
|
+ // DEMO
|
|
|
|
|
+ sock = g_can_dev[0].can_sock;
|
|
|
|
|
+ frame.can_id = 0x100;
|
|
|
|
|
+ }
|
|
|
|
|
+ else {
|
|
|
|
|
+ // DEMO
|
|
|
|
|
+ sock = g_can_dev[1].can_sock;
|
|
|
|
|
+ frame.can_id = 0x101;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for(i = 0; i < len; i += 8)
|
|
|
|
|
+ {
|
|
|
|
|
+ cnt = len - i;
|
|
|
|
|
+
|
|
|
|
|
+ if(cnt > 8)
|
|
|
|
|
+ frame.can_dlc = 8;
|
|
|
|
|
+ else
|
|
|
|
|
+ frame.can_dlc = cnt;
|
|
|
|
|
+
|
|
|
|
|
+ for(j=0; j<frame.can_dlc; j++)
|
|
|
|
|
+ {
|
|
|
|
|
+ frame.data[j] = buf[i+j];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(can_soft_send(sock, frame) < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ ret = -1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void *can_proc_send(void *arg)
|
|
|
|
|
+{
|
|
|
|
|
+ int sock = *(int *)arg;
|
|
|
|
|
+
|
|
|
|
|
+ int index = g_can_dev[0].can_sock == sock ? 0 : 1;
|
|
|
|
|
+ if (index == 0) {
|
|
|
|
|
+ prctl(PR_SET_NAME, "can_send_func0");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ prctl(PR_SET_NAME, "can_send_func1");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ while(!bexit)
|
|
|
|
|
+ {
|
|
|
|
|
+ static int cycle = 0;
|
|
|
|
|
+ if(main_mod_is_exit())
|
|
|
|
|
+ {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ cycle ++;
|
|
|
|
|
+ if (cycle >= 5000) {
|
|
|
|
|
+ cycle = 0;
|
|
|
|
|
+ switch (index) {
|
|
|
|
|
+ case 0:
|
|
|
|
|
+ can_send_data(CAN_1, (unsigned char *)"hello stm32", strlen("hello stm32") - 1);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ case 1:
|
|
|
|
|
+ can_send_data(CAN_2, (unsigned char *)"hello stm32", strlen("hello stm32") - 1);
|
|
|
|
|
+ break;
|
|
|
|
|
+
|
|
|
|
|
+ default:
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ usleep(1000);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void *can_proc_recv(void *arg)
|
|
|
|
|
+{
|
|
|
|
|
+ int nready;
|
|
|
|
|
+ int maxfd;
|
|
|
|
|
+ fd_set readfds;
|
|
|
|
|
+ int sock = *(int *)arg;
|
|
|
|
|
+
|
|
|
|
|
+ FD_ZERO(&readfds);
|
|
|
|
|
+ FD_SET(sock, &readfds);
|
|
|
|
|
+ maxfd = sock;
|
|
|
|
|
+
|
|
|
|
|
+ int index = g_can_dev[0].can_sock == sock ? 0 : 1;
|
|
|
|
|
+ if (index == 0) {
|
|
|
|
|
+ prctl(PR_SET_NAME, "can_rev_func0");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ prctl(PR_SET_NAME, "can_rev_func1");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ while(!bexit)
|
|
|
|
|
+ {
|
|
|
|
|
+ if(main_mod_is_exit())
|
|
|
|
|
+ {
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ nready = select(maxfd+1, &readfds, NULL, NULL, NULL);
|
|
|
|
|
+ if(nready < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ perror("can select");
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if(nready == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* data is ready */
|
|
|
|
|
+ if(FD_ISSET(sock, &readfds))
|
|
|
|
|
+ {
|
|
|
|
|
+ can_soft_recv_data(sock);
|
|
|
|
|
+ }
|
|
|
|
|
+ else { ; }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int can_open(char *can_name)
|
|
|
|
|
+{
|
|
|
|
|
+ struct ifreq ifr;
|
|
|
|
|
+ struct sockaddr_can addr;
|
|
|
|
|
+ int sock;
|
|
|
|
|
+ int ret = -1;
|
|
|
|
|
+ int loopback = 0;
|
|
|
|
|
+// struct can_filter rfilter[1];
|
|
|
|
|
+
|
|
|
|
|
+ /* open socket */
|
|
|
|
|
+ sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
|
|
|
|
+ if(sock < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return ret;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ strcpy(ifr.ifr_name, can_name);
|
|
|
|
|
+ if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ goto err_can_open;
|
|
|
|
|
+ }
|
|
|
|
|
+ addr.can_family = AF_CAN;
|
|
|
|
|
+ addr.can_ifindex = ifr.ifr_ifindex;
|
|
|
|
|
+ // fcntl(sock, F_SETFL, O_NONBLOCK);
|
|
|
|
|
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ goto err_can_open;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //close loopback
|
|
|
|
|
+ setsockopt(sock, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));
|
|
|
|
|
+/*
|
|
|
|
|
+ rfilter[0].can_id = 0x12;
|
|
|
|
|
+ rfilter[0].can_mask = CAN_SFF_MASK;
|
|
|
|
|
+ setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
|
|
|
|
|
+*/
|
|
|
|
|
+ return sock;
|
|
|
|
|
+
|
|
|
|
|
+err_can_open:
|
|
|
|
|
+ close(sock);
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int can_soft_recv(int sock, struct can_frame *frame)
|
|
|
|
|
+{
|
|
|
|
|
+ int nbytes;
|
|
|
|
|
+
|
|
|
|
|
+ nbytes = read(sock, frame, sizeof(struct can_frame));
|
|
|
|
|
+ if(nbytes)
|
|
|
|
|
+ {
|
|
|
|
|
+ ;//printf("[can_recv]dlc = %d, nbytes = %d\n", frame->can_dlc, nbytes);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return nbytes;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void can_soft_recv_data(int sock)
|
|
|
|
|
+{
|
|
|
|
|
+ static unsigned char tail = 0;
|
|
|
|
|
+ int i;
|
|
|
|
|
+ int can_id;
|
|
|
|
|
+ unsigned char can_dlc;
|
|
|
|
|
+ unsigned char *data;
|
|
|
|
|
+ struct can_frame frame;
|
|
|
|
|
+ int index = g_can_dev[0].can_sock == sock ? 0 : 1;
|
|
|
|
|
+
|
|
|
|
|
+ if(can_soft_recv(sock, &frame) < 0)
|
|
|
|
|
+ return ;
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ can_id = frame.can_id;
|
|
|
|
|
+ can_dlc = frame.can_dlc;
|
|
|
|
|
+ data = frame.data;
|
|
|
|
|
+
|
|
|
|
|
+ printf("CAN%d dlc = %d, can_id = %x\ndata:", index,frame.can_dlc, frame.can_id);
|
|
|
|
|
+ for(i=0; i<frame.can_dlc; i++)
|
|
|
|
|
+ printf("0x%02x ", frame.data[i]);
|
|
|
|
|
+ printf("\n");
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
/*------------------------------ 外部函数 -------------------------------------
|
|
/*------------------------------ 外部函数 -------------------------------------
|
|
|
外部函数供其它实体文件引用,必须仔细检查传入参数的合法性.
|
|
外部函数供其它实体文件引用,必须仔细检查传入参数的合法性.
|
|
@@ -346,6 +604,25 @@ int can_init(void)
|
|
|
rt_request_irq(CFG_CAN_VECTOR_BEGIN + 7,CFG_INT_LEVEL_CAN,_can_isr_err_1,"can_isr_err_11");
|
|
rt_request_irq(CFG_CAN_VECTOR_BEGIN + 7,CFG_INT_LEVEL_CAN,_can_isr_err_1,"can_isr_err_11");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 获取CAN设备句柄
|
|
|
|
|
+ if (i == 0) {
|
|
|
|
|
+ g_can_dev[i].can_sock = can_open("can0");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ g_can_dev[i].can_sock = can_open("can1");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 创建CAN设备接收线程
|
|
|
|
|
+ if (0 != pthread_create(&can_tid[i], NULL, can_proc_recv, (void *)&g_can_dev[i].can_sock))
|
|
|
|
|
+ {
|
|
|
|
|
+ return -2;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 创建CAN设备发送线程
|
|
|
|
|
+ if (0 != pthread_create(&can_tid_s[i], NULL, can_proc_send, (void *)&g_can_dev[i].can_sock))
|
|
|
|
|
+ {
|
|
|
|
|
+ return -3;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/* init and start flexcan */
|
|
/* init and start flexcan */
|
|
|
_can_chipset_init(dev, 0);
|
|
_can_chipset_init(dev, 0);
|
|
|
_can_set_normal_mode(dev);
|
|
_can_set_normal_mode(dev);
|
|
@@ -358,20 +635,30 @@ int can_init(void)
|
|
|
int can_exit(void)
|
|
int can_exit(void)
|
|
|
{
|
|
{
|
|
|
int i = 0;
|
|
int i = 0;
|
|
|
- if (g_can_fd >= 0)
|
|
|
|
|
- {
|
|
|
|
|
- close(g_can_fd);
|
|
|
|
|
- g_can_fd = -1;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // exit can recv thread
|
|
|
|
|
+ bexit = 1;
|
|
|
for (i = 0; i < CAN_BUS_NUM; i++) {
|
|
for (i = 0; i < CAN_BUS_NUM; i++) {
|
|
|
|
|
+ pthread_join(can_tid[i], NULL);
|
|
|
|
|
+ pthread_join(can_tid_s[i], NULL);
|
|
|
|
|
+
|
|
|
if (g_can_map_base[i]) {
|
|
if (g_can_map_base[i]) {
|
|
|
if (munmap(g_can_map_base, g_can_mapped_size) == -1) {
|
|
if (munmap(g_can_map_base, g_can_mapped_size) == -1) {
|
|
|
printf("can[%d] dev munmap failed!", i);
|
|
printf("can[%d] dev munmap failed!", i);
|
|
|
return -1;
|
|
return -1;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ if (g_can_dev[i].can_sock >= 0) {
|
|
|
|
|
+ close(g_can_dev[i].can_sock);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (g_can_fd >= 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ close(g_can_fd);
|
|
|
|
|
+ g_can_fd = -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
rt_free_irq(CFG_CAN_VECTOR_BEGIN + 0);
|
|
rt_free_irq(CFG_CAN_VECTOR_BEGIN + 0);
|
|
|
rt_free_irq(CFG_CAN_VECTOR_BEGIN + 1);
|
|
rt_free_irq(CFG_CAN_VECTOR_BEGIN + 1);
|
|
|
rt_free_irq(CFG_CAN_VECTOR_BEGIN + 3);
|
|
rt_free_irq(CFG_CAN_VECTOR_BEGIN + 3);
|
|
@@ -629,10 +916,9 @@ int can_stat_reset(void)
|
|
|
*/
|
|
*/
|
|
|
static int _can_set_reset_mode(struct can_dev *dev)
|
|
static int _can_set_reset_mode(struct can_dev *dev)
|
|
|
{
|
|
{
|
|
|
-
|
|
|
|
|
|
|
+ // TODO: ocean
|
|
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
/******************************************************************************
|
|
@@ -649,10 +935,9 @@ static int _can_set_reset_mode(struct can_dev *dev)
|
|
|
*/
|
|
*/
|
|
|
static int _can_set_normal_mode(struct can_dev *dev)
|
|
static int _can_set_normal_mode(struct can_dev *dev)
|
|
|
{
|
|
{
|
|
|
-
|
|
|
|
|
|
|
+ // TODO: ocean
|
|
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@@ -1137,13 +1422,16 @@ _can_isr_err(1);
|
|
|
|
|
|
|
|
int _can_irq_force(int no)
|
|
int _can_irq_force(int no)
|
|
|
{
|
|
{
|
|
|
|
|
+#ifdef __KERNEL__
|
|
|
uint32_t flags;
|
|
uint32_t flags;
|
|
|
|
|
|
|
|
no *= 4;
|
|
no *= 4;
|
|
|
rt_irq_save(flags);
|
|
rt_irq_save(flags);
|
|
|
REG_MCF_INTFRCL1 |= 1 << no;
|
|
REG_MCF_INTFRCL1 |= 1 << no;
|
|
|
rt_irq_restore(flags);
|
|
rt_irq_restore(flags);
|
|
|
-
|
|
|
|
|
|
|
+#else
|
|
|
|
|
+ g_can_tx_call[no] = 1;
|
|
|
|
|
+#endif
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|