前言
环境介绍:
1.编译环境
Ubuntu 18.04.5 LTS
2.SDK
Hi3519AV100_SDK_V2.0.1.0
3.单板
Hi3519AV100开发板
IMX347 2688x1520(4M)@30fps master mode i2c id 0x34
一、Sensor i2c寄存器读写
海思默认文件系统是有i2c读写工具的,可以使用这个工具先对Sensor 进行读写,看是否正常。具体操作可以参考我之前的文章。
海思I2C工具读取外设寄存器
不过能读写是sensor供电、复位、时钟能正常提供的情况下操作的,要是复位、时钟需要主芯片提供,还需要做具体寄存器配置,要是嫌麻烦可以跳过这一步。
二、Sensor模板
Hi3519AV100 SDK已经适配有sensor相关驱动例程,可以作为本次适配的模板。
Hi3519AV100_SDK_V2.0.1.0/smp/a53_linux/mpp/component/isp/user/sensor/hi3519av100/
根据海思提供的《Sensor 调试指南》,本次以imx334 8M作为模板,因为两者规格相对来说比较相似。
三、IMX347驱动文件修改
复制imx334文件夹,命名为imx347,并将里面的的文件都重命名为imx347,如下

依次将这4个文件内部imx334全部替换为imx347
其中
Makefile 用于生产sensor库
imx347_cmos.c 为底层驱动文件与上层运用的函数链接
imx347_cmos_ex.h 头文件
imx347_sensor_ctl.c sensor底层驱动
底层适配只要通过修改imx347_cmos.c imx347_sensor_ctl.c 这两个文件进行。
3.1 imx347_sensor_ctl.c
1. sensor i2c地址、地址位宽、数据位宽定义
const unsigned char imx347_i2c_addr = 0x34; /* I2C Address of imx347 */
const unsigned int imx347_addr_byte = 2;
const unsigned int imx347_data_byte = 1;
我这里都跟原来一直,不做改动。
2. sensor初始化模式选择
原先sensor定义了两种功能,通过传入的参数修改,本次适配就只使用一种,另外的就不出修改
imx347_8M_30FPS_12BIT_LINEAR_MODE
...
#define imx347_4M_30FPS_12BIT_LINEAR_MODE (1)
#define imx347_4M_30FPS_12BIT_2t1_DOL_MODE (2)
...
void imx347_linear_4M30_12bit_init(VI_PIPE ViPipe);
void imx347_DOL_2t1_4M30_12bit_init(VI_PIPE ViPipe);
...
重点修改void imx347_linear_4M30_12bit_init(VI_PIPE ViPipe)这个函数,这是给sensor初始化的配置,具体配置太长不贴了。
void imx347_linear_4M30_12bit_init(VI_PIPE ViPipe)
{imx347_write_register(ViPipe, 0x3000, 0x01);//standbyimx347_write_register(ViPipe, 0x3002, 0x01);/* master mode stop */imx347_write_register(ViPipe, 0x300C, 0x3B);imx347_write_register(ViPipe, 0x300D, 0x2A);imx347_write_register(ViPipe, 0x3018, 0x04);imx347_write_register(ViPipe, 0x302C, 0x30);imx347_write_register(ViPipe, 0x302E, 0x80);
...
3.2 imx347_sensor_ctl.c
这文件要修改的不多,主要是sdk的函数调用,并且之前已经进行了全局替换。我这里就只修改了相关函数的命名、ID和分辨率的修改。
...
#define imx347_ID 347
...
//sensor fps mode
#define imx347_4M_30FPS_12BIT_LINEAR_MODE (1) /* 4M@30fps Linear 12bit*/
#define imx347_4M_30FPS_12BIT_2t1_DOL_MODE (2)#define imx347_RES_IS_4M30_12BIT(w, h) ((2688 == (w)) && (1520 == (h)))
至此imx347底层驱动修改差不多了。
四、添加SENSOR_TYPE
在mpp/sample/Makefile.param添加SENSOR_TYPE,并添加对应的 libsns_xxx.a文件
我这里只有1个sensor,所以修改SENSOR0_TYPE。
################# select sensor type for your sample ###############################
#### SONY_IMX290_MIPI_2M_30FPS_12BIT #################
#### SONY_IMX290_SLAVE_MIPI_2M_60FPS_10BIT #################
#### SONY_IMX334_MIPI_8M_30FPS_12BIT #################
#### NVP6324_MIPI_2M_30FPS_8BIT #################
#### SONY_IMX347_MIPI_4M_30FPS_12BIT #################SENSOR0_TYPE ?= SONY_IMX347_MIPI_4M_30FPS_12BIT
SENSOR1_TYPE ?= SONY_IMX290_SLAVE_MIPI_2M_60FPS_10BIT
SENSOR2_TYPE ?= SONY_IMX290_SLAVE_MIPI_2M_60FPS_10BIT
SENSOR3_TYPE ?= SONY_IMX290_SLAVE_MIPI_2M_60FPS_10BIT
SENSOR4_TYPE ?= SONY_IMX334_MIPI_8M_30FPS_12BIT...
SENSOR_LIBS += $(REL_LIB)/libsns_imx290.a
SENSOR_LIBS += $(REL_LIB)/libsns_imx290_slave.a
SENSOR_LIBS += $(REL_LIB)/libsns_imx334.a
SENSOR_LIBS += $(REL_LIB)/libsns_imx347.a
在mpp/sample/common/sample_comm.h添加宏,该宏要与上面的SENSOR0_TYPE一致
typedef enum hiSAMPLE_SNS_TYPE_E
{SONY_IMX290_MIPI_2M_30FPS_12BIT,SONY_IMX290_MIPI_2M_30FPS_12BIT_WDR2TO1,SONY_IMX290_SLAVE_MIPI_2M_60FPS_10BIT,SONY_IMX334_MIPI_8M_30FPS_12BIT,SONY_IMX334_MIPI_8M_30FPS_12BIT_WDR2TO1,SONY_IMX377_MIPI_8M_30FPS_10BIT,SONY_IMX347_MIPI_4M_30FPS_12BIT,NVP6324_MIPI_2M_30FPS_8BIT,SAMPLE_SNS_TYPE_BUTT,
} SAMPLE_SNS_TYPE_E;
五、sample_comm_vi.c修改
5.1 SAMPLE_COMM_VI_GetSizeBySensor
新加一个case
case SONY_IMX347_MIPI_4M_30FPS_12BIT:*penSize = PIC_2688x1520;break;
因为PIC_2688x1520没有定义,所以需要在mpp/sample/common/sample_comm.h添加一个枚举如下
typedef enum hiPIC_SIZE_E
{PIC_CIF,PIC_D1_PAL, /* 720 * 576 */PIC_D1_NTSC, /* 720 * 480 */PIC_720P, /* 1280 * 720 */PIC_1080P, /* 1920 * 1080 */PIC_2592x1520,PIC_2592x1944,PIC_3840x2160,PIC_4096x2160,PIC_3000x3000,PIC_4000x3000,PIC_7680x4320,PIC_3840x8640,PIC_2688x1520, PIC_BUTT
} PIC_SIZE_E;
5.2 SAMPLE_COMM_VI_GetFrameRateBySensor
新加一个case
因为我这里是30fps,直接添加即可。
switch (enMode)
{case SONY_IMX290_MIPI_2M_30FPS_12BIT:case SONY_IMX290_MIPI_2M_30FPS_12BIT_WDR2TO1:case SONY_IMX334_MIPI_8M_30FPS_12BIT:case SONY_IMX334_MIPI_8M_30FPS_12BIT_WDR2TO1:case SONY_IMX377_MIPI_8M_30FPS_10BIT:case SONY_IMX347_MIPI_4M_30FPS_12BIT:*pu32FrameRate = 30;break;default:*pu32FrameRate = 30;break;}
5.3 SAMPLE_COMM_VI_GetChnAttrBySns
新加一个case
case SONY_IMX347_MIPI_4M_30FPS_12BIT:hi_memcpy(pstChnAttr, sizeof(VI_CHN_ATTR_S), &CHN_ATTR_2688x1520_420_SDR8_LINEAR, sizeof(VI_CHN_ATTR_S));break;
根据其他参数添加CHN_ATTR_2688x1520_420_SDR8_LINEAR结构体
VI_CHN_ATTR_S CHN_ATTR_2688x1520_420_SDR8_LINEAR =
{{2688, 1520},PIXEL_FORMAT_YVU_SEMIPLANAR_420,DYNAMIC_RANGE_SDR8,VIDEO_FORMAT_LINEAR,COMPRESS_MODE_NONE,0, 0,0,{ -1, -1}
};
5.4 SAMPLE_COMM_VI_GetPipeAttrBySns
新加一个case
case SONY_IMX347_MIPI_4M_30FPS_12BIT:hi_memcpy(pstPipeAttr, sizeof(VI_PIPE_ATTR_S), &PIPE_ATTR_2688x1520_RAW12_420_3DNR_RFR, sizeof(VI_PIPE_ATTR_S));break;
根据其他参数添加PIPE_ATTR_2688x1520_RAW12_420_3DNR_RFR结构体
VI_PIPE_ATTR_S PIPE_ATTR_2688x1520_RAW12_420_3DNR_RFR =
{VI_PIPE_BYPASS_NONE, HI_FALSE,HI_FALSE,2688, 1520,PIXEL_FORMAT_RGB_BAYER_12BPP,COMPRESS_MODE_LINE,DATA_BITWIDTH_12,HI_TRUE,{PIXEL_FORMAT_YVU_SEMIPLANAR_420,DATA_BITWIDTH_8,VI_NR_REF_FROM_RFR,COMPRESS_MODE_NONE},HI_FALSE,{ -1, -1}
};
5.5 SAMPLE_COMM_VI_GetDevAttrBySns
新加一个case
case SONY_IMX347_MIPI_4M_30FPS_12BIT:hi_memcpy(pstViDevAttr, sizeof(VI_DEV_ATTR_S), &DEV_ATTR_IMX347_4M_BASE, sizeof(VI_DEV_ATTR_S));break;
根据其他参数添加DEV_ATTR_IMX347_4M_BASE 结构体
VI_DEV_ATTR_S DEV_ATTR_IMX347_4M_BASE =
{VI_MODE_MIPI,VI_WORK_MODE_1Multiplex,{0xFFF00000, 0x0},VI_SCAN_PROGRESSIVE,{-1, -1, -1, -1},VI_DATA_SEQ_YUYV,{/*port_vsync port_vsync_neg port_hsync port_hsync_neg */VI_VSYNC_PULSE, VI_VSYNC_NEG_LOW, VI_HSYNC_VALID_SINGNAL,VI_HSYNC_NEG_HIGH,VI_VSYNC_VALID_SINGAL,VI_VSYNC_VALID_NEG_HIGH,/*hsync_hfb hsync_act hsync_hhb*/{0, 1280, 0,/*vsync0_vhb vsync0_act vsync0_hhb*/0, 1520, 0,/*vsync1_vhb vsync1_act vsync1_hhb*/0, 0, 0}},VI_DATA_TYPE_RGB,HI_FALSE,{2688 , 1520},{{{2688 , 1520},},{VI_REPHASE_MODE_NONE,VI_REPHASE_MODE_NONE}},{WDR_MODE_NONE,2160},DATA_RATE_X1
};
5.6 SAMPLE_COMM_VI_GetComboAttrBySns
新加一个case
case SONY_IMX347_MIPI_4M_30FPS_12BIT:hi_memcpy(pstComboAttr, sizeof(combo_dev_attr_t), &MIPI_4lane_CHN0_SENSOR_IMX347_12BIT_4M_NOWDR_ATTR, sizeof(combo_dev_attr_t));break;
根据其他参数添加MIPI_4lane_CHN0_SENSOR_IMX347_12BIT_4M_NOWDR_ATTR结构体
combo_dev_attr_t MIPI_4lane_CHN0_SENSOR_IMX347_12BIT_4M_NOWDR_ATTR =
{.devno = 0,.input_mode = INPUT_MODE_MIPI,.data_rate = MIPI_DATA_RATE_X1,.img_rect = {0, 0, 2688, 1520},{.mipi_attr ={DATA_TYPE_RAW_12BIT,HI_MIPI_WDR_MODE_NONE,{0, 1, 2, 3, -1, -1, -1, -1}}}
};
以上是对mpp/sample/common/sample_comm_vi.c的修改,接下来修改mpp/sample/common/sample_comm_isp.c
六、sample_comm_isp.c修改
6.1 SAMPLE_COMM_ISP_GetSnsObj
新加一个case
case SONY_IMX347_MIPI_4M_30FPS_12BIT:return &stSnsimx347Obj;
在mpp/include/hi_sns_ctrl.h添加obj。
...
extern ISP_SNS_OBJ_S stSnsImx334SlaveObj;
extern ISP_SNS_OBJ_S stSnsImx226Obj;
extern ISP_SNS_OBJ_S stSnsImx335Obj;
extern ISP_SNS_OBJ_S stSnsImx458Obj;
extern ISP_SNS_OBJ_S stSnsOv2735Obj;
extern ISP_SNS_OBJ_S stSnsimx347Obj;
此obj要与mpp/component/isp/user/sensor/hi3519av100/sony_imx347/imx347_cmos.c里面的obj一直
ISP_SNS_OBJ_S stSnsimx347Obj =
{.pfnRegisterCallback = sensor_register_callback,.pfnUnRegisterCallback = sensor_unregister_callback,.pfnStandby = imx347_standby,.pfnRestart = imx347_restart,.pfnMirrorFlip = HI_NULL,.pfnWriteReg = imx347_write_register,.pfnReadReg = imx347_read_register,.pfnSetBusInfo = imx347_set_bus_info,.pfnSetInit = sensor_set_init
};
6.2 SAMPLE_COMM_ISP_GetIspAttrBySns
新加一个case
case SONY_IMX347_MIPI_4M_30FPS_12BIT:memcpy(pstPubAttr, &ISP_PUB_ATTR_IMX347_4M_30FPS, sizeof(ISP_PUB_ATTR_S));break;
在mpp/include/hi_sns_ctrl.h添加obj。
...
extern ISP_SNS_OBJ_S stSnsImx334SlaveObj;
extern ISP_SNS_OBJ_S stSnsImx226Obj;
extern ISP_SNS_OBJ_S stSnsImx335Obj;
extern ISP_SNS_OBJ_S stSnsImx458Obj;
extern ISP_SNS_OBJ_S stSnsOv2735Obj;
extern ISP_SNS_OBJ_S stSnsimx347Obj;
根据其他参数添加ISP_PUB_ATTR_IMX347_4M_30FPS 结构体
ISP_PUB_ATTR_S ISP_PUB_ATTR_IMX347_4M_30FPS =
{{0, 0, 2688, 1520},{2688, 1520},30,BAYER_RGGB,WDR_MODE_NONE,0,
};
以上对于mpp的修改完成了,可以在sample目录进行make编译,可以在mpp/lib文件夹里面生成相关的xxx.o、xxx.a文件。
七、sys_config.c修改
文件 drv/interdrv/sysconfig/sys_config.c主要是进行sensor复位、时钟、i2c和行场同步信号复用配置。
7.1 sensor列表名称修改
我这边把所有都修改为imx347
static char sensor_list[SENSOR_LIST_CMDLINE_LEN]= "sns0=imx347,sns1=imx347,sns2=imx347,sns3=imx347,sns4=imx347";module_param(g_bt1120_flag, int, S_IRUGO);module_param_string(sensors, sensor_list, SENSOR_LIST_CMDLINE_LEN, 0600);MODULE_PARM_DESC(sensors,"sns0=imx347,sns1=imx347,sns2=imx347,sns3=imx347,sns4=imx347");
7.2 clock
sensor clock为24M,这里直接添加即可。
if ( (0 == strncmp("imx377", name, len))|| (0 == strncmp("imx334", name, len))|| (0 == strncmp("imx477", name, len))|| (0 == strncmp("imx299", name, len))|| (0 == strncmp("imx347", name, len))|| (0 == strncmp("cmv50000", name, len))){clock = 0x4;}
数值对应多少频率有备注说明
/*
0x0: 74.25MHz; 0x1: 72MHz;0x2: 54MHz;0x3: 50MHz;0x4: 24MHz;0x6: 32.4MHz;
0x8: 37.125MHz;0x9: 36MHz;0xA: 27MHz;0xB: 25MHz;0xC: 12MHz;
*/
7.3 BUS_TYPE
imx347为i2c,这里直接添加即可。
if ( (0 == strncmp("imx377", name, len))|| (0 == strncmp("imx334", name, len))|| (0 == strncmp("imx477", name, len))|| (0 == strncmp("imx290", name, len))|| (0 == strncmp("imx290_slave", name, len))|| (0 == strncmp("imx299", name, len))|| (0 == strncmp("imx347", name, len))|| (0 == strncmp("imx117", name, len)))
{bus_type = BUS_TYPE_I2C;
}
以上修改完之后在drv/interdrv/sysconfig路径下make重新生成sys_config.ko
八、上板测试
上述修改完之后,可以根据我之前其他文章进行测试。
Hi3519AV100 MPP部署

















