Kernel source code compilation
For the Jetson board made by yourself, you generally need to modify the device tree and driver, compile, and then replace the kernel image and device tree. Refer to the following Makefile file:
- make env_ Dependent, installation environment dependent
- make download, download the BSP source code (Sources include kernel/u-boot, etc.), and cross compile the tool chain
- make decompress, decompress the kernel source code and cross compile tool chain
- make prepare_build_kernel, which prepares for compilation, mainly puts the top-level Makefile and related files into a build folder
- make build, compile the kernel source code, including make menuconfig. The compiled kernel image is build/arch/arm64/boot/Image, and the device tree blob is build / arch / arm64 / boot / DTS / tegra186-quill-p3310-1000-c03-00-base dtb
- make scp. You can transfer the Image and dtb to the home directory of the remote TX2
BOARD = jetson-tx2-devkit PWD := $(shell pwd) # TX2 Image and dtb TX2_REMOTE= tx2@192.168.6.157 TX2_IMAGE = ${PWD}/build/arch/arm64/boot/Image TX2_DTB = ${PWD}/build/arch/arm64/boot/dts/tegra186-quill-p3310-1000-c03-00-base.dtb L4T_RELEASE_PACKAGE = jetson_linux_r32.6.1_aarch64.tbz2 SAMPLE_FS_PACKAGE = tegra_linux_sample-root-filesystem_r32.6.1_aarch64.tbz2 CROSS_COMPILE = ${PWD}/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- LOCALVERSION = -tegra TEGRA_KERNEL_OUT = ${PWD}/build RELEASE_DIR = ${PWD}/Linux_for_Tegra/kernel .PHONY: download download: # L4T Driver Package (BSP), ~355MB wget https://developer.nvidia.com/embedded/l4t/r32_release_v6.1/t186/jetson_linux_r32.6.1_aarch64.tbz2 # Sample Root Filesystem, ~1430MB wget https://developer.nvidia.com/embedded/l4t/r32_release_v6.1/t186/tegra_linux_sample-root-filesystem_r32.6.1_aarch64.tbz2 # Jetson Linux Developer Guide (downloadable version) wget https://developer.nvidia.com/embedded/l4t/r32_release_v6.1/nvidia_jetson_linux_driver_package.tar # L4T Driver Package (BSP) Sources, ~174MB wget https://developer.nvidia.com/embedded/l4t/r32_release_v6.1/sources/t186/public_sources.tbz2 # toolchain wget http://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz .PHONY: env_depend env_depend: sudo apt update sudo apt install -y qemu-user-static sudo apt install -y build-essential bc .PHONY: decompress decompress: @# ===== doc ===== mkdir -p l4t_docs & tar xvf nvidia_jetson_linux_driver_package.tar -C l4t_docs @# ===== bsp ===== @echo "\n-->\ndecompress l4t release package\n-->\n" @echo ${L4T_RELEASE_PACKAGE} tar xf ${L4T_RELEASE_PACKAGE} @# ===== rootfs ===== @# must use sudo, or apply_binaries.sh will break and tell you do this @echo "\n--->\ndecompress sample fs package\n--->\n" cd Linux_for_Tegra/rootfs/; \ sudo tar xpf ../../${SAMPLE_FS_PACKAGE}; \ cd .. .. @# ===== sources ===== @echo "\n--->\nsources\n--->\n" tar -xjf public_sources.tbz2 cd Linux_for_Tegra/source/public; \ tar xjf kernel_src.tbz2; \ cd .. .. .. @# ===== toolchain ===== @echo "\n--->\ntoolchain\n--->\n" mkdir -p l4t-gcc; \ cd l4t-gcc; \ tar xf ../gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz; \ cd .. .PHONY: apply_binaries apply_binaries: cd Linux_for_Tegra; \ sudo ./apply_binaries.sh; \ cd .. @# the last line must be Success! .PHONY: flashing flashing: cd Linux_for_Tegra; \ sudo ./flash.sh ${BOARD} mmcblk0p1 .PHONY: prepare_build_kernel prepare_build_kernel: export CROSS_COMPILE=${CROSS_COMPILE}; \ export LOCALVERSION=${LOCALVERSION}; \ mkdir -p ${TEGRA_KERNEL_OUT}; \ cd ${PWD}/Linux_for_Tegra/source/public/kernel/kernel-4.9; \ make ARCH=arm64 O=${TEGRA_KERNEL_OUT} tegra_defconfig .PHONY: build build: export CROSS_COMPILE=${CROSS_COMPILE}; \ export LOCALVERSION=${LOCALVERSION}; \ export TEGRA_KERNEL_OUT=${TEGRA_KERNEL_OUT}; \ cd ${TEGRA_KERNEL_OUT}; \ make menuconfig; \ make ARCH=arm64 O=${TEGRA_KERNEL_OUT} tegra_defconfig; \ make ARCH=arm64 O=${TEGRA_KERNEL_OUT} -j $$(nproc); \ cp ${TEGRA_KERNEL_OUT}/arch/arm64/boot/Image ${RELEASE_DIR}/; \ cp -r ${TEGRA_KERNEL_OUT}/arch/arm64/boot/dts/* ${RELEASE_DIR}/dtb/ .PHONY: scp scp: sudo scp ${TX2_IMAGE} ${TX2_DTB} ${TX2_REMOTE}:~ .PHONY: ssh ssh: ssh ${TX2_REMOTE}
Kernel and device tree updates
There are many methods:
- Plug in USB and flash SH, - K update kernel, - d update device tree file
- Change extlinux Conf, NFS mount?
- Change extlinux Conf, direct replacement, here in this way
Location reference of DTB file:
You need to set it first
Although by default, L4T is no longer in / boot / extlinux / extlinux If the FDT entry is set in conf, the user can still set this option manually to make the change take effect
# TX2 $ sudo vi /boot/extlinux/extlinux.conf # add to FDT /boot/dtb/kernel_tegra186-quill-p3310-1000-c03-00-base.dtb
Use the following
# Update kernel and device tree # PC sudo scp build/arch/arm64/boot/Image build/arch/arm64/boot/dts/tegra186-quill-p3310-1000-c03-00-base.dtb tx2@192.168.6.157:~ # TX2, 1.sh #!/bin/bash sudo mv ~/Image /boot sudo mv ~/tegra186-quill-p3310-1000-c03-00-base.dtb /boot/dtb/kernel_tegra186-quill-p3310-1000-c03-00-base.dtb # sync sudo reboot # Note that the dtb name is preceded by a kernel_
Check for updates
# The time should be 12 hours faster than the Ubuntu system time # kernel $ uname -a Linux tx2-pc 4.9.253 #1 SMP PREEMPT Wed Jan 19 22:13:36 PST 2022 aarch64 aarch64 aarch64 GNU/Linux # Device tree $ dmesg | grep DTB [ 0.164259] DTB Build time: Jan 19 2022 22:03:52 [ 0.433289] DTB Build time: Jan 19 2022 22:03:52
Some components of distribution
As mentioned in previous articles, when solving the problem of installing old distribution drivers on new computers (for example, Ubuntu 16/18 and graphics display / WiFi 6 / Bluetooth on computers released in 2021 / 20222 will certainly be abnormal), it can be supported by updating the kernel. For example, when updating to 5.11 kernel, you need to download:
# https://blog.csdn.net/weifengdq/article/details/118915007 $ tree . ├── linux-firmware_1.197.2_all.deb ├── linux-headers-5.11.0-051100-generic_5.11.0-051100.202102142330_amd64.deb ├── linux-headers-5.11.0-051100_5.11.0-051100.202102142330_all.deb ├── linux-image-unsigned-5.11.0-051100-generic_5.11.0-051100.202102142330_amd64.deb └── linux-modules-5.11.0-051100-generic_5.11.0-051100.202102142330_amd64.deb
Of which:
- Image is the kernel image. After all, the compiled kernel image is running at the end, not the source code
- Modules are modules that can be dynamically loaded into the kernel ko components, which are often compiled through the source code
- Firmware is a firmware binary blob that contains some or all functions of some hardware devices. It is usually proprietary, because some hardware manufacturers will not release the source code (such as NVIDIA graphics card, Intel's Wi Fi chipset, trying to avoid the poison of GPL, subway elderly watch. jpg)
- headers: a software package that provides Linux kernel header files and serves as interfaces between internal kernel components and between user space and the kernel
If you are building a complete kernel, obviously, you need a complete source file, not just a header file.
However, if you are compiling device drivers or other loadable modules linked to the kernel, you only need the header file, so you can save space by not installing the complete source code.
When we write kernel modules, we often see
#include<linux/module.h> #include<linux/init.h> #include<linux/kernel.h>
Where are these files? The PC files are actually in the / lib/modules/$(uname -r)/build folder, such as Linux / module H should correspond to / lib / modules / 5.13.0-27-generic / build / include / Linux / module h. There must be Linux in the source code package of TX2_ for_ Tegra/source/public/kernel/kernel-4.9/include/linux/module.h
You can even open make menuconfig directly in the folder, such as the X86 platform of the computer
# ubuntu20, now is 5.13.0-27-generic cd /lib/modules/$(uname -r)/build sudo make menuconfig # you will find Kconfig Makefile here
X86 First KO
Let's write a hello module for x86 platform:
mkdir hello cd hello vi hello.c
hello.c source code and comments
//linux headers #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> //Execute on load static int hello_init(void) { //Print messages to the kernel log buffer, usually viewed with dmesg //KERN_ALERT is the log level You can also use pr_alert() printk(KERN_ALERT "Hello Module Test\n"); pr_alert("Hello Module Test2\n"); return 0; } //Execute on uninstall static void hello_exit(void) { printk(KERN_INFO "Goodbye Hello\n"); } //Pass to API //module_init, drive initialization entry point //module_exit, the entry point that drives the exit module_init(hello_init); module_exit(hello_exit); //The author declares that with "Name < email >" or "Name", multiple authors can have multiple modules_ Author () line MODULE_AUTHOR("yiming"); //LICENSE states that it has legal effect and GPL is infectious MODULE_LICENSE("GPL"); //Description, viewed through modinfo MODULE_DESCRIPTION("First Driver");
Then vi Makefile
obj-m:=hello.o all: make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
Of which:
- -C. change directory, that is, switch to / lib/modules/$(shell uname -r)/build. Here is the kernel build directory of the current Linux version. Here is the top-level Makefile of the kernel
- M =, a variable of the top-level Makefile refers to the following source code. Let the Makefile move back to the specified directory, pwd, before trying to generate the module target, indicating hello Ko generated in current directory
# From / lib/modules/$(shell uname -r)/build/Makefile # Use make M=dir or set the environment variable KBUILD_EXTMOD to specify the # directory of external module to build. Setting M= takes precedence. ifeq ("$(origin M)", "command line") KBUILD_EXTMOD := $(M) endif
Now start walking
# hello directory $ tree . ├── hello.c └── Makefile $ make $ tree . ├── hello.c ├── hello.ko ├── hello.mod ├── hello.mod.c ├── hello.mod.o ├── hello.o ├── Makefile ├── modules.order └── Module.symvers # Check the file type, elf 64bit LSB floating program, x86-64 platform $ file hello.ko hello.ko: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), BuildID[sha1]=ea5c2968e3fe351b700b5e6f8978904e58254b8f, with debug_info, not stripped # Load hello ko $ sudo insmod hello.ko # View the last two lines $ dmesg | tail -2 [23749.761288] Hello Module Test [23749.761293] Hello Module Test2 # Uninstall hello Ko, no suffix is allowed ko $ sudo rmmod hello $ dmesg | tail -1 [23902.056184] Goodbye Hello # If you let dmesg output directly to the console # sudo dmesg -n 8 or sudo dmesg -n debug # Restore default # sudo dmesg -n 4 or # Keep dmesg displayed without exiting $ dmesg -wH &
The last command can also view the level. The Red alert:
Jetson First KO
Refer to the two sections of kernel customization - > preparing to Building External Kernel Modules and Building External Kernel Modules in the document to compile an external Jetson kernel module:
- Preprocessing: prepare the header, top-level makefile and kernel in the module source file_ source_ Tree, etc. just prepare it once
- Set variable CROSS_COMPILE to specify the cross compiler
- Set - C < top_ Makefile_ Dir > to specify the directory where the top-level Makefile is located, which is usually in the kernel directory, but here I directly threw it into the top folder
- Set M = specify the location of the module
Create a new Jetson_ Hello folder (/ home/z/jetson/test/jetson_hello), or the above hello C copy it in and then make file
obj-m:=hello.o kernel_dir = /home/z/jetson/Linux_for_Tegra/source/public/kernel/kernel-4.9 cross_compile_dir = /home/z/jetson/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- makefile_dir := $(shell pwd) top_makefile_dir := $(shell pwd)/top build_dir := $(shell pwd)/build all: @if [ ! -d ${top_makefile_dir} ]; then \ export CROSS_COMPILE=${cross_compile_dir}; \ export LOCALVERSION=-tegra; \ mkdir -p ${top_makefile_dir}; \ cd ${kernel_dir}; \ make ARCH=arm64 O=${top_makefile_dir} tegra_defconfig; \ cd ${top_makefile_dir}; \ make ARCH=arm64 O=${top_makefile_dir} -j $$(nproc) modules_prepare; \ echo "\n=================================\n"; \ fi; \ export CROSS_COMPILE=${cross_compile_dir}; \ cd ${makefile_dir};\ mkdir -p ${build_dir}; \ make ARCH=arm64 -C ${top_makefile_dir} M=${makefile_dir} -j $$(nproc); \ mv *.mod.c *.o *.order *.symvers ${build_dir} clean: @# rm -rf *.mod.* *.o *.order *.symvers *.ko rm -rf build *.ko top
Of which:
- obj-m, where m refers to module. Generally, it is selected and translated into the kernel (y) in make menuconfig with Kconfig file, or compiled by KO(m), or not compiled (n). Here - M is directly specified
- When making, first judge whether the top folder exists. If it does not exist, do the above preprocessing step
- Set the variable cross every time you compile_ Compile to specify the cross compiler
- -j $(nproc), all CPU s enter the field, but there is only one here c file, not available
Test one
$ make make[1]: Entering directory '/home/z/jetson/test/jetson_hello/top' WARNING: Symbol version dump ./Module.symvers is missing; modules will have no dependencies and modversions. LD /home/z/jetson/test/jetson_hello/built-in.o CC [M] /home/z/jetson/test/jetson_hello/hello.o Building modules, stage 2. MODPOST 1 modules CC /home/z/jetson/test/jetson_hello/hello.mod.o LD [M] /home/z/jetson/test/jetson_hello/hello.ko make[1]: Leaving directory '/home/z/jetson/test/jetson_hello/top' $ tree -L 2 . ├── build │ ├── built-in.o │ ├── hello.mod.c │ ├── hello.mod.o │ ├── hello.o │ ├── modules.order │ └── Module.symvers ├── hello.c ├── hello.ko ├── Makefile └── top ├── arch ├── include ├── kernel ├── Makefile ├── scripts └── source -> /home/z/jetson/Linux_for_Tegra/source/public/kernel/kernel-4.9 # ARM aarch64 $ file hello.ko hello.ko: ELF 64-bit LSB relocatable, ARM aarch64, version 1 (SYSV), BuildID[sha1]=8f24215154dff2b07306d655040f7c29de7a5efb, with debug_info, not stripped $ scp hello.ko tx2@192.168.6.157:~ $ ssh tx2@192.168.6.157 # TX2 $ sudo insmod hello.ko $ sudo rmmod hello $ dmesg ... [26332.410359] hello: no symbol version for module_layout [26332.416120] hello: loading out-of-tree module taints kernel. [26332.425103] Hello Module Test [26332.428150] Hello Module Test2 [26347.063612] Goodbye Hello
As shown in the figure
Longterm Kernel
The Linux Kernel Archives - Releases , Jetson's current version 4.9 was release d at the end of 16 and supported until the beginning of 23
4.9 online documentation reference of kernel: Linux Kernel Documentation — The Linux Kernel documentation , a little old... It looks comfortable without the new 5.1x organization
Command memo
# Display loaded modules lsmod # View kernel module information modinfo # Load kernel module indmod # Uninstall kernel module rmmod # View module dependencies depmod # Load or remove modules # It is more intelligent and can recursively resolve module dependencies modprobe # Determine the file type, 32/64bit file
reference resources
- Configuring Git to handle line endings - GitHub Docs
- Elimination of Git diff ^M_ Dean Chen's column - CSDN blog_^ m git
- Successfully resolved ignore git diff ^m_littlehaes blog - CSDN blog_ Git ignore differences
- [How to make and submit patch using git_ Ganggexiongqi's column - CSDN blog_ git submit patch
- gitignore ignores all files with a suffix in the subdirectory - Jianshu (jianshu.com)
- BSP/DT clarification: "quill" vs P3310 vs Jetson TX2 SOM - Jetson & Embedded Systems / Jetson TX2 - NVIDIA Developer Forums
- Tegra - Wikipedia
- Embed a shell script and function list in Makefile (breezesample. GitHub. IO)
- The Linux Kernel Module Programming Guide (tldp.org)
- Linux-headers - Gentoo Wiki
- Linux firmware - Gentoo Wiki
- View information about executable files under linux_ Blog of wojiushiwoba - CSDN blog_ View executable schema
- Message logging with printk — The Linux Kernel documentation
- c - M option in make command, Makefile - Stack Overflow
- kernel - "no symbol version for module_layout" when trying to load usbhid.ko - Ask Ubuntu
- linux kernel - Should I care that the symbol version dump is missing? How do I get one? - Stack Overflow
Welcome to scan the two-dimensional code, and pay attention to WeChat official account.