目录
一、内核编译安装
1.下载相关资料包
当前环境为ubuntu18.04版本,已安装ros-melodic环境,先查看当前系统内核版本
uname -a
得出:
Linux robotarm 5.4.0-89-generic #100~18.04.1-Ubuntu SMP Wed Sep 29 10:59:42 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
下载补丁,内核版本与补丁版本保持一致。
补丁下载地址: https://www.kernel.org/pub/linux/kernel/projects/rt/
内核地址: http://www.kernel.org/pub/linux/kernel/
patches-5.4.154-rt65.tar.gz 20-Oct-2021 15:15 389
linux-5.4.154.tar.gz 17-Oct-2021 08:48 163M2、
2.解压
先解压内核,再把补丁拷贝进内核目录
tar -xvf linux-5.4.154.tar.gz
tar -xvf patches-5.4.154-rt65.tar.gz
mv patches linux-5.4.154
cd linux-5.4.154
3.合并补丁
将patches解压出来的文件合并
#!/bin/sh
cat ./patches/series | while read line
do
patch -p1 < ./patches/$line
done
4.内核配置
sudo chrt 10 bash
make mrproper
cp /boot/config-5.4.0-89-generic .config
安装依赖包
sudo apt-get install libncurses-dev bison flex bc libelf-dev
sudo apt-get install libssl-dev
进入菜单配置界面
make menuconfig
进入“General setup”, 在"Preemption Model"中选择“Fully Preemptible Kernel(Real-Time)”
这里按enter键会先保存好然后返回上一层,然后再用方向右键移到exit那里,然后返回上一层,找到Device Drivers
找到staging drivers ,(在比较后面,慢慢找),然后按空格键,把它去掉。
然后save 、exit。
可以使用lscpu指令查看当前cpu的逻辑核心数:4
lscpu
架构: x86_64
CPU 运行模式: 32-bit, 64-bit
字节序: Little Endian
CPU: 4
在线 CPU 列表: 0-3
每个核的线程数: 2
每个座的核数: 2
座: 1
NUMA 节点: 1
厂商 ID: GenuineIntel
CPU 系列: 6
型号: 69
型号名称: Intel(R) Core(TM) i5-4250U CPU @ 1.30GHz
步进: 1
CPU MHz: 2294.841
CPU 最大 MHz: 2600.0000
CPU 最小 MHz: 800.0000
BogoMIPS: 3791.50
虚拟化: VT-x
L1d 缓存: 32K
L1i 缓存: 32K
L2 缓存: 256K
L3 缓存: 3072K
NUMA 节点0 CPU: 0-3
执行下面的指令,其中,'getconf_NPROCESSORS_ONLN' 表示内核数量是多少个。编译内核的操作会比较耗时,所以尽可能的开启多个逻辑核同时编译,可以减少编译时间。
make -j$(getconf _NPROCESSORS_ONLN)
或者 make -j4
安装内核模块
make modules_install
安装内核
make install
然后报错了
# make modules_install
sed: 无法读取 modules.order: 没有那个文件或目录
Makefile:1351: recipe for target '_modinst_' failed
make: *** [_modinst_] Error 2
# make modules
CALL scripts/checksyscalls.sh
CALL scripts/atomic/check-atomics.sh
DESCEND objtool
CHK include/generated/compile.h
CHK kernel/kheaders_data.tar.xz
make[1]: *** 没有规则可制作目标“debian/canonical-certs.pem”,由“certs/x509_certificate_list” 需求。 停止。
Makefile:1734: recipe for target 'certs' failed
make: *** [certs] Error 2
我猜可能是因为我的当前内核版本跟下载的内核版本不一样吧,就想重新去官网下载了跟5.4.0-89一样的版本,好家伙,压根没有89的。
还是先试着解决报错的问题,一个一个百度,编辑.config文件,把下面两行注释掉
gedit .config
CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
CONFIG_SYSTEM_TRUSTED_KEYS="debian/canonical-certs.pem"
make -j4
make modules_install -j4
make install
root@robotarm:/home/robotarm/文档/ethercat_master_file/linux-5.4.154# make install -j4
sh ./arch/x86/boot/install.sh 5.4.154-rt65 arch/x86/boot/bzImage \
System.map "/boot"
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 5.4.154-rt65 /boot/vmlinuz-5.4.154-rt65
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 5.4.154-rt65 /boot/vmlinuz-5.4.154-rt65
update-initramfs: Generating /boot/initrd.img-5.4.154-rt65
run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 5.4.154-rt65 /boot/vmlinuz-5.4.154-rt65
run-parts: executing /etc/kernel/postinst.d/update-notifier 5.4.154-rt65 /boot/vmlinuz-5.4.154-rt65
run-parts: executing /etc/kernel/postinst.d/xx-update-initrd-links 5.4.154-rt65 /boot/vmlinuz-5.4.154-rt65
I: /vmlinuz.old is now a symlink to boot/vmlinuz-5.4.0-89-generic
I: /initrd.img.old is now a symlink to boot/initrd.img-5.4.0-89-generic
I: /vmlinuz is now a symlink to boot/vmlinuz-5.4.154-rt65
I: /initrd.img is now a symlink to boot/initrd.img-5.4.154-rt65
run-parts: executing /etc/kernel/postinst.d/zz-update-grub 5.4.154-rt65 /boot/vmlinuz-5.4.154-rt65
Sourcing file `/etc/default/grub'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.4.154-rt65
Found initrd image: /boot/initrd.img-5.4.154-rt65
Found linux image: /boot/vmlinuz-5.4.0-89-generic
Found initrd image: /boot/initrd.img-5.4.0-89-generic
Found linux image: /boot/vmlinuz-5.4.0-87-generic
Found initrd image: /boot/initrd.img-5.4.0-87-generic
Found linux image: /boot/vmlinuz-4.15.0-142-generic
Found initrd image: /boot/initrd.img-4.15.0-142-generic
Found linux image: /boot/vmlinuz-4.15.0-45-generic
Found initrd image: /boot/initrd.img-4.15.0-45-generic
Found linux image: /boot/vmlinuz-4.9.38-xenomai-3.1
Found initrd image: /boot/initrd.img-4.9.38-xenomai-3.1
Adding boot menu entry for EFI firmware configuration
done
(我似乎下载了好几次内核吧,反正这次是154版本的)
查看编译后的内核大小: 18G
du -sh
18G .
5.修改grub启动配置文件
安装完内核之后,再手动更新一下grub。
update-grub
gedit编辑/etc/default/grub文件,改动三处:
将 "GRUB_TIMEOUT_STYLE=hidden" 注释掉(在前面加上“#”)。
将 "GRUB_TIMEOUT" 的值改为“15”。
将 "GRUB_CMDLINE_LINUX_DEFAULT" 的值改为“text”。
再更新一遍配置文件
update-grub
6.测试
reboot重启后进入GRUB界面,选154那个,然后
uname -a
Linux robotarm 5.4.154-rt65 #1 SMP PREEMPT_RT Thu Nov 4 10:21:44 CST 2021 x86_64 x86_64 x86_64 GNU/Linux
好像成功了,测试一下,运行五个线程,线程优先级为80,无限循环。
T: 0 序号为0的线程
P: 0 线程优先级为0
C: 9397 计数器。线程的时间间隔每达到一次,计数器加1
I: 1000 时间间隔为1000微秒(us)
Min: 最小延时(us)
Act: 最近一次的延时(us)
Avg: 平均延时(us)
Max: 最大延时(us)
sudo apt-get install rt-tests
sudo cyclictest -t 5 -p 80 -n
# /dev/cpu_dma_latency set to 0us
policy: fifo: loadavg: 3.63 1.72 0.90 1/711 2801
T: 0 ( 2797) P:80 I:1000 C: 6258 Min: 3 Act: 3 Avg: 4 Max: 31
T: 1 ( 2798) P:80 I:1500 C: 4172 Min: 3 Act: 4 Avg: 5 Max: 30
T: 2 ( 2799) P:80 I:2000 C: 3129 Min: 3 Act: 4 Avg: 5 Max: 21
T: 3 ( 2800) P:80 I:2500 C: 2503 Min: 3 Act: 3 Avg: 4 Max: 32
T: 4 ( 2801) P:80 I:3000 C: 2086 Min: 3 Act: 4 Avg: 5 Max: 27
看起来误差不大,跑ethercat通信应该没有问题
二、安装igh主站
下载
http://etherlab.org/download/ethercat/ethercat-1.5.2.tar.bz2
tar -vxf ethercat-1.5.2.tar.bz2
cd ethercat-1.5.2/
./configure --with-linux-dir=/usr/src/linux-headers-5.4.0-89-generic/ --enable-8139too=no --enable-wildcards=yes
make -j4
make modules -j4
然后报错了
CC [M] /home/robotarm/ethercat-1.5.2/devices/generic.o
/home/robotarm/ethercat-1.5.2/devices/generic.c: In function ‘ec_gen_device_init’:
/home/robotarm/ethercat-1.5.2/devices/generic.c:152:77: error: macro "alloc_netdev" requires 4 arguments, but only 3 given
dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null, ether_setup);
^
/home/robotarm/ethercat-1.5.2/devices/generic.c:152:19: error: ‘alloc_netdev’ undeclared (first use in this function); did you mean ‘alloc_netdev_mqs’?
dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null, ether_setup);
^~~~~~~~~~~~
alloc_netdev_mqs
/home/robotarm/ethercat-1.5.2/devices/generic.c:152:19: note: each undeclared identifier is reported only once for each function it appears in
/home/robotarm/ethercat-1.5.2/devices/generic.c:146:10: warning: unused variable ‘null’ [-Wunused-variable]
char null = 0x00;
^~~~
In file included from ./include/linux/skbuff.h:20:0,
from ./include/linux/if_arp.h:22,
from /home/robotarm/ethercat-1.5.2/devices/generic.c:40:
/home/robotarm/ethercat-1.5.2/devices/generic.c: In function ‘ec_gen_device_create_socket’:
./include/linux/socket.h:181:19: warning: passing argument 1 of ‘sock_create_kern’ makes pointer from integer without a cast [-Wint-conversion]
#define AF_PACKET 17 /* Packet family */
^
./include/linux/socket.h:235:19: note: in expansion of macro ‘AF_PACKET’
#define PF_PACKET AF_PACKET
^~~~~~~~~
/home/robotarm/ethercat-1.5.2/devices/generic.c:210:28: note: in expansion of macro ‘PF_PACKET’
ret = sock_create_kern(PF_PACKET, SOCK_RAW, htons(ETH_P_ETHERCAT),
^~~~~~~~~
In file included from ./include/linux/skbuff.h:26:0,
from ./include/linux/if_arp.h:22,
from /home/robotarm/ethercat-1.5.2/devices/generic.c:40:
./include/linux/net.h:235:5: note: expected ‘struct net *’ but argument is of type ‘int’
int sock_create_kern(struct net *net, int family, int type, int proto, struct socket **res);
^~~~~~~~~~~~~~~~
/home/robotarm/ethercat-1.5.2/devices/generic.c:211:13: warning: passing argument 4 of ‘sock_create_kern’ makes integer from pointer without a cast [-Wint-conversion]
&dev->socket);
^
In file included from ./include/linux/skbuff.h:26:0,
from ./include/linux/if_arp.h:22,
from /home/robotarm/ethercat-1.5.2/devices/generic.c:40:
./include/linux/net.h:235:5: note: expected ‘int’ but argument is of type ‘struct socket **’
int sock_create_kern(struct net *net, int family, int type, int proto, struct socket **res);
^~~~~~~~~~~~~~~~
/home/robotarm/ethercat-1.5.2/devices/generic.c:210:11: error: too few arguments to function ‘sock_create_kern’
ret = sock_create_kern(PF_PACKET, SOCK_RAW, htons(ETH_P_ETHERCAT),
^~~~~~~~~~~~~~~~
In file included from ./include/linux/skbuff.h:26:0,
from ./include/linux/if_arp.h:22,
from /home/robotarm/ethercat-1.5.2/devices/generic.c:40:
./include/linux/net.h:235:5: note: declared here
int sock_create_kern(struct net *net, int family, int type, int proto, struct socket **res);
^~~~~~~~~~~~~~~~
scripts/Makefile.build:262: recipe for target '/home/robotarm/ethercat-1.5.2/devices/generic.o' failed
make[3]: *** [/home/robotarm/ethercat-1.5.2/devices/generic.o] Error 1
scripts/Makefile.build:497: recipe for target '/home/robotarm/ethercat-1.5.2/devices' failed
make[2]: *** [/home/robotarm/ethercat-1.5.2/devices] Error 2
Makefile:1734: recipe for target '/home/robotarm/ethercat-1.5.2' failed
make[1]: *** [/home/robotarm/ethercat-1.5.2] Error 2
make[1]: 离开目录“/home/robotarm/文档/ethercat_master_file/linux-5.4.154”
Makefile:834: recipe for target 'modules' failed
make: *** [modules] Error 2
。。。可能,也许,是内核版本不对吧,重新按照个试试,然后手滑,不小心卸载了一些东西,问题应该不大吧。
下列软件包是自动安装的并且现在不需要了:
amd64-microcode intel-microcode iucode-tool linux-hwe-5.4-headers-5.4.0-84 linux-hwe-5.4-headers-5.4.0-87 linux-hwe-5.4-headers-5.4.0-89
linux-image-generic-hwe-18.04 thermald
使用'sudo apt autoremove'来卸载它(它们)。
下列软件包将被【卸载】:
linux-generic-hwe-18.04 linux-headers-5.4.0-87-generic linux-headers-5.4.0-89-generic linux-headers-generic-hwe-18.04
linux-signed-generic-hwe-18.04
升级了 0 个软件包,新安装了 0 个软件包,要卸载 5 个软件包,有 5 个软件包未被升级。
解压缩后将会空出 28.6 MB 的空间。
(正在读取数据库 ... 系统当前共安装有 273602 个文件和目录。)
正在卸载 linux-signed-generic-hwe-18.04 (5.3.0.62.115) ...
正在卸载 linux-generic-hwe-18.04 (5.4.0.89.100~18.04.79) ...
正在卸载 linux-headers-5.4.0-87-generic (5.4.0-87.98~18.04.1) ...
正在卸载 linux-headers-generic-hwe-18.04 (5.4.0.89.100~18.04.79) ...
正在卸载 linux-headers-5.4.0-89-generic (5.4.0-89.100~18.04.1) ...
赶紧重新下载回来
sudo apt install linux-headers-5.4.0-89
再认真看看报错信息,好像是里面的参数传的值少了,可能是内核版本5.4的少了点什么吧
sudo gedit devices/generic.c +154
// dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null, ether_setup);
dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null,NET_NAME_UNKNOWN, ether_setup);
sudo gedit master/ethernet.c +150
// if (!(eoe->dev = alloc_netdev(sizeof(ec_eoe_t *), name, ether_setup))) {
if (!(eoe->dev = alloc_netdev(sizeof(ec_eoe_t *), name,NET_NAME_UNKNOWN, ether_setup))) {
还有一个问题是这样的
int sock_create_kern(struct net *net, int family, int type, int proto, struct socket **res);
linux2.x版本是:
int sock_create_kern(int family, int type, int protocol, struct socket **res)
{
return __sock_create(family, type, protocol, res, 1);
}
linux3.x的版本是
int sock_create_kern(int family, int type, int protocol, struct socket **res)
{
return __sock_create(&init_net, family, type, protocol, res, 1);
}
linux4.x的版本是
int sock_create_kern(struct net *net, int family, int type, int protocol, struct socket **res)
{
return __sock_create(net, family, type, protocol, res, 1);
}
而在generic.c里的调用方式是
ret = sock_create_kern(PF_PACKET, SOCK_RAW, htons(ETH_P_ETHERCAT),&dev->socket);
int
所以会导致出问题
在4.x的版本可以这样调用
sock_create_kern(&init_net, family, type, protocol, res);
所以第211行改为
// ret = sock_create_kern(PF_PACKET, SOCK_RAW, htons(ETH_P_ETHERCAT),
ret = sock_create_kern(&init_net,PF_PACKET, SOCK_RAW, htons(ETH_P_ETHERCAT),
然后再编译一次
sudo make modules
home/robotarm/ethercat-1.5.2/examples/mini/mini.c: In function ‘init_mini_module’:
/home/robotarm/ethercat-1.5.2/examples/mini/mini.c:495:5: error: implicit declaration of function ‘init_timer’; did you mean ‘init_timers’? [-Werror=implicit-function-declaration]
init_timer(&timer);
^~~~~~~~~~
init_timers
/home/robotarm/ethercat-1.5.2/examples/mini/mini.c:496:20: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
timer.function = cyclic_task;
...example里的,我都不想管了。直接注释掉。
CC [M] /home/robotarm/ethercat-1.5.2/master/cdev.o
/home/robotarm/ethercat-1.5.2/master/cdev.c:89:14: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
.fault = eccdev_vma_fault
^~~~~~~~~~~~~~~~
/home/robotarm/ethercat-1.5.2/master/cdev.c:89:14: note: (near initialization for ‘eccdev_vm_ops.fault’)
In file included from /home/robotarm/ethercat-1.5.2/master/cdev.c:42:0:
/home/robotarm/ethercat-1.5.2/master/cdev.c: In function ‘eccdev_vma_fault’:
/home/robotarm/ethercat-1.5.2/master/cdev.c:279:46: error: ‘struct vm_fault’ has no member named ‘virtual_address’
" offset = %lu, page = %p\n", vmf->virtual_address, offset, page);
^
/home/robotarm/ethercat-1.5.2/master/master.h:115:38: note: in definition of macro ‘EC_MASTER_DBG’
master->index, ##args); \
先去把62行改为,其他的报错注释掉
#define PAGE_FAULT_VERSION KERNEL_VERSION(5, 4, 154)
继续报错
/home/robotarm/ethercat-1.5.2/master/master.c: In function ‘ec_master_eoe_start’:
/home/robotarm/ethercat-1.5.2/master/master.c:1637:12: error: variable ‘param’ has initializer but incomplete type
struct sched_param param = { .sched_priority = 0 };
^~~~~~~~~~~
/home/robotarm/ethercat-1.5.2/master/master.c:1637:35: error: ‘struct sched_param’ has no member named ‘sched_priority’
struct sched_param param = { .sched_priority = 0 };
^~~~~~~~~~~~~~
/home/robotarm/ethercat-1.5.2/master/master.c:1637:52: warning: excess elements in struct initializer
struct sched_param param = { .sched_priority = 0 };
^
/home/robotarm/ethercat-1.5.2/master/master.c:1637:52: note: (near initialization for ‘param’)
/home/robotarm/ethercat-1.5.2/master/master.c:1637:24: error: storage size of ‘param’ isn’t known
struct sched_param param = { .sched_priority = 0 };
^~~~~
/home/robotarm/ethercat-1.5.2/master/master.c:1637:24: warning: unused variable ‘param’ [-Wunused-variable]
#include <linux/sched.h>,在头文件添加了这个还是报错。。。那就手动加入
struct sched_param
{
int sched_priority;
};
...其实也不行,最后发现是linux系统目录的问题,,,///,
下一篇重写吧
参考链接
实时Linux内核(PREEMPT_RT)的编译安装以及测试_v6543210的专栏-CSDN博客_preempt_rtLinux内核编译错误:make[1]: *** 没有规则可制作目标“debian/canonical-certs.pem”,由“certs/x509_certificate_list” 需求。 停止_m0_51203305的博客-CSDN博客
服务器上使用Ubuntu18.04编译内核5.4.0 - 知乎
实时Linux内核(PREEMPT_RT)的编译安装以及测试_v6543210的专栏-CSDN博客_preempt_rt