0%

jetson-linux编译内核

本次博客记录基于x86_64平台交叉编译jetson nano的linux内核

顶层目录

首先进入到顶层目录

1
cd /home/jym/code/linux/ec20_driver_pro

顶层目录分布如下:

kernel_out为编译输出目标文件夹

gcc-linaro-x86_64_aarch64-linux-gnu为交叉编译器,下载地址Linaro Releases

其他为kernel_src.tar解压得到;内核相关文件在${PWD}/kernel/kernel-4.9

image-20240819121818432

设置环境变量

1
2
3
4
export CROSS_COMPILE_AARCH64=~/home/jym/code/linux/ec20_driver_pro/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- #尽量使用绝对路径或在内核顶层目录使用相对路径

之前方法是以下:
export CROSS_COMPILE=~/home/jym/code/linux/ec20_driver_pro/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu- #尽量使用绝对路径或在内核顶层目录使用相对路径

设置好环境变量之后,下面有两种方法编译内核:一是英伟达官方的自动编译脚本nvbuild.sh,在顶层目录执行以下命令即可:

1
./nvbuild.sh -o $PWD/kernel_out

下面对另一种方法进行介绍

手动编译

编译的项目有:config配置文件,Imagedtbsmodules

下面操作均在顶层目录下进行

生成config配置文件

1
2
3
make -C ${PWD}/kernel/kernel-4.9/ ARCH=arm64 LOCALVERSION="-tegra" CROSS_COMPILE="${CROSS_COMPILE_AARCH64}"  O=${PWD}/kernel_out  tegra_defconfig

#make ARCH=arm64 LOCALVERSION="-tegra" CROSS_COMPILE="${CROSS_COMPILE_AARCH64}" tegra_defconfig

生成menuconfig配置

1
make -C ${PWD}/kernel/kernel-4.9/ ARCH=arm64 LOCALVERSION="-tegra" CROSS_COMPILE="${CROSS_COMPILE_AARCH64}"  O=${PWD}/kernel_out  menuconfig

生成Image

1
make -C ${PWD}/kernel/kernel-4.9/ ARCH=arm64 LOCALVERSION="-tegra" CROSS_COMPILE="${CROSS_COMPILE_AARCH64}"  O=${PWD}/kernel_out  Image -j12

生成dtb

主要的设备树文件:tegra194-p2888-0001-p2822-0000.dtb
关注的目录为:
kernel_src/hardware/nvidia/platform/t19x/galen/kernel-dts
关注的文件:
tegra234-p3767-0003-p3768-0000-a0.dts

1
make -C ${PWD}/kernel/kernel-4.9/ ARCH=arm64 LOCALVERSION="-tegra" CROSS_COMPILE="${CROSS_COMPILE_AARCH64}"  O=${PWD}/kernel_out  dtbs -j12

/home/ada/jetson/nvdia_35_4/kernel_src/hardware/nvidia/platform/t23x/p3768/kernel-dts/tegra234-p3767-0003-p3768-0000-a0.dts
生成的文件在这:
./kernel_out/arch/arm64/boot/dts/nvidia/tegra234-p3767-0003-p3768-0000-a0.dtb

编译模块

编译

1
make -C ${PWD}/kernel/kernel-4.9/ ARCH=arm64 LOCALVERSION="-tegra" CROSS_COMPILE="${CROSS_COMPILE_AARCH64}"  O=${PWD}/kernel_out  modules -j12

安装模块 按照linux内核文件架构安装在kernel_out中

1
make -C ${PWD}/kernel/kernel-4.9/ ARCH=arm64 LOCALVERSION="-tegra" CROSS_COMPILE="${CROSS_COMPILE_AARCH64}"  O=${PWD}/kernel_out INSTALL_MOD_STRIP=1 modules_install INSTALL_MOD_PATH=modules

清除构建

1
make -C ${PWD}/kernel/kernel-5.10/ ARCH=arm64 LOCALVERSION="-tegra" CROSS_COMPILE="${CROSS_COMPILE_AARCH64}"  O=${PWD}/kernel_out clean

