跳到主要内容

SDK 内核设置

menuconfig 是 Linux 内核提供的交互式配置工具,具有基于终端的图形化界面,可直观地浏览和修改内核配置选项。它能够自动处理配置项之间的依赖关系,避免手动修改配置文件时可能出现的冲突。 除了 menuconfig 外,内核还提供了 nconfig、xconfig 等其他配置界面。以下将介绍 menuconfig 的主要功能和基本使用方法。

1. 配置界面

执行如下指令,打开配置界面:

./build.sh lunch
./build.sh kernel-config

2. 基本操作

  1. 执行命令后显示的配置界面如下:
    Luckfox

从界面上方我们可以看到 menuconfig 的基本操作和说明。

  1. 按键操作:

    • PgUpPgDn:浏览、选择内核功能
    • :选择Select、Exit等操作
    • Enter:进入子菜单吃的
    • Y:选中这项功能
    • N:排除这项功能
    • M:以模块的形式选择
    • Esc:双击Esc返回上一级菜单
    • ?:查看这项功能的帮助信息
    • /:搜索
  2. 图例说明:

    • [*] :已选中的项目
    • [ ] :未选中的项目
    • <M> :已选中的项目(以模块形式)
    • < > :未选中的项目(以模块形式)
  3. 中间区域是用户选择各项功能的地方,您可以使用上下方向键进行导航,同时也支持直接按下行首带颜色的字母,跳转到该行,如 Kernel Features 的首字母 K,当我们按下 K 键时就会直接跳转至该行。

  4. 底部区域包含了一些常用的操作选项,为用户提供了重要的交互功能。它们的作用如下:

    • <Select>:进入当前高亮配置项的子菜单
    • <Exit>:退出当前菜单,返回上一层
    • <Help>:提供当前高亮配置项的帮助信息
    • <Save>:保存当前的配置更改,但不退出配置工具
    • <Load>:加载指定的配置文件

3. 功能简述

内核配置界面的中间部分是一个多层级的菜单系统,您可以通过上下方向键进行导航,按 Enter 键进入子菜单,按 Esc 键返回上一级菜单,通过这个界面,用户可以根据系统需求灵活配置内核,选择需要的功能和驱动,以构建适合特定硬件和用途的定制内核,以下是 Linux 内核配置界面中的主要项目:

  • General setup(常规设置):运行时的基本配置
  • Kernel Features(内核特性):核心功能的配置,如模块化、块设备支持等
  • CPU Power Management(CPU 功耗管理):配置 CPU 的功耗管理选项
  • Enable loadable module support(启用可加载模块支持):是否支持内核模块
  • IO Schedulers(I/O 调度器):配置磁盘 I/O 调度器
  • Networking support(网络支持):配置网络支持,包括协议、设备等
  • Device Drivers(设备驱动):配置各种设备驱动,如输入设备、USB 设备等
  • File systems(文件系统):配置文件系统支持,选择支持的文件系统类型
  • Security options(安全选项):配置内核安全相关选项
  • Cryptographic API(加密 API):配置加密 API 支持

4. Kernel 添加驱动示例

以下示例演示如何在 Kernel 中添加 USB TO AUDIO 驱动:

  1. 打开配置界面。进入 SDK 根目录,启动 kernel 配置界面。对于尚未编译过的 SDK,请先根据所使用的开发板选择相应的分支:
  2. 按 / 键后输入 SND_USB_AUDIO 并回车开始搜索。
    Luckfox
  3. 若仅有一个匹配项,按 1 即可跳转至该配置位置。若存在多个匹配结果,请根据路径选择对应的组件。
    Luckfox
  4. 按下 Y 或 Space 勾选 SND_USB_AUDIO,然后选择 Save 保存配置。
    Luckfox
  5. 编译内核和编译 rootfs:
    ./build.sh kernel
    ./build.sh rootfs
[提示]

在内核中将驱动配置为 =m(模块)时,虽然编译内核会生成 .ko 文件,但这些模块会被安装到根文件系统(rootfs)的 /lib/modules/<kernel-version>/ 目录中,因此除了编译内核本身外,还必须重新编译 rootfs 才能将模块正确打包进系统镜像。

5. 单独烧录内核和 rootfs

  1. 打开 瑞芯微写入工具(RKDevTool),首先执行 清空所有项(Clear Items) 操作。
    Luckfox
  2. 在空白处右键选择 导入配置(Load Config)。
    Luckfox
  3. 选中所有文件后,双击 parameter.txt 并点击 打开(Open),工具会自动加载分区配置。
    Luckfox
  4. 加载 MiniLoaderAll.bin 与 rootfs.img 文件,并勾选对应选项。最后点击 Run 按钮开始更新固件。
    Luckfox
  5. 登录开发板验证:
    Luckfox

6. Linux下加载 ko 驱动模块

6.1 ko 文件简介

在Linux操作系统中,.ko文件是内核模块文件的扩展名。内核模块是一种可以在运行时加载和卸载的代码,用于扩展Linux内核的功能,无需重新编译整个内核。每个.ko文件包含模块的代码和元数据,允许用户在不重新启动系统的情况下添加或移除特定功能,如驱动程序或文件系统支持。

