rv1126移植摄像头模组

rv1126通用性移植摄像头模组讲解,使用当前方式移植过gc2053、gc2093、imx415、sc8238、imx258等摄像头模组;

一、硬件接口

sc8238接口:
在这里插入图片描述
imx258接口:
在这里插入图片描述

整个摄像头模组连接到soc是靠iic和mipi接口,iic接口来注册驱动驱动、mipi接口来取图片数据;
如在当前首次注册驱动时报错,则去查找iic接口方面问题,在取图的时候出错则去查找mipi接口配置方面的问题。

二、软件调用

1、dts配置

(1)dts配置先查看数据手册sensor在工作时的时序要求,然后在查看硬件配置,看某些硬件是否是外部拉高。
(2)rv1126有两种dts mipi链路:
链路1(直接接到isp上):sensor --》 phy --》rkisp_vir
链路2(直接接到cif上):sensor --》 phy --》mipi-csi --》rkcif --》 rkisp_vir
在1126上如果要取raw数据的话建议是链接到cif上,当可正常取raw数据之后需要取nv12数据时链路到isp上。
例如下面使用的是链路1方式配置的dts

&i2c1 {
	status = "okay";
	imx258: imx258@1a {
		status = "okay";
		compatible = "sony,imx258";
		reg = <0x1a>;
		clocks = <&cru CLK_MIPICSI_OUT>;  //MIPI接口只有这一个
		clock-names = "xvclk";
		power-domains = <&power RV1126_PD_VI>;
		pinctrl-names = "rockchip,camera_default";
		pinctrl-0 = <&mipicsi_clk1>;   //声明时钟引脚 MIPI_CSI_CLK1
		
		avdd-supply = <&vcc_avdd>;
		dovdd-supply = <&vcc_dovdd>;
		dvdd-supply = <&vcc_dvdd>;
	
		//pwdn-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_LOW>;    
		reset-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_LOW>;  //复位,默认拉高
		rockchip,camera-module-index = <1>;
		rockchip,camera-module-facing = "front";
		//指定iq 例如:imx258_GD110_IR120-4MP.xml
        rockchip,camera-module-name = "GD110";    
        rockchip,camera-module-lens-name = "IR120-4MP";  
		
		port {
			ucam_out5: endpoint {
				remote-endpoint = <&csi_dphy1_input>;
				data-lanes = <1 2 3 4>;
			};
		};
	};
};
//物理层
&csi_dphy0 {
	status = "disabled";
	ports {
		port@0 {
			mipi_in_ucam0: endpoint@1 {
				//remote-endpoint;
				remote-endpoint = <&ucam_out0>;
				data-lanes = <1 2 3 4>;
			};
		};
		port@1 {
			csidphy0_out: endpoint@0 {
				// remote-endpoint;
				remote-endpoint = <&isp_in>;
				data-lanes = <1 2 3 4>;
			};
		};
	};
};

&csi_dphy1 {
	status = "okay";
	ports {
		port@0 {
			csi_dphy1_input: endpoint@1 {
				remote-endpoint = <&ucam_out5>;
				data-lanes = <1 2 3 4>;
			};
		};
		port@1 {
			csi_dphy1_output: endpoint@0 {
				//remote-endpoint = <&isp_virt1_in>;
				remote-endpoint = <&isp_in>;
				data-lanes = <1 2 3 4>;
			};
		};
	};
};
//kernel
&mipi_csi2 {
	status = "disabled";
	ports {
		port@0 {
			mipi_csi2_input: endpoint@1 {
				 remote-endpoint = <&csi_dphy1_output>;
				//remote-endpoint;
				data-lanes = <1 2 3 4>;
			};
		};

		port@1 {
			mipi_csi2_output: endpoint@0 {
				 remote-endpoint = <&cif_mipi_in>;
				//remote-endpoint;
				data-lanes = <1 2 3 4>;
			};
		};
	};
};

//LVDS接口
&rkcif_mipi_lvds {
	status = "disabled";
	port {
		cif_mipi_in: endpoint {
			// remote-endpoint = <&mipi_csi2_output>;
			/delete-property/ remote-endpoint;
			data-lanes = <1 2 3 4>;
		};
	};
};

