文章目录

  • 内核源码编译
  • 内核和设备树更新
  • 发行版部分组件
  • X86 First KO
  • Jetson First KO
  • Longterm Kernel
  • 命令备忘
  • 参考

内核源码编译

对于自己做的Jetson的板子一般需要修改设备树和驱动, 编译, 然后替换内核镜像(Image)和设备树(FDT), 参考下面的Makefile文件:

  • make env_depend, 安装环境依赖
  • make download, 下载BSP源码(Sources包含kernel/u-boot等), 交叉编译工具链
  • make decompress, 解压kernel源码和交叉编译工具链
  • make prepare_build_kernel, 为编译做准备, 主要是把顶级Makefile和相关文件等放到一个build文件夹里
  • make build, 编译内核源码, 里面包含make menuconfig, 编译出来的内核镜像为build/arch/arm64/boot/Image, 设备树blob为build/arch/arm64/boot/dts/tegra186-quill-p3310-1000-c03-00-base.dtb
  • make scp, 可以把Image和dtb传到远程TX2的home目录
BOARD = jetson-tx2-devkitPWD := $(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.dtbL4T_RELEASE_PACKAGE = jetson_linux_r32.6.1_aarch64.tbz2
SAMPLE_FS_PACKAGE = tegra_linux_sample-root-filesystem_r32.6.1_aarch64.tbz2CROSS_COMPILE = ${PWD}/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
LOCALVERSION = -tegraTEGRA_KERNEL_OUT = ${PWD}/build
RELEASE_DIR = ${PWD}/Linux_for_Tegra/kernel.PHONY: download
download:# L4T Driver Package (BSP), ~355MBwget https://developer.nvidia.com/embedded/l4t/r32_release_v6.1/t186/jetson_linux_r32.6.1_aarch64.tbz2# Sample Root Filesystem, ~1430MBwget 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, ~174MBwget https://developer.nvidia.com/embedded/l4t/r32_release_v6.1/sources/t186/public_sources.tbz2# toolchainwget 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 updatesudo apt install -y qemu-user-staticsudo 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.tbz2cd 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}

内核和设备树更新

方法比较多:

  • 插上USB, 用flash.sh, -K更新内核, -d更新设备树文件
  • extlinux.conf, NFS挂载?
  • extlinux.conf, 直接替换, 这里用这种方式

DTB文件所在的位置参考:

  • Jetson/Device Tree
  • Jetson/TX2 DTB elinux.org

需要先进行设置

虽然默认情况下L4T不再在/boot/extlinux/extlinux.conf中设置FDT条目, 用户仍然可以手动设置此选项,以使更改生效

# TX2
$ sudo vi /boot/extlinux/extlinux.conf
# 添加
FDT /boot/dtb/kernel_tegra186-quill-p3310-1000-c03-00-base.dtb

使用如下

# 更新内核和设备树
# 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# 注意dtb的名字前面多了 kernel_

检查更新情况

# 时间应该比Ubuntu系统时间快12小时# 内核
$ uname -a
Linux tx2-pc 4.9.253 #1 SMP PREEMPT Wed Jan 19 22:13:36 PST 2022 aarch64 aarch64 aarch64 GNU/Linux# 设备树
$ 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

发行版部分组件

之前的文章里写过, 解决新电脑装旧发行版驱动问题时(如2021/20222年出的电脑装Ubuntu 16/18, 图形显示/WiFi6/蓝牙等肯定会不正常), 可以通过更新内核的方式进行支持, 如更新到5.11内核, 需要下载的有:

# 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

其中:

  • image 就是内核镜像, 毕竟最后运行的是编译好的内核镜像, 而不是源码
  • modules是一些可以动态加载到内核的 .ko 组件, 这些往往是通过源码编译出来的
  • firmware是包含某些硬件设备的部分或全部功能所需的固件二进制 blob, 通常是专有的, 因为某些硬件制造商不会发布源码(如NVIDIA显卡, Intel的Wi-Fi芯片组, 想方设法避开中GPL的毒, 地铁老人看手机.jpg)
  • headers: 一个提供Linux内核头文件的软件包, 充当内部内核组件之间 以及 用户空间和内核之间 的接口

如果你正在构建一个完整的内核,那么,显然,你需要完整的源文件,而不仅仅是头文件。

但是,如果您正在编译链接到内核的设备驱动程序或其他可加载模块,那么您只需要头文件,因此可以通过不安装完整源代码来节省空间。

我们编写内核模块时, 经常会看见

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

那这些文件在哪里, PC的其实就在/lib/modules/$(uname -r)/build 文件夹里面, 如 linux/module.h 应该就对应X86主机的 /lib/modules/5.13.0-27-generic/build/include/linux/module.h, 那 TX2 的源码包里肯定也有 Linux_for_Tegra/source/public/kernel/kernel-4.9/include/linux/module.h

甚至可以直接在文件夹里面打开 make menuconfig, 如电脑X86平台的

# 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

下面先来写一个 x86 平台的 hello module:

mkdir hello
cd hello
vi hello.c

hello.c的源码和注释

//linux headers
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>//加载时执行
static int hello_init(void)
{//打印消息到内核日志缓冲区, 通常用dmesg查看//KERN_ALERT为日志级别. 也可以用 pr_alert()printk(KERN_ALERT "Hello Module Test\n");pr_alert("Hello Module Test2\n");return 0;
}//卸载时执行
static void hello_exit(void)
{printk(KERN_INFO "Goodbye Hello\n");
}//传递给API
//module_init, 驱动初始化入口点
//module_exit, 驱动退出的入口点
module_init(hello_init);
module_exit(hello_exit);//作者声明, 用 "Name <email>" 或 "Name", 多个作者可以多个 MODULE_AUTHOR() 行
MODULE_AUTHOR("yiming");
//LICENSE声明, 有法律效应, GPL有传染性
MODULE_LICENSE("GPL");
//描述, 通过 modinfo 查看
MODULE_DESCRIPTION("First Driver");

然后是vi Makefile

obj-m:=hello.oall:make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modulesclean:make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean

其中:

  • -C, 为change directory, 即切换目录到 /lib/modules/$(shell uname -r)/build, 这里是 当前Linux版本 的 内核构建目录, 这里有内核的顶级Makefile
  • M=, 顶级Makefile的一个变量参考下面源码, 让Makefile在尝试生成模块目标之前移回指定目录, pwd, 就指明了hello.ko生成在当前目录
# 来自 /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

现在开始走一把

# hello目录
$ 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# 查看文件类型, elf 64bit LSB 浮动程序, x86-64 平台
$ file hello.ko
hello.ko: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), BuildID[sha1]=ea5c2968e3fe351b700b5e6f8978904e58254b8f, with debug_info, not stripped# 加载hello.ko
$ sudo insmod hello.ko # 查看最后两行
$ dmesg | tail -2
[23749.761288] Hello Module Test
[23749.761293] Hello Module Test2# 卸载hello.ko, 可以不加后缀.ko
$ sudo rmmod hello
$ dmesg | tail -1
[23902.056184] Goodbye Hello# 如果让dmesg直接输出到console
# sudo dmesg -n 8  或 sudo dmesg -n debug
# 恢复默认
# sudo dmesg -n 4  或
# 让dmesg一直显示不退出
$ dmesg -wH &