6.2 ko文件的优点

  1. 动态加载和卸载:内核模块可以在运行时动态加载到内核中,也可以随时卸载,无需重新启动系统。这使得系统管理员和开发人员能够在不中断系统运行的情况下添加、测试或修复功能。
  2. 节约资源:内核模块允许将不常用的功能作为模块加载,从而减少了系统内核的大小和内存占用。这有助于提高系统的资源利用率。
  3. 定制性: 内核模块允许用户根据需要添加或移除特定功能,从而实现定制化的系统。这对于嵌入式系统、特定硬件支持和特定应用场景非常有用。
  4. 减少编译时间: 重新编译整个内核可能会花费大量时间,而使用内核模块则可以避免这种情况。只需编译和加载所需的模块,节省了时间和资源。
  5. 快速调试和开发:内核模块可以在不重新启动系统的情况下加载和卸载,这使得驱动程序和其他内核代码的调试和开发变得更加高效。
  6. 易于维护: 内核模块的独立性使得它们可以独立于整个内核进行维护和升级。这有助于降低系统维护的复杂性。
  7. 增加兼容性:内核模块可以根据需要支持多个内核版本,从而增加了软件的兼容性和灵活性。

6.3 应用实例

下载工程文件戳我下载,整个工程只有两个文件,一个helloworld.c,一个用来控制编译的Makefile。

  1. 将工程文件复制到已经安装了编译通过的 Luckfox Lyra SDK 的 Ubuntu 主机或虚拟机上。

  2. 打开并修改 Makefile 文件,以便 make 命令能够进入指定的内核源代码目录,即 Luckfox Lyra SDK 中的 kernel-6.1 目录。建议直接下载 Makefile 文件,若使用复制粘贴,请自行调整 Tab 缩进问题。

    obj-m += helloworld.o
    KDIR:=/home/xt/zt-ssd/kernel-6.1
    PWD?=$(shell pwd)
    all:
    make -C $(KDIR) M=$(PWD) modules
    echo $(PWD)
    clean:
    rm -f *.ko *.o *.mod *.mod.o *.mod.c *.symvers *.order
  3. 代码部分:

    #include <linux/module.h>
    #include <linux/init.h>

    static int helloworld_init(void)
    {
    printk("helloworld!\n");
    return 0;
    }

    static void helloworld_exit(void)
    {
    printk("helloworld bye\n");
    }

    module_init(helloworld_init);
    module_exit(helloworld_exit);

    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Luckfox");
    MODULE_VERSION("V1.0");
    • 模块加载函数:当通过insmod或modprobe命令加载内核模块时,模块的加载函数会自动被内核执行,完成本模块的相关初始化工作。 Linux内核模块加载函数一般以__init标识声明,模块加载函数以“module_init(函数名)”的形式被指定。它返回整型值,若初始化成功,应返回0。而在初始化失败时,应该返回错误编码。在Linux内核里,错误编码是一个接近于0的负值。
    • 模块卸载函数:当通过rmmod命令卸载某模块时,模块的卸载函数会自动被内核执行,完成与模块卸载函数相反的功能。 Linux内核模块加载函数一般以__exit标识声明,模块卸载函数在模块卸载的时候执行,而不返回任何值,且必须以“module_exit(函数名)”的形式来指定。
    • 模块许可证声明许可证(LICENSE):明描述内核模块的许可权限,如果不声明LICENSE,模块被加载时,将收到内核被污染(Kernel Tainted)的警告。在Linux内核模块领域,可接受的LICENSE包括“GPL”、“GPL v2”、“GPLand additional rights”、“Dual BSD/GPL”、“Dual MPL/GPL”和“Proprietary”(关于模块是否可以采用非GPL许可权,如“Proprietary”,这个在学术界和法律界都有争议)。大多数情况下,内核模块应遵循GPL兼容许可权。Linux内核模块最常见的是以MODULE_LICENSE(“GPL v2”)语句声明模块采用GPL v2。
    • 模块作者等信息声明:MODULE_AUTHOR、MODULE_DESCRIPTION、MODULE_VERSION、MODULE_DEVICE_TABLE、MODULE_ALIAS分别声明模块的作者、描述、版本、设备表和别名
  4. 进入工程文件中,执行以下命令(其中CROSS_COMPILE的地址需要按SDK的实际路径填写):

    export ARCH=arm CROSS_COMPILE=/home/ubuntu/Luckfox/Luckfox-Lyra-sdk/prebuilts/gcc/linux-x86/arm/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf/bin/arm-none-linux-gnueabihf-

    make
    #执行 make 后打印信息
    $ make
    make -C /home/xt/zt-ssd/kernel-6.1 M=/home/xt/ko-test modules
    make[1]: Entering directory '/mnt/zitai-ssd/xt/kernel-6.1'
    CC [M] /home/xt/ko-test/helloworld.o
    MODPOST /home/xt/ko-test/Module.symvers
    CC [M] /home/xt/ko-test/helloworld.mod.o
    LD [M] /home/xt/ko-test/helloworld.ko
    make[1]: Leaving directory '/mnt/zitai-ssd/xt/kernel-6.1'
    echo /home/xt/ko-test
    /home/xt/ko-test
  5. 把 helloworld.ko上传到开发板上,可以使用 SCP,ADB等方式。

    scp  helloworld.ko root@192.168.10.188:/
  6. 执行以上命令可以进行验证。

    root@luckfox:~# insmod helloworld.ko
    root@luckfox:~# rmmod helloworld.ko
  7. 最后我们使用 dmesg 查看日志。

    root@luckfox:~# dmesg | grep hello
    [13105.396731] helloworld!
    [13181.378401] helloworld bye