如何修改 Jetson Orin Nano 中 的 port bind

在Jetson Orin Nano中,我首先执行了这个命令:sudo dmesg |grep -i kernel ,得到的日志信息如下:

[sudo] password for nvidia-user: 
[    0.000000] CPU features: kernel page table isolation forced ON by KASLR
[    0.000000] CPU features: detected: Kernel page table isolation (KPTI)
[    0.000000] alternatives: patching kernel code
[    0.000000] Kernel command line: root=PARTUUID=3885645a-97fd-4160-96e0-0286f0210613 rw rootwait rootfstype=ext4 mminit_loglevel=4 console=ttyTCU0,115200 console=ttyAMA0,115200 firmware_class.path=/etc/firmware fbcon=map:0 net.ifnames=0 nospectre_bhb 
[    0.000000] Memory: 7375292K/8136832K available (18304K kernel code, 3208K rwdata, 7092K rodata, 3904K init, 1447K bss, 499396K reserved, 262144K cma-reserved)
[    0.002956] DTS File Name: /dvs/git/dirty/git-master_linux/kernel/kernel-5.10/arch/arm64/boot/dts/../../../../../../hardware/nvidia/platform/t23x/p3768/kernel-dts/tegra234-p3767-0003-p3768-0000-a0.dts
[    0.216108] DMA: preallocated 1024 KiB GFP_KERNEL pool for atomic allocations
[    0.216174] DMA: preallocated 1024 KiB GFP_KERNEL|GFP_DMA pool for atomic allocations
[    0.216230] DMA: preallocated 1024 KiB GFP_KERNEL|GFP_DMA32 pool for atomic allocations
[    0.257211] eventlib_kernel: keventlib is initialized, test id: 0
[    1.931309] Loaded X.509 cert 'Build time autogenerated kernel key: 9d0e915459018d8c252c1d5b7ab6c24caeb6a5f8'
[    3.904461] Freeing unused kernel memory: 3904K
[    6.106036] systemd[1]: Listening on udev Kernel Socket.
[    6.331679] systemd[1]: Mounting Kernel Debug File System...
[    6.419576] systemd[1]: Mounting Kernel Trace File System...
[    6.657791] systemd[1]: Starting Create list of static device nodes for the current kernel...
[    6.755983] systemd[1]: Starting Load Kernel Module chromeos_pstore...
[    6.822007] systemd[1]: Condition check resulted in Load Kernel Module drm being skipped.
[    6.823766] systemd[1]: Starting Load Kernel Module efi_pstore...
[    6.887625] systemd[1]: Starting Load Kernel Module pstore_blk...
[    6.960073] systemd[1]: Starting Load Kernel Module pstore_zone...
[    7.028043] systemd[1]: Starting Load Kernel Module ramoops...
[    7.334659] systemd[1]: Starting Load Kernel Modules...
[    7.396244] systemd[1]: Starting Remount Root and Kernel File Systems...
[    7.698534] nvgpu: module verification failed: signature and/or required key missing - tainting kernel
[   10.583713] nvidia: loading out-of-tree module taints kernel.
[   10.723165] NVRM: loading NVIDIA UNIX Open Kernel Module for aarch64  35.4.1  Release Build  (user@ubuntu)  Wed 15 Nov 2023 05:48:51 PM PST
[   22.730249] nvidia-modeset: Loading NVIDIA UNIX Open Kernel Mode Setting Driver for aarch64  35.4.1  Release Build  (user@ubuntu)  Wed 15 Nov 2023 05:48:52 PM PST

可以看出,我的内核执行的摄像头设备树文件是:
DTS File Name:tegra234-p3767-0003-p3768-0000-a0.dts
该文件在Linux_for_Tegra中的路径是:
Linux_for_Tegra/source/public/hardware/nvidia/platform/t23x/p3768/kernel-dts

通过查看该dtsi文件中的头文件包含,我们可以看到:
tegra234-p3767-0003-p3768-0000-a0.dts 文件中包含了 tegra234-p3767-0000-p3768-0000-a0.dts
tegra234-p3767-0000-p3768-0000-a0.dts 文件中包含了 cvb/tegra234-p3768-0000-a0.dtsi
tegra234-p3768-0000-a0.dtsi 文件中包含了imx219和imx477的设备树dtsi文件:
tegra234-p3768-camera-rbpcv2-imx219.dtsi
tegra234-p3768-camera-rbpcv3-imx477.dtsi

