【瑞芯微RV1103B】sensor驱动和摄像头开发记录

一、前言

开发使用的摄像头为sc132gs,板级编号18。

二、开发记录

1.Sensor驱动

1).驱动编译

瑞芯微sdk包提供了非常多的摄像头驱动,可支持的摄像头驱动在/rockchip/sysdrv/source/kernel/drivers/media/i2c/目录下查看。可以在该目录下找到我们需要的sc132gs.c文件。

而sdk包中已经提供且支持的摄像头有"imx415 os04a10 sc4336 sc3336 sc530ai gc2053 sc200ai sc401ai sc450ai sc4336p sc850sl gc4653 gc4023"等,正常编译后不会生成我们需要的sc132gs.ko,所以要先做一下内核配置。

cd rockchip/sysdrv/source/kernel

make menuconfig

找到sc132gs,=m,编译为模块。

问题:瑞芯微sdk的内核配置生成的.config并未使用,所以按如上配置是无效的。找到实际使用的config文件,添加CONFIG_VIDEO_SC132GS=m即可。瑞芯微内核有多个config文件共同作用,其中关于摄像头驱动部分的配置在如下config文件中:

sysdrv/source/kernel/arch/arm/configs/rv1103b-evb.config

重新编译后会生成sc132gs.ko。

2).加载驱动

烧录到板子上,加载内核。(可能需要指定sc132gs.ko的实际路径)

# insmod ./oem/usr/ko/sc132gs.ko
sc132gs 4-0030-9:driver version:00.01.07
sc132gs 4-0030-9:supply avdd not found, using dummy regulator
sc132gs 4-0030-9: supply dovdd not found, using dummy regulator
sc132gs 4-0030-9:supply dvdd not found, using dummy regulator
sc132gs;4-0030-9:could not get default pinstate
sc132gs4-0030-9:could not get sleep pinstate
s4-0030-9:Unexpected sensor id(0000),ret(-5)

根据信息,加载内核没有获取到sensor id。以及设备树中找不到配置avdd,dovdd,dvdd,default-pinctl,sleep-pinctl。

3).加载驱动时的初始化代码

 以上信息可以在sc132gs.c文件中找到对应的输出代码。执行insmod sc132gs.ko时会执行一部分初始化函数。

//初始化,把sensor add到i2c上
static int __init sensor_mod_init(void)
{
    return i2c_add_driver(&sc132gs_i2c_driver);
}

//注册函数,其中sc132gs_probe函数负责了初始化的内容。加载驱动时报的信息也在这个函数中。
static struct i2c_driver sc132gs_i2c_driver = {
    .driver = {
        .name = SC132GS_NAME,
        .pm = &sc132gs_pm_ops,
        .of_match_table = of_match_ptr(sc132gs_of_match),
    },
    .probe		= &sc132gs_probe,
    .remove		= &sc132gs_remove,
    .id_table	= sc132gs_match_id,
};

可以查看sc132gs_probe函数,最后通过i2c查找sensor id,返回失败。说明i2c没有通。

 2.设备树

1).设备树中添加sensor

设备树文件: /rockchip/sysdrv/source/kernel/arch/arm/boot/dts/rv1103b-evb1-v10.dts

其中sysdrv/source/kernel/arch/arm/boot/dts/rv1103b-evb-cam.dtsi是sensor相关的设备树头文件,所以修改rv1103b-evb-cam.dtsi文件即可。设备树中已经支持了imx415 os04a10......等之前提到过的sensor,所以我们按照原有的设备树添加自己的sensor即可。

&csi2_dphy0 {
        status = "okay";

        ports {
                #address-cells = <1>;
                #size-cells = <0>;

                port@0 {
                        reg = <0>;
                        #address-cells = <1>;
                        #size-cells = <0>;
//... (其他支持的sensor)
//添加sc132gs
                        csi_dphy_input12: endpoint@c {
                                reg = <0x0c>;
                                remote-endpoint = <&sc132gs_out>;
                                data-lanes = <1 2>;
                        };
                };

                port@1 {
                        reg = <1>;
                        #address-cells = <1>;
                        #size-cells = <0>;

                        csi_dphy_output: endpoint@0 {
                                reg = <0>;
                                remote-endpoint = <&mipi_csi2_input>;
                        };
                };
        };
};


