TX2上的Raspberry Pi相机

在撰写本文时,使用了L4T 28.1 Production Release。只要对所有未来更新的更改很小,那么这些说明就不会有太大变化。

驱动程序L4T文档是很好的资源,特别是“传感器驱动程序编程指南”,实际上,该文档仅应作为操作方法的粗略示例。

总览

整个过程的概述如下:

  1. 准备设备树源。
  2. 配置内核。
  3. 修改IMX219驱动程序。
  4. 用户区测试

 

1,准备设备树源

有两种修改内核的方法。

  • 内核配置文件:这将告诉内核应该构建哪些功能和驱动程序。您还可以指定哪些驱动程序应打包到内核中,哪些驱动程序应编译但与内核分开。例如:我们将对此进行修改,以告知内核建立对IMX219驱动程序的支持。
  • 设备树源(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摄像机。为此,我们必须描述以下内容:

  • 摄像机连接到哪个CSI端口。
  • 如何使用I2C配置摄像机。
  • 相机有哪些模式(有1920x1080和/或1280x720)。
  • 如何配置TX2的视频输入架构。

我们可以从头开始编写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 <t18x-common-platforms/tegra186-quill-common-p3310-1000-a00.dtsi>
#include <t18x-common-platforms/tegra186-quill-power-tree-p3310-1000-a00-00.dtsi>
#include <t18x-common-platforms/tegra186-quill-camera-modules.dtsi>
#include <t18x-common-modules/tegra186-display-e3320-1000-a00.dtsi>
/* comms dtsi file should be included after gpio dtsi file */
#include <t18x-common-platforms/tegra186-quill-comms.dtsi>
#include <t18x-common-plugin-manager/tegra186-quill-p3310-1000-a00-plugin-manager.dtsi>
#include <t18x-common-modules/tegra186-super-module-e2614-p2597-1000-a00.dtsi>
#include <t18x-common-plugin-manager/tegra186-quill-display-plugin-manager.dtsi>
#include <t18x-common-prod/tegra186-priv-quill-p3310-1000-a00-prod.dtsi>
#include <t18x-common-plugin-manager/tegra186-quill-camera-plugin-manager.dtsi>
#include <dt-bindings/linux/driver-info.h>

对其进行修改,如下所示:

为了简化摄像头连接器的开发,我将禁用Nvidia的智能摄像头插件管理器,并删除对其他摄像头板的所有引用。

#include <t18x-common-platforms/tegra186-quill-common-p3310-1000-a00.dtsi>
#include <t18x-common-platforms/tegra186-quill-power-tree-p3310-1000-a00-00.dtsi>
//#include <t18x-common-platforms/tegra186-quill-camera-modules.dtsi>
#include <t18x-common-modules/tegra186-display-e3320-1000-a00.dtsi>
/* comms dtsi file should be included after gpio dtsi file */
#include <t18x-common-platforms/tegra186-quill-comms.dtsi>
#include <t18x-common-plugin-manager/tegra186-quill-p3310-1000-a00-plugin-manager.dtsi>
#include <t18x-common-modules/tegra186-super-module-e2614-p2597-1000-a00.dtsi>
#include <t18x-common-plugin-manager/tegra186-quill-display-plugin-manager.dtsi>
#include <t18x-common-prod/tegra186-priv-quill-p3310-1000-a00-prod.dtsi>
//#include <t18x-common-plugin-manager/tegra186-quill-camera-plugin-manager.dtsi>
#include <dt-bindings/linux/driver-info.h>

现在,我们删除了对以前相机的所有引用,我们将添加两个文件。一个将配置板级摄像头,另一个将配置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 <t18x-common-modules/tegra186-my-camera-config-a00.dtsi>

在“模块”文件中,我们需要配置内核以执行以下操作:

  • 为GPIO留出空间
    • 重置线路
    • 可能的GPIO I2C多路复用器
  • TX2的主机
    • NVCSI组件:配置CSI通道以正确与所有摄像机通信。
    • VI:将NVCSI输出配置为ISP或直接配置为内存。
    • I2C:如何配置摄像头以输出所需的视频。
  • 通用输入输出
    • 配置GPIO以执行某些行为,例如重置摄像头,打开或关闭摄像头调节器。
  • 一体式相机平台
    • 描述摄像机的物理位置。
    • 配置ISP以处理图像。
    • 描述组成相机的其他元素,例如聚焦器。

为了帮助可视化,我创建了一个框图。该图没有显示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 <dt-bindings/pinctrl/pinctrl-tegra.h>
#include <dt-bindings/gpio/tegra186-gpio.h>
#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通道的总数。相机重要的特定元素是“徽章”,“位置”和“方向”

  • 方向:将告诉系统此相机朝向后方或前方。
  • position:描述摄像机的物理位置,三个摄像机的最佳位置分别为“底部”,“顶部”和“中心”。
  • 徽章:这一点很重要,它在配置ISP(尤其是ISP如何处理摄像机视频)中发挥作用。如果配置不正确,您的视频可能会被冲洗掉,而黑色可能看起来是紫色的。我还没有完全解决这个问题,但是下面会详细介绍。
/* 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 <t18x-common-platforms/tegra186-my-camera-config-a00.dtsi>

它应该像这样

#include "tegra186-quill-p3310-1000-a00-00-base.dts"
#include <t18x-common-platforms/tegra186-my-camera-config-a00.dtsi>/ {
  nvidia,dtsfilename = __FILE__;
  nvidia,dtbbuildtime = __DATE__, __TIME__;

2,配置内核。

与上一步相比,这将很容易。输入内核菜单配置。如果您使用的是我在TX2弹出指南中编写的脚本,则只需键入./build_kernel.sh -m,这将弹出内核菜单配置。

 

通过按“ /”搜索i2c-gpio-mux,然后键入“ I2C_MUX_GPIO”,按Enter,您应该看到以下内容:

 

按“ 1”,然后按空格键,直到选择为“ *”为止,看起来像这样:

 

通过搜索“ imx219”来执行相同的操作。

使用箭头键突出显示退出并继续遵循“退出”,直到询问您是否要保存配置。说“是”。

现在您可以构建内核,它应该将设备树源构建为正确的二进制Blob。

3,修改IMX219驱动程序。

不幸的是,NVIDIA提供的imx219驱动程序与Raspberry Pi不兼容,因此需要进行一些小的修改。除其他事项外,需要删除调节器要求,并需要更改模式表。

此处没有进行所有更改,而是提供了指向imx219驱动程序文件和imx219设备树dtsi的下载链接。

imx219驱动与设备树代码.rar

使用以上文件覆盖以下目录中的imx219.c和imx219_mode_tbls.h文件:

Linux_for_Tegra/sources/kernel/kernel-4.4/drivers/media/i2c

现在重建内核,它应该具有正确的驱动程序。

4,用户区测试

一切构建完成后,刻录到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,应该重新构建它们。

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值