因此我认为,当我注释掉#include “tegra234-p3768-camera-rbpcv2-imx219.dtsi”,并重新编译烧录后
在Jetson Orin Nano 模块上应该不再支持imx219摄像头驱动,即使有驱动文件编译出的imx219.ko文件。
因为已经没有imx219的设备树节点了

但是当我连接上imx219摄像头后,执行nvgstcapture-1.0命令,摄像头依然在正常工作,当我执行命令后:
sudo dmesg |grep -i imx219
显示的内核日志打印信息如下:

nvidia-user@tegra-ubuntu:~$ sudo dmesg |grep -i imx219
[sudo] password for nvidia-user: 
[   11.964824] imx219 9-0010: probing v4l2 sensor at addr 0x10
[   11.965124] imx219 9-0010: tegracam sensor driver:imx219_v2.0.6
[   11.975961] imx219 9-0010: imx219_board_setup: error during i2c read probe (-121)
[   11.981121] imx219 9-0010: board setup failed
[   11.990916] imx219: probe of 9-0010 failed with error -121
[   11.992787] imx219 10-0010: probing v4l2 sensor at addr 0x10
[   11.993034] imx219 10-0010: tegracam sensor driver:imx219_v2.0.6
[   12.009325] tegra-camrtc-capture-vi tegra-capture-vi: subdev imx219 10-0010 bound
[   12.069151] imx219 10-0010: detected imx219 sensor

这似乎表示内核仍然在执行imx219的驱动程序,于是我执行了这个命令查看设备绑定情况:
sudo media-ctl -p -d /dev/media0
显示的日志如下:

nvidia-user@tegra-ubuntu:~$ sudo media-ctl -p -d /dev/media0
Media controller API version 5.10.120

Media device information
------------------------
driver          tegra-camrtc-ca
model           NVIDIA Tegra Video Input Device
serial          
bus info        
hw revision     0x3
driver version  5.10.120

Device topology
- entity 1: 13e40000.host1x:nvcsi@15a00000- (2 pads, 0 link)
            type V4L2 subdev subtype Unknown flags 0
            device node name /dev/v4l-subdev0
	pad0: Sink
	pad1: Source

- entity 4: 13e40000.host1x:nvcsi@15a00000- (2 pads, 2 links)
            type V4L2 subdev subtype Unknown flags 0
            device node name /dev/v4l-subdev1
	pad0: Sink
		<- "imx219 10-0010":0 [ENABLED]
	pad1: Source
		-> "vi-output, imx219 10-0010":0 [ENABLED]

- entity 7: imx219 10-0010 (1 pad, 1 link)
            type V4L2 subdev subtype Sensor flags 0
            device node name /dev/v4l-subdev2
	pad0: Source
		[fmt:SRGGB10_1X10/3280x2464 field:none colorspace:srgb]
		-> "13e40000.host1x:nvcsi@15a00000-":0 [ENABLED]

- entity 9: vi-output, imx219 10-0010 (1 pad, 1 link)
            type Node subtype V4L flags 0
            device node name /dev/video0
	pad0: Sink
		<- "13e40000.host1x:nvcsi@15a00000-":1 [ENABLED]

这似乎表示当前的Jetson Orin Nano设备仍然绑定的是imx219

那么问题来了:如果我想更改Jetson Orin Nano设备的port bind应该怎么做?
比如说,我想让设备绑定imx477摄像头,从而让内核能够执行imx477的相关程序,打印相关日志信息

This message tell you didn’t replace the dtb file correctly.
If replaced successful the path should be the source in your host instead of “/dvs/git/dirty/git-master_linux/”

当我解压内核文件后,我执行的操作是这样的:
cd ~/Desktop/Folder/Linux_for_Tegra/source/public/kernel/kernel-5.10/scripts
sudo ./rt-patch.sh apply-patches
cd ~/Desktop/Folder/Linux_for_Tegra/source/public/
mkdir kernel_out

