在撰写本文时,使用了L4T 28.1 Production Release。只要对所有未来更新的更改很小,那么这些说明就不会有太大变化。
驱动程序L4T文档是很好的资源,特别是“传感器驱动程序编程指南”,实际上,该文档仅应作为操作方法的粗略示例。
整个过程的概述如下:
有两种修改内核的方法。
设备树源(DTS):这是您可以在引导时配置内核的方式,使其在一个板上与另一个板上的行为有所不同。例如,Raspberry Pi和The Raspberry Pi Zero看起来非常
不同,但是具有相同的内核,因为有两个不同的DTS文件。我们需要添加对IMX219相机(Raspberry Pi Model 2相机)的支持。因为在内核运行时没有识别CSI摄像机的机制,所以我们必须修改DTS才能告诉内核如何识别它们。这与USB不同,因为USB具有标准机制,内核可以用来识别何时插入新设备。
每块板均配置有一个最终的DT(B)(B)二进制文件。该DTB是(S)our DT(S)和(I)包含的DTS(I)文件的编译版本。
我们需要配置DTS文件以识别IMX219摄像机。为此,我们必须描述以下内容:
我们可以从头开始编写DTS文件,但对于许多应用程序,您可以使用NVIDIA开发板使用的默认DTS文件。如果您想花更多的钱,请参见上面的链接,了解如何将TX2移植到新平台。
TX2开发板的默认配置文件是:
Linux_for_Tegra/sources/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-c03-00-base.dts
该文件中没有太多内容,因为它的大部分配置来自:
Linux_for_Tegra/sources/hardware/nvidia/platform/t18x/quill/kernel-dts/tegra186-quill-p3310-1000-a00-00-base.dts
在该文件的顶部,您将找到:
#include
#include
#include
#include
/* comms dtsi file should be included after gpio dtsi file */
#include
#include
#include
#include
#include
#include
#include
对其进行修改,如下所示:
为了简化摄像头连接器的开发,我将禁用Nvidia的智能摄像头插件管理器,并删除对其他摄像头板的所有引用。
#include
#include
//#include
#include
/* comms dtsi file should be included after gpio dtsi file */
#include
#include
#include
#include
#include
//#include
#include
现在,我们删除了对以前相机的所有引用,我们将添加两个文件。一个将配置板级摄像头,另一个将配置TX2视频接口的内部架构。
在以下目录中创建一个新文件“ tegra186-my-camera-config-a00.dtsi”:
Linux_for_Tegra/sources/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-platforms/
在以下目录中创建另一个同名文件
Linux_for_Tegra/sources/hardware/nvidia/platform/t18x/common/kernel-dts/t18x-common-modules/
可以将“ my-camera-config”更改为所需的名称,“ a00”只是此文件的第一个版本。
目前,我一直在使用文件的“平台”版本作为模块的传递,但从技术上讲,您可以覆盖某些通用平台的预期抽象“模块”,但是当我发现该文件时,我只是保留了该文件的位置它的用途。如果您对此有任何反馈,我希望听到。
在文件的“平台”版本中,包含以下行
#include
在“模块”文件中,我们需要配置内核以执行以下操作:
为了帮助可视化,我创建了一个框图。该图没有显示GPIO,因为它已经很忙了:
所有的Raspberry Pi摄像机都具有相同的I2C地址,因此我们需要一种将一个摄像机与另一个摄像机区分开的方法。最简单的方法是使用多路复用器。由于驱动程序已内置在内核中,因此我们将使用GPIO多路复用器。多路复用器的GPIO之一在AON处理器上,因此为此添加了第二个GPIO盒。
较高级别的紫色Raspberry Pi摄像机的数据通过蓝色CSI通道进入TX2。我们只需要两个通道的CSI总线,所以我们采用CSI A,如果需要四个通道,我们将保留两个CSI块,如上图所示。NVCSI核心将从CSI协议中提取原始图像,并将数据发送到VI。“视频输入”本质上是一个视频路由器,它将视频路由到ISP或直接路由到内存。如果Raspberry Pi相机具有内部图像信号处理器将图像转换为有用的RGB图像,我们只需要告诉VI将图像数据路由到内存即可,但是由于相机没有ISP,我们在TX2上使用了ISP。内核启动后,在VI中在用户区中完成VI后路由视频数据的过程,以便在VI正确连接后完成。
在t18x-common-modules / tegra186-my-camera-config-a00.dtsi文件中,添加以下行:
#include "dt-bindings/clock/tegra186-clock.h"
#include
#include
#define CAM0_RST_L TEGRA_MAIN_GPIO(R, 0)
#define CAM1_RST_L TEGRA_MAIN_GPIO(N, 2)
#define CAM2_RST_L TEGRA_MAIN_GPIO(R, 5)
#define CAM_0_MUX TEGRA_AON_GPIO(V, 5)
#define CAM_1_MUX TEGRA_MAIN_GPIO(X, 6)
上面的添加内容包括用于控制引脚和时钟的宏,以及下面将用来配置GPIO定义的宏。
以下内容将告诉内核保留和配置GPIO。我们已经将GPIO配置为所有输出都位于默认的低位。
/ {
/* set camera gpio direction to output */
gpio@2200000 {
camera-control-output-low {
status = "okay";
gpio-hog;
output-low;
gpios = < CAM0_RST_L 0
CAM1_RST_L 0
CAM2_RST_L 0
CAM_1_MUX 0>;
label = "cam0-rst",
"cam1-rst",
"cam2-rst",
"cam-mux1";
};
};
gpio@c2f0000 {
aon-camera-control-output-low {
status = "okay";
gpio-hog;
output-low;
gpios = < CAM_0_MUX 0>;
label = "cam-mux0";
};
};
};
现在配置host1x接口。视频接口是其子块:
视频界面:我们需要描述它将管理的频道数量。每个通道都需要一个输入和一个输出。带有“ vi_inX”标签的输入是路由NVCSI输出的位置,而“ vi_portX”是用户可以访问它的位置。
/ {
host1x {
vi@15700000 {
num-channels = <3>;
ports {
#address-cells = <1>; #size-cells = <0>; vi_port0: port@0 {
status = "okay";
reg = <0>;
vi_in0: endpoint {
status = "okay";
csi-port = <0>;
bus-width = <2>;
remote-endpoint = <&imx219_csi_out0>;
};
};
vi_port1: port@1 {
status = "okay";
reg = <1>;
vi_in1: endpoint {
status = "okay";
csi-port = <2>;
bus-width = <2>;
remote-endpoint = <&imx219_csi_out1>;
};
};
vi_port2: port@2 {
status = "okay";
reg = <2>;
vi_in2: endpoint {
status = "okay";
csi-port = <4>;
bus-width = <2>;
remote-endpoint = <&imx219_csi_out2>;
};
};
};
};
};
};
端口中有3个“端口”,它们的en元素称为“端点”,这是我们描述NVCSI与VI之间的连接的地方。我们为它提供数据来自的csi端口,总线的宽度和内部DTSI指针。
下一个块是NVCSI,它用于配置CSI通道,您可以将其配置为使用1,2或4个视频通道,这将从物理CSI连接中获取数据并提取图像。与视频输入类似,有些通道包含输入和输出端口。他们选择将通道的端口0用作描述CSI物理接口与模块之间的物理连接的输入,并将端口1用作将数据发送到的输出。
/ {
host1x {
nvcsi@150c0000 {
status = "okay";
num-channels = <3>;
#address-cells = <1>; #size-cells = <0>; channel@0 {
reg = <0>;
status = "okay";
ports {
#address-cells = <1>; #size-cells = <0>; port@0 {
status = "okay";
reg = <0>;
imx219_csi_in0: endpoint@0 {
status = "okay";
csi-port = <0>;
bus-width = <2>;
remote-endpoint = <&imx219_phy_out0>;
};
};
port@1 {
status = "okay";
reg = <1>;
imx219_csi_out0: endpoint@1 {
status = "okay";
remote-endpoint = <&vi_in0>;
};
};
};
};
channel@1 {
reg = <1>;
status = "okay";
ports {
#address-cells = <1>; #size-cells = <0>; port@0 {
status = "okay";
reg = <0>;
imx219_csi_in1: endpoint@2 {
status = "okay";
csi-port = <2>;
bus-width = <2>;
remote-endpoint = <&imx219_phy_out1>;
};
};
port@1 {
status = "okay";
reg = <1>;
imx219_csi_out1: endpoint@3 {
status = "okay";
remote-endpoint = <&vi_in1>;
};
};
};
};
channel@2 {
reg = <2>;
status = "okay";
ports {
#address-cells = <1>; #size-cells = <0>; port@0 {
status = "okay";
reg = <0>;
imx219_csi_in2: endpoint@4 {
status = "okay";
csi-port = <4>;
bus-width = <2>;
remote-endpoint = <&imx219_phy_out2>;
};
};
port@1 {
status = "okay";
reg = <1>;
imx219_csi_out2: endpoint@5 {
remote-endpoint = <&vi_in2>;
status = "okay";
};
};
};
};
};
};
};
下一个块很长。它向ISP和Linux Media子系统描述了摄像机的配置。
因为我们正在使用上述的GPIO I2C多路复用器,所以控制块的第一个条目是称为“ i2c-camera-mux”的I2C多路复用器,因此它通过“ i2c-parant”值链接到Camera I2C或I2C3 @ 0x3180000。
我们输入上面为控件声明的GPIO配置值。这样就创建了3个“新总线”,其行为类似于用户区中的标准I2C总线。这是我的/ dev目录I2C设备的副本:
/dev/i2c-0 /dev/i2c-10 /dev/i2c-2 /dev/i2c-4 /dev/i2c-7 /dev/i2c-9
/dev/i2c-1 /dev/i2c-11 /dev/i2c-3 /dev/i2c-6 /dev/i2c-8
没有这个多路复用器,我们将只有8个条目。
在每条总线上,我们声明一个位于地址0x10(Raspberry Pi I2C地址)的设备。这将描述我们对Linux Media Subsystem的传感器。
以多路复用器(i2c @ 0)的总线0为例,我们有第一个传感器imx219_a,它位于I2C总线上的地址0x10。在本节中,我们将告诉它此配置与“ nvidia,imx219”传感器的物理尺寸以及它将使用的串行接口兼容的驱动程序。我们还将介绍本相机支持的模式。“模式”是视频配置,例如1920x1080 @ 30FPS或1280x720 @ 60FPS。所有这些信息用于配置各个核心,以期从相机中获得什么。如果此处未描述相机模式,则Linux Media Interface将无法识别它。
在“模式”之后的每个配置的底部,都有此模块的声明端口。这是CSI phy的物理配置连接到NVCSI的位置。
这描述了所有三个相机。
/ {
host1x {
//Make seperate module i2c-camera-mux {
//i2c@3180000 status = "okay";
compatible = "i2c-mux-gpio";
#address-cells = <1>; #size-cells = <0>; mux-gpios = < &tegra_aon_gpio CAM_0_MUX GPIO_ACTIVE_HIGH
&tegra_main_gpio CAM_1_MUX GPIO_ACTIVE_HIGH>;
i2c-parent = <&cam_i2c>;
//idle-state = <0>;
i2c@0 {
#address-cells = <1>; #size-cells = <0>; reg = <0>;
imx219_a@10 {
#address-cells = <1>; #size-cells = <0>;
//ADDED clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>;
clock-names = "extperiph1";
mclk = "extperiph1";
reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_LOW>;
//reset-gpios = <&tegra_main_gpio CAM0_RST_L GPIO_ACTIVE_HIGH>; //vana-supply = <&en_vdd_cam_hv_2v8>; //vana-supply = <&en_vdd_cam_hv_2v8>; //vdig-supply = <&en_vdd_sys>; //dovdd-supply = <&en_vdd_cam>; //END
devnode = "video0";
compatible = "nvidia,imx219";
reg = <0x10>;
physical_w = "5.095";
physical_h = "4.930";
sensor_model ="imx219";
//dovdd-supply = <&en_vdd_cam>; //avdd-reg = "vana"; //dvdd-reg = "vdig"; //iovdd-reg = "dovdd";
mode0 { // IMX219_MODE_1920X1080 mclk_khz = "24000";
mclk_multiplier = "25";
pix_clk_hz = "182400000";
//pix_clk_hz = "170000000";
num_lanes = "2";
tegra_sinterface = "serial_a";
discontinuous_clk = "yes";
cil_settletime = "0";
pixel_t = "bayer_rggb";
readout_orientation = "90";
inherent_gain = "1";
active_w = "1920";
active_h = "1080";
line_length = "3448";
dpcm_enable = "false";
min_gain_val = "1.0";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "30";
//min_exp_time = "33"; min_exp_time = "11";
max_exp_time = "683709";
embedded_metadata_height = "0";
};
mode1 { // IMX219_MODE_1280X720 mclk_khz = "24000";
mclk_multiplier = "25";
pix_clk_hz = "182400000";
//pix_clk_hz = "170000000";
num_lanes = "2";
tegra_sinterface = "serial_a";
discontinuous_clk = "yes";
cil_settletime = "0";
pixel_t = "bayer_rggb";
readout_orientation = "90";
inherent_gain = "1";
active_w = "1280";
active_h = "720";
line_length = "3448";
dpcm_enable = "false";
//line_length = "1752";
min_gain_val = "1";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "60";
//min_exp_time = "16"; min_exp_time = "11";
max_exp_time = "683710";
embedded_metadata_height = "0";
};
mode2 { // IMX219_MODE_640X480 //mclk_khz = "47000"; mclk_khz = "24000";
mclk_multiplier = "25.0";
pix_clk_hz = "182400000";
//pix_clk_hz = "170000000";
num_lanes = "2";
tegra_sinterface = "serial_a";
discontinuous_clk = "yes";
cil_settletime = "0";
pixel_t = "bayer_rggb";
readout_orientation = "90";
inherent_gain = "1";
active_w = "640";
active_h = "480";
//line_length = "3448"; line_length = "3559";
dpcm_enable = "false";
min_gain_val = "1";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "90";
min_exp_time = "11";
max_exp_time = "358731";
embedded_metadata_height = "0";
};
ports {
#address-cells = <1>; #size-cells = <0>;
port@0 {
reg = <0>;
imx219_phy_out0: endpoint {
csi-port = <0>;
bus-width = <2>;
remote-endpoint = <&imx219_csi_in0>;
};
};
};
};
};
i2c@1 {
#address-cells = <1>; #size-cells = <0>; reg = <1>;
imx219_c@10 {
#address-cells = <1>; #size-cells = <0>;
//ADDED! clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>;
clock-names = "extperiph1";
mclk = "extperiph1";
reset-gpios = <&tegra_main_gpio CAM1_RST_L GPIO_ACTIVE_LOW>;
//reset-gpios = <&tegra_main_gpio CAM1_RST_L GPIO_ACTIVE_HIGH>; //vana-supply = <&en_vdd_cam_hv_2v8>; //vdig-supply = <&en_vdd_sys>; //dovdd-supply = <&en_vdd_cam>; //END
devnode = "video1";
compatible = "nvidia,imx219";
reg = <0x10>;
physical_w = "5.095";
physical_h = "4.930";
sensor_model ="imx219";
//avdd-reg = "vana"; //dvdd-reg = "vdig"; //iovdd-reg = "dovdd";
mode0 { // IMX219_MODE_1920X1080 mclk_khz = "24000";
mclk_multiplier = "25";
pix_clk_hz = "182400000";
//pix_clk_hz = "170000000";
num_lanes = "2";
tegra_sinterface = "serial_c";
discontinuous_clk = "yes";
cil_settletime = "0";
pixel_t = "bayer_rggb";
readout_orientation = "270";
//readout_orientation = "90"; inherent_gain = "1";
active_w = "1920";
active_h = "1080";
line_length = "3448";
dpcm_enable = "false";
min_gain_val = "1";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "30";
min_exp_time = "11";
max_exp_time = "683709";
embedded_metadata_height = "0";
};
mode1 { // IMX219_MODE_1280X720 mclk_khz = "24000";
mclk_multiplier = "25";
pix_clk_hz = "182400000";
//pix_clk_hz = "170000000";
num_lanes = "2";
tegra_sinterface = "serial_c";
discontinuous_clk = "yes";
cil_settletime = "0";
pixel_t = "bayer_rggb";
readout_orientation = "270";
inherent_gain = "1";
active_w = "1280";
active_h = "720";
line_length = "3448";
dpcm_enable = "false";
//line_length = "1752";
min_gain_val = "1";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "60";
//min_exp_time = "16"; min_exp_time = "13";
max_exp_time = "683709";
embedded_metadata_height = "0";
};
mode2 { // IMX219_MODE_640X480
//mclk_khz = "47000"; mclk_khz = "24000";
mclk_multiplier = "25.0";
pix_clk_hz = "182400000";
//pix_clk_hz = "170000000";
num_lanes = "2";
tegra_sinterface = "serial_c";
discontinuous_clk = "yes";
cil_settletime = "0";
pixel_t = "bayer_rggb";
readout_orientation = "270";
inherent_gain = "1";
active_w = "640";
active_h = "480";
//line_length = "3448"; line_length = "3559";
dpcm_enable = "false";
min_gain_val = "1";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "90";
min_exp_time = "11";
max_exp_time = "358733";
embedded_metadata_height = "0";
};
ports {
#address-cells = <1>; #size-cells = <0>;
port@0 {
reg = <0>;
imx219_phy_out1: endpoint {
csi-port = <2>;
bus-width = <2>;
remote-endpoint = <&imx219_csi_in1>;
};
};
};
};
};
i2c@2 {
#address-cells = <1>; #size-cells = <0>; reg = <2>;
imx219_e@10 {
#address-cells = <1>; #size-cells = <0>;
//ADDED clocks = <&tegra_car TEGRA186_CLK_EXTPERIPH1>;
clock-names = "extperiph1";
mclk = "extperiph1";
reset-gpios = <&tegra_main_gpio CAM2_RST_L GPIO_ACTIVE_LOW>;
//reset-gpios = <&tegra_main_gpio CAM2_RST_L GPIO_ACTIVE_HIGH>; //vana-supply = <&en_vdd_cam_hv_2v8>; //vdig-supply = <&en_vdd_sys>; //dovdd-supply = <&en_vdd_cam>; //END
devnode = "video2";
compatible = "nvidia,imx219";
reg = <0x10>;
physical_w = "5.095";
physical_h = "4.930";
sensor_model ="imx219";
//avdd-reg = "vana"; //dvdd-reg = "vdig"; //iovdd-reg = "dovdd";
mode0 { // IMX219_MODE_1920X1080 mclk_khz = "24000";
mclk_multiplier = "25";
pix_clk_hz = "182400000";
//pix_clk_hz = "170000000";
num_lanes = "2";
tegra_sinterface = "serial_e";
discontinuous_clk = "yes";
cil_settletime = "0";
pixel_t = "bayer_rggb";
readout_orientation = "270";
inherent_gain = "1";
active_w = "1920";
active_h = "1080";
line_length = "3448";
dpcm_enable = "false";
min_gain_val = "1";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "30";
min_exp_time = "11";
max_exp_time = "683709";
embedded_metadata_height = "0";
};
mode1 { // IMX219_MODE_1280X720 mclk_khz = "24000";
mclk_multiplier = "25";
pix_clk_hz = "182400000";
//pix_clk_hz = "170000000";
num_lanes = "2";
tegra_sinterface = "serial_e";
discontinuous_clk = "yes";
cil_settletime = "0";
pixel_t = "bayer_rggb";
readout_orientation = "270";
inherent_gain = "1";
active_w = "1280";
active_h = "720";
line_length = "3448";
dpcm_enable = "false";
//line_length = "1752";
min_gain_val = "1";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "60";
//min_exp_time = "16"; min_exp_time = "13";
max_exp_time = "683709";
embedded_metadata_height = "0";
};
mode2 { // IMX219_MODE_640X480
mclk_khz = "24000";
mclk_multiplier = "25.0";
pix_clk_hz = "182400000";
num_lanes = "2";
tegra_sinterface = "serial_e";
discontinuous_clk = "yes";
cil_settletime = "0";
pixel_t = "bayer_rggb";
readout_orientation = "270";
inherent_gain = "1";
active_w = "640";
active_h = "480";
line_length = "3559";
dpcm_enable = "false";
min_gain_val = "1.0";
max_gain_val = "16";
min_hdr_ratio = "1";
max_hdr_ratio = "64";
min_framerate = "1";
max_framerate = "90";
//min_exp_time = "22"; min_exp_time = "11";
max_exp_time = "358733";
embedded_metadata_height = "0";
};
ports {
#address-cells = <1>; #size-cells = <0>;
port@0 {
reg = <0>;
imx219_phy_out2: endpoint {
csi-port = <4>;
bus-width = <2>;
remote-endpoint = <&imx219_csi_in2>;
};
};
};
};
};
};
};
};
最后,我们进入Tegra相机平台。相机可以由多个部分组成,例如聚焦器和图像传感器。Tegra Camera Platform管理着多个元素,并将用户或Linux Media Subystem呈现为一个相干传感器。以下配置仅具有图像传感器,因此只有1个“模块”。
有一些很简单的要素,例如CSI通道的总数。相机重要的特定元素是“徽章”,“位置”和“方向”
/* camera control gpio definitions *// {
tegra-camera-platform {
compatible = "nvidia, tegra-camera-platform";
num_csi_lanes = <6>;
max_lane_speed = <1500000>;
max_pixel_rate = <750000>;
min_bits_per_pixel = <10>;
vi_peak_byte_per_pixel = <2>;
vi_bw_margin_pct = <25>;
isp_peak_byte_per_pixel = <5>;
isp_bw_margin_pct = <25>;
modules {
module0 {
status = "okay";
//badge = "imx185_bottom_liimx185"; //badge = "e3322_bottom_A815P2"; badge = "e3326_bottom_P5V27C";
position = "bottom";
orientation = "0";
drivernode0 {
status = "okay";
pcl_id = "v4l2_sensor";
devname = "imx219 9-0010";
proc-device-tree = "/proc/device-tree/host1x/i2c-camera-mux/i2c@0/imx219_a@10";
};
};
module1 {
status = "okay";
//badge = "imx185_top_liimx185"; //badge = "e3322_top_A815P2"; badge = "e3326_top_P5V27C";
position = "top";
orientation = "1";
drivernode0 {
status = "okay";
pcl_id = "v4l2_sensor";
devname = "imx219 10-0010";
proc-device-tree = "/proc/device-tree/host1x/i2c-camera-mux/i2c@1/imx219_c@10";
};
};
module2 {
status = "okay";
//badge = "imx185_center_liimx185"; //badge = "e3322_center_A815P2"; badge = "e3326_center_P5V27C";
position = "center";
orientation = "1";
drivernode0 {
status = "okay";
pcl_id = "v4l2_sensor";
devname = "imx219 11-0010";
proc-device-tree = "/proc/device-tree/host1x/i2c-camera-mux/i2c@2/imx219_e@10";
};
};
};
};
};
以上所有元素均应复制并放置在“模块”目录下的“ tegra186-my-camera-config-a00.dtsi”文件中。
我们需要在顶级dts配置文件中包含平台“ tegra186-my-camera-config-a00.dtsi”。
在tegra186-quill-p3310-1000-c03-00-base.dts中,在前一个“ include”之后添加一行
#include
它应该像这样
#include "tegra186-quill-p3310-1000-a00-00-base.dts"
#include / {
nvidia,dtsfilename = __FILE__;
nvidia,dtbbuildtime = __DATE__, __TIME__;
与上一步相比,这将很容易。输入内核菜单配置。如果您使用的是我在TX2弹出指南中编写的脚本,则只需键入./build_kernel.sh -m,这将弹出内核菜单配置。
通过按“ /”搜索i2c-gpio-mux,然后键入“ I2C_MUX_GPIO”,按Enter,您应该看到以下内容:
按“ 1”,然后按空格键,直到选择为“ *”为止,看起来像这样:
通过搜索“ imx219”来执行相同的操作。
使用箭头键突出显示退出并继续遵循“退出”,直到询问您是否要保存配置。说“是”。
现在您可以构建内核,它应该将设备树源构建为正确的二进制Blob。
不幸的是,NVIDIA提供的imx219驱动程序与Raspberry Pi不兼容,因此需要进行一些小的修改。除其他事项外,需要删除调节器要求,并需要更改模式表。
此处没有进行所有更改,而是提供了指向imx219驱动程序文件和imx219设备树dtsi的下载链接。
使用以上文件覆盖以下目录中的imx219.c和imx219_mode_tbls.h文件:
Linux_for_Tegra/sources/kernel/kernel-4.4/drivers/media/i2c
现在重建内核,它应该具有正确的驱动程序。
一切构建完成后,刻录到TX2上并启动内核。您应该有三个新的/ dev / videoX条目。
您可以运行以下命令来捕获简短的视频剪辑:
gst-launch-1.0 -v nvcamerasrc sensor-id=0 fpsRange="30 30" num-buffers=100 ! 'video/x-raw(memory:NVMM), width=(int)1920, height=(int)1080, format=(string)I420, framerate=(fraction)30/1' ! omxh264enc ! 'video/x-h264, width=(int)1920, height=(int)1080, format=(string)I420, framerate=(fraction)30/1' ! h264parse ! qtmux ! filesink location=test.mp4 -e
因为您以30FPS的速度运行并且捕获了100帧,所以剪辑的长度为2.33秒。您可以使用这些值进行修改。您还可以使用'sensor-id'值在不同的传感器之间切换。
最后一点。您可能需要刷新ISP的图像配置缓存,以要求内核为您的特定摄像机重建ISP配置。
缓存位于:
/var/nvidia/nvcam/settings
删除所有这些文件,然后重新启动TX2,应该重新构建它们。