新换了工作,用到海思Hi3519v101,最开始先和摄像头sensor打交道。之前一直没有深入研究这一块,正好利用这个机会随调试随做些记录,算做研发文档了。
load3519v101是加载Hi3519v101mpp库和ko的脚本,里边也包含了摄像头的配置,现在先贴出部分代码,在其中深入分析imx274、imx274_mipi和imx290。
if [ ${SNS_TYPE0} != "NULL" ] ; then
case $SNS_TYPE0 in
imx226)
tmp=0x11;
himm 0x12010040 0x11; # sensor0 clk_en, 72MHz
# SDK config: IVE:396M, GDC:475M, VGS:500M, VEDU:600M, VPSS:300M
#imx226: viu0:600M,isp0:600M, viu1:300M,isp1:300M
himm 0x1201004c 0x00094c23;
himm 0x12010054 0x00024041;
spi0_4wire_pin_mux;
insmod extdrv/hi_ssp_sony.ko;
;;
imx274)
tmp=0x11;
himm 0x12010040 0x11; # sensor0 clk_en, 72MHz
# SDK config: IVE:396M, GDC:475M, VGS:500M, VEDU:600M, VPSS:300M
#imx274:viu0: 600M,isp0:300M, viu1:300M,isp1:300M
himm 0x1201004c 0x00094c23;
himm 0x12010054 0x0004041;
spi0_4wire_pin_mux;
insmod extdrv/hi_ssp_sony.ko;
;;
imx274_mipi)
tmp=0x14;
# SDK config: IVE:396M, GDC:475M, VGS:500M, VEDU:600M, VPSS:300M
# viu0:300M,isp0:300M, viu1:300M,isp1:300M
himm 0x1201004c 0x00094c21;
himm 0x12010054 0x0004041;
himm 0x12010040 0x14; # sensor0 clk_en, 24MHz
i2c0_pin_mux;
;;
imx290)
tmp=0x18;
# SDK config: IVE:396M, GDC:475M, VGS:500M, VEDU:600M, VPSS:300M
#imx290:viu0:340M,isp0:214M, viu1:340M,isp1:214M
himm 0x1201004c 0x00094c24;
himm 0x12010054 0x0004;
himm 0x12010040 0x18; # sensor0 clk_en, 37.125MHz
i2c0_pin_mux;
;;
ov4689)
tmp=0x14;
# SDK config: IVE:396M, GDC:475M, VGS:500M, VEDU:600M, VPSS:300M
#ov4689: viu0:300M,isp0:300M, viu1:300M,isp1:300M
himm 0x1201004c 0x00094c21;
himm 0x12010054 0x0004041;
himm 0x12010040 0x14; # sensor0 clk_en, 24MHz
i2c0_pin_mux;
;;
os08a10)
tmp=0x14;
# SDK config: IVE:396M, GDC:475M, VGS:500M, VEDU:600M, VPSS:300M
#os08a10: viu0: 600M, isp0:300M, viu1:300M,isp1:300M
himm 0x1201004c 0x00094c23;
himm 0x12010054 0x0004041;
himm 0x12010040 0x14; # sensor0 clk_en, 24MHz
i2c0_pin_mux;
;;
bt1120)
# SDK config: IVE:396M, GDC:475M, VGS:500M, VEDU:600M, VPSS:300M
# viu0:300M,isp0:300M, viu1:300M,isp1:300M
himm 0x1201004c 0x00094c21;
himm 0x12010054 0x0004041;
himm 0x113c6200 0x0; #disable dehaze
himm 0x113d1400 0x0; #disable acm
himm 0x113c5200 0x0; #disable sharpen
#himm 0x20670000 0x0;
;;
*)
echo "xxxx Invalid sensor type $SNS_TYPE0 xxxx"
report_error;;
esac
fi
下边先来详细分析imx274:
imx274)
tmp=0x11;
himm 0x12010040 0x11; # sensor0 clk_en, 72MHz
# SDK config: IVE:396M, GDC:475M, VGS:500M, VEDU:600M, VPSS:300M
#imx274:viu0: 600M,isp0:300M, viu1:300M,isp1:300M
himm 0x1201004c 0x00094c23;
himm 0x12010054 0x0004041;
spi0_4wire_pin_mux;
insmod extdrv/hi_ssp_sony.ko;
;;
第1句程序tmp=0x11:
笔者开始以为这句代码没有用处,因为第2句中直接用了0x11。但后来看到SNS_TYPE1时才知道这是给它用的,这是后话。
第2句程序himm 0x12010040 0x11:
这句话需要参考《Hi3519V101 专业型HD IP Camera SoC用户指南》,在108-110页(3-27~3-29)中,这3页说明的是PERI_CRG16。PERI_CRG16 为 Sensor 时钟配置寄存器。 我们只看写入1的项。
bit0为1,代表sensor0_clksel 为0001,即Sensor0 时钟(芯片输出给 sensor 的参考时钟)选择72MHz。
bit4为1,代表sensor0_clken为1,即Sensor0 时钟(芯片输出给 sensor 的参考时钟)门控选择时钟打开。
实际上这句话的作用已经在后边有了英文注释,很准确。
第3句程序himm 0x1201004c 0x00094c23:
同样需要参考《Hi3519V101 专业型HD IP Camera SoC用户指南》,在113-114页(3-32~3-33)中,这2页说明的是PERI_CRG19。PERI_CRG19 为媒体 CBB 频率配置寄存器 1。 我们只看写入1的项。
bit0、bit1为1,代表vi0_clksel 为011,即VI0 时钟选择600MHz。
bit5为1,代表vpss_clksel 为001,即VPSS 时钟选择300MHz。
bit10、bit11为1,代表vedu_clksel 为011,即VEDU 时钟选择594MHz。
bit14为1,代表vgs_clksel 为010,即VGS 时钟选择500MHz。
bit16为1,代表gdc_clksel 为001,即GDC 时钟选择475MHz。
bit19为1,代表ive_clksel 为001,即IVE 时钟选择396MHz。
第4句程序himm 0x12010054 0x0004041:
同样参考《Hi3519V101 专业型HD IP Camera SoC用户指南》,在115-116页(3-34~3-35)中,这2页说明的是PERI_CRG21。PERI_CRG21 为媒体 CBB 频率配置寄存器 2。 我们只看写入1的项。
bit0为1,代表vi1_clksel 为001,即VI1 时钟选择300MHz。
bit6为1,代表isp1_clksel 为00001,即ISP1 时钟选择300MHz。
bit14为1,代表isp0_clksel 为00001,即ISP0 时钟选择300MHz。
第5句程序spi0_4wire_pin_mux:
这是脚本中的一个函数,源码如下:
spi0_4wire_pin_mux()
{
#pinmux
himm 0x1204018c 0x1; #SPI0_SCLK
himm 0x12040190 0x1; #SPI0_SD0
himm 0x12040194 0x1; #SPI0_SDI
himm 0x12040198 0x1; #SPI0_CSN
#drive capability
himm 0x12040998 0x150; #SPI0_SCLK
himm 0x1204099c 0x160; #SPI0_SD0
himm 0x120409a0 0x160; #SPI0_SDI
himm 0x120409a4 0x160; #SPI0_CSN
}
依然一句一句解读:
himm 0x1204018c 0x1; #SPI0_SCLK
这回就不是参考《Hi3519V101 专业型HD IP Camera SoC用户指南》了,需要参考《Hi3519V101_PINOUT_CN》,这是一个excel文件,在 00.hardware\chip\document_cn 路径下。
参考《Hi3519V101_PINOUT_CN》中的 3.管脚复用寄存器,其中有这样一项:
muxctrl_reg99 | SPI0_SCLK管脚复用寄存器。 | 0x1204018C | 0 | SPI0_SCLK管脚复用关系选择。 0 : GPIO12_4 1 : SPI0_SCLK 2 : I2C0_SCL 3 : SPI0_3WIRE_CLK 其它:reserved |
可以看到,当设置为1时,选择的是SPI0_SCLK,与注释一致。
himm 0x12040190 0x1; #SPI0_SD0
路子同上。
muxctrl_reg100 | SPI0_SDO管脚复用寄存器。 | 0x12040190 | 0 | SPI0_SDO管脚复用关系选择。 0 : GPIO12_5 1 : SPI0_SDO 2 : I2C0_SDA 3 : SPI0_3WIRE_DATA 其它:reserved |
可以看到,当设置为1时,选择的是SPI0_SDO,与注释一致。
himm 0x12040194 0x1; #SPI0_SDI
muxctrl_reg101 | SPI0_SDI管脚复用寄存器。 | 0x12040194 | 0 | SPI0_SDI管脚复用关系选择。 0 : GPIO12_6 1 : SPI0_SDI 其它:reserved |
可以看到,当设置为1时,选择的是SPI0_SDI,与注释一致。
himm 0x12040198 0x1; #SPI0_CSN
muxctrl_reg102 | SPI0_CSN管脚复用寄存器。 | 0x12040198 | 0 | SPI0_CSN管脚复用关系选择。 0 : GPIO12_7 1 : SPI0_CSN 3 : SPI0_3WIRE_CSN 其它:reserved |
可以看到,当设置为1时,选择的是SPI0_CSN,与注释一致。
himm 0x12040998 0x150; #SPI0_SCLK
参考《Hi3519V101_PINOUT_CN》中的 4.管脚驱动能力寄存器,其中有这样一项:
pad_ctrl_reg102 | SPI0_SCLK管脚驱动能力寄存器。 | 0x12040998 | 0x00000170 | reserved | reserved | reserved | SPI0_SCLK管脚电平转换速率。 0 : 快沿 1 : 慢沿 |
SPI0_SCLK管脚驱动能力选择: 0000:IO6_档位8 0001:IO6_档位7 0010:IO6_档位6 0011:IO6_档位5 0100:IO6_档位4 0101:IO6_档位3 0110:IO6_档位2 0111:IO6_档位1 |
reserved |
bit7~4: 0101,SPI0_SCLK管脚驱动能力选择IO6_档位3。
bit8: 1,SPI0_SCLK管脚电平转换速率选择慢沿。
himm 0x1204099c 0x160; #SPI0_SD0
pad_ctrl_reg103 | SPI0_SDO管脚驱动能力寄存器。 | 0x1204099C | 0x00000170 | reserved | reserved | reserved | SPI0_SDO管脚电平转换速率。 0 : 快沿 1 : 慢沿 |
SPI0_SDO管脚驱动能力选择: 0000:IO6_档位8 0001:IO6_档位7 0010:IO6_档位6 0011:IO6_档位5 0100:IO6_档位4 0101:IO6_档位3 0110:IO6_档位2 0111:IO6_档位1 |
reserved |
bit7~4: 0110,SPI0_SDO管脚驱动能力选择IO6_档位2。
bit8: 1,SPI0_SDO管脚电平转换速率选择慢沿。
himm 0x120409a0 0x160; #SPI0_SDI
pad_ctrl_reg104 | SPI0_SDI管脚驱动能力寄存器。 | 0x120409A0 | 0x00000170 | reserved | reserved | reserved | SPI0_SDI管脚电平转换速率。 0 : 快沿 1 : 慢沿 |
SPI0_SDI管脚驱动能力选择: 0000:IO6_档位8 0001:IO6_档位7 0010:IO6_档位6 0011:IO6_档位5 0100:IO6_档位4 0101:IO6_档位3 0110:IO6_档位2 0111:IO6_档位1 |
reserve |
bit7~4: 0110,SPI0_SDI管脚驱动能力选择IO6_档位2。
bit8: 1,SPI0_SDI管脚电平转换速率选择慢沿。
himm 0x120409a4 0x160; #SPI0_CSN
pad_ctrl_reg105 | SPI0_CSN管脚驱动能力寄存器。 | 0x120409A4 | 0x00000170 | reserved | reserved | reserved | SPI0_CSN管脚电平转换速率。 0 : 快沿 1 : 慢沿 |
SPI0_CSN管脚驱动能力选择: 0000:IO6_档位8 0001:IO6_档位7 0010:IO6_档位6 0011:IO6_档位5 0100:IO6_档位4 0101:IO6_档位3 0110:IO6_档位2 0111:IO6_档位1 |
reserved |
bit7~4: 0110,SPI0_CSN管脚驱动能力选择IO6_档位2。
bit8: 1,SPI0_CSN管脚电平转换速率选择慢沿。
第6句程序insmod extdrv/hi_ssp_sony.ko:
这句很好理解,插入extdrv/下的hi_ssp_sony.ko模块。
综合以上各语句,就能够完整地看出SNS_TYPE0为imx274时所做的全部配置了。先是配置各个时钟并使能,而后配置管脚复用以及配置驱动能力,最后插入对应模块。也能够得出结论:Hi3519和imx274通过SPI(Hi3519的SPI0)进行通讯;需要额外加载SONY的驱动才能正常通信。
=================================================================================================
分析完了imx274,该分析imx274_mipi了。
imx274_mipi)
tmp=0x14;
# SDK config: IVE:396M, GDC:475M, VGS:500M, VEDU:600M, VPSS:300M
# viu0:300M,isp0:300M, viu1:300M,isp1:300M
himm 0x1201004c 0x00094c21;
himm 0x12010054 0x0004041;
himm 0x12010040 0x14; # sensor0 clk_en, 24MHz
i2c0_pin_mux;
;;
实际上和上边imx274非常类似。
第1句程序tmp=0x14:
笔者开始以为这句代码没有用处,因为第4句中直接用了0x14。但后来看到SNS_TYPE1时才知道这是给它用的,这是后话。
第2句程序himm 0x1201004c 0x00094c21:
这句话需要参考《Hi3519V101 专业型HD IP Camera SoC用户指南》,在113-114页(3-32~3-33)中,这2页说明的是PERI_CRG19。PERI_CRG19 为媒体 CBB 频率配置寄存器 1。 我们只看写入1的项。
bit0为1,代表vi0_clksel 为001,即VI0 时钟选择300MHz。
bit5为1,代表vpss_clksel 为001,即VPSS 时钟选择300MHz。
bit10、bit11为1,代表vedu_clksel 为011,即VEDU 时钟选择594MHz。
bit14为1,代表vgs_clksel 为010,即VGS 时钟选择500MHz。
bit16为1,代表gdc_clksel 为001,即GDC 时钟选择475MHz。
bit19为1,代表ive_clksel 为001,即IVE 时钟选择396MHz。
第3句程序himm 0x12010054 0x0004041:
同样参考《Hi3519V101 专业型HD IP Camera SoC用户指南》,在115-116页(3-34~3-35)中,这2页说明的是PERI_CRG21。PERI_CRG21 为媒体 CBB 频率配置寄存器 2。 我们只看写入1的项。
bit0为1,代表vi1_clksel 为001,即VI1 时钟选择300MHz。
bit6为1,代表isp1_clksel 为00001,即ISP1 时钟选择300MHz。
bit14为1,代表isp0_clksel 为00001,即ISP0 时钟选择300MHz。
第4句程序himm 0x12010040 0x14:
同样参考《Hi3519V101 专业型HD IP Camera SoC用户指南》,在108-110页(3-27~3-29)中,这3页说明的是PERI_CRG16。PERI_CRG16 为 Sensor 时钟配置寄存器。 我们只看写入1的项。
bit2为1,代表sensor0_clksel 为0100,即Sensor0 时钟(芯片输出给 sensor 的参考时钟)选择24MHz。
bit4为1,代表sensor0_clken为1,即Sensor0 时钟(芯片输出给 sensor 的参考时钟)门控选择时钟打开。
第5句程序i2c0_pin_mux:
这是脚本中的一个函数,源码如下:
i2c0_pin_mux()
{
#pinmux
himm 0x12040190 0x2; #I2C0_SDA
himm 0x1204018c 0x2; #I2C0_SCL
#drive capability
himm 0x1204099c 0x120; #I2C0_SDA
himm 0x12040998 0x120; #I2C0_SCL
}
由于在上边介绍imx274的时候已经把寄存器贴出来了,并且进行了详细分析,因此这里就不再一一详细分析了,只做简单分析:
himm 0x12040190 0x2; #I2C0_SDA
参考《Hi3519V101_PINOUT_CN》中的 3.管脚复用寄存器:
当设置为2时,选择的是I2C0_SDA,与注释一致。
himm 0x1204018c 0x2; #I2C0_SCL
当设置为2时,选择的是I2C0_SCL,与注释一致。
参考《Hi3519V101_PINOUT_CN》中的 4.管脚驱动能力寄存器:
himm 0x1204099c 0x120; #I2C0_SDA
bit7~4: 0010,SPI0_SDO管脚驱动能力选择IO6_档位6。
bit8: 1,SPI0_SDO管脚电平转换速率选择慢沿。
himm 0x12040998 0x120; #I2C0_SCL
bit7~4: 0010,SPI0_SCLK管脚驱动能力选择IO6_档位6。
bit8: 1,SPI0_SCLK管脚电平转换速率选择慢沿。
对于最后2项,有人会有疑问:都选择I2C了,怎么还是SPI0_SDO和SPI0_SCLK?其实笔者开始也有疑问,后来想明白了,应该是前边复用寄存器选择了i2c,之后这2个寄存器的功能就变了,不再是配置SPI0的驱动能力了,而是配置I2C0的,只是资料中的名字还是叫SPIXX。
至此,imx274_mipi的配置就结束了。可以看到,imx274_mipi的配置语句比imx274的简单了一些,主要是因为4线制SPI要配置4个引脚,而I2C只需要配置2个引脚即可。也不需要加载对应的ko。
综合以上各语句,就能够完整地看出SNS_TYPE0为imx274_mipi时所做的全部配置了。先是配置各个时钟并使能,而后配置管脚复用以及配置驱动能力。也能够得出结论:Hi3519和imx274_mipi通过I2C(Hi3519的I2C0)进行通讯;不需要额外加载SONY的驱动就可以正常通信。
=================================================================================================
分析完了imx274和imx274_mipi,该分析imx290了,但由于实际项目中是将imx290作为后置摄像头,因此我把imx290放在SNS_TYPE1的代码中进行讲解。
if [ ${SNS_TYPE1} != "NULL" ] ; then
case $SNS_TYPE1 in
imx290)
tmp1=0x1800;
tmp2=$((tmp+tmp1));
himm 0x12010040 $tmp2; # sensor1 clk_en, 37.125MHz
i2c1_pin_mux;
;;
ov4689)
tmp1=0x1400;
tmp2=$((tmp+tmp1));
himm 0x12010040 $tmp2; # sensor1 clk_en, 24MHz
i2c1_pin_mux;
;;
os08a10)
tmp1=0x1400;
tmp2=$((tmp+tmp1));
himm 0x12010040 $tmp2; # sensor1 clk_en, 24MHz
i2c1_pin_mux;
;;
bt1120)
himm 0x114c6200 0x0; #disable dehaze
himm 0x114d1400 0x0; #disable acm
himm 0x114c5200 0x0; #disable sharpen
#himm 0x20670000 0x0;
;;
*)
echo "xxxx Invalid sensor type $SNS_TYPE1 xxxx"
report_error;;
esac
fi
下边来详细分析imx290作为SNS_TYPE1的代码:
imx290)
tmp1=0x1800;
tmp2=$((tmp+tmp1));
himm 0x12010040 $tmp2; # sensor1 clk_en, 37.125MHz
i2c1_pin_mux;
;;
第1句程序tmp1=0x1800:
这句没什么好说的,一目了然。
第2句程序tmp2=$((tmp+tmp1)):
这句程序就是把tmp和tmp1的值相加,赋给tmp2。其中:tmp1在上1句中赋值,值为0x1800;tmp在imx274_mipi中的第1句赋值(前边也提到了),值为0x14。因此tmp2的值为0x14+0x1800=0x1814。
这里多说一句,$(( )) 用来作整数运算的。
第3句程序himm 0x12010040 $tmp2; # sensor1 clk_en, 37.125MHz:
这句话需要参考《Hi3519V101 专业型HD IP Camera SoC用户指南》,在108-110页(3-27~3-29)中,这3页说明的是PERI_CRG16。PERI_CRG16 为 Sensor 时钟配置寄存器。 我们只看写入1的项。
bit0为1,代表sensor0_clksel 为0100,即Sensor0 时钟(芯片输出给 sensor 的参考时钟)选择24MHz。
bit4为1,代表sensor0_clken为1,即Sensor0 时钟(芯片输出给 sensor 的参考时钟)门控选择时钟打开。
到这里就能明白为何把值赋给tmp了,就是为了保留SNS_TYPE0的值,不会在设置SNS_TYPE1时被干扰到。
bit11为1,代表sensor1_clksel 为1000,即Sensor1 时钟(芯片输出给 sensor 的参考时钟)选择37.125MHz。
bit12为1,代表sensor1_clken为1,即Sensor0 时钟(芯片输出给 sensor 的参考时钟)门控选择时钟打开。
实际上这句话的作用已经在后边有了英文注释,很准确。
第4句程序i2c1_pin_mux:
这是脚本中的一个函数,源码如下:
i2c1_pin_mux()
{
#pinmux
himm 0x1204001c 0x2; #I2C1_SDA
himm 0x12040018 0x2; #I2C1_SCL
#drive capability
himm 0x1204081c 0x120; #I2C1_SDA
himm 0x12040818 0x120; #I2C1_SCL
}
依然一句一句解读:
himm 0x1204001c 0x2; #I2C1_SDA
参考《Hi3519V101_PINOUT_CN》中的 3.管脚复用寄存器,其中有这样一项:
muxctrl_reg7 | SPI1_SDO管脚复用寄存器。 | 0x1204001C | 0 | SPI1_SDO管脚复用关系选择。 0 : GPIO0_5 1 : SPI1_SDO 2 : I2C1_SDA 3 : SPI1_3WIRE_DATA 其它:reserved |
可以看到,当设置为2时,选择的是I2C1_SDA,与注释一致。
himm 0x12040018 0x2; #I2C1_SCL
muxctrl_reg6 | SPI1_SCLK管脚复用寄存器。 | 0x12040018 | 0 | SPI1_SCLK管脚复用关系选择。 0 : GPIO0_4 1 : SPI1_SCLK 2 : I2C1_SCL 3 : SPI1_3WIRE_CLK 其它:reserved |
可以看到,当设置为2时,选择的是I2C1_SCL,与注释一致。
himm 0x1204081c 0x120; #I2C1_SDA
参考《Hi3519V101_PINOUT_CN》中的 4.管脚驱动能力寄存器,其中有这样一项:
pad_ctrl_reg7 | SPI1_SDO管脚驱动能力寄存器。 | 0x1204081C | 0x00000170 | reserved | reserved | reserved | SPI1_SDO管脚电平转换速率。 0 : 快沿 1 : 慢沿 |
SPI1_SDO管脚驱动能力选择: 0000:IO6_档位8 0001:IO6_档位7 0010:IO6_档位6 0011:IO6_档位5 0100:IO6_档位4 0101:IO6_档位3 0110:IO6_档位2 0111:IO6_档位1 |
reserved |
bit7~4: 0010,SPI1_SDO管脚驱动能力选择IO6_档位6。
bit8: 1,SPI1_SDO管脚电平转换速率选择慢沿。
himm 0x12040818 0x120; #I2C1_SCL
pad_ctrl_reg6 | SPI1_SCLK管脚驱动能力寄存器。 | 0x12040818 | 0x00000170 | reserved | reserved | reserved | SPI1_SCLK管脚电平转换速率。 0 : 快沿 1 : 慢沿 |
SPI1_SCLK管脚驱动能力选择: 0000:IO6_档位8 0001:IO6_档位7 0010:IO6_档位6 0011:IO6_档位5 0100:IO6_档位4 0101:IO6_档位3 0110:IO6_档位2 0111:IO6_档位1 |
reserve |
bit7~4: 0010,SPI1_SCLK管脚驱动能力选择IO6_档位6。
bit8: 1,SPI1_SCLK管脚电平转换速率选择慢沿。
对于最后2项,有人会有疑问:都选择I2C了,怎么还是SPI1_SDO和SPI1_SCLK?其实笔者开始也有疑问,后来想明白了,应该是前边复用寄存器选择了i2c,之后这2个寄存器的功能就变了,不再是配置SPI1的驱动能力了,而是配置I2C1的,只是资料中的名字还是叫SPIXX。
综合以上各语句,就能够完整地看出SNS_TYPE1为imx290时所做的全部配置了。先是配置各个时钟并使能,而后配置管脚复用以及配置驱动能力。也能够得出结论:Hi3519和imx290通过I2C(Hi3519的I2C1)进行通讯;不需要额外加载SONY的驱动就可以正常通信。