嵌入式主板上更新xenomai +can通信测试--WT

一、更新安装的xenomai:

本文硬件基于嵌入式主板pc104+peak can通信卡
系统基于linux-4.9.38+xenoma3.0.5
就遇到的几个问题进行总结:
在给Linux内核打上补丁构建出xenomai内核后,另外需要xenomai提供的一些实用程序与库,编译安装xenomai2.5.5后系统正常运行,且实时xenomai运行正常.但是现在需要xenomai为xenomai3.0.5,就需要更新库以提供使用。
更新xenomai必然更新对应的打补丁的Linux内核,在打补丁的内核中配置好xenomai后,将其替换到主机中,且运行正常。
1、编译选项
这里遇到一个问题,我用的是xenomai下的can部分,在Linux+xenomai上配置sja1000下相应的can卡具体的硬件驱动型号时应注意Linux内核下有同样一套检查硬件的驱动程序,要是用xenomai下的驱动去探测硬件时,应在配置内核时将普通Linux内核下相关can的选项去掉,否者将会产生冲突,无法注册实时can的接口。
如果发现驱动配置正常,但是没有成功在注册can 的接口,就是在/proc/rtcan文件夹下不存在can口,另外注意是在没有加载虚拟can 驱动的情况下。可利用lsmod 查看此时主板上加载的驱动:
嵌入式主板上更新xenomai +can通信测试--WT_第1张图片

如果发现存在两个关于硬件can卡的驱动,我这里那么可以断定是发生了驱动加载冲突而导致的问题。我当时就是存在一个peak_can_pci 和 一个xeno_can_peak_pci的两个peak的驱动,就导致在xenomai中无法注册can 的接口。如果在编译时将这两个驱动都编译进内核了,那就需要重新编译内核,在编译内核的时候将普通linux内核的相关驱动关闭,我的硬件是peak can 卡,所有只需将linux下的以下选项关闭:
这个位置的选项即可
嵌入式主板上更新xenomai +can通信测试--WT_第2张图片
如果你是动态编译的驱动,则可在目录

/lib/modules/”选择自己运行的内核“/kernel/drivers/net/can/sja1000

下将关于peak相关驱动删除,重启即可。

2、需要添加3.0.5的库以及配置相关的环境变量。
当使用xenomai下的一些命令时,发现找不到命令,

--bash:xeno:command not found

这是由于系统 PATH 设置问题,PATH没有设置正确,系统就无法找到精确命令了。

首先在xenomai3.0.5正常编译安装xenomai3.0.5.然后如下添加环境变量

echo '
###Xenomai
export XENOMAI_ROOT_DIR=/usr/xenomai
export XENOMAI_PATH=/usr/xenomai
export PATH=$PATH:$XENOMAI_PATH/bin:$XENOMAI_PATH/sbin
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$XENOMAI_PATH/lib/pkgconfig
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$XENOMAI_PATH/lib
export OROCOS_TARGET=xenomai
' >> ~/.xenomai_rc

echo 'source ~/.xenomai_rc' >> ~/.bashrc
source ~/.bashrc

3、权限问题
一些就绪后,此时xenomai自带的小程序便可以运行,但是这些程序应当给与sudo 权限运行,在运行过程中利用chmod 777 *** 改变权限后同样需要sudo权限,这个暂时不明白,但是暂时不影响程序的运行。
嵌入式主板上更新xenomai +can通信测试--WT_第3张图片
但是当我们需要用到自己写的程序时我们注意到两处错误
4、xeno-config
xeno-config在xenomai中是利用xeno-config链接到各个皮肤以编译xenomai的程序。但是在以前可能存在旧版本的xeno-config(2.5.5),与新的xeno-config运行的效果是不同的,若是是运行时出现xeno-config使用不当的问题,那么就应当找到旧版本的xeno-config替换为新的xeno-config。
以下是两个版本的差异;
xeno-config 2
嵌入式主板上更新xenomai +can通信测试--WT_第4张图片
xenomai3
嵌入式主板上更新xenomai +can通信测试--WT_第5张图片
5、编译通过后,运行程序遇到了依赖库的问题

