6. Compilation of Linux kernel¶
6.1. Why compile the Kernel yourself?¶
Although the kernel we provide already supports most functions, some customers who need customized functions may not necessarily have the functional configuration they need. So this chapter will explain how to configure and compile the kernel.
6.2. Get kernel¶
6.2.1. Download source code¶
There are three ways to obtain the Kernel source code, one is the official Kernel source code, the other is the official RockChip kernel source code, and the other is the kernel source code that we have modified to adapt to our board. We use the source code we provide as an example here. Friends who are interested in the official source code can also download it to learn configuration.
Our kernel is customized based on the kernel officially provided by Rockchip. Rockchip’s kernel is chip adapted based on the official LTS (long-term support) version of the kernel. As embedded developers, we generally only need to use the kernel adapted by the chip manufacturer for development. This is what chip manufacturers do to download new versions from the official kernel to adapt.
Currently LubanCat-RK356x-Linux-SDK uses kernel version 4.19. LubanCat-RK3588-Linux-SDK uses kernel version 5.10.
Since the launch of rk356x/rk3588 was not very long ago, Rockchip has submitted fewer official adaptations to the kernel. As a result, many functions of the chip have not been implemented, so currently we can only use Rockchip’s older kernel version.
Kernel official kernel source code: https://www.kernel.org/
Rockchip kernel source code: https://github.com/rockchip-linux/kernel/
LubanCat kernel source code: https://github.com/LubanCat/kernel
Use what we provide
1 2 3 4 5 | # LubanCat-RK356x
git clone -b stable-4.19-rk356x https://github.com/LubanCat/kernel
# LubanCat-RK3588
git clone -b develop-5.10 https://github.com/LubanCat/kernel
|
6.3. Kernel engineering structure analysis¶
To learn a software, especially open source software, you should first start by analyzing the engineering structure of the software. A good software has a good engineering structure, which is very helpful for readers to learn and understand the software’s architecture and workflow.
The kernel source code directory is as follows:
arch COPYING drivers init kernel make_deb.sh README sound
block CREDITS firmware ipc lib Makefile samples tools
build_image crypto fs Kbuild LICENSES mm scripts usr
certs Documentation include Kconfig MAINTAINERS net security virt
We can see that there are many directories in the Linux kernel source code directory, and there are also many files in the directories. Let’s briefly analyze the main functions of these directories.
arch : Mainly contains code related to hardware architecture, such as arm, x86, MIPS, and PPC. Each CPU platform occupies a corresponding directory. Stored in the arch directory are the support for Linux kernel process scheduling, memory management, interrupts, etc. of each platform and chip on each platform, as well as the board-level support code for each specific SoC and circuit board.
block : In Linux, block represents a block device (accessed as a whole in units of blocks (a whole composed of multiple bytes, similar to sectors)). For example, SD cards, Nands, hard disks, etc. are all block devices. The block directory contains some code for block device management in the Linux storage system.
crypto : This directory stores commonly used encryption and hashing algorithms (such as md5, AES, SHA, etc.), as well as some compression and CRC verification algorithms.
Documentation: Document description of each part of the kernel.
drivers : Device driver, which lists the driver source codes of all hardware devices supported by the Linux kernel. Each different driver occupies a subdirectory, such as char, block, net, mtd, i2c, etc.
fs : fs is file system, which contains various file systems supported by Linux, such as EXT, FAT, NTFS, JFFS2, etc.
include : The directory includes most of the header files needed to compile the core. For example, platform-independent header files are in the include/linux
subdirectory, and header files related to the CPU architecture are in the corresponding subdirectory of the include directory.
init : Kernel initialization code. The code in this directory is the code that initializes the kernel when the Linux kernel starts.
ipc : ipc is inter process communication
. This directory contains codes for linux inter-process communication.
kernel : Kernel is the Linux kernel, which is the core part of Linux, including process scheduling, timers, etc., and some code related to the platform is placed in the arch/*/kernel directory.
lib :lib means library. The lib directory stores some commonly used and useful library functions. Note that the library functions here are different from the C language library functions, because the C language standard library functions cannot be used in kernel programming. Therefore, you need to use library functions in lib. In addition, the library function codes related to the processor structure are placed in the arch/*/lib/
directory.
mm : Directory contains all memory management code that is independent of the CPU architecture, such as page storage management memory allocation and release, etc. The memory management code related to the specific hardware architecture is located in the arch/*/mm
directory, such as arch/arm/mm/fault.c
.
net : Network protocol stack related codes, implementing various common network protocols in the net directory.
scripts : All script files in this directory are not used when the Linux kernel works, but are used to configure and compile the Linux kernel.
security : Code related to the kernel security model, such as the most famous SELINUX.
sound : Driver core code and common device drivers for ALSA and OSS audio devices.
usr : Implement cpio for packaging and compression, etc.
Just some common directories are listed here.
6.4. Kernel configuration options¶
提示
This section requires entering commands, which must be performed in the kernel directory.
6.4.1. Configure kernel options and use LubanCat board configuration¶
The configuration files used in different versions of the kernel and different series of Lubancat boards are saved in arch/arm64/configs in the kernel directory. The specific configuration files used are as follows:
Kernel 4.19: LubanCat-RK356x series boards are usedlubancat2_defconfig
Kernel 5.10: LubanCat-RK356x series boards are usedlubancat_rk356x_linux_defconfig
Kernel 5.10: LubanCat-RK3588 series boards are usedlubancat_rk3588_linux_defconfig
The following uses the LubanCat-2 board as an example for explanation.
The Linux kernel configuration system consists of three parts, namely:
Makefile: distributed in the Linux kernel source code root directory and directories at each level, defining the compilation rules of the Linux kernel;
Configuration file: Provides users with the function of configuration selection. For example, the Kconfig file defines configuration items. When compiling, use the
arch/arm64/configs/lubancat2_defconfig
file to assign values to configuration items;
Configuration tools: including configuration command interpreter (interprets the configuration commands used in the configuration script) and configuration user interface (Linux provides character-based interface, Ncurses-based graphical interface and user configuration interface based on the Xwindows graphical interface, corresponding to make config, make menuconfig and make xconfig respectively).
注意
If you customize the configuration file, you must modify the definition of RK_KERNEL_DEFCONFIG in the device/rockchip/rk356x/BoardConfig.mk file corresponding to the board when compiling.
We can view our configuration through the make menuconfig KCONFIG_CONFIG=arch/arm64/configs/lubancat2_defconfig ARCH=arm64
command.
“make menuconfig” is a configuration interface based on text selection and is recommended for use in a character terminal.
And this configuration file is lubancat2_defconfig
.
At this point you can see the configuration selection in lubancat2_defconfig.
You can select and configure through the keyboard’s “up”, “down”, “left”, “right”, “enter”, “space”, “?”, “ESC” and other keys. For details, see:
1 2 3 4 5 | # Using the graphical interface configuration requires additional installation of libncurses-dev
sudo apt install libncurses-dev
# Excuting an order
make menuconfig KCONFIG_CONFIG=arch/arm64/configs/lubancat2_defconfig ARCH=arm64
|
For example, we choose to configure the ov5648 camera driver of the board: ov5648
.
If you cannot find this configuration option, you can use the search function in make menuconfig
.
Press “/” in the English input method state. Then you can enter “ov5648” to find the location of configuration options.
When typing a mistake, you can use Ctrl+Backspace to delete the input.
For details :
From the picture, it is obvious that the configuration options of ov5648
are located in -> Device Drivers
~ -> Multimedia support (MEDIA_SUPPORT [=y])``~
-> I2C Encoders, decoders , sensors and other helper chips``
In fact, you can also press "1"
to directly navigate to the corresponding option.
Then select the following content, see the picture for details:
You can use the y, n, m
keys to change the configuration of the ov5648 driver.
Among them, y means compiled into the kernel, m means compiled into a module, and n means not compiled.
You can also use spaces to select configuration options for the ov5648 driver.
The same goes for configuring other drivers.
After the modification is completed, we save and exit, and then use the following command to save the defconfig file and overwrite the original configuration file
1 2 3 4 5 | # Save defconfig file
make savedefconfig ARCH=arm64
# Overwrite the original configuration file
cp defconfig arch/arm64/configs/lubancat2_defconfig
|
6.5. Kernel compilation¶
提示
The operations that require entering commands in this section must be performed in the root directory of the SDK.
In LubanCat-SDK, automatic compilation scripts are basically stored in build.sh, which is the main function entrance of the SDK.
There are two ways to compile the kernel. One is the rk standard boot partition, called the rkboot partition, and the other is the Embedfire-modified extboot partition.
The rkboot partition is packaged in binary form, and the addresses stored in each part are strictly defined. When reading a file, the binary file header is used to determine the type of file. Currently, the LubanCat board has stopped supporting it.
The extboot partition we modified stores files in ext4 format, which is readable and modifiable in the system, greatly increasing convenience. Based on this, we added the functions of online updating the kernel version, modifying the device tree plug-in, and switching the main device tree to the extboot partition system. Finally, we realized a mirror function that can be used for all LubanCat boards using the same model of processor.
6.5.1. extboot partition compilation¶
Because when packaging the extboot partition, the kernel deb package will be packaged. Therefore, before building the extboot partition image, we must first proceed to the next step to build the kernel deb package.
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | function build_extboot(){
check_config RK_KERNEL_DTS RK_KERNEL_DEFCONFIG || return 0
echo "============Start building kernel============"
echo "TARGET_ARCH =$RK_ARCH"
echo "TARGET_KERNEL_CONFIG =$RK_KERNEL_DEFCONFIG"
echo "TARGET_KERNEL_DTS =$RK_KERNEL_DTS"
echo "TARGET_KERNEL_CONFIG_FRAGMENT =$RK_KERNEL_DEFCONFIG_FRAGMENT"
echo "=========================================="
pwd
build_check_cross_compile
cd kernel
make ARCH=$RK_ARCH $RK_KERNEL_DEFCONFIG $RK_KERNEL_DEFCONFIG_FRAGMENT
make ARCH=$RK_ARCH $RK_KERNEL_DTS.img -j$RK_JOBS
make ARCH=$RK_ARCH dtbs -j$RK_JOBS
echo -e "\e[36m Generate extLinuxBoot image start\e[0m"
KERNEL_VERSION=$(cat $TOP_DIR/kernel/include/config/kernel.release)
EXTBOOT_IMG=${TOP_DIR}/kernel/extboot.img
EXTBOOT_DIR=${TOP_DIR}/kernel/extboot
EXTBOOT_DTB=${EXTBOOT_DIR}/dtb/
rm -rf $EXTBOOT_DIR
mkdir -p $EXTBOOT_DTB/overlay
mkdir -p $EXTBOOT_DIR/uEnv
mkdir -p $EXTBOOT_DIR/kerneldeb
cp ${TOP_DIR}/$RK_KERNEL_IMG $EXTBOOT_DIR/Image-$KERNEL_VERSION
if [ "$RK_ARCH" == "arm64" ];then
cp ${TOP_DIR}/kernel/arch/${RK_ARCH}/boot/dts/rockchip/*.dtb $EXTBOOT_DTB
cp ${TOP_DIR}/kernel/arch/${RK_ARCH}/boot/dts/rockchip/overlay/*.dtbo $EXTBOOT_DTB/overlay
cp ${TOP_DIR}/kernel/arch/${RK_ARCH}/boot/dts/rockchip/uEnv/uEnv*.txt $EXTBOOT_DIR/uEnv
else
cp ${TOP_DIR}/kernel/arch/${RK_ARCH}/boot/dts/*.dtb $EXTBOOT_DTB
cp ${TOP_DIR}/kernel/arch/${RK_ARCH}/boot/dts/overlay/*.dtbo $EXTBOOT_DTB/overlay
fi
cp -f $EXTBOOT_DTB/${RK_KERNEL_DTS}.dtb $EXTBOOT_DIR/rk-kernel.dtb
if [[ -e ${TOP_DIR}/kernel/ramdisk.img ]]; then
cp ${TOP_DIR}/kernel/ramdisk.img $EXTBOOT_DIR/initrd-$KERNEL_VERSION
echo -e "\tinitrd /initrd-$KERNEL_VERSION" >> $EXTBOOT_DIR/extlinux/extlinux.conf
fi
cp ${TOP_DIR}/kernel/.config $EXTBOOT_DIR/config-$KERNEL_VERSION
cp ${TOP_DIR}/kernel/System.map $EXTBOOT_DIR/System.map-$KERNEL_VERSION
cp ${TOP_DIR}/kernel/logo.bmp $EXTBOOT_DIR/
cp ${TOP_DIR}/linux-headers-"$KERNEL_VERSION"_"$KERNEL_VERSION"-*.deb $EXTBOOT_DIR/kerneldeb
cp ${TOP_DIR}/linux-image-"$KERNEL_VERSION"_"$KERNEL_VERSION"-*.deb $EXTBOOT_DIR/kerneldeb
rm -rf $EXTBOOT_IMG && truncate -s 128M $EXTBOOT_IMG
fakeroot mkfs.ext4 -F -L "boot" -d $EXTBOOT_DIR $EXTBOOT_IMG
finish_build
}
|
check_config checks whether the configuration file exists
build_check_cross_compile sets cross-compilation parameters
Application-defined kernel configuration file
Compile the kernel image
Compile device tree
Create the EXTBOOT_DIR temporary folder to store the files used to generate the boot partition
Copy the kernel image, device tree file, device tree plug-in, and uEnv environment variable file
Determine whether to add ramdisk image
Copy the startup logo, kernel configuration file, System.map, and kernel deb package
Package the files in the EXTBOOT_DIR folder to extboot.img in ext4 format
In the subsequent steps, extboot.img will be soft linked to rockdev/boot.img
6.6. Build kernel deb package¶
When we run make bindeb-pkg in the kernel, up to 5 Debian software packages will be generated. In LubanCat-SDK, we can directly use the following commands to build them.
1 | ./build.sh kerneldeb
|
Its build script is as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ./build.sh kerneldeb
function build_kerneldeb(){
check_config RK_KERNEL_DTS RK_KERNEL_DEFCONFIG || return 0
build_check_cross_compile
echo "============Start building kernel deb============"
echo "TARGET_ARCH =$RK_ARCH"
echo "TARGET_KERNEL_CONFIG =$RK_KERNEL_DEFCONFIG"
echo "TARGET_KERNEL_DTS =$RK_KERNEL_DTS"
echo "TARGET_KERNEL_CONFIG_FRAGMENT =$RK_KERNEL_DEFCONFIG_FRAGMENT"
echo "=========================================="
pwd
cd kernel
make ARCH=$RK_ARCH $RK_KERNEL_DEFCONFIG $RK_KERNEL_DEFCONFIG_FRAGMENT
make ARCH=$RK_ARCH bindeb-pkg RK_KERNEL_DTS=$RK_KERNEL_DTS -j$RK_JOBS
finish_build
}
|
Check_config checks whether the configuration file exists
Build_check_cross_compile sets cross-compilation parameters
Application-defined kernel configuration file
Compile the kernel deb package
The generated software package is as follows:
linux-image-version: Generally includes kernel image and kernel module, we also added device tree and device tree plug-in
linux-headers-version: includes header files required to create external modules
linux-firmware-image-version: includes firmware required by some drivers (not generated here)
linux-image-version-dbg: adds debug symbols based on linux-image-version
linux-libc-dev: includes headers related to user libraries such as GNU glibc
提示
version is the kernel version
Among them, the most important ones we use are linux-image and linux-headers, and linux-firmware can be installed through the network.
By installing linux-headers, we can install the gcc compiler directly on the board for local compilation. Please see the application deployment chapter for specific usage methods.
By installing linux-image, you can update the kernel image, device tree, device tree plug-in, and kernel module.
6.6.1. Installation of kernel deb package¶
We copy the generated deb package to the board running Ubuntu or Debian image through a USB storage device or network, and use the following command to install the package.
错误
Be careful not to cut off the power during the update, otherwise the system may be damaged and unable to start.
1 2 3 4 5 6 7 | # The kernel is version 4.19
sudo dpkg -i linux-headers-4.19.xxx_4.19.xxx-xxx_arm64.deb
sudo dpkg -i linux-image-4.19.xxx_4.19.xxx-xxx_arm64.deb
# The kernel is version 5.10
sudo dpkg -i linux-headers-5.10.xxx_5.10.xxx-xxx_arm64.deb
sudo dpkg -i linux-image-5.10.xxx_5.10.xxx-xxx_arm64.deb
|
注解
When installing a local deb package, run the above command in the directory where the deb package is located. xxx is the actual number corresponding to the deb package.
Wait for the deb package to be installed and then restart to complete the kernel update.
In addition to using the deb package directly for local updates, you can also use the Embedfire software source for online updates.
1 2 3 4 5 6 7 8 9 10 11 12 13 | sudo apt update
# Update all packages to be updated
sudo apt upgrade
# Only update linux-image and linux-headers
# The kernel is version 4.19.232
sudo apt install linux-image-4.19.232
sudo apt install linux-headers-4.19.232
# The kernel is version 5.10.160
sudo apt install linux-image-5.10.160
sudo apt install linux-headers-5.10.160
|
After the upgrade is completed, restart the board to complete the kernel update.