然后在Linux_for_Tegra/source/public/hardware/nvidia/platform/t23x/p3768/kernel-dts/cvb
路径下的tegra234-p3768-0000-a0.dtsi文件中,删除了#include “tegra234-p3768-camera-rbpcv2-imx219.dtsi”

然后./nvbuild.sh -o ~/Desktop/Folder/Linux_for_Tegra/source/public/kernel_out编译内核文件

编译成功后,
cd ~/Desktop/Folder/Linux_for_Tegra/source/public/kernel_out/arch/arm64/boot/
cp Image ~/Desktop/Folder/Linux_for_Tegra/kernel/Image
cp dts/nvidia/ ~/Desktop/Folder/Linux_for_Tegra/kernel/dtb/ -rf

cd ~/Desktop/Folder/Linux_for_Tegra/source/public/kernel/kernel-5.10/

sudo make ARCH=arm64 O=~/Desktop/Folder/Linux_for_Tegra/source/public/kernel_out modules_install INSTALL_MOD_PATH=~/Desktop/Folder/Linux_for_Tegra/rootfs

cd …/…/kernel_out/drivers/gpu/nvgpu
sudo cp nvgpu.ko ~/Desktop/Folder/Linux_for_Tegra/rootfs/usr/lib/modules/5.10.120-rt70-tegra/kernel/drivers/gpu/nvgpu/nvgpu.ko

cd ~/Desktop/Folder/Linux_for_Tegra/rootfs
tar --owner root --group root -cjf kernel_supplements.tbz2 lib/modules
cp kernel_supplements.tbz2 …/kernel/kernel_supplements.tbz2
cd …/
sudo ./apply_binaries.sh

然后构建显示器驱动,之后进行烧录。
每一个步骤日志都显示是成功的,但是我不清楚你所说的没有正确替换dtb文件是什么情况
按理来说成功的情况下应该显示什么?我该如何做

  1. find -name tegra234-p3767-0003-p3768-0000-a0.dtb at ~/Desktop/Folder/Linux_for_Tegra
  2. check those dtb are builded by you. You can use text edit to check the dtb file should have the file path like below.

你好,在你之前的建议下,我重新看了一遍操作步骤,我发现了问题所在:
之前在复制dtb文件到kernel下的dtb时,由于使用的命令,导致复制后具有两个相同名字的dtb文件
于是我事先把kernel下的t23和t19开头的文件都删除,然后进行手动复制,最后烧录后可以看到使用的是我自己的dtb。

但是现在我有一个小问题,就是我如果想在imx系列的摄像头驱动文件的imxXXX_probe()函数下增加新的
dev_info()
我需要重新编译重新烧录到jetson orin nano中才能生效。

有没有一种更快捷的办法,可以直接在jetson orin nano中操作??
我现在有一个想法,但不知道是否正确:
先在ubuntu主机上修改imxXXX.c中的imxXXX_probe()函数打印信息,然后把编译出的imxXXX.ko文件替换jetson Orin Nano中的imxXXX.ko文件,然后重启设备。
我不知道这样做是否可行

Yes, you can configure the sensor driver as loadable module(*.ko) and replace it. Or just replace the /boot/Image in Orin Nano and reboot to apply new kernel Image instead of flash whole system.

我烧录使用的是这个命令:
sudo ./tools/kernel_flash/l4t_initrd_flash.sh --external-device nvme0n1p1 -c tools/kernel_flash/flash_l4t_external.xml -p “-c bootloader/t186ref/cfg/flash_t234_qspi.xml” --showlogs --network usb0 jetson-orin-nano-devkit internal

我该如何做才能只烧录Image

Just copy the Image to Orin Nano and replace the /boot/Image

你好,我成功的将我的imx586的设备驱动和设备树替换到了jetson orin nano中,当我开机后,使用:
sudo dmesg | grep -i imx586
来查找我的imx586的内核日志信息,发现有如下的错误:

nvidia-user@tegra-ubuntu:~/Desktop$ sudo dmesg |grep -i imx
[sudo] password for nvidia-user: 
[   11.708089] imx586 2-001a: imx586_probe : probing v4l2 sensor, i2c-2, 3 mode
[   11.708447] imx586 2-001a: tegracam sensor driver:imx586_v2.0.6
[   11.708451] imx586 2-001a: imx586_probe : tegracam_device_register end!!!--------
[   11.708454] imx586 2-001a: imx586_board_setup start !!!------------
[   11.711474] imx586 2-001a: imx586_board_setup camera_common_mclk_enable end !!!------------
[   11.711496] imx586_power_on: power_on
[   11.711498] imx586 2-001a: imx586_power_on: set reset gpio = 397.
[   11.711683] imx586 2-001a: imx586_board_setup imx586_power_on end !!!------------
[   11.711688] imx586 2-001a: imx586_probe : imx586_board_setup end!!!--------
[   11.711692] imx586 2-001a: imx586_probe : ctrlprops->gain_factor = 10, ctrlprops->framerate_factor = 1000000,ctrlprops->inherent_gain = 1!--------
[   11.711697] imx586 2-001a: imx586_probe : ctrlprops->min_gain_val = 10, ctrlprops->max_gain_val = 240,ctrlprops->min_hdr_ratio = 1, ctrlprops->max_hdr_ratio = 1 !--------
[   11.711703] imx586 2-001a: imx586_probe : ctrlprops->min_framerate = 1000000, ctrlprops->max_framerate = 30003939,ctrlprops->step_gain_val = 1, ctrlprops->step_framerate = 1 !--------
[   11.711708] imx586 2-001a: imx586_probe : ctrlprops->exposure_factor = 1000000, ctrlprops->default_gain = 10,ctrlprops->default_framerate = 30003939, ctrlprops->is_interlaced = 0, ctrlprops->interlace_type = 0 !--------
[   11.711714] imx586 2-001a: imx586_probe : ctrlprops->min_exp_time = 32 !--------
[   11.711718] imx586 2-001a: imx586_probe : ctrlprops->max_exp_time = 33333 !--------
[   11.711722] imx586 2-001a: imx586_probe : ctrlprops->step_exp_time = 2 !--------
[   11.711726] imx586 2-001a: imx586_probe : ctrlprops->default_exp_time = 33333 !--------
[   11.711730] imx586 2-001a: imx586_probe: frame_length:0, numctrls:0, mode_prop_idx:0, mode:0, csi_port:0, numlanes:4, numfmts: 7, def_mode: 0, def_width: 4000, def_height:3000, def_clk_freq:24000000, fmt_width: 4000, fmt_height:3000
[   11.711739] imx586 2-001a: imx586_probe: framerates:30, num_framerates:1, mode:0, hdr_en:1
[   11.712292] imx586 2-001a: imx586_write_reg: i2c write reg failed, addr: 0x0204, val: 00, err: -121
[   11.712300] imx586 2-001a: Error -121 in control hdl setup
[   11.712308] imx586 2-001a: Failed to init ctrls imx586
[   11.712311] imx586 2-001a: tegra camera subdev registration failed
[   11.722088] imx586: probe of 2-001a failed with error -121

这是我的imx586_probe()函数,这个函数最后在日志中返回了-121的错误码

