NVIDIA JETSON 平台的 MIPI-CSI 相机驱动程序开发

由 Tegra 处理器驱动的 Nvidia Jetson 平台已经在边缘分析市场中占据了一席之地,尤其是在视频分析、机器视觉等领域。 凭借 MIPI-CSI、USB、千兆以太网等广泛的接口,可以通过许多不同的接口获取视频数据。其中,CSI 接口仍然是机器视觉应用的首选接口。

在这篇博客中,我们将详细讨论 Jetson Tegra 平台中的相机接口和数据流以及 MIPI CSI 驱动程序的典型配置和设置。具体来说,我们将考虑 Jetson Nano 和 Onsemi OV5693 相机。

Jetson 相机子系统

尽管 Tegra TX1、TX2、Xavier 和 Nano 平台之间存在显着的架构差异,但相机硬件子系统或多或少保持不变。下面捕获了相同的高级设计。

NVIDIA JETSON 平台的 MIPI-CSI 相机驱动程序开发_第1张图片

Nvidia Tegra 相机子系统

正如所见,主要组件及其功能是:

  • CSI Unit: MIPI-CSI兼容输入子系统,负责从摄像头获取数据,组织像素格式并将其发送到VI单元。有 6 个像素解析器 (PP) 单元,每个单元都可以接受来自单个 2 车道相机的输入。除了这个 6 摄像头模型之外,还可以重新配置输入,以便将 3 个单声道或立体声 4 通道摄像头连接到 PPA、CSI1_PPA 和 CSI2_PPA 对。
  • VI:视频输入单元通过 24 位总线接收来自 CSI 单元的数据,数据的位置由输入格式决定。然后可以将该数据路由到以下任何一个或两个相关方。VI 还具有一个带有 2 个通道的 Host 1x 接口——一个用于控制对相机的 I2C 访问,另一个用于 VI 寄存器编程。
  • 内存:写入系统内存以供应用程序进一步使用。
  • 图像信号处理器 ISP A:用于预处理输入数据并将其转换/打包为不同的格式。ISP A 还可以从内存中获取数据。
  • 图像信号处理器 ISP B:用于预处理输入数据并将其转换/打包为不同的格式。ISP A 还可以从内存中获取数据。

VI Unit 提供了一种称为 VI 同步点 (syncpts) 的硬件-软件同步机制,用于等待满足特定条件并增加计数器或希望计数器达到特定值。多个预定义索引可用,每个索引对应于一次功能,例如帧开始、行结束、ISP 处理的完成。例如,软件可以选择等待,直到通过下一个与索引对应的计数器值指示的 VI 接收到一个帧。

借助这些强大的组件,Tegra 相机子系统提供了无缝处理来自不同格式的多个来源的数据的选项。

Linux 4 Tegra 相机驱动程序

了解了硬件子系统后,我们现在将研究 Tegra 相机接口的软件架构。Nvidia 通过其 Linux4Tegra (L4T) 软件支持 Linux 操作系统。相机驱动程序通过 CSI 总线以传感器的本机格式配置和读取来自相机传感器的数据,并可选择将它们转换为不同的格式。

Nvidia 提供两种类型的相机访问路径,可以根据相机和应用程序用例进行选择:

  • 直接 V4L2 接口

主要用于从相机捕获 RAW 数据,这是一条不进行任何处理且数据直接由用户应用程序使用的最小路径。

  • 相机核心库接口

在此模型中,相机数据通过少数 Nvidia 库(例如 Camera Core、libArgus)使用。在这种情况下,可以有效地利用内核中可用的 GPU 对输入数据进行各种数据处理。

在任何一种情况下,应用程序都可以是 Gstreamer 插件或自定义插件。

Jetson OV5693 相机

为了深入了解,让我们考虑默认随 Tegra TX1 和 TX2 载板一起提供的 5MP(2592 x 1944,拜耳传感器)Omnivision CSI 摄像头模块 OV5693。高级软件架构如下:

NVIDIA JETSON 平台的 MIPI-CSI 相机驱动程序开发_第2张图片

L4T 相机驱动架构