移植移远4G模块

修改内核文件

option.c

修改 [KERNEL_SRC] /kernel/kernel-5.10/drivers/usb/serial/option.c 文件

1.添加USB设备VID和PID

1
2
3
4
5
6
7
8
9
static const struct usb_device_id option_ids[] = {
/****************** modify *************************/
{ USB_DEVICE(0x2C7C, 0x6005) },/* Quectel EC200A: add VID and PID */
/****************** modify *************************/
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_LIGHT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA_QUAD_LIGHT) },

image-20240820131402657

2.添加掉电恢复机制

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
static struct usb_serial_driver option_1port_device = {
.driver = {
.owner = THIS_MODULE,
.name = "option1",
},
.description = "GSM modem (1-port)",
.id_table = option_ids,
.num_ports = 1,
.probe = option_probe,
.open = usb_wwan_open,
.close = usb_wwan_close,
.dtr_rts = usb_wwan_dtr_rts,
.write = usb_wwan_write,
.write_room = usb_wwan_write_room,
.chars_in_buffer = usb_wwan_chars_in_buffer,
.tiocmget = usb_wwan_tiocmget,
.tiocmset = usb_wwan_tiocmset,
.ioctl = usb_wwan_ioctl,
.attach = option_attach,
.release = option_release,
.port_probe = usb_wwan_port_probe,
.port_remove = usb_wwan_port_remove,
.read_int_callback = option_instat_callback,
#ifdef CONFIG_PM
.suspend = usb_wwan_suspend,
.resume = usb_wwan_resume,
/****************** modify *************************/
.reset_resume = usb_wwan_resume, /*Quectel EC200A: add reset resume*/
/****************** modify *************************/
#endif
};

image-20240820131549697

usb_wwan.c

修改 [KERNEL_SRC] /kernel/kernel-5.10/drivers/usb/serial/usb_wwan.c 文件

添加零包机制

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
static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
int endpoint,
int dir, void *ctx, char *buf, int len,
void (*callback) (struct urb *))
{
struct usb_serial *serial = port->serial;
struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
struct urb *urb;

urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
if (!urb)
return NULL;

usb_fill_bulk_urb(urb, serial->dev,
usb_sndbulkpipe(serial->dev, endpoint) | dir,
buf, len, callback, ctx);

if (intfdata->use_zlp && dir == USB_DIR_OUT)
urb->transfer_flags |= URB_ZERO_PACKET;


/****************** modify *************************/

/*Quectel 2C7C modules: add the zero packet mechanism*/
if(dir == USB_DIR_OUT){
struct usb_device_descriptor *desc = &serial->dev->descriptor;
if(desc->idVendor == cpu_to_le16(0x2c7c))
urb->transfer_flags |= URB_ZERO_PACKET;
}
/****************** modify *************************/

return urb;
}

image-20240819123646238

配置并编译内核

在下载完内核源码之后,我们可以首先手动编译一次,这样我们后续修改文件再次编译内核的时候速度会更快。

执行命令按照手动编译步骤进行即可。

  • 生成config配置文件
  • 生成menuconfig配置
  • 生成Image
  • 编译模块

在我们配置menuconfig时按照默认配置是可以编译出ko文件的,有时候我们需要编译出特定几个模块,需要在menuconfig中手动进行配置。

image-20240820132308979

在menuconfig下按下/键为查找(同vim) 比如我们需要如下图所示USB driver for GSM and CDMA modems,我们可以利用vscode查找功能在linux内核源码中查找对应模块。

image-20240820132459718

如下图为查找到内容,此时我们直接在menuconfig中键入USB_SERIAL_OPTION进行查询即可对其进行操作

image-20240820132704868

同样,笔者在第一次编译时并未编译出来qcserial.ko文件,我们直接在vscode中暴力搜索qcserial,

image-20240820132946467

从图中可以看到其对应配置为CONFIG_USB_SERIAL_QUALCOMM,选择它按下M即可将其编译成模块,便于后续移植。

image-20240820133113728

image-20240820133123001