最后的命令还可以查看级别, 红色的alert:

Jetson First KO

参考文档中的Kernel Cusomization -> Preparing to Building External Kernel Modules 和 Building External Kernel Modules两小节, 编译一个外部的Jetson内核模块的步骤:

  • 预处理: 准备module源文件里面header, 顶级Makefile, kernel_source_tree等, 只准备一次就可以
  • 设置变量CROSS_COMPILE来指定交叉编译器
  • 设置 -C <top_makefile_dir> 来指定顶级Makefile所在目录, 一般在内核目录, 但这里我直接丢到了top文件夹里面
  • 设置 M= 指定module的位置

新建一个jetson_hello文件夹(/home/z/jetson/test/jetson_hello), 还是上面的hello.c不变拷贝进去, 接着撸Makefile

obj-m:=hello.okernel_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)/buildall:@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 *.korm -rf build *.ko top

其中:

  • obj-m, 这里的m指module, 一般是配合Kconfig文件在make menuconfig里面选编译进内核(y), 还是编译成KO(m), 或者不编译(n), 这里直接指定-m
  • make的时候先判断top文件夹是否存在, 不存在就做上面的预处理那一步
  • 每次编译都要设置变量CROSS_COMPILE来指定交叉编译器
  • -j $(nproc), 全部CPU进场, 不过这里只有一个.c文件, 用不上