error while loading shared libraries: libXXX.so.X: cannot open shared object file: No such file

这是由于已经安装了该共享库, 但执行需要调用该共享库的程序的时候, 程序按照默认共享库路径找不到该共享库文件. 因为我们的共享库是安装在usr/lib下的,因此我们需要运行ldconfig。
ldconfig命令的用途, 主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下, 搜索出可共享的动态链接库(格式如lib*.so*), 进而创建出动态装入程序(ld.so)所需的连接和缓存文件. 缓存文件默认为/etc/ld.so.cache, 此文件保存已排好序的动态链接库名字列表.
参考:https://blog.csdn.net/sahusoft/article/details/7388617

一切问题解决后便可以编译自己的程序进行实验了。

二、pc104+peak_can卡通信实验:

利用周立功can分析仪,连接CAN卡通信口与PC机的USB,可在PC 机观察该can口的数据发送情况。利用can分析仪,从上位机发送1帧数据,当can卡接收到数据后,从同一can卡连续发出5帧数据出去:
1、编写收发程序,使can口在接收到1帧数据后从同一CAN口发送5帧数据出去:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 

#include 

static void print_usage(char *prg)
{
    fprintf(stderr,
	    "Usage: %s [] [Options]\n"
	    "Options:\n"
	    " -f  --filter=id:mask[:id:mask]... apply filter\n"
	    " -e  --error=mask      receive error messages\n"
	    " -t, --timeout=MS      timeout in ms\n"
	    " -T, --timestamp       with absolute timestamp\n"
	    " -R, --timestamp-rel   with relative timestamp\n"
	    " -v, --verbose         be verbose\n"
	    " -p, --print=MODULO    print every MODULO message\n"
	    " -h, --help            this help\n",
	    prg);
}


extern int optind, opterr, optopt;

static int s = -1, verbose = 0, print = 1,dlc=0;
static nanosecs_rel_t timeout = 0, with_timestamp = 0, timestamp_rel = 0;

RT_TASK rt_task_desc;

#define BUF_SIZ	255
#define MAX_FILTER 16
static struct can_frame fram;
struct sockaddr_can recv_addr;
struct can_filter recv_filter[MAX_FILTER];
static int filter_count = 0;

static int add_filter(u_int32_t id, u_int32_t mask)
{
    if (filter_count >= MAX_FILTER)
	return -1;
    recv_filter[filter_count].can_id = id;
    recv_filter[filter_count].can_mask = mask;
    printf("Filter #%d: id=0x%08x mask=0x%08x\n", filter_count, id, mask);
    filter_count++;
    return 0;
}

static void cleanup(void)
{
    int ret;

    if (verbose)
	printf("Cleaning up...\n");

    if (s >= 0) {
	ret = close(s);
	s = -1;
	if (ret) {
	    fprintf(stderr, "close: %s\n", strerror(-ret));
	}
	exit(EXIT_SUCCESS);
    }
}

static void cleanup_and_exit(int sig)
{
    if (verbose)
	printf("Signal %d received\n", sig);
    cleanup();
    exit(0);
}

