linux5.4内核搭建igh主站第二次尝试

想了一下,还是重来一遍。

tar -vxf ethercat-1.5.2.tar.bz2
cd ethercat-1.5.2/
./configure --enable-8139too=no
make
sudo make modules

目录

1. netdev和sock_create_kern问题

2. init_timer问题

3. eccdev_vma_fault问题

4.(ec_cdev_priv_t *)问题

5.sched_param 问题

6.一次性快速成功的安装方式



1. netdev和sock_create_kern问题

就会出现和昨天一样的错误

首先是devices/generic.c
的152行,加 NET_NAME_UNKNOWN
dev->netdev = alloc_netdev(sizeof(ec_gen_device_t *), &null, NET_NAME_UNKNOWN, ether_setup);

的210行
ret = sock_create_kern(&init_net, PF_PACKET, SOCK_RAW, htons(ETH_P_ETHERCAT),&dev->socket);

2. init_timer问题

继续sudo make modules

/home/robotarm/文档/ethercat_master_file/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_master_file/ethercat-1.5.2/examples/mini/mini.c:496:20: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
     timer.function = cyclic_task;

参考链接:

Linxu内核编程报错 ‘init_timer’

Improving the kernel timers API [LWN.net]

timer.h - include/linux/timer.h - Linux source code (v5.4.154) - Bootlin

将195行左右那一段改成这样
printk(KERN_INFO PFX "Starting cyclic sample thread.\n");
    #if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
    init_timer(&timer);
    timer.function = cyclic_task;
    timer.expires = jiffies + 10;
    add_timer(&timer);
    #else 
    // void timer_setup(struct timer_list *timer, void (*callback)(struct timer_list *),
	// 	     unsigned int flags);
    timer_setup(&timer,cyclic_task, 0);

然后把310行左右改为
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0)
void cyclic_task(unsigned long data)
#else 
void cyclic_task(struct timer_list *t)
#endif

3. eccdev_vma_fault问题

/home/robotarm/文档/ethercat_master_file/ethercat-1.5.2/master/cdev.c:87:14: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
     .fault = eccdev_vma_fault
              ^~~~~~~~~~~~~~~~
/home/robotarm/文档/ethercat_master_file/ethercat-1.5.2/master/cdev.c:87:14: note: (near initialization for ‘eccdev_vm_ops.fault’)
In file included from /home/robotarm/文档/ethercat_master_file/ethercat-1.5.2/master/cdev.c:42:0:
/home/robotarm/文档/ethercat_master_file/ethercat-1.5.2/master/cdev.c: In function ‘eccdev_vma_fault’:
/home/robotarm/文档/ethercat_master_file/ethercat-1.5.2/master/cdev.c:277:46: error: ‘struct vm_fault’ has no member named ‘virtual_address’
             " offset = %lu, page = %p\n", vmf->virtual_address, offset, page);
                                              ^
/home/robotarm/文档/ethercat_master_file/ethercat-1.5.2/master/master.h:115:38: note: in definition of macro ‘EC_MASTER_DBG’
                     master->index, ##args); \

将master.cdev文件64开始的那行改为

#define PAGE_FAULT_VERSION KERNEL_VERSION(2, 6, 23)

#if LINUX_VERSION_CODE >= PAGE_FAULT_VERSION
    // #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)
    //     static vm_fault_t eccdev_vma_fault(struct vm_fault *);
    // #else
    //     static int eccdev_vma_fault(struct vm_area_struct*, struct vm_fault *);
    // #endif
    static vm_fault_t eccdev_vma_fault(struct vm_fault *);
#else
static struct page *eccdev_vma_nopage(
        struct vm_area_struct *, unsigned long, int *);
#endif

第259行开始的那个函数定义改为

//static int eccdev_vma_fault(
 //   #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0)
// vm_area_struct *vma, /**< Virtual memory area. */
 //   #endif
   //     struct vm_fault *vmf /**< Fault data. */
   //     )
//
static vm_fault_t eccdev_vma_fault(struct vm_fault *vmf)

第282行

EC_MASTER_DBG(priv->cdev->master, 1, "Vma fault, virtual_address = %p,"
            " offset = %lu, page = %p\n", vmf->virtual_address, offset, page);
改为
EC_MASTER_DBG(priv->cdev->master, 1, "Vma fault, virtual_address = %p,"
            " offset = %lu, page = %p\n", vmf->address, offset, page);

mm.h - include/linux/mm.h - Linux source code (v5.4.154) - Bootlin

另外发现, 在5.4的版本中, .fault 的类型已经定义为vm_fault_t ,并且也只有vm_fault这一类型的参数

5.4的版本:

struct vm_operations_struct {
	void (*open)(struct vm_area_struct * area);
	void (*close)(struct vm_area_struct * area);
	int (*split)(struct vm_area_struct * area, unsigned long addr);
	int (*mremap)(struct vm_area_struct * area);
	vm_fault_t (*fault)(struct vm_fault *vmf);
	vm_fault_t (*huge_fault)(struct vm_fault *vmf,
			enum page_entry_size pe_size);
	void (*map_pages)(struct vm_fault *vmf,
			pgoff_t start_pgoff, pgoff_t end_pgoff);
	unsigned long (*pagesize)(struct vm_area_struct * area);
	vm_fault_t (*page_mkwrite)(struct vm_fault *vmf);
	vm_fault_t (*pfn_mkwrite)(struct vm_fault *vmf);
	int (*access)(struct vm_area_struct *vma, unsigned long addr,
		      void *buf, int len, int write);
	const char *(*name)(struct vm_area_struct *vma);

3.14的版本:

struct vm_operations_struct {
	void (*open)(struct vm_area_struct * area);
	void (*close)(struct vm_area_struct * area);
	int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
	void (*map_pages)(struct vm_area_struct *vma, struct vm_fault *vmf);
	int (*page_mkwrite)(struct vm_area_struct *vma, struct vm_fault *vmf);
	int (*access)(struct vm_area_struct *vma, unsigned long addr,
		      void *buf, int len, int write);
#ifdef CONFIG_NUMA
	int (*set_policy)(struct vm_area_struct *vma, struct mempolicy *new);

	struct mempolicy *(*get_policy)(struct vm_area_struct *vma,
					unsigned long addr);
	int (*migrate)(struct vm_area_struct *vma, const nodemask_t *from,
		const nodemask_t *to, unsigned long flags);
#endif
	/* called by sys_remap_file_pages() to populate non-linear mapping */
	int (*remap_pages)(struct vm_area_struct *vma, unsigned long addr,
			   unsigned long size, pgoff_t pgoff);
};

4.(ec_cdev_priv_t *)问题

/home/robotarm/文档/ethercat_master_file/ethercat-1.5.2/master/cdev.c:267:47: error: ‘vma’ undeclared (first use in this function); did you mean ‘vmf’?
     ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;

将267行改为

ec_cdev_priv_t *priv = (ec_cdev_priv_t *) vma->vm_private_data;

改为
ec_cdev_priv_t *priv = (ec_cdev_priv_t *)vmf->vma->vm_private_data;

5.sched_param 问题

/home/robotarm/文档/ethercat_master_file/ethercat-1.5.2/master/master.c: In function ‘ec_master_eoe_start’:
/home/robotarm/文档/ethercat_master_file/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_master_file/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_master_file/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_master_file/ethercat-1.5.2/master/master.c:1637:52: note: (near initialization for ‘param’)
/home/robotarm/文档/ethercat_master_file/ethercat-1.5.2/master/master.c:1637:24: error: storage size of ‘param’ isn’t known
     struct sched_param param = { .sched_priority = 0 };

昨天就是卡在这个问题这里,然后在目录下找了其他调用sched_param这个的文件,发现是包含的,后续进一步发现,sched.h这个文件在/usr/lib  ,/usr/lib/linux ,  /usr/lib/linux_x86_64...  这些目录都有,进一步发现,以这个名字命名的头文件在系统里有上百个。。。其中,最神奇的是,在igh的源码里,在example的文件夹里的一些main里面,调用ched_param和sched_get_priority_max这个函数,它们之间的距离不到两行,但是用vscode跳转到定义的时候,是在不同目录下的头文件,进一步的分析:

在usr/include/sched.h里是这样开头的
#ifndef	_SCHED_H
#define	_SCHED_H	

在/usr/include/x86_64-linux-gnu/bits/sched.h 里的开头是这样的
#ifndef _BITS_SCHED_H
#define _BITS_SCHED_H 1

#ifndef _SCHED_H
# error "Never include  directly; use  instead."
#endif

在/usr/include/linux/sched.h 的开头
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef _LINUX_SCHED_H
#define _LINUX_SCHED_H

十分神奇,水平有限,看不太懂

后来开了个会,一个大大大佬用github下载的igh源码一下子就装好了

出于好奇,再比较一下两者区别

在github下载的 对 sched_param 进行go to definition的时候,跳转到的文件是

usr/include/linux/sched/types.h

#ifndef _LINUX_SCHED_TYPES_H
#define _LINUX_SCHED_TYPES_H

#include 

struct sched_param {
	int sched_priority;
};

而在master.c的头文件里也加入了

#ifdef EC_EOE
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include  // struct sched_param
#include  // sched_setscheduler
#endif

6.一次性快速成功的安装方式

安装igh_ze3000的博客-CSDN博客

git clone http://gitlab.com/etherlab.org/ethercat.git
cd ethercat/
./bootstrap
./configure --enable-8139too=no
sudo make
sudo make modules
sudo make install
sudo make modules_install 

配置

cd /opt/etherlab 

将ifconfig查到的根ethercat通信的网卡mac地址复制一下,然后
gedit etc/sysconfig/ethercat

将下面两行按照文件的位置填进去

MASTER0_DEVICE="00:e8:4c:68:30:cd"
DEVICE_MODULES="generic"

配置一下路径,注意这个/etc/init.d这个

sudo cp etc/sysconfig/ethercat /etc/sysconfig/
sudo ln -s /opt/etherlab/etc/init.d/ethercat /etc/init.d/
sudo /etc/init.d/ethercat start
出现
Starting EtherCAT master 1.5.2  done
就代表成功了

。。。后面那些懒得复制粘贴了,反正在另一篇那里有

你可能感兴趣的:(linux,ethercat)