配置好之后再次从menuconfig后面执行一遍手动编译操作即可

移植加载内核

将对应.ko文件复制到内核对应文件夹下使用uname -r查看对应内核版本

1
2
3
$sudo cp option.ko /lib/modules/4.9.253-tegra/kernel/drivers/usb/serial
$sudo cp usb_wwan.ko /lib/modules/4.9.253-tegra/kernel/drivers/usb/serial
$sudo cp qcserial.ko /lib/modules/4.9.253-tegra/kernel/drivers/usb/serial

加载模块

1
2
$sudo depmod -a
$sudo reboot

驱动测试

1
2
3
4
5
$sudo modprobe usbmon    # 加载usbmon驱动模块
$sudo dmesg #接入USB设备时输出对应信息
$lsmod #查看已加载的内核模块
$lsusb #出现移远4G模块
$nmcli device status #会出现ttyUSB1和ppp0两个

设置静态IP

1.使用图形化界面设置
image-20240725165404282

在设置完静态IP之后,图形化界面记得设置为manual即可。
输入nmcli connection show MV424_2G4替换自己的网络即可。
静态网络不会有valid_lft和preferred_lft

image-20240725172139726

image-20240725180247241

2.使用nmcli设置

使用nmcli查看wifi进行连接

1
2
3
4
5
6
7
nmcli device wifi list
sudo nmcli device wifi connect <SSID> password <PASSWORD> #nmcli在终端连接wifi
nmcli device wifi disconnect #断开wifi
nmcli connection show #查看网络连接
nmcli device wifi rescan #重新扫描
sudo systemctl restart NetworkManager #重启服务
sudo nmcli connection delete <connection-name-or-uuid> #删除某个连接
  1. 打开NetworkManager配置模式

    1
    sudo nmcli networking off
  2. 设置静态IP地址

    使用 nmcli 设置 wlan0 的静态IP地址。替换 <IP地址><子网掩码><网关><DNS服务器> 为你的网络配置。这里避免产生多余的连接号

1
2
3
4
sudo nmcli con mod MV424_5G8 ipv4.addresses 10.0.0.109/24
sudo nmcli con mod MV424_5G8 ipv4.gateway 10.0.0.1
sudo nmcli con mod MV424_5G8 ipv4.dns 8.8.8.8
sudo nmcli con mod MV424_5G8 ipv4.method manual
  1. 设置完成后left_time为forever

    image-20240725182814475

  2. 重新启用网络管理

    1
    sudo nmcli networking on
  3. 验证IP配置: 使用 ip addr 命令来验证 wlan0 接口的IP地址配置:

    1
    ip addr show wlan0

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

添加字数统计于阅读统计

1.安装hexo-wordcount插件

1
npm i --save hexo-wordcount

成功会在根目录下的package.json中多出"hexo-wordcount": "^6.0.1"

2.安装hexo-symbols-count-time

1
npm install hexo-symbols-count-time --save

3.安装eslint

1
npm install eslint --save

4.在站点配置文件添加如下配置

1
2
3
4
5
6
symbols_count_time:
symbols: true # 文章字数统计
time: true # 文章阅读时长
total_symbols: true # 站点总字数统计
total_time: true # 站点总阅读时长
exclude_codeblock: false # 排除代码字数统计

5.在主题配置文件中添加如下配置

1
2
3
4
5
6
7
symbols_count_time:
separated_meta: true # 是否另起一行(true的话不和发表时间等同一行)
item_text_post: true # 首页文章统计数量前是否显示文字描述(本文字数、阅读时长)
item_text_total: false # 页面底部统计数量前是否显示文字描述(站点总字数、站点阅读时长)
awl: 4 # Average Word Length
wpm: 275 # Words Per Minute(每分钟阅读词数)
suffix: mins.

6.Next主题添加字数统计和阅读统计
在主题配置文件做如下更改

1
2
3
4
5
6
post_wordcount: 		# 字数统计
item_text: true # 是否显示文字
wordcount: true # 显示字数
min2read: true # 显示阅读时间
totalcount: true # 显示总数
separated_meta: true # 是否分开