我目前正在为 Xilinx 的 Zybo 开发板构建嵌入式 Linux。为此,我使用 Buildroot。现在我想添加一个 driver ,用 C 语言编写,用户程序可以使用它来写入某些特定的寄存器,从而使其能够控制某些 LED。当我检查 manual ,它基本上说要做的第一件事是在新的包文件夹中创建一个 Config.in,您可以在其中写一些解释驱动程序的文本。好的,我做到了。但是现在是 makefile:我不太明白里面需要什么。它只是像 gcc -o ledcontrol hellofunc.c
这样的编译命令吗?除了 Config.in 和 Makefile,我还需要做些什么吗?
最佳答案
全自动树外 QEMU 示例
此处还提供了以下设置的一个版本:https://github.com/cirosantilli/linux-kernel-module-cheat/tree/753cbe68ff50bea0982e1791c8a2178a999d8377/buildroot_packages/kernel_modules 并记录在:https://cirosantilli.com/linux-kernel-module-cheat/kernel-modules-buildroot-package 但是,下面的设置是从该存储库中完全提取的,并且可以独立运行。
源代码树:
buildroot/
:Buildroot 2017.02,理想情况下作为 git 子模块kernel_module/
:包含一些模块的外部包,最好在 git 存储库中跟踪Config.in
external.mk
external.desc
生成文件
hello.c
: Hello World 模块overlay/etc/inittab
:只是为了使 shell 工作而进行的小修复,与内核模块本身无关
kernel_module/Config.in
config BR2_PACKAGE_KERNEL_MODULE
bool "kernel_module"
depends on BR2_LINUX_KERNEL
help
Linux Kernel Module Cheat.
内核模块/外部.mk
KERNEL_MODULE_VERSION = 1.0
KERNEL_MODULE_SITE = $(BR2_EXTERNAL_KERNEL_MODULE_PATH)
KERNEL_MODULE_SITE_METHOD = local
$(eval $(kernel-module))
$(eval $(generic-package))
内核模块/external.desc
name: KERNEL_MODULE
内核模块/生成文件
obj-m += $(addsuffix .o, $(notdir $(basename $(wildcard $(BR2_EXTERNAL_KERNEL_MODULE_PATH)/*.c))))
ccflags-y := -DDEBUG -g -std=gnu99 -Wno-declaration-after-statement
.PHONY: all clean
obj-m += $(addsuffix .o, $(notdir $(basename $(wildcard $(BR2_EXTERNAL_KERNEL_MODULE_PATH)/*.c))))
ccflags-y := -DDEBUG -g -std=gnu99 -Wno-declaration-after-statement
.PHONY: all clean
all:
$(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' modules
clean:
$(MAKE) -C '$(LINUX_DIR)' M='$(PWD)' clean
内核模块/hello.c
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
static int myinit(void)
{
printk(KERN_INFO "hello init\n");
return 0;
}
static void myexit(void)
{
printk(KERN_INFO "hello exit\n");
}
module_init(myinit)
module_exit(myexit)
覆盖/etc/inittab
::sysinit:/bin/mount -t proc proc /proc
::sysinit:/bin/mount -o remount,rw /
::sysinit:/bin/mkdir -p /dev/pts
::sysinit:/bin/mkdir -p /dev/shm
::sysinit:/bin/mount -a
::sysinit:/bin/hostname -F /etc/hostname
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::shutdown:/etc/init.d/rcK
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r
用法:
sudo apt install make gcc file bzip2 build-essential wget cpio python unzip rsync bc
git clone https://github.com/buildroot/buildroot
cd buildroot
git checkout 2017.2
make BR2_EXTERNAL="$(pwd)/../kernel_module" qemu_x86_64_defconfig
echo '
BR2_PACKAGE_KERNEL_MODULE=y
BR2_TARGET_ROOTFS_EXT2_EXTRA_BLOCKS=1024
BR2_ROOTFS_OVERLAY="overlay"
' >> .config
make olddefconfig
make BR2_JLEVEL="$(nproc)" all
qemu-system-x86_64 -M pc -kernel output/images/bzImage -drive file=output/images/rootfs.ext2,if=virtio,format=raw -append 'root=/dev/vda console=ttyS0' -net nic,model=virtio -nographic -serial mon:stdio -net user
QEMU 打开,然后运行:
modprobe hello
modprobe -r hello
dmesg
显示:
hello init
hello exit
关键行是 external.mk
中的 $(eval $(kernel-module))
,它为我们设置好一切,并在 中安装模块>modprobe
将找到它们 (/lib/modules/*/extra/hello.ko
),包括用于模块间依赖关系的 modules.dep
:How to call exported kernel module functions from another module?
如何使用 GDB 逐步调试内核模块:How to debug Linux kernel modules with QEMU?
要在启动时自动加载模块,请使用 BR2_ROOTFS_OVERLAY="../rootfs_overlay"
和执行 的
。rootfs_overlay/etc/init.d/S99modules
文件调制探测器
树内示例:https://github.com/cirosantilli/buildroot/tree/9580078b98f885ca94e4dfc896265a8a491f6ae1 它不太干净,但也能用。
在 Ubuntu 16.04 主机上测试。
关于c - 如何将 Linux 内核驱动模块添加为 Buildroot 包?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40307328/