By: fu linux
E-mail: fulinux@sina.com
Blog: https://blog.csdn.net/fulinus
喜欢的盆友欢迎点赞和订阅!
你的喜欢就是我写作的动力!
问题导向
前面讲的很多内容都是如何添加或修改应用程序,很多盆友应该很好奇如何在yocto中添加或修改BSP的东西,比如如何添加一个熟知的hello驱动实例,
上一篇我们编译成功的SDK也可以用来编译linux内核源码树外的驱动模块,SDK交叉工具链之所以可以用来编译linux kernel模块,是因为SDK镜像中包含了开发使用的dev-pikgs, 内核开发相关的kernel-dev 和kernel-devsrc packages已经安装到SDK Image中了。以此按照使用SDK的步骤之后,在驱动模块源码里面直接就可以make编译。
但是对于我希望整合到yocto项目的要求来说显然是不符合我们的气质的
本篇讲解如何在自己的layer中添加一个hello驱动的recipe。
hello驱动recipe模板
好在poky/meta-skeleton的layer中已经为我们提供了一个hello驱动模板,只需要做简单的复制既可以实现我们的需求。meta-skeleton中的skeleton英文单词的意思是骨架的意思,这个meta-skeleton的layer就是一个框架性质的层,用于提供创建layer的一个参考。例如hello模块的recipe模板如下路径:
hello驱动模块的BB文件
cd poky/
ls meta-skeleton/recipes-kernel/hello-mod/
files hello-mod_0.1.bb
ls meta-skeleton/recipes-kernel/hello-mod/files/
COPYING hello.c Makefile
cat meta-skeleton/recipes-kernel/hello-mod/hello-mod_0.1.bb
SUMMARY = "Example of how to build an external Linux kernel module"
LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=12f884d2ae1ff87c09e5b7ccc2c4ca7e"
inherit module
SRC_URI = "file://Makefile \
file://hello.c \
file://COPYING \
"
S = "${WORKDIR}"
# The inherit of module.bbclass will automatically name module packages with
# "kernel-module-" prefix as required by the oe-core build environment.
RPROVIDES_${PN} += "kernel-module-hello"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
驱动源码hello.c
参考如下:
cat meta-skeleton/recipes-kernel/hello-mod/files/hello.c
- 1
/******************************************************************************
*
* Copyright (C) 2011 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*****************************************************************************/
#include <linux/module.h>
int init_module(void)
{
printk("Hello World!\n");
return 0;
}
void cleanup_module(void)
{
printk("Goodbye Cruel World!\n");
}
MODULE_LICENSE("GPL");
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
驱动Makefile文件
cat meta-skeleton/recipes-kernel/hello-mod/files/Makefile
obj-m := hello.o
SRC := $(shell pwd)
all:
$(MAKE) -C $(KERNEL_SRC) M=$(SRC)
modules_install:
$(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install
clean:
rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
rm -f Module.markers Module.symvers modules.order
rm -rf .tmp_versions Modules.symvers
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
这里需要注意的重要一点是KERNEL_SRC变量。module类将此变量和KERNEL_PATH变量设置为${STAGING_KERNEL_DIR},并提供构建模块所需的Linux内核构建信息。如果你的模块Makefile使用不同的变量,你可以重写do_compile任务(或者说是函数),或者为Makefile创建一个patch文件,以使用更典型的KERNEL_SRC或KERNEL_PATH变量。
还有一个需要的License文件COPYING,它对于的md5值是:
poky]$ md5sum meta-skeleton/recipes-kernel/hello-mod/files/COPYING
12f884d2ae1ff87c09e5b7ccc2c4ca7e meta-skeleton/recipes-kernel/hello-mod/files/COPYING
- 1
- 2
与bb文件中的值匹配哦
这里说明下,一般我们会在recipe目录下创建一个files目录,然后然后将补丁文件或者源码文件等其他文件放在files目录下,然后在bb文件中引用时,在 SRC_URI 变量后面用**“file://”**前缀引用相应的文件。参考上面的hello-mod_0.1.bb文件。
在meta-mylayer中添加模块的recipe
之前的项目中我们已经创建了我们自己的meta-mylayer,下面在meta-mylayer中创建一个recipe目录,命名为recipes-mymodules,过程如下:
poky]$ mkdir -p meta-mylayer/recipes-mymodules
- 1
之后将hello-mod目录复制到我们自己的recipe目录下:
poky]$ cp -rf meta-skeleton/recipes-kernel/hello-mod/ meta-mylayer/recipes-mymodules/
- 1
好了,可以开始编译了:
poky]$ source oe-init-build-env
build]$ bitbake hello-mod
- 1
- 2
没有任何错误,编译完成了。我们看下ko文件所在目录:
build]$ cd tmp/work/qemux86_64-poky-linux/hello-mod/0.1-r0/
0.1-r0]$ ls image/
etc lib usr
0.1-r0]$ ls image/lib/modules/5.4.50-yocto-standard/extra/hello.ko
- 1
- 2
- 3
- 4
hello-mod模块编译出来的模块就是hello.ko文件,我们看到image目录下还有etc/和user目录,etc下创建了两个子目录用于添加模块的启动脚本,但是因为我们没有写这个启动脚本所以是空目录,而user目录如下:
cat image/usr/include/hello-mod/Module.symvers
#空
- 1
- 2
驱动模块添加到images中
此时模块编译完成,但是驱动模块并没有在文件系统中,我们需要在机器的配置文件中添加下面4个之一变量,参考如下:
- MACHINE_ESSENTIAL_EXTRA_RDEPENDS
- MACHINE_ESSENTIAL_EXTRA_RRECOMMENDS
- MACHINE_EXTRA_RDEPENDS
- MACHINE_EXTRA_RRECOMMENDS
每个变量都有不同的含义,这里我们使用MACHINE_EXTRA_RRECOMMENDS,而不是MACHINE_EXTRA_RDEPENDS是因为我们希望即便镜像中无法包含该模块,也不会导致构建失败。因为这个是一个无关紧要的模块,对于系统正常运行没有任何影响。
使用MACHINE_EXTRA_RRECOMMENDS变量如下:
MACHINE_EXTRA_RRECOMMENDS += "kernel-module-hello"
- 1
该值是通过将不带.ko扩展名的模块文件名附加到字符串“kernel module-”中而得到的。
在哪里添加呢?如下所示:
poky]$ vim meta/conf/machine/qemux86-64.conf
- 1
找到下面这行:
MACHINE_EXTRA_RRECOMMENDS = "kernel-module-snd-ens1370 kernel-module-snd-rawmidi"
- 1
在该行后面追加hello模块,如下:
MACHINE_EXTRA_RRECOMMENDS = "kernel-module-snd-ens1370 kernel-module-snd-rawmidi kernel-module-hello"
- 1
重新使能一下环境编译(通常我修改了bb文件后保险起见会重新source环境):
poky]$ source oe-init-build-env
build]$ bitbake hello-mod
build]$ bitbake core-image-sato
- 1
- 2
- 3
为确保hello.ko文件已经在文件系统里面了我们可以先看下rootfs里面是否存在:
build]$ ls tmp/work/qemux86_64-poky-linux/core-image-sato/1.0-r0/rootfs/lib/modules/5.4.50-yocto-standard/extra/
hello.ko
- 1
- 2
是存在的。
验证驱动加载和卸载演示
接着运行验证:
build]$ runqemu qemux86-64
- 1
另起一个终端:
$ ssh-keygen -f "/home/peeta/.ssh/known_hosts" -R 192.168.7.2
$ ssh root@192.168.7.2
- 1
- 2
首先清空内核log:
root@qemux86-64:~# dmesg -c
- 1
然后加载驱动:
root@qemux86-64:~# modprobe hello
root@qemux86-64:~# dmesg
[ 292.480170] Hello World!
- 1
- 2
- 3
打印了驱动初始化字符串。
卸载驱动演示
root@qemux86-64:~# rmmod hello
root@qemux86-64:~# dmesg
[ 292.480170] Hello World!
[ 354.720800] Goodbye Cruel World!
- 1
- 2
- 3
- 4
打印了驱动移除时的字符串。
综上hello模块添加成功了。
End~