最近工作需要,领导要求测试nuc977开发板上的CAN模块测试工作,之前听说过CAN通信,但是实际上没有操作过,所以有些东西是欠缺的.目前在做CAN口通信测试时遇到问题,所以再次后脸皮回到论坛请教.
问题如下: linux系统下CAN接口数据收发遇到问题:
1.linux内核对于can支持配置如下
--- >CAN bus subsystem support
<*> Raw CAN Protocol (raw access with CAN-ID filtering)
<*> Broadcast Manager CAN Protocol (with content filtering)
<*> CAN Gateway/Router (with netlink configuration)
CAN Device Drivers --->
--- NUC970 CAN0/CAN1 devices
[*] NUC970 CAN0 support
[*] Enable CAN0 wake-up function
NUC970 CAN0 pin selection (Tx:PI4, Rx:PI3) --->
[*] NUC970 CAN1 support
[*] Enable CAN1 wake-up function
NUC970 CAN1 pin selection (Tx:PH15, Rx:PH14) --->
使用的是官方bsp固件包中 nu970bsp/applications/demo/CAN/main.c 修改之后的文件,这里我只修改了main函数,实现一个一直发生数据的功能.
因此这里我只粘贴我的main函数吧(main函数之前的内容没有修改)
int main(int argc, char **argv)
{
struct can_frame frame;
struct can_frame Rx_frame;
struct ifreq ifr;
struct sockaddr_can addr;
int family = PF_CAN, type = SOCK_RAW, proto = CAN_RAW;
int dlc = 8;
int can0_fd, ret, i, rtr = 0, extended = 0;
int j;
int ret1;
int Rx_cnt = 0;
can_set_bitrate("can0", 5000);
can_do_start("can0");
strcpy(ifr.ifr_name, "can0");
can0_fd = socket(family, type, proto);
if (can0_fd < 0)
{
printf("ERROR");
return 1;
}
addr.can_family = family;
if (ioctl(can0_fd, SIOCGIFINDEX, &ifr) < 0)
{
printf("ERROR");
return 1;
}
addr.can_ifindex = ifr.ifr_ifindex;
if (bind(can0_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("ERROR");
return 1;
}
for(i = 0; i < dlc; i++)
{
frame.data[i] = Rx_cnt%34 + i;
Rx_frame.data[i] = 0;
}
frame.can_id = 0x100;
frame.can_dlc = dlc;
if (extended)
{
frame.can_id &= CAN_EFF_MASK;
frame.can_id |= CAN_EFF_FLAG;
}
else
{
frame.can_id &= CAN_SFF_MASK;
}
if (rtr)
frame.can_id |= CAN_RTR_FLAG;
printf("\n CAN0 transfer id: %d", frame.can_id);
printf("\n CAN0 transfer dlc: %d", frame.can_dlc);
printf("\n CAN0 transfer Data:\n");
for (i = 0; i < frame.can_dlc; i++)
printf(" 0x%02x", frame.data[i]);
printf("\n");
ret1 = 0;
for(;;){
for(i = 0; i < dlc; i++)
{
frame.data[i] = Rx_cnt%34 + i;
Rx_frame.data[i] = 0;
}
ret = write(can0_fd, &frame, sizeof(frame));
if (ret == -1)
{
printf("write error !! \n");
}
printf("\n CAN0 transfer Data:\t");
for (i = 0; i < frame.can_dlc; i++)
printf(" 0x%02x", frame.data[i]);
Rx_cnt++;
printf("\t Rx: %d \n", Rx_cnt);
}
can_do_stop("can0");
return 0;
}
编译完成之后在linux下测试,数据不能正确发送.
(这里给之后看的人一些提示, nuvoton官方bsp中的rootfs的命令很简化,很多命令不全,需要自己重新编译busybox来获得更多的命令及其参数设置等)
之后有查阅资料,要求使用ip命令来开启can0设备,结果出错.希望晕哥给点提示.
错误提示如下:
~ # ip link set can0 up
nuc970-can0 nuc970-can0 can0: bit-timing not yet defined
nuc970-can0 nuc970-can0 can0: failed to open can device
ip: ioctl 0x8914 failed: Invalid argument
离线
没有玩过linux下的can,我记得新唐的开发手册有提到如何使用
离线
没有玩过linux下的can,我记得新唐的开发手册有提到如何使用
能厚脸皮请问一下,您说的官方手册是哪个文件啊或者pdf啥的啊?
我上面贴的代码是官方bsp包中的代码,然后配置是按照<<nuc970 LInux BSP 用户手册.pdf>>去设置,但是结果不是很理想.虚心求教
离线
https://blog.csdn.net/horotororensu/article/details/78251865
http://www.mcuzone.com/BBS/read.php?tid=10909
ifconfig can0 down //关闭can0,以便配置
ip link set can0 up type can bitrate 250000 //设置can0波特率
ip -details link show can0 //显示can0信息
没有玩过linux下的can, 楼主看下上面两个链接有没有参考价值。
离线
https://blog.csdn.net/horotororensu/article/details/78251865
http://www.mcuzone.com/BBS/read.php?tid=10909ifconfig can0 down //关闭can0,以便配置
ip link set can0 up type can bitrate 250000 //设置can0波特率
ip -details link show can0 //显示can0信息没有玩过linux下的can, 楼主看下上面两个链接有没有参考价值。
我的linux启动之后shell里不支持ip link set can0 up type can bitrate 250000 这个命令,提示是不支持type选项. 这样的话是不是我还需要重新编译busybox啊
离线
晕哥 说:https://blog.csdn.net/horotororensu/article/details/78251865
http://www.mcuzone.com/BBS/read.php?tid=10909ifconfig can0 down //关闭can0,以便配置
ip link set can0 up type can bitrate 250000 //设置can0波特率
ip -details link show can0 //显示can0信息没有玩过linux下的can, 楼主看下上面两个链接有没有参考价值。
我的linux启动之后shell里不支持ip link set can0 up type can bitrate 250000 这个命令,提示是不支持type选项. 这样的话是不是我还需要重新编译busybox啊
ip: ioctl 0x8914 failed: Invalid argument
是这个错误吗?貌似驱动没有实现 0x8914 命令
离线
https://blog.csdn.net/horotororensu/article/details/78251865
http://www.mcuzone.com/BBS/read.php?tid=10909ifconfig can0 down //关闭can0,以便配置
ip link set can0 up type can bitrate 250000 //设置can0波特率
ip -details link show can0 //显示can0信息没有玩过linux下的can, 楼主看下上面两个链接有没有参考价值。
我按照两个博文上的提示去编译ip命令,老是不能通过,目前出现的问题为
cookie@Cookie ~/Downloads/iproute2-3.6.0 % make CC=arm-linux-gcc
make[1]: Entering directory '/home/cookie/Downloads/iproute2-3.6.0/lib'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/home/cookie/Downloads/iproute2-3.6.0/lib'
make[1]: Entering directory '/home/cookie/Downloads/iproute2-3.6.0/ip'
arm-linux-gcc -Wall -Wstrict-prototypes -O2 -I../include -DRESOLVE_HOSTNAMES -DLIBDIR=\"/usr/lib\" -DCONFDIR=\"/etc/iproute2\" -D_GNU_SOURCE -DHAVE_SETNS -c -o ipnetns.o ipnetns.c
ipnetns.c: In function ‘netns_exec’:
ipnetns.c:146:2: warning: implicit declaration of function ‘setns’ [-Wimplicit-function-declaration]
if (setns(netns, CLONE_NEWNET) < 0) {
^
arm-linux-gcc -Wl,-export-dynamic ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o ipxfrm.o xfrm_state.o xfrm_policy.o xfrm_monitor.o iplink_vlan.o link_veth.o link_gre.o iplink_can.o iplink_macvlan.o iplink_macvtap.o ipl2tp.o link_vti.o ../lib/libnetlink.a ../lib/libutil.a -lresolv ../lib/libnetlink.a ../lib/libutil.a -ldl -o ip
../lib/libutil.a(utils.o): In function `format_host':
utils.c:(.text+0x10d0): warning: gethostbyaddr is obsolescent, use getaddrinfo() instead.
ipnetns.o: In function `netns_exec':
ipnetns.c:(.text+0x58): undefined reference to `setns'
collect2: error: ld returned 1 exit status
make[1]: *** [<builtin>: ip] Error 1
make[1]: Leaving directory '/home/cookie/Downloads/iproute2-3.6.0/ip'
make: *** [Makefile:48: all] Error 2
你们有遇到这个问题了,我没有查到相关的setns的库啊 ‘
离线
离线
http://man7.org/linux/man-pages/man2/setns.2.html
修改 ipnetns.c,
添加两行:
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>
这个我查看源码别人源码里面是由这个头文件包含的,宏定义也是有的,编译之后提示,宏重复定义了,但是仍然找不到setn()函数。这个是不是交叉编译器的问题啊
离线
晕哥 说:http://man7.org/linux/man-pages/man2/setns.2.html
修改 ipnetns.c,
添加两行:
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>这个我查看源码别人源码里面是由这个头文件包含的,宏定义也是有的,编译之后提示,宏重复定义了,但是仍然找不到setn()函数。这个是不是交叉编译器的问题啊
也有这种可能,c库是不是uclibc?
离线
thy442156388 说:晕哥 说:这个我查看源码别人源码里面是由这个头文件包含的,宏定义也是有的,编译之后提示,宏重复定义了,但是仍然找不到setn()函数。这个是不是交叉编译器的问题啊
也有这种可能,c库是不是uclibc?
这个应该怎么查看啊?
离线
晕哥 说:thy442156388 说:这个我查看源码别人源码里面是由这个头文件包含的,宏定义也是有的,编译之后提示,宏重复定义了,但是仍然找不到setn()函数。这个是不是交叉编译器的问题啊
也有这种可能,c库是不是uclibc?
这个应该怎么查看啊?
没有找到方便的查看方法, 这里有 uclibc 与 glibc 的区别: https://blog.csdn.net/clirus/article/details/50145959
我看了一下 buildroot 自带了 iproute 软件包功能,配置一下就可以生成可执行文件.
离线
嗯,刚刚试了一下,配置好BR2_PACKAGE_IPROUTE2=y
很容易就生成成功了:
root@ubuntu:/opt/buildroot-2018.08.2# find output/target/ |grep ip
output/target/sbin/iptunnel
output/target/sbin/iplink
output/target/sbin/ipneigh
output/target/sbin/iprule
output/target/sbin/ip
output/target/sbin/ipaddr
output/target/sbin/iproute
output/target/etc/iproute2
output/target/etc/iproute2/nl_protos
output/target/etc/iproute2/rt_dsfield
output/target/etc/iproute2/rt_protos
output/target/etc/iproute2/bpf_pinning
output/target/etc/iproute2/group
output/target/etc/iproute2/ematch_map
output/target/etc/iproute2/rt_tables
output/target/etc/iproute2/rt_scopes
output/target/etc/iproute2/rt_realms
output/target/usr/lib/ts/skip.so
output/target/usr/share/udhcpc/default.script
output/target/usr/share/udhcpc/default.script.d
output/target/usr/bin/unzip
output/target/usr/bin/bunzip2
output/target/usr/bin/ipcs
output/target/usr/bin/ipcrm
output/target/bin/gzip
output/target/bin/pipe_progress
output/target/bin/gunzip
离线
嗯,刚刚试了一下,配置好BR2_PACKAGE_IPROUTE2=y
很容易就生成成功了:
root@ubuntu:/opt/buildroot-2018.08.2# find output/target/ |grep ip output/target/sbin/iptunnel output/target/sbin/iplink output/target/sbin/ipneigh output/target/sbin/iprule output/target/sbin/ip output/target/sbin/ipaddr output/target/sbin/iproute output/target/etc/iproute2 output/target/etc/iproute2/nl_protos output/target/etc/iproute2/rt_dsfield output/target/etc/iproute2/rt_protos output/target/etc/iproute2/bpf_pinning output/target/etc/iproute2/group output/target/etc/iproute2/ematch_map output/target/etc/iproute2/rt_tables output/target/etc/iproute2/rt_scopes output/target/etc/iproute2/rt_realms output/target/usr/lib/ts/skip.so output/target/usr/share/udhcpc/default.script output/target/usr/share/udhcpc/default.script.d output/target/usr/bin/unzip output/target/usr/bin/bunzip2 output/target/usr/bin/ipcs output/target/usr/bin/ipcrm output/target/bin/gzip output/target/bin/pipe_progress output/target/bin/gunzip
好的 我尝试一下,本来我都准备重新编译一个交叉工具链,可能是新唐的交叉工具链带的软件库版本低的问题。所iprouter2编译不通过。
离线
关于buildroot的编译过程晕哥有没有合适nuc970 的参考博客啊。我这里配置的一头雾水,toolchains选择,内核版本选择,如何兼容3.10内核,都是问题,头大。
离线
还有一个问题,所以重新编译工具链算是一个解决办法么 ?
离线
我使用buildroot编译完成之后的工具链来编译我的程序,但是下载到开发板中不能够正确执行啊 。这个是什么问题啊
离线
没有在之前新唐给的rootfs上不能运行,用buildroot制作出来的文件系统就能够正常运行的,另外我使用的是ouput/image/rootfs.tar 解包作为根文件系统的,你说的那个目录output/target下有个很大的说明:说这个不是你的根文件系统,我就没用。稍后几天我会整理一个博文供大家分享。
回到正题,现在ip命令,canutil相关命令可以正常使用了。但是开发板还是不能正常进行CAN通信.
IP命令打开can0时会报错:
# ip link set can0 up
nuc970-can0 nuc970-can0 can0: bit-timing not yet defined
nuc970-can0 nuc970-can0 can0: failed to open can device
RTNETLINK answers: Invalid argument
ip命令can0接口详细信息如下
# ip -detail link show can0
2: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
link/can promiscuity 0
can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0
bitrate 0 sample-point 0.000
tq 0 prop-seg 0 phase-seg1 0 phase-seg2 0 sjw 0
nuc970_can: tseg1 2..16 tseg2 1..8 sjw 1..4 brp 1..1024 brp-inc 1
clock 75000000numtxqueues 0
离线
我又测试了下,使用buildroot编译的工具链能够正常的去编译成功IProuter2命令包。
离线
开发板还是不能正常进行CAN通信.
IP命令打开can0时会报错:
# ip link set can0 up
nuc970-can0 nuc970-can0 can0: bit-timing not yet defined
nuc970-can0 nuc970-can0 can0: failed to open can device
RTNETLINK answers: Invalid argument
ip命令can0接口详细信息如下
# ip -detail link show can0
2: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
link/can promiscuity 0
can state STOPPED (berr-counter tx 0 rx 0) restart-ms 0
bitrate 0 sample-point 0.000
tq 0 prop-seg 0 phase-seg1 0 phase-seg2 0 sjw 0
nuc970_can: tseg1 2..16 tseg2 1..8 sjw 1..4 brp 1..1024 brp-inc 1
clock 75000000numtxqueues 0
晕哥求教,这种问题是哪里出错了,是nuc970驱动的问题么 ?我是不是应该朝着驱动这个方向看
离线
bit-timing calculation not available
Enable CAN bit-timing calculation in the Linux kernel.
kernel -> Networking support -> CAN bus subsystem support -> CAN Device Drivers -> CAN bit-timing calculation
bit-timing not yet defined
First run
ip link set can0 type can bitrate 125000 triple-sampling on
then run
ifconfig can0 up
试一试这样
离线
我查看了我内核编译选项,里面勾选了CAN bit-timing calculationbit-timing。 但是我使用命令
[root@XXXXX ~] # ip link set can0 type can bitrate 125000 triple-sampling on
RTNETLINK answers: Operation not supported
我怎么老感觉是驱动的问题, 内核我也使用新的工具链编译过了。
离线
这个问题最好还是通过代理商找原厂问下, 估计玩这个组合 NUC97x + Linux + CAN
即使有人玩,也不一定分享出来了。
好,我继续找一下解决方案,做出来了,我来分享把。
离线
如果之后有人使用的,这里我整理了一个我编译buildroot的过程的博文。分享给大家,持续更新中。。
另外很感谢晕哥给与的指导
http://cookiedemo.ml/2018/12/14/buildro … %E4%BD%9C/
最近编辑记录 thy442156388 (2018-12-18 21:52:16)
离线
写得很棒,继续加油!
以后没事翻翻,就会感叹,想不到当年我如此厉害
万一后续技术更新换代,被人一做都是一键搞定得,那不就是尴尬啦,
哈哈哈
开玩笑得,自己做过的东西记录下,怕后期遗忘,如果做熟练了,还可以考虑自动化脚本啊想buildroot就很厉害啊。一起加油
离线
求助晕哥,我们的板子是自己做的,到目前位置,CAN还是不能正常通讯,我项请问下晕哥,有没有合适的功能相对齐全的nuc977开发板,给我推荐一下 ,我打算购买两块,测试CAN先确定我的软件没有问题,在让我们的硬件团队处理硬件问题。
离线
我们以前用 mcuzone 的 972 开发板, 但是没有测过 can 功能, 你可以淘宝咨询一下店主.
离线
好的,咨询中
离线
又回来请教了,这个问题困扰我快一个月了,目前又了很大的进展,问题是这样。目前我的板子是nuc977DK62Y(这里强调一下是因为市场上都是972的开发板),内核代码使用的是新唐的官方代码。
我们已经制作出了板子,PI3和PI4上连接了CAN收发器。但是在PI3和PI4上却不能正常进行CAN通信。
我重新找了一个nuc977最小系统板,经过配置之后,发现在PB10和PB11上能够正常收发,修改内核配置之后配置到PI3和PI4上却又不行了。
官方提示我,查看是否配置了NANDflash,cmos sensor等,我们自己制作的板子只有SPI-FLASH,我查看内核也没有配置NAND-FLASH支持。这种情况下我的问题出在哪里啊 ?附上新唐的关于PI3和PI4的引脚功能说明
离线
读取出来了, 数据为0x00000000,功能作为通用IO了,那现在我就要在Linux下,一个裸机的程序么 ?
离线
还是我应该向新唐报告BUG ? 因为我内核配置了PI3和PI4 为CAN0 的引脚
离线
配值了这个驱动器,CAN接口在PI3和PI4仍然不工作
离线
#if defined (CONFIG_NUC970_CAN0_PB)
pinctrl = devm_pinctrl_get_select(&pdev->dev, "can0-PB");
#elif defined (CONFIG_NUC970_CAN0_PH)
pinctrl = devm_pinctrl_get_select(&pdev->dev, "can0-PH");
#elif defined (CONFIG_NUC970_CAN0_PI)
pinctrl = devm_pinctrl_get_select(&pdev->dev, "can0-PH");
#endif
我查看了新唐的内核代码关于nuc970的配置代码,第三个define中,是不是写错了啊
应该是pinctrl = devm_pinctrl_get_select(&pdev->dev, "can0-PI");吧
最近编辑记录 thy442156388 (2019-01-11 12:13:05)
离线
要真的是这样,我要哭死, 一个月纠结这个问题,帮他们排查错误了 。。就是在PI3和PI4上测试出来。
离线
通过了,但是这个问题出在哪里呢? 我沟通新唐的人,他们官方的代码时没有问题的。 我的内核代码是在百度云上下载的,坑的我好苦啊。我在mcuzone购买的板子,配套的固件库中的内核代码也是错误的,估计这个问题要坑很多人。
最近编辑记录 thy442156388 (2019-01-11 12:54:19)
离线
通过了,但是这个问题出在哪里呢? 我沟通新唐的人,他们官方的代码时没有问题的。 我的内核代码是在百度云上下载的,坑的我好苦啊。我在mcuzone购买的板子,配套的固件库中的内核代码也是错误的,估计这个问题要坑很多人。
改好之后, 现在 NUC977 的 PI 口控制 CAN 口没有问题了对吗?
估计有两个原因:
1. 有人改了官方的代码之后, 传播出去了, 然后大家都使用了这份SDK
2. 新唐官方的代码是后来改过的
离线
代码修改之后在nuc972 和我的nuc977 上均通过测试.
应该就是这样,让一份错误的代码传播了这么久.最后给大家一个建议,内核代码,固件驱动最好找官方的,如果直接使用官方的,我就不会被这个问题困扰这么久.
最近编辑记录 thy442156388 (2019-01-14 12:23:26)
离线