&i2c4 {
        status = "okay";
        clock-frequency = <400000>;
        pinctrl-names = "default";
        pinctrl-0 = <&i2c4m1_xfer_pins>;

//添加sc132gs
        sc132gs: sc132gs@30 {
                compatible = "smartsens,sc132gs";
                status = "okay";
                reg = <0x30>;
                clocks = <&cru CLK_MIPI0_OUT2IO>;
                clock-names = "xvclk";
                reset-gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>;
                pwdn-gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>;
                pinctrl-names = "rockchip,camera_default", "rockchip,camera_sleep";
                pinctrl-0 = <&cam_clk0_pins>;// pinctl setting
                pinctrl-1 = <&cam_clk0_sleep_pins>;
                rockchip,camera-module-index = <0>;
                rockchip,camera-module-facing = "back";
                rockchip,camera-module-name = "default";
                rockchip,camera-module-lens-name = "default";
                port {
                        sc132gs_out: endpoint {
                                remote-endpoint = <&csi_dphy_input1>;
                                data-lanes = <1 2>;
                        };
                };
        };
};
 2).部分字段参数解读
1. I2C通信线SDA,SCL

clock-frequency = <400000>;

pinctrl-names = "default";

pinctrl-0 = <&i2c4m1_xfer_pins>;

可以查看i2c4m1_xfer_pins定义,在in rv1103b-pinctrl.dtsi文件中

i2c4m1_xfer_pins: i2c4m1-xfer-pins {
        rockchip,pins =
        /* i2c4_scl_m1 */
        <1 RK_PB7 2 &pcfg_pull_none_smt>,
        /* i2c4_sda_m1 */
        <1 RK_PC0 2 &pcfg_pull_none_smt>;
};

 确认RK_PB7和RK_PC0两个引脚是不是SCL,SDA。(硬件发开提供GPIO引脚编号)

2. Sensor在I2C上的通信地址

sc132gs@30 {  
   compatible = "smartsens,sc132gs";  
   status = "okay";  
   reg = <0x30>;
}

sc132gs@30和reg=<0x30>,即sc132gs在i2c上的通信地址。该地址需要查看sc132gs硬件手册,或者在sc132gs的驱动中查看。

可以查到地址为0x60。但根据rv1103b提供的文档中描述"8bits 中的最低位 (LSB) 表示 R/W,高 7bits 即是我们需要的 i2c slave id。",所以根据转换,得到地址为0x30。

3. 时钟频率24MHz

clocks = <&cru CLK_MIPI0_OUT2IO>;
clock-names = "xvclk";

cat /sys/kernel/debug/clk/clk_summary | grep -E "mipi0"可以查看CLK_MIPI0_OUT2I0的频率(24000000)

其次在驱动初始化中power on时会调用ret = clk_set_rate(sc132gs->xvclk, SC132GS_XVCLK_FREQ)设置24MHz。

4. gpio & pinctr

reset-gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>;
pwdn-gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>;
pinctrl-names = "rockchip,camera_default", "rockchip,camera_sleep";
pinctrl-0 = <&cam_clk0_pins>;// pinctl setting
pinctrl-1 = <&cam_clk0_sleep_pins>;

 

根据硬件提供的引脚编号,得到reset引脚GPIO1_B6_D,pwdn引脚GPIO1_C1_U。

根据驱动初始化代码,需要获取pinctr中的default和sleep。可以写也可不写,只是加载驱动时会提示not find。如果要写,以下这两个名字要去看sc132gs.c初始化中查找defult和sleep时的匹配字段,要一致。

pinctrl-names = "rockchip,camera_default", "rockchip,camera_sleep";

3.点亮Sensor

1).检查snesor与i2c是否通信

如果insmod sc132gs.ko可以获取Sensor id,或者执行i2cdetect -y 4,如果通信显示如下:(显示UU表示驱动被内核占用,属于正常)

# i2cdetect -y 4
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: 30 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

 表明Sensor和i2c已经连通。

很可惜,我到这一步时并没有点亮。在设备树中已经排除了通信地址不对,时钟频率不对等问题,还有一个可能,就是Sensor未供电。硬件同事帮忙分析,供电三个信号由一个GPIO引脚控制,需要把这个GPIO引脚拉高后才可以供电。引脚号GPIO2_A1。

2).拉GPIO引脚

计算引脚号:GPIO2_A1

# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 0-31, parent: platform/20520000.gpio, gpio0:
 gpio-3   (                    |vccio_sd            ) out hi
 gpio-4   (                    |vcc3v3-sd           ) out hi ACTIVE LOW

