海思的sensor驱动大部分工作在应用层,即应用层驱动(非ko形式存在),这样一来在对sensor改动时,就不需要重新编译内核了。
缺点是,不稳定,效率会比较低。纯应用层驱动是没办法操作硬件的,所以需要调用底层i2c驱动。
1、驱动源码路径
Hi3518E_SDK_V1.0.3.0\package\mpp\mpp\component\isp\sensor目录下。
2、sensor驱动调用
sensor驱动编译完之后会生成xxx.a和xxx.so两个库,一个是静态链接用的,一个是动态链接用的。
这两个文件会被放到Hi3518E_SDK_V1.0.3.0\package\mpp\mpp\lib目录下。
3、sensor驱动文件命名规则
xxxx_cmos.c中定义回调和上层函数。
xxxx_sensor_ctl.c中定义底层硬件相关的寄存器值配置函数。
4、sensor驱动在哪被调用
从之前的sample_venc开始看,在第三部分step 3: start vi dev & chn to capture
SAMPLE_COMM_VI_StartVi()
SAMPLE_COMM_VI_StartIspAndVi()
SAMPLE_COMM_ISP_Init()
sensor_register_callback()
sensor_register_callback这个函数就在sensor驱动里面,这里会调用到kernel内的i2c驱动对sensor进行硬件操作。
5、sensor_register_callback
这个函数就是对整个sensor初始化,内部封装了操作sensor所需要的函数,(ISP、AE(自动曝光)、AWB(白平衡))
其中的cmos_init_sensor_exp_function函数将sensor操作时所需要的函数一一挂接起来,例如初始化调用的sensor_init。
6、sensor_init
初始化sensor,初始化的方式就是调用i2c函数接口来实现操作sensor内部寄存器。
7、黑电平
黑电平(Black Level Correction)也就是黑色的最低点,以8bit数据来说,指在经过一定校准的显示装置上,没有一行光亮输出的视频信号电平。定义图像数据为0时对应的信号电平。
sensor中的黑电平是可以调节的,就相当于标准值,就像零摄氏度这种概念。
8、sensor驱动编译实战
(1)修改驱动源码
以AR0130为例,修改mpp\component\isp\sensor\ar0130目录下的应用驱动源码。
如果是调整黑电平,就修改ar0130目录下的ar0130_coms.c文件里面的cmos_get_isp_black_level函数中的au16BlackLevel数组。
(2)清除,并重新编译
首次编译需要在mpp\component\isp目录下将整个isp进行编译。
执行make clean指令。
再执行make
(3)确认mpp中lib目录下的libsnsxxx.a/so已经被更新。
(4)重新编译sample并运行查看效果。
9、AR0130sensor寄存器
参考AR0130_RR_C.pdf文档的Register Behavior寄存器章节,了解各寄存器用途。
- sensor开发框图
wKiom1fSl5mwA2ESAABzoRmaSVU881.jpg
- 设备驱动加载及硬件系统配置
cd mpp/ko
default online
./load3518e -a -sensor sc2135 -osmem 32 -total 64
vi_vpss offline
./load3518e -a -sensor sc2135 -osmem 32 -total 64 -offline
load3518e脚本主要是用来配置硬件系统的参数(引脚复用、sensor时钟、VI时钟)加载驱动(.ko),包括访问sensor的I2C接口驱动。
离线模式时图像存入DDR中,在线模式时图像不存入DDR中。
在load3518e脚本中添加sensor的相关配置,这里使用smartsens的SC2135的200万像素的图像传感器。
insert_sns()
{
case $SNS_TYPE in
sc2135)
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 27MHz, VI 148.5MHz
himm 0x20030104 0x1; # vpss 148.5MHz
;;
*)
echo "xxxx Invalid sensor type $SNS_TYPE xxxx"
report_error;;
esac
}
insert_ko()
{
# sys config
sys_config;
# driver load
insmod mmz.ko mmz=anonymous,0,$mmz_start,$mmz_size anony=1 || report_error
insmod hi_media.ko
insmod hi3518e_base.ko
insmod hi3518e_sys.ko vi_vpss_online=$b_arg_online sensor=$SNS_TYPE
insmod hi3518e_tde.ko
insmod hi3518e_region.ko
insmod hi3518e_vgs.ko
insmod hi3518e_isp.ko
insmod hi3518e_viu.ko detect_err_frame=10;
insmod hi3518e_vpss.ko rfr_frame_comp=1;
insmod hi3518e_vou.ko
#insmod hi3518e_vou.ko transparentTransmit=1 #enable transparentTransmit
insmod hifb.ko video="hifb:vram0_size:1620" # default pal
insmod hi3518e_rc.ko
insmod hi3518e_venc.ko
insmod hi3518e_chnl.ko ChnlLowPower=1
insmod hi3518e_h264e.ko
insmod hi3518e_jpege.ko
insmod hi3518e_ive.ko save_power=0;
insmod hi3518e_ive.ko
insmod extdrv/sensor_i2c.ko
echo "==== Your input Sensor type is $SNS_TYPE ===="
insmod extdrv/pwm.ko
insmod extdrv/piris.ko
#insert_sns > /dev/null
insert_sns
insert_audio
insmod hi_mipi.ko
echo "==== Your input Sensor type is $SNS_TYPE ===="
}
- sensor的库文件生成(.so)
sensor的库文件需要在Linux服务器中的SDK包中编译得到,将生成的.so文件放到SDK包中的stream软件包中的Hi3518E_Stream_xxx/libs目录下。
wKiom1fSrKWSwkQLAAB-bfCJ3DQ706.jpg
sensor_ctl.c实现sensor的读写初始化。
sensor_cmos.c主要实现ISP需要的回调函数,包括ISP、AE、AWB等。
//ISP function
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;
}
//AE function
HI_S32 cmos_init_ae_exp_function(AE_SENSOR_EXP_FUNC_S *pstExpFuncs)
{
memset(pstExpFuncs, 0, sizeof(AE_SENSOR_EXP_FUNC_S));
pstExpFuncs->pfn_cmos_get_ae_default = cmos_get_ae_default;
pstExpFuncs->pfn_cmos_fps_set = cmos_fps_set;
pstExpFuncs->pfn_cmos_slow_framerate_set= cmos_slow_framerate_set;
pstExpFuncs->pfn_cmos_inttime_update = cmos_inttime_update;
pstExpFuncs->pfn_cmos_gains_update = cmos_gains_update;
pstExpFuncs->pfn_cmos_again_calc_table = cmos_again_calc_table;
pstExpFuncs->pfn_cmos_get_inttime_max = cmos_get_inttime_max;
return 0;
}
//AWB function
HI_S32 cmos_init_awb_exp_function(AWB_SENSOR_EXP_FUNC_S *pstExpFuncs)
{
memset(pstExpFuncs, 0, sizeof(AWB_SENSOR_EXP_FUNC_S));
pstExpFuncs->pfn_cmos_get_awb_default = cmos_get_awb_default;
return 0;
}
- 修改stream软件包的.ini文件
sc2135_1080p_line.ini文件在Hi3518E_Stream_xxx/configs目录下,改文件主要指定.so文件的位置、输入视频的接口(LVDS/MIPI/DVP)、视频格式(分辨率、同步方式、目标帧率等)等系统配置。
- 运行stream软件
运行stream软件包中的HiIspTool.sh脚本,通过以太网卡与上位机的PQTools建立通信。
cd /Hi3518E_Stream_V1.0.2.0
./HiIspTool.sh -a -p sc2135_1080p_line.ini
ittb_control进程是基于TCP的服务端,负责控制信号的传输。
ittb_stream进程也是基于TCP的服务端,负责播放H.264或YUV视频流。
wKioL1fSsq-wXKC9AADRHXJoipc306.jpg
- 运行PQ Tools
双击PQ Tools图片,弹出如下对话框,设置IP地址。
wKiom1fStgiBOLd5AABV6TYUyy8974.jpg
在下拉菜单中选择TTP_Stream.exe选项
wKiom1fStkDxwy9rAADdoeFseIU165.jpg
- 最终结果
本文来自 什么鬼__ 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qq_36164813/article/details/52620112?utm_source=copy
问题1:
由于是新sensor,跑海思自带的测试代码肯定会提示“This sensor type is not surpport!”
解决方案:
添加新sensor的枚举类型 到typedef enum sample_vi_mode_e {}SAMPLE_VI_MODE_E;
并根据自己sensor的参数正确命名。
问题2:
最棘手的问题,get venc stream time out, exit thread
既然是新添加sensor,那么能出现这个超时问题一定就是视频摄入有问题了,最主要的结构在sample_common_vi.c 的combo_dev_attr_t结构体。
你要对照sensor厂商给的ini配置,参照其他厂商的形式为你的sensor写一个此结构体的初始化代码。当然我们的是CMOS3V3的,直接使用如下初始化结构:
combo_dev_attr_t MIPI_CMOS3V3_ATTR =
{
/* input mode */
.input_mode = INPUT_MODE_CMOS_33V,
{
}
};