&rkcif_mipi_lvds_sditf {
	status = "disabled";

	port {
		cif_sditf: endpoint {
			// remote-endpoint = <&isp_virt1_in>;
			/delete-property/ remote-endpoint;
			data-lanes = <1 2 3 4>;
		};
	};
};

&rkisp_vir0 {
	status = "okay";
	ports {
		port@0 {
			isp_in: endpoint@0 {
				//  remote-endpoint;
				//remote-endpoint = <&csidphy0_out>;
				remote-endpoint = <&csi_dphy1_output>;
			};
		};
	};
};

&rkisp_vir1 {
	status = "disabled";
	ports {
		port@0 {
			isp_virt1_in: endpoint@0 {
				remote-endpoint = <&csi_dphy1_output>;
				//remote-endpoint;
			};
		};
	};
};

&rkispp_vir0 {
	status = "okay";
};

&rkispp {
	status = "okay";
	/* the max input w h and fps of mulit sensor */
	max-input = <4208 3120 30>;
};

2、驱动注册

代码路径:/kernel/drivers/media/i2c

(1)在代码路径中添加自己的sensor驱动

在这里插入图片描述

(2)修改代码路径中的Makefile

在Makefile中添加imx258配置

obj-$(CONFIG_VIDEO_IMX258)      += imx258.o

(3)修改代码路径中的Kconfig

在Kconfig中添加imx258配置

config VIDEO_IMX258
        tristate "Sony IMX258 sensor support"
        depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
        depends on MEDIA_CAMERA_SUPPORT
        ---help---
          This is a Video4Linux2 sensor driver for the Sony
          IMX258 camera.

          To compile this driver as a module, choose M here: the
          module will be called imx258.

(4)在kernel中添加imx258驱动

操作目录:rv1126_SDK/kernel
make ARCH=arm menuconfig
在这里插入图片描述
进入可视化配置界面
在这里插入图片描述
点击键盘上的 " / "按键,会跳出一个搜索框
在这里插入图片描述
输入 imx258 回车
在这里插入图片描述
选择1,可看到这个就是前面在Kconfig中写入的配置名字,把【Sony IMX258 sensor support】配置选中,标为*号,即可保存退出。
在这里插入图片描述
退出到kernel目录之后 ,进行配置文件同步

make ARCH=arm savedefconfig    //保存当前配置,生产配置文件
cp defconfig arch/arm/configs/rv1126_defconfig   //进行配置同步

(5)保存iq文件

操作目录:rv1126_SDK/buildroot/output/rockchip_rv1126_rv1109/target/etc/iqfiles
把供应商提供的iq文件或者自己修改适合当前sensor分辨率的iq文件拷贝到rv1126_SDK/buildroot/output/rockchip_rv1126_rv1109/target/etc/iqfiles目录
在这里插入图片描述

3、取raw数据

(1)进行链路激活

查找节点:
sensor的节点为 rkisp_mainpath 对应的 video 节点,video 节点名称可能会变,但是
rkisp_mainpath 名称不会变,使用 media-ctl 指令可以找到具体的 video 节点。

media-ctl -p -d /dev/media

内容过多,只展示部分内容,rkisp_mainpath 先找到这个节点,可以看到这个节点的状态不是
enabled

pad2: Source
[fmt:YUYV8_2X8/1920x1080 field:none
crop.bounds:(0,0)/1920x1080
crop:(0,0)/1920x1080]
-> "rkisp-bridge-ispp":0 [ENABLED]
-> "rkisp_mainpath":0 [] # 找到它
-> "rkisp_selfpath":0 [ENABLED]
pad3: Source
-> "rkisp-statistics":0 [ENABLED]
-> "rkisp-mipi-luma":0 [ENABLED]

然后找到 rkisp_mainpath 对应的video节点

