igh+preempt_rt主战搭建

目录

一、内核编译安装

1.下载相关资料包

2.解压

3.合并补丁

4.内核配置

修改grub启动配置文件

参考链接 


一、内核编译安装

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

igh+preempt_rt主战搭建

 进入“General setup”, 在"Preemption Model"中选择“Fully Preemptible Kernel(Real-Time)”

igh+preempt_rt主战搭建

 这里按enter键会先保存好然后返回上一层,然后再用方向右键移到exit那里,然后返回上一层,找到Device Drivers

igh+preempt_rt主战搭建

 找到staging drivers ,(在比较后面,慢慢找),然后按空格键,把它去掉。

igh+preempt_rt主战搭建

  然后save 、exit。

igh+preempt_rt主战搭建

可以使用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 - 知乎

实时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

上一篇:OSI七层模型、CAN、CiA、CANopen、CiA301CiA402和EtherCAT介绍


下一篇:linux 服务器对拷命令scp