SENSOR 使用参考


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 07/10/2025

    1. 概述

    本文以 PCUPID 系列芯片的 Comake_Pi_D1 开发板为例,为图像传感器(sensor)的使用提供参考。使用时需了解一些基础技术知识,包括 MIPI 协议里的 CSI 接口、CCI 接口,以及sensor的规格等。

    为确保图像sensor正常输出图像,请按以下步骤操作:

    1. 确认sensor与 SOC 芯片的硬件连接是否正确;
    2. 明确 SOC 芯片上哪些引脚可用于sensor的 MIPI 接口;
    3. 在设备树(dts)中正确配置 CSI 和 sensor_if 接口参数;
    4. 确认需要加载的模块 ko 文件;
    5. 确认需要加载的sensor驱动 ko 文件;
    6. 正确使用 MI 模块的 API 接口。

    2. 关键字说明

    • sensor : 即传感器。在嵌入式音视频开发中,单独提及 “sensor” 时,特指 CMOS 图像传感器,其功能为采集图像数据。

    • sensor pad : 指sensor硬件对应的 SoC 芯片引脚。

    • mipi : 即 MIPI 协议簇,涵盖触摸、图像采集、图像显示等协议。在传感器使用场景中,“mipi” 特指 CSI-2 协议 / 接口(一种图像采集协议);在面板(panel)或显示(disp)场景中,“mipi” 特指 DSI 协议 / 接口(一种图像显示协议)。

    • lane : 对实际物理接线的抽象概念,称为 “通道”,例如时钟通道(时钟 lane)、数据通道(数据 lane)。一个 lane 对应的物理接线可为 1 根或多根,以 MIPI 协议簇中 CSI-2 协议的物理层 D-PHY 为例,其单个数据 lane 包含 “data-” 和 “data+” 两根物理线。部分传感器支持多数据 lane,如 GC2053 传感器配备 2 个数据 lane(基于 D-PHY),对应 4 根物理数据线。默认情况下,单独提及 “lane” 时,均指 “数据通道”。

    3. 功能描述

    pcupid系列芯片支持sensor的mipi模式,bt601模式,bt656模式。不同的模式通过dts文件指定,本章以sensor的mipi模式为例,讲解sensor的使用方法。

    sensor 与 SoC 接线说明​

    sensor 与 SoC 之间的接线逻辑主要包含以下两部分:​

    • 基础接线​

      sensor 自身需连接基础引脚,例如 reset(复位)引脚、clk(时钟)输入引脚等,此类引脚 / 接线不属于 MIPI 协议簇范畴。​

    • MIPI 接口接线​

      sensor 配备 MIPI 接口(部分场景下,接口与协议概念可通用,存在术语混用情况),包含以下两类接口:​

      1. CSI 接口:作为 sensor 的数据面接口,用于传输图像数据

      2. CCI 接口:作为 sensor 的控制面接口,用于通过读写寄存器实现对 sensor 工作方式及参数的配置

    说明:SigmaStar 芯片的 CCI 接口基于 I2C 协议实现。

    sensor和soc接线示意图

    SoC 芯片内部 MIPI 协议簇的 CSI-2 接口 RX 接收器,硬件支持 2 条数据通道(data lanes)和 2 条时钟通道(clock lanes),其配置方式如下:

    • 可配置为 “1 条时钟lane + 2 条数据lane”,供单个sensor使用

    • 也可配置为两组 “1 条时钟lane + 1 条数据lane”,同时为两个sensor使用

    具体配置细节请参见芯片数据手册。

    sensor pad通道分配说明

    • snr0 对应 3 个通道(lane),包含 2 个数据通道(data lane)和 1 个时钟通道(clock lane)

    • snr2 对应 2 个通道(lane),包含 1 个数据通道(data lane)和 1 个时钟通道(clock lane)

    mipi rx接口解析图

    SigmaStar的不同芯片支持的mclk频率存在差异,pcupid系列芯片支持的mclk如下

    mclk支持配置时钟类型

    4. 硬件连接介绍

    4.1 soc硬件接口确认

    确认soc芯片哪些引脚和sensor连接

    下面几张图是Comake_Pi_D1板载soc芯片的hw_checklist表的子表“ARMTmux”。对reg_mipi_rx_mode寄存器写不同的值,连接sensor的mipi_rx引脚也将会不同。支持snr0的2lane单独出流,支持snr0的1lane+snr2的1lane同时出流。dts里用snr_sr0_mipi_mode和snr_sr2_mipi_mode配置项对reg_mipi_rx_mode寄存器传值。

    mipi的csi-2_RX引脚

    对reg_sr00_mclk_mode,reg_sr01_mclk_mode寄存器写不同的值,soc对外的sensor mclk引脚也会不同。对reg_sr00_rst_mode,reg_sr01_rst_mode寄存器写不同的值,soc对外的sensor rst引脚也会不同。dts里用snr_sr0_mipi_mclk_mode配置项对reg_sr00_mclk_mode寄存器传值,用snr_sr0_mipi_rst_mode配置项对reg_sr00_rst_mode寄存器传值。

    sensor的mclk引脚和rst引脚

    对reg_sr00_pdn_mode,reg_sr01_pdn_mode寄存器写不同的值,soc对外的sensor pdn引脚也会不同。dts里用snr_sr0_mipi_pdn_mode配置项对reg_sr00_pdn_mode寄存器传值。需要注意的是,有的sensor pdn引脚可以悬空不接,不需要控制。Comake_Pi_D1板子的snr2的pdn引脚就是悬空的,没有接入到soc。

    sensor的pdn引脚

    配置snr0,snr2各自的reg_mipi_rx_mode,reg_mclk_mode,reg_rst_mode,reg_i2c_mode寄存器为不同值时,有不同的用法,下面给出推荐性的使用组合。

    类型 1个sensor用2lane单独出流 两个sensor各自用1lane同时出流(1lane+1lane)
    mipi_rx_mode 设置snr0 mode=1 设置snr0 mode=5且snr2 mode=5
    mclk_mode 设置snr0 mode=2 设置snr0 mode=2且snr2 mode=2
    rst_mode 设置snr0 mode=2 设置snr0 mode=2且snr2 mode=2
    i2c_mode 设置snr0 mode=4 设置snr0 mode=4且snr2 mode=4

    注意:pcupid 最高规格支持2lane(数据lane),可以配置成snr0 2lane 或者拆成 snr0 1lane + snr2 1lane。

    确认snr0和snr2连接了哪两个接线座

    Comake_Pi_D1板子上这两个sensor的pad都连接到接线座上,方便开发者连接sensor。

    snr0连接到J5接线座上,原理图上"OUTP_RX_CH0"和"PAD_OUTP_RX0_CH[0]"是连接的。J5接线座上SSR0_CH1N/P这两个引脚是data0 lane,SSR0_CH2N/P是data1 lane,SSR0_CH0N/P是clk lane。可见它是一个最大支持2个data lane的mipi csi-2 rx接口。

    J5-snr0接线座

    snr2连接到J6接线座上,原理图上"OUTP_RX_CH2"和"PAD_OUTP_RX0_CH[2]"是连接的。J6接线座上SSR0_CH2N/P这两个引脚是data0 lane,SSR0_CH3N/P是clk lane。可见它是一个最大支持1个data lane的mipi csi-2 rx接口。

    J6-snr2接线座

    4.2 sensor接口确认

    确认sensor的接线座

    Comake_Pi_D1板子配套的是gc2053的sensor,它并没有直接焊在板子上,而是做成了一个单独的sensor硬件模块(一个硬件小板子),该sensor模块用排线和Comake_Pi_D1板子连接。

    左侧图片 中间图片 右侧图片

    gc2053_mipi接口板

    查看gc2053的数据手册,它要引出的有三类接线,一类是前面说的“基础接线”,包括RESET和MCLK,一类是“CCI接口线”,包括SBCL和SBDA,一类是“CSI接口线”,包括MDN/P<0>,MDN/P<1>和MCN/P。

    gc2053_block_diagram

    gc2053_mipi接口板的原理图如下,右侧的J8是接线座,用排线一端接J8,一端接Comake_Pi_D1板子的J5或者J6可以出流。可以看见J8接线座,和J5,J6接线座的线序是匹配的。

    gc2053_mipi

    4.3 MIPI 接口线序匹配

    为了方便后续dts的配置,这里总结出mipi的csi接线关系。gc2053_mipi接口板J8接线座和Comake_Pi_D1板子J5,J6接线座,sensor pad的匹配关系

    当J8用排线接J5时,sensor和snr0 pad是接通的。

    J8 J5 snr0 pad
    MIPI_D0N/P(data0 lane) SSR0_CH1N/P PAD_OUTN/P_RX0_CH[1]
    MIPI_D1N/P(data1 lane) SSR0_CH2N/P PAD_OUTN/P_RX0_CH[2]
    clock lane SSR0_CH0N/P PAD_OUTN/P_RX0_CH[0]

    如果把PAD_OUTN/P_RX0_CH[0]简写成CH0,有如下表

    sensor snr0 pad
    data0 lane CH1
    data1 lane CH2
    clock lane CH0

    当J8用排线接J6时,sensor和snr1 pad是接通的,同上步骤,可得到下表

    sensor snr1 pad
    data0 lane CH3
    clock lane CH2

    注意:J5和J6共用了CH2 pad,这对后续的两个sensor同时使用产生了限制,在dts章节讨论它

    5. kernel用法介绍

    5.1 dts 配置

    前面提到sensor和soc芯片之间的三类接线,“基础接线”,“CCI接口线”,“CSI接口线”。需要在dts里做好配置,内核会根据dts的配置,初始化好soc的这三类pad。“基础接线”和“CCI接口线”通过sensorif节点配置,“CSI接口线”通过csi接口配置。dts配置只是决定了初始化哪些snr pad的哪些lane,没有数量限制。Comake_Pi_D1板子通用的配置如下

    初始化snr0的2lane和snr2的1lane:

        csi: csi {
            compatible = "sstar,csi";
            io_phy_addr = <0x1f000000>;
            banks = <0x153C>,<0x153D>,<0x153E>,<0x1538>,<0x153A>,<0x153B>;
            atop_banks = <0x153F>;
            clkgen_banks = <0x1038>;
            interrupts=  <GIC_SPI INT_IRQ_MIPI_CSI2 IRQ_TYPE_LEVEL_HIGH>;
            status = "okay";
            /* Config max lane number */
            csi_sr0_lane_num = <2>;
            csi_sr2_lane_num = <1>;
            /* Config lane selection */
            csi_sr0_lane_select = <0 1 2>;
            csi_sr2_lane_select = <0 1>;
            /* Config lane P/N swap */
            csi_sr0_lane_pn_swap = <0 0 0>;
            csi_sr2_lane_pn_swap = <0 0>;
        };
    
        sensorif: sensorif {
            compatible = "sstar,sensorif";
            status = "okay";
            clocks = <&CLK_sr00_mclk>, <&CLK_sr01_mclk>;
    
            /* Config sensor 0 pad mux */
            snr_sr0_mipi_mode         = <5>;
            snr_sr0_mipi_rst_mode     = <2>;
            snr_sr0_mipi_pdn_mode     = <0>;
            snr_sr0_mipi_mclk_mode    = <2>;
            snr_sr0_rst_gpio          = <73>;
            snr_sr0_pdn_gpio          = <77>;
    
            ...
    
            /* Config sensor 2 pad mux */
            snr_sr2_mipi_mode         = <5>;
            snr_sr2_rst_gpio          = <77>;
            snr_sr2_mipi_pdn_mode     = <0>;
            snr_sr2_mipi_mclk_mode    = <2>;
    
            /* Config mclk 37.125MHz supported */
            snr_sr0_mclk_37p125 = <1>;
            snr_sr2_mclk_37p125 = <1>;
    
            /* Config CCI interface */
            snr0_mipi_i2c = <0>;
            snr2_mipi_i2c = <1>;
        };
    

    csi部分释义如下:

    参数 释义 备注
    interrupts mipi rx csi中断 不需要修改
    clocks mipi rx csi时钟源 不需要修改
    csi_sr0_lane_num 配置snr0 data lane的初始化数量 根据需要初始化,snr0最大只有两个data lane,可选值0,1,2,注意:这里lane_num需要小于等于reg_mipi_mode寄存器指定的lane数量。如果初始化snr0为2lane,实际使用时,也可以只使1lane
    csi_sr0_lane_select 配置csi接口snr0 lane的相对线序 <clk_lane的相对序号 data0_lane的相对序号 data1_lane的相对序号>,相对序号是指clk_lane,data0_lane,data1_lane三者比较各自CH值的大小顺序,CH值最小的相对序号是0,中间的是1,最大的是2。例如当csi_sr0_lane_num=2,结合前面提到的J8-J5-snr0线序表,clk_lane接的是CH0,data0_lane接的是CH1,data1_lane接的是CH2,那么 csi_sr0_lane_select=<0 1 2 >
    csi_sr0_lane_pn_swap 配置snr0的lane极性是否反转 <clk_lane的极性反转标志 data0_lane的极性反转标志 data1_lane的极性反转标志> 反转标志值只有两个,0和1。0表示lane的极性没有反转,N线接N线,P线接P线。1表示lane的极性出现反转,N线接了P线,P线接了N线。这是芯片兼容性设计,防止外部电路设计出错改版,只要改这里的配置就行了。Comake_Pi_D1板子snr0的所有lane和snr2的所有lane极性都没有反转。例如 csi_sr0_lane_pn_swap=<0 0 0>
    csi_sr2_lane_num 配置snr2 data lane的初始化数量 根据需要初始化,snr2最大只有1个data lane,可选值0,1
    csi_sr2_lane_select 配置csi接口snr2 lane的相对线序 同上分析,clk_lane接的是CH2,data0_lane接的是CH3,clk_lane的CH值是2,data0_lane的CH值是3,2比3小,所以clk_lane的相对序号是0,data0_lane的相对序号是1,即 csi_sr2_lane_select=<0 1>
    csi_sr2_lane_pn_swap 配置snr2的lane极性是否反转 同上分析,极性没有反转,例如 csi_sr2_lane_pn_swap=<0 0>

    注意:默认设置snr0_lane_num=2和snr2_lane_num=1。如果只有snr0接sensor,那么sensor可以使用1lane或者使用2lane出流。如果只有snr2接sensor,那么sensor只能用1lane出流。如果srn0和snr2都接了sensor,要注意CH2共线的问题,想要两个sensor都同时出流,两个sensor都只能用1lane出流。

    sensorif部分释义如下:

    参数 释义 备注
    clocks sensor mclk时钟源 需要按照snr0 snr2的顺序配置
    snr_sr0_mipi_mode snr0 mipi的mode,不同mode主要是csi接口pad(引脚)不同 参考hw_checklist的ARMTmux子表
    snr_sr0_mipi_rst_mode snr0用mipi接口时reset引脚的mode,不同mode主要是pad(引脚)差异 参考hw_checklist的ARMTmux子表
    snr_sr0_mipi_pdn_mode snr0用mipi接口时pdn引脚的mode,不同mode主要是pad(引脚)差异 参考hw_checklist的ARMTmux子表
    snr_sr0_mipi_mclk_mode snr0用mipi接口时mclk引脚的mode,不同mode主要是pad(引脚)差异 参考hw_checklist的ARMTmux子表
    snr_sr0_rst_gpio snr0 的reset gpio 引脚index 同时配置rst mode和rst gpio的话优先使用gpio的设定
    snr_sr0_pdn_gpio snr0 的pdn gpio 引脚设置 同时配置pdn mode和pdn gpio的话优先使用gpio的设定
    snr_sr0_mclk_37p125 配置snr0 支持37.125MHz 1-支持37.125MHz
    snr0_mipi_i2c 配置snr0 使用的i2c bus id 需要根据实际使用的i2c bus进行配置

    5.2 padmux配置

    上节所示snr0_mipi_i2c和snr2_mipi_i2c配置指定了使用哪一个i2c bus控制器。i2c控制器对应的引脚要通过padmux指定,在kernel/arch/arm/boot/dts/pcupid-comake-pi-d1-dual-sensor-padmux.dtsi

    / # cat kernel/arch/arm/boot/dts/pcupid-comake-pi-d1-dual-sensor-padmux.dtsi
    ...
    //sensor 0/1 i2c
    <PAD_GPIOB_00            PINMUX_FOR_I2C0_MODE_4           MDRV_PUSE_I2C0_SCL>,
    <PAD_GPIOB_01            PINMUX_FOR_I2C0_MODE_4           MDRV_PUSE_I2C0_SDA>,
    <PAD_GPIOB_04            PINMUX_FOR_I2C1_MODE_4           MDRV_PUSE_I2C1_SCL>,
    <PAD_GPIOB_05            PINMUX_FOR_I2C1_MODE_4           MDRV_PUSE_I2C1_SDA>,
    ...
    

    5.3 project config配置

    在project目录下执行"make menuconfig"命令,然后打开,关闭或修改某些配置项。如果要保存修改后的配置,需执行"make savedefconfig"命令,然后执行"cp defconfig 目标defconfig"命令

    5.3.1 配置打包的sensor驱动ko

    • CONFIG_SENSOR_LIST:填写打包的sensor驱动ko名称列表,不同ko名称之间用空格隔开,该配置项对应make menuconfig看到的"List of sensor ko for image packaging"

    例如某defconfig默认打包imx323.ko, imx307_mipi.ko, gc2053_mipi.ko文件

    /project# make menuconfig
        Sensor  --->
            ...
            (imx323.ko imx307_mipi.ko gc2053_mipi.ko) List of sensor ko for image packaging  --->
            ...
    

    5.3.2 配置sensor加载的驱动ko

    • CONFIG_SENSOR0 / 1 / 2:填写snr接口要加载的驱动ko名称。该配置项对应make menuconfig看到的"Snr0 / 1 / 2 ko"

    • CONFIG_SENSOR0 / 1 / 2_OPT:填写驱动ko要传递的参数chmap。该配置项对应make menuconfig看到的"Parameters for snr0 / 1 / 2 ko"

    参数"chmap"的值,决定初始化不同接口的sensor

    单独初始化snr0接口的sensor      ----> chmap=1
    单独初始化snr2接口的sensor      ----> chmap=4
    同时初始化snr0+snr2接口的sensor ----> chmap=5
    

    例如snr0单独接gc2053型号sensor的配置如下

    /project# make menuconfig
        Sensor  --->
            (common/base_iqfile.bin) IQFILE_BASE_IQ0  --->
            () IQFILE_BASE_IQ1  --->
            () IQFILE_BASE_IQ2  --->
            () IQFILE_BASE_IQ3  --->
            (gc2053/gc2053_api.bin) IQFILE_API_IQ0  --->
            () IQFILE_API_IQ1  --->
            () IQFILE_API_IQ2  --->
            () IQFILE_API_IQ3  --->
            (gc2053_mipi.ko) List of sensor ko for image packaging  --->
            (gc2053_mipi.ko) Snr0 ko  --->
            (chmap=1) Parameters for snr0 ko  --->
            () Snr1 ko  --->
            () Parameters for snr1 ko  --->
            () Snr2 ko  --->
            () Parameters for snr2 ko  --->
        ...
    

    例如snr0接gc2053型号sensor,snr2接ov2710型号sensor的配置如下

    /project# make menuconfig
        Sensor  --->
            (common/base_iqfile.bin) IQFILE_BASE_IQ0  --->
            () IQFILE_BASE_IQ1  --->
            (common/base_iqfile.bin) IQFILE_BASE_IQ2  --->
            () IQFILE_BASE_IQ3  --->
            (gc2053/gc2053_api.bin) IQFILE_API_IQ0  --->
            () IQFILE_API_IQ1  --->
            (ov2701/ov2701_api.bin) IQFILE_API_IQ2  --->
            () IQFILE_API_IQ3  --->
            (gc2053_mipi.ko ov2701_mipi.ko) List of sensor ko for image packaging  --->
            (gc2053_mipi.ko) Snr0 ko  --->
            (chmap=1) Parameters for snr0 ko  --->
            () Snr1 ko  --->
            () Parameters for snr1 ko  --->
            (ov2701_mipi.ko) Snr2 ko  --->
            (chmap=4) Parameters for snr2 ko  --->
        ...
    

    5.3.3 配置IQ文件

    IQ文件是ISP模块依赖的参数配置文件,PCUPID 系列芯片公板的 IQ 文件分为以下两类

    • 驱动层使用的IQ文件:基础固定的iq文件,(bin 类型,下文简称 “iq base bin 文件”)。

    • 应用层使用的IQ文件:按需修改的iq文件,(bin 类型,下文简称 “iq api bin 文件”)。

    IQ文件打包说明:

    • CONFIG_IQFILE_IQ0 / 1 / 2 /3:填写要打包iq base bin文件的“相对目录/文件名称”。相对目录是相对于"project/board/pcupid/iqfile/"的路径,该配置项对应make menuconfig看到的IQFILE_BASE_IQ0 / 1 / 2 / 3

    • CONFIG_IQAPI_IQ0 / 1 / 2 /3:填写要打包iq api bin文件的“相对目录/文件名称”。相对目录是相对于"project/board/pcupid/iqfile/"的路径,该配置项对应make menuconfig看到的IQFILE_API_IQ0 / 1 / 2 / 3

    例如snr0接gc2053型号sensor,两种IQ文件的打包配置如下

    /project# make menuconfig
        Sensor  --->
            (common/base_iqfile.bin) IQFILE_BASE_IQ0  --->
            () IQFILE_BASE_IQ1  --->
            () IQFILE_BASE_IQ2  --->
            () IQFILE_BASE_IQ3  --->
            (gc2053/gc2053_api.bin) IQFILE_API_IQ0  --->
            () IQFILE_API_IQ1  --->
            () IQFILE_API_IQ2  --->
            () IQFILE_API_IQ3  --->
        ...
    

    注意:部分defconfig会默认将所有snr接口 IQ 文件打包至镜像中,此情况对实际sensor的正常使用无影响,可以按需删掉不用的IQ文件

    这两个bin文件的打包操作分别在miservice.mk和customer.mk中执行(脚本读写配置项值时,需删除配置项名称的CONFIG_前缀)

    • iq base bin的打包:CONFIG_IQFILE_IQx指定的iq base bin文件在customer.mk里被拷贝到/config/iqfile/目录下,并命名为iqfile0 / 1 / 2 / 3.bin
    / # cat project/image/packaging/common/miservice.mk
    ...
        if [ "$(IQFILE_IQ0)" != "" ]; then \
            cp -rf $(PROJ_ROOT)/board/$(CHIP)/iqfile/$(IQFILE_IQ0) $(miservice$(RESOURCE))/iqfile/ -vf; \
            cd $(miservice$(RESOURCE))/iqfile; \
            chmod +x $(shell echo $(IQFILE_IQ0) | awk -F'/' '{print $$NF}'); \
            ln -sf $(shell echo $(IQFILE_IQ0) | awk -F'/' '{print $$NF}') iqfile0.bin; cd -; \
        fi;
    ...
    

    注意:mi_common.ko固定加载名称为iqfile0 / 1 / 2 / 3.bin的 iq base bin 文件,打包的文件名不可修改,但打包的目标路径可调整,打包路径修改后,modparam.json文件要同步修改,见下文"IQ文件加载说明"小节。

    • iq api bin的打包:CONFIG_IQAPI_IQx指定的iq api bin文件在customer.mk里被拷贝到/customer/目录下,并且被重命名为iqApiBin0 / 1 / 2 / 3.bin
    / # cat project/image/packaging/common/customer.mk
    ...
        # pack iq api bin
        if [ "$(IQAPI_IQ0)" != "" ]; then \
            cp -rf $(PROJ_ROOT)/board/$(CHIP)/iqfile/$(IQAPI_IQ0) $(customer$(RESOURCE))/iqApiBin0.bin -vf; \
        fi;
    ...
    

    注意:打包的iq base bin文件名和打包的目标路径均可修改,修改后,应用程序要同步修改,见下文"IQ文件加载说明"小节。

    最终打包结果如下

    / # ls -l /config/iqfile/
    total 188
    ...
    -rwxr-xr-x    1 13280    1513         39274 Aug 29  2025 base_iqfile.bin
    lrwxrwxrwx    1 13280    1513            15 Aug 29  2025 iqfile0.bin -> base_iqfile.bin
    ...
    / #
    / # ls -l /customer/
    total 9798
    ...
    -rw-r--r--    1 13280    1513         92124 Aug 29  2025 iqApiBin0.bin
    ...
    

    IQ文件加载说明:

    上文已介绍两类 IQ 文件的打包过程,以下说明其具体加载方式:

    • iq base bin的加载:加载mi_common.ko时,该ko会从modparam.json中指定的"rootPath"路径加载 iq base bin 文件,并根据文件内容读写寄存器,完成 ISP 硬件初始化。"rootPath"依赖iq base bin文件的打包路径,两者要保持一致

      例如miservice.mk已将iq base bin文件打包到文件系统/config/iqfile/目录,"rootPath"的赋值如下

      / # cat /config/modparam.json
      {
      ...
      "E_MI_MODULE_ID_ISP" :
      {
          "rootPath" : "/config/iqfile"
      },
      ...
      }
      

      注意:"rootPath"指定的路径可自行修改,其他注意项如下

      • 如果modparam.json中无E_MI_MODULE_ID_ISP节点,或该节点下无rootPath配置项,则默认从/config/iqfile/目录加载 iq base bin 文件。

      • 如果iq base bin文件没有加载成功,串口会有错误打印,例如"[ERR]Failed to open IQ file /config/iqfile/iqfile0.bin.Invalid path!!!!!!!!!"

    • iq api bin的加载: 应用层在初始化sensor时,需主动调用MI_ISP_ApiCmdLoadBinFile( )函数,利用iq api bin文件的打包路径和名称来加载该文件。

      例如customer.mk已将iq api bin文件打包到文件系统/customer/iqApiBin0.bin,函数调用如下

      MI_ISP_ApiCmdLoadBinFile(isp_dev_id, isp_channel_id, "/ customer/iqApiBin0.bin", 0);
      

      注意:

      • 如果customer.mk打包的iq api bin文件目标路径和名称修改了,函数入参也要相应修改。

      • 如果iq api bin文件没有加载成功,串口会有错误打印,例如"[isp_cus3a_api.c][MI_ISP_ApiCmdLoadBinFile] File path does not exist. /customer/iqApiBin0.bin not found!"。

      • 如果iq base/api bin两个文件都没有加载成功,除了错误打印之外,图像画面也会发黄

    IQ文件的来源说明:

    上面提到了两类IQ文件的打包和加载过程,接下来说明这两类IQ文件的产生及修改方式。

    • iq base bin的来源:sigmastar原厂提供,sdk中自带,内容不可修改。最终使用的 iq base bin 文件名称固定为iqfile0 / 1 / 2 / 3.bin,名称不可更改

    • iq api bin的来源:sigmastar原厂提供默认的iq api bin文件,sdk里自带,客户可以用IQ tool工具,根据sensor和使用场景的不同 按需修改文件内容和名称,IQ tool的使用方法参考《ISP API Tuning SOP》文档

    5.3.4 配置打包mi模块

    sigmastar平台使用sensor必须依赖mi_common.ko,mi_sensor.ko等ko,mi模块的详情见《功能模块开发指南》。

    使用sensor必需依赖的mi模块ko如下表

    类型 作用
    mi_common.ko 为sensor的使用提供基础的环境,底层接口等功能
    mi_sys.ko 为sensor的使用提供基础的环境,底层接口等功能
    mi_sensor.ko 为sensor驱动提供统一的函数实现和调用接口等功能
    mi_vif.ko 用于绑定和启用视频输入通道的设备驱动,快速搭建起接收视频流的pipeline

    默认的defconfig打包的mi模块配置如下,按需修改

    /project# make menuconfig
        [*] Sdk Config  --->
        [*]    Interface Compile Config --->
        [*]       common
        [*]       sys
        [*]       sensor
        [*]       vif
        ...
    

    5.4 加载相关ko

    5.4.1 加载mi模块ko

    /customer/demo.sh默认加载mi模块ko,它由customer.mk生成,并且被/etc/init.d/rcS 启动脚本拉起运行,

    / # cat /customer/demo.sh
    ...
    #mi module
    insmod /config/modules/6.1/mi_common.ko g_ModParamPath=/config/modparam.json
    insmod /config/modules/6.1/mi_sys.ko
    insmod /config/modules/6.1/mi_sensor.ko
    insmod /config/modules/6.1/mi_vif.ko
    ...
    

    5.4.2 加载sensor驱动ko

    /customer/demo.sh默认加载sensor驱动ko

    / # cat /customer/demo.sh
    ...
    #mi sensor
    insmod /config/modules/6.1/gc2053_mipi.ko chmap=5
    ...
    

    5.5 应用层调用

    snr vif 初始化函数如下,更详细的应用层sensor使用流程请见sdk里的demo代码

    MI_S32 ST_VifInit(ST_Stream_Attr_T *pStreamAttr)
    {
        /************************************************
        Step1:  Init Sensor
        *************************************************/
        MI_SNR_PADInfo_t stSnrPadInfo;
        MI_SNR_PlaneInfo_t stSnrPlaneInfo;
    
    
        MI_SNR_PADID snrPadId = pStreamAttr->u32SnrId;
        MI_U32 u32ResCount = 0;
    
        memset(&stSnrPadInfo, 0x0, sizeof(MI_SNR_PADInfo_t));
        memset(&stSnrPlaneInfo, 0x0, sizeof(MI_SNR_PlaneInfo_t));
    
        ExecFunc(MI_SNR_SetPlaneMode(snrPadId, FALSE), DRM_SUCCESS);
        ExecFunc(MI_SNR_QueryResCount(snrPadId, &u32ResCount), DRM_SUCCESS);
    
        if(pStreamAttr->u32SnrChoiceRes > u32ResCount-1){
            printf("MI_SNR_QueryResCount :%d\n", u32ResCount);
            return -1;
        }
    
        ExecFunc(MI_SNR_SetRes(snrPadId, pStreamAttr->u32SnrChoiceRes), DRM_SUCCESS);
        ExecFunc(MI_SNR_Enable(snrPadId), DRM_SUCCESS);
    
        /************************************************
        Step2:  Init Vif
        *************************************************/
        MI_VIF_GROUP VifGroupId = 0;
        MI_VIF_DEV VifDevId = 0;
        MI_VIF_DEV VifChnId = pStreamAttr->VifChnId;
        MI_VIF_PORT VifPortId = pStreamAttr->VifPortId;
        MI_VIF_GroupAttr_t stVifGroupAttr;
        MI_VIF_DevAttr_t stVifDevAttr;
        MI_VIF_OutputPortAttr_t stVifPortAttr;
    
        get_vif_from_snrpad(snrPadId, &VifGroupId, &VifDevId);
    
    
        memset(&stVifGroupAttr, 0x0, sizeof(MI_VIF_GroupAttr_t));
        memset(&stVifDevAttr, 0x0, sizeof(MI_VIF_DevAttr_t));
        memset(&stVifPortAttr, 0x0, sizeof(MI_VIF_OutputPortAttr_t));
    
        ExecFunc(MI_SNR_GetPadInfo(snrPadId, &stSnrPadInfo), DRM_SUCCESS);
        ExecFunc(MI_SNR_GetPlaneInfo(snrPadId, 0, &stSnrPlaneInfo), DRM_SUCCESS);
        printf(
                    "MI_SNR_GetPlaneInfo %d, outputsize(%d, %d, %d, %d)\n",
                    snrPadId,stSnrPlaneInfo.stCapRect.u16X,stSnrPlaneInfo.stCapRect.u16Y,
                    stSnrPlaneInfo.stCapRect.u16Width,stSnrPlaneInfo.stCapRect.u16Height);
    
        stVifGroupAttr.eIntfMode = E_MI_VIF_MODE_MIPI;
        stVifGroupAttr.eWorkMode = E_MI_VIF_WORK_MODE_1MULTIPLEX;
        stVifGroupAttr.eHDRType = E_MI_VIF_HDR_TYPE_OFF;
        if (stVifGroupAttr.eIntfMode == E_MI_VIF_MODE_BT656) {
            stVifGroupAttr.eClkEdge = (MI_VIF_ClkEdge_e)stSnrPadInfo.unIntfAttr.stBt656Attr.eClkEdge;
        } else {
            stVifGroupAttr.eClkEdge = E_MI_VIF_CLK_EDGE_DOUBLE;
        }
    
        ExecFunc(MI_VIF_CreateDevGroup(VifGroupId, &stVifGroupAttr), DRM_SUCCESS);
        stVifDevAttr.stInputRect.u16X = stSnrPlaneInfo.stCapRect.u16X;
        stVifDevAttr.stInputRect.u16Y = stSnrPlaneInfo.stCapRect.u16Y;
        stVifDevAttr.stInputRect.u16Width = stSnrPlaneInfo.stCapRect.u16Width;
        stVifDevAttr.stInputRect.u16Height = stSnrPlaneInfo.stCapRect.u16Height;
        if (stSnrPlaneInfo.eBayerId >= E_MI_SYS_PIXEL_BAYERID_MAX) {
            stVifDevAttr.eInputPixel = stSnrPlaneInfo.ePixel;
        } else {
            stVifDevAttr.eInputPixel = (MI_SYS_PixelFormat_e)RGB_BAYER_PIXEL(
                    stSnrPlaneInfo.ePixPrecision, stSnrPlaneInfo.eBayerId);
        }
        ExecFunc(MI_VIF_SetDevAttr(VifDevId, &stVifDevAttr), DRM_SUCCESS);
        ExecFunc(MI_VIF_EnableDev(VifDevId), DRM_SUCCESS);
        stVifPortAttr.stCapRect.u16X = stSnrPlaneInfo.stCapRect.u16X;
        stVifPortAttr.stCapRect.u16Y = stSnrPlaneInfo.stCapRect.u16Y;
        stVifPortAttr.stCapRect.u16Width = stSnrPlaneInfo.stCapRect.u16Width;
        stVifPortAttr.stCapRect.u16Height = stSnrPlaneInfo.stCapRect.u16Height;
        stVifPortAttr.stDestSize.u16Width = stSnrPlaneInfo.stCapRect.u16Width;
        stVifPortAttr.stDestSize.u16Height = stSnrPlaneInfo.stCapRect.u16Height;
        stVifPortAttr.eFrameRate = E_MI_VIF_FRAMERATE_FULL;
        if (stSnrPlaneInfo.eBayerId >= E_MI_SYS_PIXEL_BAYERID_MAX) {
            stVifPortAttr.ePixFormat = stSnrPlaneInfo.ePixel;
        } else {
            stVifPortAttr.ePixFormat = (MI_SYS_PixelFormat_e)RGB_BAYER_PIXEL(
                    stSnrPlaneInfo.ePixPrecision, stSnrPlaneInfo.eBayerId);
        }
        ExecFunc(MI_VIF_SetOutputPortAttr(VifDevId, VifPortId, &stVifPortAttr), DRM_SUCCESS);
    
    
        return 0;
    }
    

    5.6 sensor 驱动开发

    5.6.1 sensor 驱动开发参考

    不同接口类型的sensor 驱动实现基本一样,具体请参考Sensor_Porting

    5.6.2 sensor 驱动函数介绍

    函数名 功能
    cus_camsensor_init_handle 设置sensor基础参数、注册功能回调
    handle->pCus_sensor_init
    handle->pCus_sensor_release
    初始化\反初始化sensor(通过iic配置参数)
    handle->pCus_sensor_poweron
    handle->pCus_sensor_poweroff
    上电\掉电函数(poweron会在sensor_init之前调用)
    handle->sif_bus 接口类型(MIPI、DVP等)
    handle->data_prec 数据类型(raw8\10\12 YUV等)
    handle->bayer_id
    handle->RGBIR_id
    BAYE或者RGB排列顺序
    handle->interface_attr.attr_mipi MIPI 配置
    handle->video_res_supported 支持多少种配置
    handle->i2c_cfg iic配置
    handle->pwdn_POLARITY
    handle->reset_POLARITY
    handle->VSYNC_POLARITY
    handle->HSYNC_POLARITY
    handle->PCLK_POLARITY
    控制引脚的极性配置
    handle->mclk MCLK clk
    sensor_if->SetCSI_Clk
    sensor_if->SetCSI_Lane
    sensor_if->SetCSI_LongPacketType
    CSI 配置(clk、 lane 数、支持收包类型(1c代表支持收Raw8、10、12))
    Preview_line_period 行长(包含h blank)
    params->expo.vts 帧长(包含V blank& h blank)

    PS: Preview_line_period = 1*10^9/(fps*(data_h+v_blank))

    帧结构图

    6. 已验证的sensor列表

    6.1 MIPI Interface Camera Sensor Support list

    在芯片验证阶段,验证的MIPI 接口的sensor 如下表所示:

    接口类型 Lane 数 种类 关键指标 数据格式
    MIPI 2Lane IMX307 1920x1080@30FPS,2lane Bayer
    2/1Lane gc2053 1920x1080@30FPS,2/1lane Bayer
    1Lane sc035hgs 640x480@30FPS,1lane Bayer

    6.2 BT601(DVP) Interface Camera Sensor Support List

    在芯片验证阶段,验证的BT601(DVP)接口的sensor 如下表所示:

    接口类型 data pin数 种类 关键指标 数据格式
    parallel 10 pin IMX323 1920x1080@30fps Bayer

    6.3 BT656 Interface Camera Sensor Support List

    在芯片验证阶段,验证的BT656接口的sensor 如下表所示:

    接口类型 data pin数 种类 关键指标 数据格式
    BT656 8pin NVP6158C 1280x720@30fps YUV

    7. FAQ

    Q1:如何查看sensor出图

    echo dumptaskfile 0 2 /mnt/pcm > /proc/mi_modules/mi_isp/mi_isp0 echo dumptaskfile 0 2 /mnt/pcm > /proc/mi_modules/mi_scl/mi_scl0

    /mnt/pcm :存图路径 2:抓2张图 0: chnNum

    Q2:如何进一步确认sensor 中断信息

    请参考MI VIF API 章节5.PROCFS介绍