static int imx586_probe(struct i2c_client *client,
		const struct i2c_device_id *id)
{
	struct device *dev = &client->dev;
	struct tegracam_device *tc_dev;
	struct imx586 *priv;
	
	struct camera_common_data *cam_data;
	struct sensor_control_properties *ctrlprops = NULL;	
	
	int err;
	__u64 temp = 0;

	dev_info(dev, "%s : probing v4l2 sensor, i2c-2, 3 mode\n", __func__);

	if (!IS_ENABLED(CONFIG_OF) || !client->dev.of_node)	return -EINVAL;

	priv = devm_kzalloc(dev,sizeof(struct imx586), GFP_KERNEL);
	if (!priv)	return -ENOMEM;

	tc_dev = devm_kzalloc(dev,sizeof(struct tegracam_device), GFP_KERNEL);
	if (!tc_dev)	return -ENOMEM;

	priv->i2c_client = tc_dev->client = client;
	tc_dev->dev = dev;
	strncpy(tc_dev->name, "imx586", sizeof(tc_dev->name));
	tc_dev->dev_regmap_config = &sensor_regmap_config;
	tc_dev->sensor_ops = &imx586_common_ops;
	tc_dev->v4l2sd_internal_ops = &imx586_subdev_internal_ops;
	tc_dev->tcctrl_ops = &imx586_ctrl_ops;

	err = tegracam_device_register(tc_dev);
	if (err) {
		dev_err(dev, "tegra camera driver registration failed\n");
		return err;
	}
	else
	{
		dev_info(dev, "%s : tegracam_device_register end!!!--------\n", __func__);
	}

	priv->tc_dev = tc_dev;
	priv->s_data = tc_dev->s_data;
	priv->subdev = &tc_dev->s_data->subdev;
	priv->check_encrypt = 0;
	tegracam_set_privdata(tc_dev, (void *)priv);

#if (1 != IMX586_CHECK_TRACKID)
	priv->check_encrypt = 1;
#endif

#if (PDAF_SOLUTION_NO != PDAF_SOLUTION)
	priv->kthread_focus = NULL;
	priv->frame_rate = 0;
	priv->streamflag = 0;
	priv->readingpd = false;
	priv->dis_infinity = IMX586_MOTOR_STEPS_INFINNITY;
	priv->dis_micro = IMX586_MOTOR_STEPS_MICRO;
	priv->cur_pos = priv->dis_micro;
#endif

#if (1 == IMX586_CHECK_TRACKID)
	imx586_trackid_init(priv);

	if ( 0 != check_trackid(priv))
	{
		dev_info(dev, "%s : imx586_board_setup encrypt check faild, return!!!--------\n", __func__);
		return -1;
	}

	priv->check_encrypt = 1;
#endif

	err = imx586_board_setup(priv);
	if (err) {
		dev_err(dev, "board setup failed\n");
		return err;
	}
	else{
		dev_info(dev, "%s : imx586_board_setup end!!!--------\n", __func__);
	}
	
	cam_data = tc_dev->s_data;

	ctrlprops =&cam_data->sensor_props.sensor_modes[0].control_properties;
	dev_info(dev, "%s : ctrlprops->gain_factor = %d, ctrlprops->framerate_factor = %d,ctrlprops->inherent_gain = %d!--------\n", __func__, 
		ctrlprops->gain_factor, ctrlprops->framerate_factor, ctrlprops->inherent_gain);

	dev_info(dev, "%s : ctrlprops->min_gain_val = %d, ctrlprops->max_gain_val = %d,ctrlprops->min_hdr_ratio = %d, ctrlprops->max_hdr_ratio = %d !--------\n", __func__, 
		ctrlprops->min_gain_val, ctrlprops->max_gain_val, ctrlprops->min_hdr_ratio, ctrlprops->max_hdr_ratio);

	dev_info(dev, "%s : ctrlprops->min_framerate = %d, ctrlprops->max_framerate = %d,ctrlprops->step_gain_val = %d, ctrlprops->step_framerate = %d !--------\n", __func__, 
		ctrlprops->min_framerate, ctrlprops->max_framerate, ctrlprops->step_gain_val, ctrlprops->step_framerate);

	dev_info(dev, "%s : ctrlprops->exposure_factor = %d, ctrlprops->default_gain = %d,ctrlprops->default_framerate = %d, ctrlprops->is_interlaced = %d, ctrlprops->interlace_type = %d !--------\n", __func__, 
		ctrlprops->exposure_factor, ctrlprops->default_gain, ctrlprops->default_framerate, ctrlprops->is_interlaced, ctrlprops->interlace_type);

	temp = (__u64)(ctrlprops->min_exp_time.val);
	dev_info(dev, "%s : ctrlprops->min_exp_time = %llu !--------\n", __func__, temp);

	temp = (__u64)(ctrlprops->max_exp_time.val);
	dev_info(dev, "%s : ctrlprops->max_exp_time = %llu !--------\n", __func__, temp);

	temp = (__u64)(ctrlprops->step_exp_time.val);
	dev_info(dev, "%s : ctrlprops->step_exp_time = %llu !--------\n", __func__, temp);

	temp = (__u64)(ctrlprops->default_exp_time.val);
	dev_info(dev, "%s : ctrlprops->default_exp_time = %llu !--------\n", __func__, temp);

	dev_info(dev, "%s: frame_length:%d, numctrls:%d, mode_prop_idx:%d, mode:%d, csi_port:%d, numlanes:%d, numfmts: %d, def_mode: %d, def_width: %d, def_height:%d, def_clk_freq:%d, fmt_width: %d, fmt_height:%d\n", 
				__func__, priv->frame_length, priv->s_data->numctrls, priv->s_data->mode_prop_idx, priv->s_data->mode, priv->s_data->csi_port, priv->s_data->numlanes, 
				priv->s_data->numfmts, priv->s_data->def_mode, priv->s_data->def_width, priv->s_data->def_height, priv->s_data->def_clk_freq, priv->s_data->fmt_width, priv->s_data->fmt_height);

	dev_info(dev, "%s: framerates:%d, num_framerates:%d, mode:%d, hdr_en:%d\n", 
				__func__, *(priv->s_data->frmfmt->framerates), priv->s_data->frmfmt->num_framerates, priv->s_data->frmfmt->mode, priv->s_data->frmfmt->hdr_en);

	err = tegracam_v4l2subdev_register(tc_dev, true);
	if (err) {
		dev_err(dev, "tegra camera subdev registration failed\n");
		return err;
	}
	else
	{
		dev_info(dev, "%s : tegracam_v4l2subdev_register end!!!--------\n", __func__);
	}

	dev_info(dev, "%s : Detected IMX586 sensor, %d\n", __func__, priv->i2c_client->adapter->nr);

#if (PDAF_SOLUTION_NO != PDAF_SOLUTION)
	// focus motor
	err = imx586_focus_device_init(priv);
	dev_info(dev, "%s imx586_focus_device_init: %d\n", __func__, err);

	imx586_focus_init(priv);

	imx586_focus_set_position(priv, priv->dis_infinity);
	dev_info(dev, "%s imx586_focus_set_position: %d\n", __func__, priv->dis_infinity);

	// eeprom */
	err = imx586_eeprom_device_init(priv);
	dev_info(dev, "%s imx586_eeprom_device_init: %d\n", __func__, err);
#endif

#if (PDAF_SOLUTION_1 == PDAF_SOLUTION || PDAF_SOLUTION_2 == PDAF_SOLUTION)
	mutex_init(&priv->kthread_lock);
#endif

	return 0;
}

