修改 摄像头SDK中支持的sensor需要做的事
例如:ar0130 --> ov9712
1.修改加载load3518e脚本的参数 vi /etc/profile
./load3518e -i -sensor ar0130 -osmem 32 -total 64
修改参数为
/load3518e -i -sensor ov9712 -osmem 32 -total 64
2.应用程序修改配置
1)使用提供的已配置好的程序进行测试
执行sample_9712
rtsp://192.168.1.10:554/test.264
测试无误
2)修改mpp/sample/makefile.param重新编译之前的程序
SENSOR_TYPE ?= OMNIVISION_OV9712_DC_720P_30FPS
#SENSOR_TYPE ?= APTINA_AR0130_DC_720P_30FPS
make clean
cd venc_ortp
make
cp sample_venc_ortp ~/nfs_hi/ov9712_ortp
./ov9712_ortp 0
VLC播放器打开文件demo.sdp
4.1.本季课程主要内容和安排
4.1.1、本课程主要内容
(1)查看SDK中相应文档,重点是SoC对Sensor的支持
load3518e脚本中的重点内容
#!/bin/sh
# Useage: ./load3518e [ -r|-i|-a ] [ sensor ]
# -r : rmmod all modules
# -i : insmod all modules
# default : rmmod all moules and then insmod them
#
# imx222 9m034 ov9752 ar0230 ar0130 ov9712 mn34222
####################Variables Definition##########################
SNS_TYPE=ar0230 # sensor type
mem_total=64; # 64M, total mem
mem_start=0x80000000; # phy mem start
os_mem_size=32; # 32M, os mem
mmz_start=0x82000000; # mmz start addr
mmz_size=32M; # 32M, mmz size
##################################################################
insert_sns()
{
case $SNS_TYPE in
ar0130|9m034)
himm 0x200f0040 0x2; # I2C0_SCL
himm 0x200f0044 0x2; # I2C0_SDA
#cmos pinmux
himm 0x200f007c 0x1; # VI_DATA13
himm 0x200f0080 0x1; # VI_DATA10
himm 0x200f0084 0x1; # VI_DATA12
himm 0x200f0088 0x1; # VI_DATA11
himm 0x200f008c 0x2; # VI_VS
himm 0x200f0090 0x2; # VI_HS
himm 0x200f0094 0x1; # VI_DATA9
himm 0x2003002c 0xc4001; # sensor unreset, clk 27MHz, VI 99MHz
;;
ar0230)
himm 0x200f0040 0x2; # I2C0_SCL
himm 0x200f0044 0x2; # I2C0_SDA
himm 0x2003002c 0xb4005; # sensor unreset, clk 27MHz, VI 148.5MHz
himm 0x20030104 0x1; # vpss 148.5MHz
;;
imx222)
himm 0x200f0040 0x1 # SPI0_SCLK
himm 0x200f0044 0x1 # SPI0_SDO
himm 0x200f0048 0x1 # SPI0_SDI
himm 0x200f004c 0x1 # SPI0_CSN
#cmos pinmux
himm 0x200f007c 0x1; # VI_DATA13
himm 0x200f0080 0x1; # VI_DATA10
himm 0x200f0084 0x1; # VI_DATA12
himm 0x200f0088 0x1; # VI_DATA11
himm 0x200f008c 0x2; # VI_VS
himm 0x200f0090 0x2; # VI_HS
himm 0x200f0094 0x1; # VI_DATA9
himm 0x2003002c 0x94001; # sensor unreset, clk 37.125MHz, VI 99MHz
insmod extdrv/sensor_spi.ko;
;;
ov9712)
himm 0x200f0040 0x2; # I2C0_SCL
himm 0x200f0044 0x2; # I2C0_SDA
#cmos pinmux
himm 0x200f007c 0x1; # VI_DATA13
himm 0x200f0080 0x1; # VI_DATA10
himm 0x200f0084 0x1; # VI_DATA12
himm 0x200f0088 0x1; # VI_DATA11
himm 0x200f008c 0x2; # VI_VS
himm 0x200f0090 0x2; # VI_HS
himm 0x200f0094 0x1; # VI_DATA9
himm 0x2003002c 0xb4001; # sensor unreset, clk 24MHz, VI 99MHz
;;
ov9732)
himm 0x200f0040 0x2; # I2C0_SCL
himm 0x200f0044 0x2; # I2C0_SDA
#cmos pinmux
himm 0x200f007c 0x1; # VI_DATA13
himm 0x200f0080 0x1; # VI_DATA10
himm 0x200f0084 0x1; # VI_DATA12
himm 0x200f0088 0x1; # VI_DATA11
himm 0x200f008c 0x2; # VI_VS
himm 0x200f0090 0x2; # VI_HS
himm 0x200f0094 0x1; # VI_DATA9
himm 0x2003002c 0xc4001; # sensor unreset, clk 24MHz, VI 99MHz
;;
ov9752)
himm 0x200f0040 0x2; # I2C0_SCL
himm 0x200f0044 0x2; # I2C0_SDA
himm 0x2003002c 0xc4001; # sensor unreset, clk 24MHz, VI 99MHz
;;
ov9750)
himm 0x200f0040 0x2; # I2C0_SCL
himm 0x200f0044 0x2; # I2C0_SDA
himm 0x2003002c 0xc4001; # sensor unreset, clk 24MHz, VI 99MHz
;;
ov2718)
himm 0x200f0040 0x2; # I2C0_SCL
himm 0x200f0044 0x2; # I2C0_SDA
himm 0x2003002c 0xc4001; # sensor unreset, clk 24MHz, VI 99MHz
;;
mn34222)
himm 0x200f0040 0x2; # I2C0_SCL
himm 0x200f0044 0x2; # I2C0_SDA
himm 0x2003002c 0x94001; # sensor unreset, clk 37.125MHz, VI 99MHz
;;
bt1120)
himm 0x200f0008 0x4; # VI_VS
himm 0x200f000c 0x4; # VI_HS
himm 0x200f007c 0x1; # VI_DATA13
himm 0x200f0080 0x1; # VI_DATA10
himm 0x200f0084 0x1; # VI_DATA12
himm 0x200f0088 0x1; # VI_DATA11
himm 0x200f008c 0x1; # VI_DATA15
himm 0x200f0090 0x1; # VI_DATA14
himm 0x200f0094 0x1; # VI_DATA9
himm 0x2003002c 0x94003; # sensor unreset, clk 24MHz, VI 99MHz
;;
*)
echo "xxxx Invalid sensor type $SNS_TYPE xxxx"
report_error;;
esac
}
查看/etc/profile中的内容(此次为自行添加的内容)
ifconfig lo 127.0.0.1
ifconfig eth0 192.168.1.10
cd /ko
./load3518e -i -sensor ar0130 -osmem 32 -total 64
mount -t nfs -o nolock 192.168.1.14:/home/swann/nfs_hi /mnt
cd /mnt
.
修改参数为
/load3518e -i -sensor ov9712 -osmem 32 -total 64
(2)更换另一个Sensor(OV9712),并实现之前的实验
(3)Sensor接口:并口/LVDS/MIPI CSI
(4)SoC的Sensor接口引脚复用设置
(5)sensor驱动源码详解
(6)sample中sensor相关的部分详解
4.1.2、查看SDK的2个相关文档
4.2.更换OV9712并且做配置更改和测试
4.2.1、更改配置脚本
4.2.2、运行rtsp传输的测试版本
4.2.3、运行官方SDK sample的测试版本
4.2.4、运行ORTP传输的测试版本
4.2.5、更换sensor的总结
(1)程序框架做好多种sensor支持的框架
(2)注意硬件接线上面的差异
(3)加载不同的驱动,做不同的参数设置
修改mpp/sample/makefile.param,更换sensor type,如何make clean,
进入venc文件夹,make
4.3_4.MIPI和LVDS和并口的细节讲解1_2
4.3.1、并口Sensor
(1)OV9712和AR0130都是并口的
(2)并口的接口定义:参考AR0130的原理图pdf
(3)并口传输的是CMOS电平信号(重点是非差分)
(4)并口sensor属于较低端老旧的,新型高像素的都是MIPI/LVDS/HISPI等差分信号的
4.3.2、LVDS
(1)low voltage differential signal,低电压差分信号
(2)接口由1组差分clock和若干组差分信号线组成
(3)LVDS主要用于视频传输的2个领域:camera和主控、LCD和主控
(4)LVDS利用差分抗干扰能力,提升clock频率从而提升带宽,传输距离也更远
(5)LVDS的数据线组数越多带宽越大、clock频率越高带宽越大(牺牲抗干扰和距离)
(6)并口和LVDS之间可以互转,但是需要专门的电平转换芯片(类似于232和485)
4.3.3、MIPI(MIPI-CSI2)
(1)MIPI: mobile industry processor interface,移动工业处理器接口
(2)MIPI接口由1组差分clock和1-4组差分信号线组成
(3)MIPI和LVDS虽然都是差分对信号,但是不兼容,不能直接对接
(4)MIPI的架构层次更分明,广泛应用在手机平板等领域中,可以认为MIPI是LVDS的升级版
(5)MIPI的数据线组数越多带宽越大、clock频率越高带宽越大(牺牲抗干扰和距离)
(6)MIPI和LVDS和并口之间均可以互相转换,但是需要专门的电平转换芯片
4.3.4、总结
(1)老旧的、低端的、数据量小的就用电平信号;新的、高端的、数据量大的都用差分信号
(2)要通信,物理层、协议层、应用层都得能对接才行。
(3)因为历史原因,很多行业会使用不同的接口标准,必要时需要去互相转换
4.5_6.HI3518E的Sensor接口引脚复用设置1_2
4.5.1、查看引脚定义框图
4.5.2、找到相应设置寄存器
4.5.3、himm工具
4.7.sensor驱动源码解析1
4.7.1、sensor驱动源码寻找
(1)从sample入手
(2)sensor层驱动在component/isp中(mppcomponentispsensorar0130)
(3)底层i2c驱动在kernel中
4.7.2、sensor驱动的框架
(1)mpp定义了一套sensor驱动的实现和封装
(2)xxxx_cmos.c中定义回调和上层函数
(3)xxxx_sensor_ctl.c中定义底层硬件相关的寄存器值配置函数
(4)kernel中的I2C驱动提供i2c层面的物理层操作接口
SAMPLE_COMM_VI_StartIspAndVi
SAMPLE_COMM_ISP_Init
sensor_register_callback由开始对接驱动和应用层
cmos_init_sensor_exp_function(&stIspRegister.stSnsExp);
s32Ret = HI_MPI_ISP_SensorRegCallBack(IspDev, AR0130_ID, &stIspRegister);
HI_S32 cmos_init_sensor_exp_function(ISP_SENSOR_EXP_FUNC_S *pstSensorExpFunc)
{
memset(pstSensorExpFunc, 0, sizeof(ISP_SENSOR_EXP_FUNC_S));
pstSensorExpFunc->pfn_cmos_sensor_init = sensor_init;
pstSensorExpFunc->pfn_cmos_sensor_exit = sensor_exit;
pstSensorExpFunc->pfn_cmos_sensor_global_init = sensor_global_init;
pstSensorExpFunc->pfn_cmos_set_image_mode = cmos_set_image_mode;
pstSensorExpFunc->pfn_cmos_set_wdr_mode = cmos_set_wdr_mode;
pstSensorExpFunc->pfn_cmos_get_isp_default = cmos_get_isp_default;
pstSensorExpFunc->pfn_cmos_get_isp_black_level = cmos_get_isp_black_level;
pstSensorExpFunc->pfn_cmos_set_pixel_detect = cmos_set_pixel_detect;
pstSensorExpFunc->pfn_cmos_get_sns_reg_info = cmos_get_sns_regs_info;
return 0;
}
void sensor_init()
{
if (1 == gu8SensorImageMode) /* SENSOR_720P_30FPS_MODE */
{
sensor_init_720p_30fps();
bSensorInit = HI_TRUE;
}
else if (2 == gu8SensorImageMode) /* SENSOR_960P_30FPS_MODE */
{
sensor_init_960p_30fps();
bSensorInit = HI_TRUE;
}
else
{
printf("Not support this mode
");
}
}
sensor_write_register(0x200, 0x31); //sensor_write_register(0x200, 0x01)
在以下函数中对接sensor驱动和内核IIC接口
int sensor_write_register(int addr, int data) { #ifdef HI_GPIO_I2C i2c_data.dev_addr = sensor_i2c_addr; i2c_data.reg_addr = addr; i2c_data.addr_byte_num = sensor_addr_byte; i2c_data.data = data; i2c_data.data_byte_num = sensor_data_byte; ret = ioctl(g_fd, GPIO_I2C_WRITE, &i2c_data); if (ret) { printf("GPIO-I2C write faild! "); return ret; } #else int idx = 0; int ret; char buf[8]; buf[idx++] = addr & 0xFF; if (sensor_addr_byte == 2) { ret = ioctl(g_fd, I2C_16BIT_REG, 1); buf[idx++] = addr >> 8; } else { ret = ioctl(g_fd, I2C_16BIT_REG, 0); } if (ret < 0) { printf("CMD_SET_REG_WIDTH error! "); return -1; } buf[idx++] = data; if (sensor_data_byte == 2) { ret = ioctl(g_fd, I2C_16BIT_DATA, 1); buf[idx++] = data >> 8; } else { ret = ioctl(g_fd, I2C_16BIT_DATA, 0); } if (ret) { printf("hi_i2c write faild! "); return -1; } ret = write(g_fd, buf, idx); if(ret < 0) { printf("I2C_WRITE error! "); return -1; } #endif return 0; }
4.8.sensor驱动源码解析2
4.8.1、xxxx_cmos.c中实现和注册回调
4.8.2、xxxx_sensor_ctl.c中配置sensor寄存器
4.9.ISP_3A框架解读
4.10.sensor驱动编译实战
4.10.1、sensor的注册接口分析
4.10.2、黑电平
HI_U32 cmos_get_isp_black_level(ISP_CMOS_BLACK_LEVEL_S *pstBlackLevel) { HI_S32 i; if (HI_NULL == pstBlackLevel) { printf("null pointer when get isp black level value! "); return -1; } /* Don't need to update black level when iso change */ pstBlackLevel->bUpdate = HI_FALSE; switch (genSensorMode) { default : case WDR_MODE_NONE : for (i=0; i<4; i++) { pstBlackLevel->au16BlackLevel[i] = 0xC8; } break; } return 0; }
修改 pstBlackLevel->au16BlackLevel[i] = 0xC8;更改黑电平值
4.10.3、sensor驱动编译实战
(1)修改驱动源码
(2)清除,并重新编译
(3)确认mpp中lib目录下的libsnsxxx.a/so已经被更新
(4)重新编译sample并运行查看效果
4.11.sensor驱动的寄存器操作
4.11.1、sensor的寄存器设置
(1)sensor内部有若干寄存器,可以通过I2C接口来读写
(2)数据手册有对寄存器的基本说明
(3)经验:大部分寄存器设置厂家会给,偶尔需要自己调一些
4.8.4、实战任务:修改sensor的flip和mirror寄存器查看效果
(1)查sensor数据手册的寄存器列表
(2)改sensor驱动代码
void sensor_init_720p_30fps()
在pll初始化前添加
(3)重新编译isp
(4)确认sensor库已经更新到mpp中
(5)重新编译sample,运行测试
4.12.sensor驱动部分贯通总结
4.12.1、体系思想
(1)成熟的商业解决方案都是一整套设计好的模式
(2)第一步是理解,第二步是用起来,第三步是小修改,第四步是大修改,第五步是创造
4.12.2、海思方案的sensor驱动相关体系关键点
(1)搞清楚sensor的本质:光电转换+AD+ISP+并口/MIPI/LVDS
(2)ISP有多种实现:sensor内置、主SoC内置、外接专用ISP芯片
(3)3A是为最终图像效果负责的,3A的实现有赖于镜头、sensor、isp等各部门协同工作
(4)海思的体系中把sensor和3A、ISP实现为:指针挂接注册的各自独立模块
4.12.3、扩展学习方向
(1)sensor的各种参数
(2)其他几种sensor的驱动和对比实现
(3)isp的firmware
(4)3A算法相关知识