gpiochip1: GPIOs 32-63, parent: platform/20d80000.gpio, gpio1:

gpiochip2: GPIOs 64-95, parent: platform/20840000.gpio, gpio2:
 gpio-65  (                    |sysfs               ) out hi
 gpio-74  (                    |reset               ) out lo ACTIVE LOW
 

GPIO2的范围是64~95,所以GPIO2_A1 = 64 + 1,65 (64是GPIO2_A0)

echo 65 >> /sys/class/gpio/export
echo out >> /sys/class/gpio/gpio65/direction
echo 1 >> /sys/class/gpio/gpio65/value

 设置为输出,值为1。

再执行 i2cdetect -y 4,sensor和i2c已连通。

4.抓图测试

1).编译v4l-utils工具

RV1103B默认没有配置v4l-utils,工具提供指令v4l2-ctl和media-ctl。

修改配置media/cfg/cfg.mk,export CONFIG_LIBV4L=y

2).查看摄像头信息

media-ctl -p -d /dev/media0

3).抓图

查看支持格式:v4l2-ctl -d /dev/video7 --list-formats-ext

/# v4l2-ctl -d /dev/video7 --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture Multiplanar

        [0]: 'UYVY' (UYVY 4:2:2)
                Size: Stepwise 32x32 - 1080x1280 with step 8/8
        [1]: 'NV16' (Y/CbCr 4:2:2)
                Size: Stepwise 32x32 - 1080x1280 with step 8/8
        [2]: 'NV61' (Y/CrCb 4:2:2)
                Size: Stepwise 32x32 - 1080x1280 with step 8/8
        [3]: 'NV21' (Y/CrCb 4:2:0)
                Size: Stepwise 32x32 - 1080x1280 with step 8/8
        [4]: 'NV12' (Y/CbCr 4:2:0)
                Size: Stepwise 32x32 - 1080x1280 with step 8/8
        [5]: 'NM21' (Y/CrCb 4:2:0 (N-C))
                Size: Stepwise 32x32 - 1080x1280 with step 8/8
        [6]: 'NM12' (Y/CbCr 4:2:0 (N-C))
                Size: Stepwise 32x32 - 1080x1280 with step 8/8

选择NV12格式抓图:

v4l2-ctl -d /dev/video7 --set-fmt-video=width=1080,height=1280,pixelformat=NV12 --stream-mmap --stream-to=frame.raw --stream-count=1

可能遇到问题:抓图指令阻塞,数据流没有到达isp,输出不了图片。根据摄像头修改驱动中的参数。

4).预览图片和手动曝光

需要下载工具可支持预览以上几种格式图片。确认分辨率一致。如果图片一片漆黑,是因为默认曝光很低,可以用手电对着镜头抓图试试。

如需要手动曝光,通过指令v4l2-ctl -d /dev/v4l-subdev2 --list-ctrls查看曝光参数。

其中设备不一定是v4l-subdev2,从video0~video14,v4l-subdev0~v4l-subdev4依次查看。

/# v4l2-ctl -d /dev/v4l-subdev2 --list-ctrls

User Controls

                       exposure 0x00980911 (int)    : min=6 max=2116 step=1 default=328 value=500

Image Source Controls

              vertical_blanking 0x009e0901 (int)    : min=842 max=64255 step=1 default=842 value=842
            horizontal_blanking 0x009e0902 (int)    : min=616 max=616 step=1 default=616 value=616 flags=read-only
                  analogue_gain 0x009e0903 (int)    : min=32 max=913 step=1 default=32 value=100

Image Processing Controls

                 link_frequency 0x009f0901 (intmenu): min=0 max=1 default=0 value=0
                     pixel_rate 0x009f0902 (int64)  : min=0 max=90000000 step=1 default=72000000 value=72000000 flags=read-only
                   test_pattern 0x009f0903 (menu)   : min=0 max=4 default=0 value=0

输出类似exposure和anaiogue_gain则是曝光和曝光增益参数。

设置曝光:

v4l2-ctl -d /dev/v4l-subdev2 --set-ctrl exposure=500 

设置曝光增益:

v4l2-ctl -d /dev/v4l-subdev2 --set-ctrl analogue_gain=913

如上两条指令设置时,都会调用sc132gs.c驱动中的sc132gs_set_ctrl函数。

评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值