测试一把

$ make
make[1]: Entering directory '/home/z/jetson/test/jetson_hello/top'WARNING: Symbol version dump ./Module.symversis missing; modules will have no dependencies and modversions.LD      /home/z/jetson/test/jetson_hello/built-in.oCC [M]  /home/z/jetson/test/jetson_hello/hello.oBuilding modules, stage 2.MODPOST 1 modulesCC      /home/z/jetson/test/jetson_hello/hello.mod.oLD [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

如图所示

Longterm Kernel

The Linux Kernel Archives - Releases, Jetson目前的4.9版本在16年底就release了, 支持到23年初.

4.9内核的在线文档参考: Linux Kernel Documentation — The Linux Kernel documentation, 有点老了… 看着没有新的5.1x的组织的舒服…

命令备忘

# 显示已加载模块
lsmod
# 查看内核模块信息
modinfo
# 载入内核模块
indmod
# 卸载内核模块
rmmod
# 查看模块依赖
depmod
# 载入或移除模块
# 比较智能一点, 可以递归解析模块依赖
modprobe# 确定文件类型, 32/64bit
file

参考

  • Configuring Git to handle line endings - GitHub Docs
  • Git diff ^M的消除_Dean Chen的专栏-CSDN博客_^m git
  • 成功解决 忽略git diff ^m_littlehaes的博客-CSDN博客_git忽略差异
  • [如何利用git制作和提交patch_ganggexiongqi的专栏-CSDN博客_git 提交patch
  • gitignore忽略子目录下所有某后缀的文件 - 简书 (jianshu.com)
  • BSP/DT clarification: “quill” vs P3310 vs Jetson TX2 SOM - Jetson & Embedded Systems / Jetson TX2 - NVIDIA Developer Forums
  • Tegra - Wikipedia
  • Makefile中嵌入一段shell脚本及函数列表 | (breezetemple.github.io)
  • The Linux Kernel Module Programming Guide (tldp.org)
  • Linux-headers - Gentoo Wiki
  • Linux firmware - Gentoo Wiki
  • linux下查看可执行文件的相关信息_wojiushiwoba的博客-CSDN博客_查看可执行文件架构
  • 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

欢迎扫描二维码关注微信公众号, 及时获取最新文章:

Jetson基本笔录2 -- 源码编译与KO生成相关推荐

  1. mysql编译innodb_源码编译MySQL5.1生成InnoDB存储引擎_MySQL

    bitsCN.com 源码编译MySQL 5.1生成InnoDB存储引擎 这里就仅列出主要步骤: [plain] ./configure --prefix=/home/mysql51/mysql/ - ...

  2. android 编译完后镜像在哪个文件夹,Android源码编译后

    在out/target/product/generic下生成的三个镜像文件:ramdisk.img,system.img,userdata.img以及它们对应的目录树root,system,data. ...

  3. Jetson Agx Xavier USB驱动裁剪+can时钟修改+内核源码编译流程(jetpack4.6.1)

    自己做了一块Xavier载板,硬件裁剪了一些功能,导致官方镜像usb无法使用,我使用的是jetpack4.6.1(R32.7.1),所以进行驱动修改,重新编译内核. 一.虚拟机环境 在Windows下 ...

  4. Jetson Nano 源码编译安装PySide6

    背景 最近要将一个使用PySide6写GUI的程序部署到英伟达Jetson Nano上.原本以为装个conda就能很快装好环境,结果发现arm的生态有点太糟糕了,啥都要自己编译安装,尤其是这个Pysi ...

  5. Jetson Xavier NX 内核编译、源码编译流程

    [NVIDIA] 从零入手 Jetson Xavier NX 内核编译.源码编译流程 – ***注明:感谢网友提醒,我当时买的时候nx套件还没开售,因为核心板兼容b01,先买了核心板和b01的板子合在 ...

  6. Jetson TX1刷机教程(解决Auvidea carrier boards(2x USB3.0)+ 源码编译安装opencv3.2存储空间不足问题)

    最近一周感觉都是在给Jetson TX1刷机,然而每次都得各种查资料,然后从师兄那得到启示(养成记录的好习惯),感觉是时候写下刷机的心路历程了. Jetson TX1刷机不难,直接跟着官方教程走就行D ...

  7. tx2+opencv源码编译教程(tx2+opencv4.4.0+opencv_contrib-4.4.0)

    tx2+opencv源码编译教程(tx2+opencv4.4.0+opencv_contrib-4.4.0) 一.卸载TX2上已安装的opencv 打开终端,输入以下指令卸载已经安装的opencv: ...

  8. java调用clang编译的so_写Java这么久,JDK源码编译过没?编译JDK源码踩坑纪实

    好奇害死羊 很多小伙伴们做Java开发,天天写Java代码,肯定离不开Java基础环境:JDK,毕竟我们写好的Java代码也是跑在JVM虚拟机上. 一般来说,我们学Java之前,第一步就是安装JDK环 ...

  9. 5单个编译总会编译全部_玩转Android10(五)源码编译开发中常用命令

    源码开发编译中,熟练掌握常用命令,可以提高开发工作效率.Android源码中,将相关的命令分为如下几类: 1.初始化源码编译环境 初始化编译环境,为后续提供如lunch.make.xxgrep.god ...

最新文章

  1. Hibernate学习笔记(一)----针对不同的数据库不同的配置
  2. 最萌算法学习来啦,看不懂才怪!
  3. netty io.netty.buffer简介
  4. 福师计算机应用基础离线作业一答案,18秋福师《计算机应用基础》在线作业一答案...
  5. JavaWeb(九)——JavaBean、Filter
  6. mysql webhook_sql 数据定时发送webhook golang 服务
  7. 【转】数学与编程——求余、取模运算及其性质
  8. 动态网页开发技术(三):jsp
  9. PHP危险函数被禁止怎么绕过,PHP危险函数(disable_functions)设置
  10. drbd+corosync+pacemaker实现mysql的高可用性“上”
  11. Spring源码窥探之:@Value
  12. html语言考点,HTML知识点
  13. IBM heapAnalyzer分析dump文件
  14. Cortex-M可以跑Linux操作系统吗?
  15. Android MTK CAMERA DRIVER 摄像头驱动
  16. 手机支付宝面临的风险和应对(III)---手机支付宝能照搬PC的思路吗?
  17. 通知 | 关于组织开展湖北省2022年度高新技术企业认定工作的通知
  18. 如何应对“创可贴”式员工
  19. 苹果V10附件参数配置
  20. FireFox火狐浏览器设置不加载图片

热门文章

  1. H5小游戏从修改到发布--无编程基础修改版
  2. 分享两款智慧物业系统源码,前后端分离,前端VUE,Uni-app框架
  3. 什么是CRM系统?CRM的价值体现在哪里?
  4. 用友华表Cell一些用法小结(cs.net版本)
  5. WooCommerce Memberships 中文汉化版会员系统插件版下载
  6. 自注册DM(六)中国电信自注册 CT Register 介绍和常见问题
  7. JAVA:实现二进制转十六进制算法(附完整源码)
  8. java编程思想-关于final
  9. [渝粤教育] 沈阳工业大学 模拟电子技术 参考 资料
  10. windows便签快捷键_如何将Win7自带便签添加到桌面快捷方式?