static void rt_task(void)
{
    int i, ret, count = 0 ,k=0;
    struct can_frame frame;
    struct sockaddr_can addr;
    socklen_t addrlen = sizeof(addr);
    struct msghdr msg;
    struct iovec iov;
    nanosecs_abs_t timestamp, timestamp_prev = 0;

    if (with_timestamp) 
    {
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_name = (void *)&addr;
	msg.msg_namelen = sizeof(struct sockaddr_can);
	msg.msg_control = (void *)&timestamp;
	msg.msg_controllen = sizeof(nanosecs_abs_t);
    }

    while (1) 
{
	if (with_timestamp)
	 {
	    iov.iov_base = (void *)&frame;
	    iov.iov_len = sizeof(can_frame_t);
	    ret = recvmsg(s, &msg, 0);
	 } 

	ret = recvfrom(s, (void *)&frame, sizeof(can_frame_t), 0,(struct sockaddr *)&addr, &addrlen);
	if (ret < 0) 
	{
	    switch (ret) 
		{
		    case -ETIMEDOUT:
			if (verbose)
			    printf("recv: timed out");
			continue;
		    case -EBADF:
			if (verbose)
			    printf("recv: aborted because socket was closed");
			break;
		    default:
			fprintf(stderr, "recv: %s\n", strerror(-ret));
	   	 }
	    break;
	}
	else
	{ 
	if (print && (count % print) == 0) {
	    printf("#%d: (%d) ", count, addr.can_ifindex);
	    if (with_timestamp && msg.msg_controllen) {
		if (timestamp_rel) {
		printf("%lldns ", (long long)(timestamp - timestamp_prev));
		    timestamp_prev = timestamp;
		} else
		    printf("%lldns ", (long long)timestamp);
	    }
	    if (frame.can_id & CAN_ERR_FLAG)
		printf("!0x%08x!", frame.can_id & CAN_ERR_MASK);
	    else if (frame.can_id & CAN_EFF_FLAG)
		printf("<0x%08x>", frame.can_id & CAN_EFF_MASK);
	    else
		printf("<0x%03x>", frame.can_id & CAN_SFF_MASK);

	    printf(" [%d]", frame.can_dlc);
	    if (!(frame.can_id & CAN_RTR_FLAG))
		for (i = 0; i < frame.can_dlc; i++) {
		    printf(" %02x", frame.data[i]);
		}
	    if (frame.can_id & CAN_ERR_FLAG) {
		printf(" ERROR ");
		if (frame.can_id & CAN_ERR_BUSOFF)
		    printf("bus-off");
		if (frame.can_id & CAN_ERR_CRTL)
		    printf("controller problem");
	    } else if (frame.can_id & CAN_RTR_FLAG)
		printf(" remote request");
	    printf("\n");
	}
	count++;

	 while(k<5)
	{


		ret = sendto(s, (void *)&fram, sizeof(can_frame_t), 0,
					(struct sockaddr *)&addr, sizeof(addr));
		k++;
			if(ret <0)
			printf("fail\n");
			else
			{
	
			    printf(" [%d]", fram.can_dlc);
			    for (i = 0; i < fram.can_dlc; i++) 
			    {
				printf(" %02x", fram.data[i]);
			    }
			    printf("\n");
			}
	 }
       k=0;	
      }	
		
    }
	
	
    	
}