OV5693 摄像头通过 TCA9548 I2C 扩展芯片连接到 I2C 总线 0x06(默认\I2C 地址为 0x36)。这可以通过在 SID 引脚上添加一个上拉电阻来更改为 0x40。

OV5693 驱动程序使用 I2C 总线驱动程序触发,并将自身注册到 Tegra V4L2 相机框架。这反过来又会暴露 /dev/videoX 设备,应用程序可以使用该设备来消费数据。

要启动 OV5693 驱动程序,必须处理以下内容,并在下一节中进一步说明:

  • 设备树中的相应节点
  • V4L2 兼容传感器驱动程序

在下一节中,我们将看到如何为 OV5693 摄像头设置设备树。

Tegra 相机的设备树更改

该  tegra194相机-e3333-a00.dtsi文件位于/硬件/ NVIDIA /平台/ t19x /普通/内核DTS / t19x常见模块/文件夹。

Tegra相机平台:

tegra-camera-platform 由一个或多个模块组成,这些模块定义了连接到 Tegra SoC 的相机/传感器的基本信息。虽然顶部的公共部分包含有关所有连接的综合信息,但每个模块子部分都单独定义了它们。在这种情况下,单个 OV5693 摄像头通过两个 MIPI 通道连接。

tegra-camera-platform {
    compatible = "nvidia, tegra-camera-platform";
    num_csi_lanes = <2>;        //Number of lanes
    max_lane_speed = <1500000>; //Maximum lane speed
    min_bits_per_pixel = <12>;  //bits per pixel
    vi_peak_byte_per_pixel = <2>;   //byte per pixel
    vi_bw_margin_pct = <25>;    //Don't care
    max_pixel_rate = <160000>;  //Don't care
    isp_peak_byte_per_pixel = <5>;//Don't care
    isp_bw_margin_pct = <25>;   //Don't care

    modules {
        module0 { //OV5693 basic details
            badge = "ov5693_right_iicov5693";
            position = "right";
            orientation = "1";
            drivernode0 {
                pcl_id = "v4l2_sensor";
                devname = "ov5693 06-0036";
                proc-device-tree = "/proc/device-tree/i2c@31c0000/tca9548@77/i2c@6/ov5693_a@36"; //Device tree node path
            };
        };
    };
};  

设备树节点

在设备树节点中,必须添加所有相机属性(输出分辨率、FPS、Mipi 时钟等)以确保设备正常运行。

I2c@31c0000 {   //I2C-6 base address
	tca9548@77 { //I2C expander IC
		i2c@6 {
			ov5693_a@36 {
				compatible = nvidia,ov5693";
				reg = <0x36>; //I2C slave address
				devnode = "video0";//device name

				/* Physical dimensions of sensor */
				physical_w = "3.674";	//physical width of the sensor
				physical_h = "2.738";	//physical height of the sensor

				/* Enable EEPROM support */
				has-eeprom = "1";

				/* Define any required hw resources needed by driver */
				/* ie. clocks, io pins, power sources */
				avdd-reg = "vana";	//Power Regulator 
				iovdd-reg = "vif";	//Power Regulator
				mode0 { // OV5693_MODE_2592X1944
					mclk_khz = "24000";		//MIPI driving clock
					num_lanes = "2";		//Number of lanes
					tegra_sinterface = "serial_a"; //Serial interface
					phy_mode = "DPHY";		//physical connection mode
					discontinuous_clk = "yes";
					dpcm_enable = "false";		//Don't care
					cil_settletime = "0";		//Don't care

					active_w = "2592";		//active width
					active_h = "1944";		//active height
					mode_type = "bayer";		//sensor type
					pixel_phase = "bggr";		//output format
					csi_pixel_bit_depth = "10";	//bit per pixel
					readout_orientation = "0";	//Don't care
					line_length = "2688";		//Total width
					inherent_gain = "1";		//Don't care
					mclk_multiplier = "6.67";	//pix_clk_hz/mclk_khz
					pix_clk_hz = "160000000";	//Pixel clock HTotal*VTotal*FPS 
					gain_factor = "10";		//Don't care
					min_gain_val = "10";/* 1DB*/	//Don't care
					max_gain_val = "160";/* 16DB*/ //Don't care
					step_gain_val = "1";		//Don't care
					default_gain = "10";		//Don't care
					min_hdr_ratio = "1";		//Don't care
					max_hdr_ratio = "1";		//Don't care
					framerate_factor = "1000000";	//Don't care
					min_framerate = "1816577";	//Don't care
					max_framerate = "30000000";
					step_framerate = "1";
					default_framerate = "30000000";
					exposure_factor = "1000000";	//Don't care
					min_exp_time = "34";		//Don't care
					max_exp_time = "550385";	//Don't care
					step_exp_time = "1";		//Don't care
					default_exp_time = "33334";	//Don't care
					embedded_metadata_height = "0";//Don't care
			};	
			};
		};
	}; 
};