- entity 13: rkisp-bridge-ispp (1 pad, 1 link)
type V4L2 subdev subtype Unknown flags 0
pad0: Sink
<- "rkisp-isp-subdev":2 [ENABLED]
- entity 17: rkisp_mainpath (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video5 # 对应video5 节点
pad0: Sink
<- "rkisp-isp-subdev":2 []
- entity 23: rkisp_selfpath (1 pad, 1 link)
type Node subtype V4L flags 0
device node name /dev/video6
pad0: Sink
<- "rkisp-isp-subdev":2 [ENABLED]

然后激活 rkisp_mainpath 链路

media-ctl -d /dev/media1 -l '"rkisp-isp-subdev":2->"rkisp-bridge-ispp":0[0]'
media-ctl -d /dev/media1 -l '"rkisp-isp-subdev":2->"rkisp_mainpath":0[1]'

注:如果使用的是cif链路方式,则可以不需要进行链路激活,直接使用v4l2抓取图像就行;建议使用cif链路方式来测试raw数据。

(2)使用v4l2抓取图像

v4l2-ctl -d /dev/video5 --set-fmt-video=width=4208,height=3120,pixelformat=RG10 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cif2.out --stream-skip=2 --stream-poll

(3)查看图像

将 raw 添加 pgm 的文件头,就可以将其转成可以在 ubuntu 直接查看的 pgm 图像。可以根据如下操作生成文件头

cat > /tmp/cif2.pgm << EOF
P5
4280 3120
65535
EOF
---------------------------------------------------------------------------------------1为固定标识
行 2 为分辨率,与抓取的图像分辨率一致
行 3 标识深度,6553516bit ,如果是 8bit 则为 255

然后将数据追加到 cif2.pgm

cat /tmp/cif2.out >> /tmp/cif2.pgm

4、取nv12数据

取nv12使用可以使用rv1126自带的rkmedia方式
因为在摄像头刚刚启动的时候可能开始几帧数据会过暗或者过亮,所以我们取13帧数据

rkmedia_vi_get_frame_test  -a /etc/iqfiles --width 4208 --height 3120 -o /usr/4208p.nv12 -c 13

去除前面12帧,保留第13帧数据

dd if=4208p.nv12 of=3120p.nv12 bs=19693440 skip=12

在使用ffmpeg把nv12格式数据转换为jpg格式图片

ffmpeg -y -f rawvideo -pix_fmt nv12 -ss 00:01 -r 1 -s 4208x3120 -i 4208p.nv12  1.jpg

注:去除前面12帧数据的方式也可以在rkmedia_vi_get_frame_test代码中修改。

 if (save_file) {
	    if(frame_id == 12){
     		fwrite(RK_MPI_MB_GetPtr(mb), 1, RK_MPI_MB_GetSize(mb), save_file);
      		printf("#Save frame-%d to %s\n", frame_id++, save_path);
    	    }
	    else
	    frame_id++;
    }

rkmedia_vi_get_frame_test.c修改参考dome:
https://download.csdn.net/download/qq_46030455/89603967

三、可能存在bug

1、驱动无法正常注册

(1)对比原理图,查找供电是否正常。

(2)查看数据手册,iic地址是否填写对。

(3)在驱动的的读写sensor的地方加入while(1),再量下iic各个管脚的波形,看波形是否正常,如果那个引脚不正常就分析那个管脚。查看是否被复用。
在这里插入图片描述

(4)无法获取模块信息:could not get module information!

[root@RV1126_RV1109:/]# dmesg |grep imx258
[    0.945166] imx258 1-0034: driver version: 00.01.06
[    0.945206] imx258_probe_11111111111111
[    0.945231] imx258 1-0034: could not get module information!
[    0.945411] imx258: probe of 1-0034 failed with error -22

分析imx258_probe()函数,查看返回值;看看是否在dts中漏掉某个配置,例如iq指向、各个引脚定义等
在这里插入图片描述

2、无法正常取raw数据 ,取raw数据时候超时

[root@RV1126_RV1109:/]# v4l2-ctl -d /dev/video0 --set-fmt-video=width=4208,heigh
t=3120,pixelformat=RG10 --stream-mmap=4 --stream-count=1 --stream-to=/tmp/cap.ra
w --stream-skip=2 --stream-poll
select timeout
[root@RV1126_RV1109:/]# ls -l /tmp/cap.raw
-rw-r--r-- 1 root root 0 Aug  4 09:44 /tmp/cap.raw
[root@RV1126_RV1109:/]#

解决方案:
(1)先查看sensor输出数据流此时使用示波器测量mipi_clk_p/n、mipi_data_p/n的波形、确认sensor是否真正发送数据出来;
(2)在链路代码中添加各种打印,保证链路都有正确连接上;

kernel/drivers/media/platform/rockchip/cif$ grep -nr ".start_streaming"
capture.c:6984:static int rkcif_start_streaming(struct vb2_queue *queue, unsigned int count)
capture.c:6999: .start_streaming = rkcif_start_streaming,
cif-tools.c:547:rkcif_tools_vb2_start_streaming(struct vb2_queue *queue,
cif-tools.c:565:        .start_streaming = rkcif_tools_vb2_start_streaming,
cif-scale.c:873:rkcif_scale_vb2_start_streaming(struct vb2_queue *queue,
cif-scale.c:897:        .start_streaming = rkcif_scale_vb2_start_streaming,
cif-luma.c:182:rkcif_luma_vb2_start_streaming(struct vb2_queue *queue,
cif-luma.c:204: .start_streaming = rkcif_luma_vb2_start_streaming,

kernel/drivers/phy/rockchip$ grep -nr "stream"
phy-rockchip-csi2-dphy.c:549:static int csi2_dphy_s_stream(struct v4l2_subdev *sd, int on)
phy-rockchip-csi2-dphy.c:761:   .s_stream = csi2_dphy_s_stream,

kernel/drivers/media/i2c$ grep -nr "imx215_s_stream"
imx215.c:2448:static int imx215_s_stream(struct v4l2_subdev *sd, int on)
imx215.c:2781:  .s_stream = imx215_s_stream,

在这里插入图片描述
(3)查看硬件接口是否有正常添加阻抗,如果是转接板子,查看是否排线过长或者板子为加阻抗;(注:我有多个项目都是因为转接板子线过长或者为加阻抗而堵塞)。

3、使用rkmedia取流时候堵塞不动

(1)使用rkmedia取流时候一直堵塞不动,切换到cif链路去取raw数据,保证当前链路是对的。
(2)dts配置不对,最后的isp道路不对;rkisp_vir0 和rkisp_vir1开启错误,建议对着当前上面的dts配置修改。
在这里插入图片描述

4、无法正常调用iq

(1)iq文件格式不对;
在这里插入图片描述
(2)iq文件像素不对;
在这里插入图片描述
(3)找不到iq文件
在这里插入图片描述
注:建议iq文件找原厂提供,或者找主控厂家提供适配的iq文件;后期在自行进行调优,可节省很大开发时间

5、图像偏色、曝光等问题

图像偏色:只能进行二次调试iq文件;
图像曝光:可以使用rkisp2x_tuner工具开启自动曝光或者手动曝光并且在驱动中调节曝光率;驱动代码不做详细讲解

gc2093_probe()  //对应dts寻找模块
 --> gc2093_initialize_controls()  //初始化
-->gc2093_ctrl_ops()  //设备操作函数
-->gc2053_set_ctrl()  //设置sensor的所有属性
-->V4L2_CID_EXPOSURE  //曝光时间
-->V4L2_CID_ANALOGUE_GAIN  //曝光增益
-->4L2_CID_VBLANK    // /* The exposure goes up and reduces the frame rate, no need to write vb */
-->V4L2_CID_HFLIP //成像翻转   0号寄存器     
-->V4L2_CID_VFLIP  //成像翻转   1号寄存器
注:翻转是10寄存器组合决定 四种状态

黑白成像:如果使用的是gc2053、gc2093 默认是黑白图像;修改iq中的【COLOR_AS_GREY】 配置 0 为彩色, 1 则为黑白;
注:如果iq文件不适配可能会存在多屏分层、蓝白条纹、黑屏等情况;
在这里插入图片描述

6、 ispserver 问题

如果需要开启ispserver服务,需要设置export HDR_MODE=0;如果不进行设置的话开启ispserver服务会存在曝光设置失败问题,并且再驱动中强制写入曝光参数的话也只是第一帧有效,后面帧数无效。

留言:创作不易,如果哪里写的不对,请及时指出;求赞!!!
  • 15
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值