int main(int argc, char **argv)
{
    int opt, ret,i;
    u_int32_t id, mask;
    u_int32_t err_mask = 0;
    struct can_ifreq ifr;
    char *ptr;
    char name[32];

    struct option long_options[] = {
	{ "help", no_argument, 0, 'h' },
	{ "verbose", no_argument, 0, 'v'},
	{ "filter", required_argument, 0, 'f'},
	{ "error", required_argument, 0, 'e'},
	{ "timeout", required_argument, 0, 't'},
	{ "timestamp", no_argument, 0, 'T'},
	{ "timestamp-rel", no_argument, 0, 'R'},
	{ 0, 0, 0, 0},
    };

    signal(SIGTERM, cleanup_and_exit);
    signal(SIGINT, cleanup_and_exit);

    while ((opt = getopt_long(argc, argv, "hve:f:t:p:RT",
			      long_options, NULL)) != -1) {
	switch (opt) {
	case 'h':
	    print_usage(argv[0]);
	    exit(0);

	case 'p':
	    print = strtoul(optarg, NULL, 0);
	    break;

	case 'v':
	    verbose = 1;
	    break;

	case 'e':
	    err_mask = strtoul(optarg, NULL, 0);
	    break;

	case 'f':
	    ptr = optarg;
	    while (1) {
		id = strtoul(ptr, NULL, 0);
		ptr = strchr(ptr, ':');
		if (!ptr) {
		    fprintf(stderr, "filter must be applied in the form id:mask[:id:mask]...\n");
		    exit(1);
		}
		ptr++;
		mask = strtoul(ptr, NULL, 0);
		ptr = strchr(ptr, ':');
		add_filter(id, mask);
		if (!ptr)
		    break;
		ptr++;
	    }
	    break;

	case 't':
	    timeout = (nanosecs_rel_t)strtoul(optarg, NULL, 0) * 1000000;
	    break;

	case 'R':
	    timestamp_rel = 1;
	case 'T':
	    with_timestamp = 1;
	    break;

	default:
	    fprintf(stderr, "Unknown option %c\n", opt);
	    break;
	}
    }

    ret = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (ret < 0) {
	fprintf(stderr, "socket: %s\n", strerror(-ret));
	return -1;
    }
    s = ret;

    if (argv[optind] == NULL) {
	if (verbose)
	    printf("interface all\n");

	ifr.ifr_ifindex = 0;
    } else {
	if (verbose)
	    printf("interface %s\n", argv[optind]);

	strncpy(ifr.ifr_name, argv[optind], IFNAMSIZ);
	if (verbose)
	    printf("s=%d, ifr_name=%s\n", s, ifr.ifr_name);

	ret = ioctl(s, SIOCGIFINDEX, &ifr);
	if (ret < 0) {
	    fprintf(stderr, "ioctl GET_IFINDEX: %s\n", strerror(-ret));
	    goto failure;
	}
    }

    if (err_mask) {
	ret = setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
				&err_mask, sizeof(err_mask));
	if (ret < 0) {
	    fprintf(stderr, "setsockopt: %s\n", strerror(-ret));
	    goto failure;
	}
	if (verbose)
	    printf("Using err_mask=%#x\n", err_mask);
    }

    if (filter_count) {
	ret = setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER,
				&recv_filter, filter_count *
				sizeof(struct can_filter));
	if (ret < 0) {
	    fprintf(stderr, "setsockopt: %s\n", strerror(-ret));
	    goto failure;
	}
    }

    recv_addr.can_family = AF_CAN;
    recv_addr.can_ifindex = ifr.ifr_ifindex;
    ret = bind(s, (struct sockaddr *)&recv_addr,
		      sizeof(struct sockaddr_can));
    if (ret < 0) {
	fprintf(stderr, "bind: %s\n", strerror(-ret));
	goto failure;
    }
/*******************************************************/
	for (i = optind + 1; i < argc; i++) 
	{
	    fram.data[dlc] = strtoul(argv[i], NULL, 0);
	    dlc++;
	    if( dlc == 8 )
		break;
	}
	fram.can_dlc = dlc;	
/********************************************************/
    if (timeout) {
	if (verbose)
	    printf("Timeout: %lld ns\n", (long long)timeout);
	ret = ioctl(s, RTCAN_RTIOC_RCV_TIMEOUT, &timeout);
	if (ret) {
	    fprintf(stderr, "ioctl RCV_TIMEOUT: %s\n", strerror(-ret));
	    goto failure;
	}
    }

    if (with_timestamp) {
	ret = ioctl(s, RTCAN_RTIOC_TAKE_TIMESTAMP, RTCAN_TAKE_TIMESTAMPS);
	if (ret) {
	    fprintf(stderr, "ioctl TAKE_TIMESTAMP: %s\n", strerror(-ret));
	    goto failure;
	}
    }

    snprintf(name, sizeof(name), "rtcanrecv-%d", getpid());
    ret = rt_task_shadow(&rt_task_desc, name, 0, 0);
    if (ret) {
	fprintf(stderr, "rt_task_shadow: %s\n", strerror(-ret));
	goto failure;
    }

    rt_task();
    /* never returns */

 failure:
    cleanup();
    return -1;
}

同样首先配置通信双方的波特率:
终端:

sudo ./rtcanconfig rtcan1 --baudrate=125000 start

上位机:
嵌入式主板上更新xenomai +can通信测试--WT_第6张图片

实验结果如下:
终端显示:
嵌入式主板上更新xenomai +can通信测试--WT_第7张图片

上位机显示:

嵌入式主板上更新xenomai +can通信测试--WT_第8张图片

你可能感兴趣的:(嵌入式)