然后我又查找了i2c的内核日志和连接状态:

nvidia-user@tegra-ubuntu:~/Desktop$ sudo dmesg |grep -i i2c
[    0.725128] i2c /dev entries driver
[    0.725265] tegra-i2c 3160000.i2c: Adding to iommu group 2
[    0.725497] tegra-i2c c240000.i2c: Adding to iommu group 2
[    0.725597] tegra-i2c 3180000.i2c: Adding to iommu group 2
[    0.725669] tegra-i2c 3190000.i2c: Adding to iommu group 2
[    0.725746] tegra-i2c 31b0000.i2c: Adding to iommu group 2
[    0.725803] tegra-i2c 31c0000.i2c: Adding to iommu group 2
[    0.725870] tegra-i2c c250000.i2c: Adding to iommu group 2
[    0.725931] tegra-i2c 31e0000.i2c: Adding to iommu group 2
[   11.708089] imx586 2-001a: imx586_probe : probing v4l2 sensor, i2c-2, 3 mode
[   11.712292] imx586 2-001a: imx586_write_reg: i2c write reg failed, addr: 0x0204, val: 00, err: -121
nvidia-user@tegra-ubuntu:~/Desktop$ sudo i2cdetect -l
i2c-3	i2c       	3190000.i2c                     	I2C adapter
i2c-1	i2c       	c240000.i2c                     	I2C adapter
i2c-8	i2c       	31e0000.i2c                     	I2C adapter
i2c-6	i2c       	31c0000.i2c                     	I2C adapter
i2c-4	i2c       	Tegra BPMP I2C adapter          	I2C adapter
i2c-2	i2c       	3180000.i2c                     	I2C adapter
i2c-0	i2c       	3160000.i2c                     	I2C adapter
i2c-9	i2c       	NVIDIA SOC i2c adapter 0        	I2C adapter
i2c-7	i2c       	c250000.i2c                     	I2C adapter
i2c-5	i2c       	31b0000.i2c                     	I2C adapter

我不太清楚这是什么原因造成的

对于这个问题,我是否需要新开一个主题来讨论

This error telling unable communicated with sensor via i2c.
You may need to check the power/rest/standby pins for sensor.