在本例中,像素时钟计算如下:

pix_clk_hz = HTotal*VTotal*FPS

OV5693:- 2592×1944@30fps

2592×1944 的总高度和总宽度为 2688×1984

pix_clk_hz = 2688 x 1984 x 30 = 159989760

pix_clk_hz 是 ~160000000

而 mclk 乘数是

mclk_multiplier = pix_clk_hz / mclk_khz
mclk_multiplier = 160000000 / 24000000 = 6.66

DTS绑定

如前所述,相机数据流如下:

传感器输出 CSI输入 CSI输出 VI输入
ov5693_ov5693_out0 ov5693_csi_in0 ov5693_csi_out0 ov5693_vi_in0

硬件 – 设备树节点数据流映射

内部端口之间的绑定是通过使用以下设置完成的。

ports {
	#address-cells = <1>;
	#size-cells = <0>;
port@0 {
	reg = <0>;
	ov5693_ov5693_out0: endpoint {
		port-index = <0>;
		bus-width = <2>;
		remote-endpoint = <&ov5693_csi_in0>;
	};
};
};

nvcsi@15a00000 {
	num-channels = <1>;
	#address-cells = <1>;
	#size-cells = <0>;
	status = "okay";
	channel@0 {
		reg = <0>;
		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				ov5693_csi_in0: endpoint@0 {
					port-index = <0>;
					bus-width = <2>;
					remote-endpoint = <&ov5693_ov5693_out0>;
					};
				};
			port@1 {
				reg = <1>;
				ov5693_csi_out0: endpoint@1 {
					remote-endpoint = <&ov5693_vi_in0>;
					};
				};
			};
		};
	};
		
			
host1x {
	vi@15c10000 {
		num-channels = <1>;
		ports {
			#address-cells = <1>;
			#size-cells = <0>;
			port@0 {
				reg = <0>;
				ov5693_vi_in0: endpoint {
				port-index = <0>;
				bus-width = <2>;
				remote-endpoint = <&ov5693_csi_out0>;
				};
			};
		};
	};

驱动程序通过 Host1x DMA 引擎模块从 VI 输出中获取数据。

覆盖

L4T 采用 DTB 覆盖机制来启用/禁用驱动程序。ov5693 驱动程序可以通过将其状态字段设置为“okay”在 DTS 中启用。

fragment-ov5693@0 {
    ids = "2180-*";
    override@0 {
        target = <&ov5693_cam0>;
        _overlay_ {
            status = "okay";
        };
    };

};

在启动过程中,如果检测到正确的相机模块,则添加到设备树节点的覆盖层以及进一步的驱动程序和设备注册由相机驱动程序 (ov5693.c) 完成,如下一篇博客所述。

关于 Embien: Embien 是领先的产品工程服务,在 Nvidia Tegra 和 Jetson 平台上提供专业知识。我们一直在通过不同接口将各种类型的相机与 Nvidia 平台连接起来,并通过 libargus 框架以及定制的 Gstreamer 插件和应用程序启用它们。我们的客户包括国防、航空电子、工业自动化、医疗、汽车和半导体领域的财富 500 强公司。

你可能感兴趣的:(jetsonNano,深度学习,神经网络,人工智能,机器学习,cnn)