1.libmmcamera_imx258.so 代码分析

Sensor LIB 库代码位于 /vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor/libs
本文以 imx258 为例。
先来看下imx258_lib.c,其最核心的函数就是 sensor_open_lib,
返回 sensor_lib_ptr 结构体,所有的 Camera 信息,都保存在该结构体中。

@ /vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor/libs/imx258/imx258_lib.c/*** FUNCTION: sensor_open_lib* DESCRIPTION: Open sensor library and returns data pointer**/
void *sensor_open_lib(void)
{return &sensor_lib_ptr;
}

我们来看下 sensor_lib_ptr 结构体的定义。

@ /vendor/qcom/proprietary/mm-camerasdk/sensor/includes/sensor_lib.h
typedef struct {/* sensor slave info */ // 从设备包括,I2C地址、I2C速率、Sensor_id 寄存器地址及Sensor_id 值、上下电的时序及电压值struct camera_sensor_slave_info sensor_slave_info;/* sensor output settings */// 包括 出图的格式(BAYER / YCbCr), 连接类型为 MIPI CSIsensor_output_t sensor_output;/* sensor output register address */// 输出寄存器的地址,pclk,及line length pclk 、 frame length linesstruct sensor_output_reg_addr_t output_reg_addr;/* sensor exposure gain register address */// 曝光增益struct sensor_exp_gain_info_t exp_gain_info;/* sensor aec info */sensor_aec_data_t aec_info;/* number of frames to skip after start stream info */// preview 前丢弃过的 帧数unsigned short sensor_num_frame_skip;/* number of frames to skip after start HDR stream info */// HDR 丢弃的帧数unsigned short sensor_num_HDR_frame_skip;/* sensor pipeline delay */// pipeline 帧延时unsigned int sensor_max_pipeline_frame_delay;/* sensor lens info */// sensor line info 信息sensor_property_t sensor_property;/* imaging pixel array size info */// 像素点大小,宽高sensor_imaging_pixel_array_size pixel_array_size_info;/* Sensor color level information */// 颜色等级sensor_color_level_info color_level_info;/* sensor port info that consists of cid mask and fourcc mapaping */sensor_stream_info_array_t sensor_stream_info_array;/* Sensor Settings */// 初始化Camera 寄存器配置struct camera_i2c_reg_setting_array start_settings;// 关闭Camera 时的寄存器配置struct camera_i2c_reg_setting_array stop_settings;struct camera_i2c_reg_setting_array groupon_settings;struct camera_i2c_reg_setting_array groupoff_settings;struct camera_i2c_reg_setting_array embedded_data_enable_settings;struct camera_i2c_reg_setting_array embedded_data_disable_settings;struct camera_i2c_reg_setting_array aec_enable_settings;struct camera_i2c_reg_setting_array aec_disable_settings;struct camera_i2c_reg_setting_array dualcam_master_settings;struct camera_i2c_reg_setting_array dualcam_slave_settings;/* sensor test pattern info */// 测试图信息sensor_test_info test_pattern_info;/* sensor effects info */struct sensor_effect_info effect_info;/* Sensor Settings Array *///初始化 Camera 寄存器配置struct sensor_lib_reg_settings_array init_settings_array;struct sensor_lib_reg_settings_array res_settings_array;// 不同辨率的输出信息,xy像素大小,pclk,fps,数据传输速率struct sensor_lib_out_info_array     out_info_array;// MIPI CSI 信息struct sensor_csi_params             csi_params;struct sensor_csid_lut_params_array  csid_lut_params_array;struct sensor_lib_crop_params_array  crop_params_array;/* Exposure Info */sensor_exposure_table_t exposure_func_table;/* video_hdr mode info*/struct sensor_lib_meta_data_info_array meta_data_out_info_array;/* sensor optical black regions */sensor_optical_black_region_t optical_black_region_info;/* sensor_capability */sensor_capability_t sensor_capability;/* sensor_awb_table_t */sensor_awb_table_t awb_func_table;/* sensor_awb_table_t */sensor_fps_table_t fps_func_table;/* Parse RDI stats callback function */sensor_RDI_parser_stats_t parse_RDI_stats;/* full size info */sensor_rolloff_config rolloff_config;/* analog-digital conversion time */long long adc_readout_time;/* number of frames to skip for fast AEC use case */unsigned short sensor_num_fast_aec_frame_skip;/* add soft delay for sensor settings like exposure, gain ...*/unsigned char app_delay[SENSOR_DELAY_MAX];/* for noise profile calculationTuning team must update with proper values. */struct sensor_noise_coefficient_t noise_coeff;/* Flag to be set if any external library are to be loaded */unsigned char external_library;sensorlib_pdaf_apis_t sensorlib_pdaf_api;// PDAF 配轩pdaf_lib_t            pdaf_config;/* sensor orientation flag */sensor_orientation_type_t  sensor_orientation;} sensor_lib_t;

imx258_lib.h 头文件分析

@ /vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/sensor/libs/imx258/imx258_lib.h/* imx258_lib.h** Copyright (c) 2015-2018 Qualcomm Technologies, Inc.* All Rights Reserved.* Confidential and Proprietary - Qualcomm Technologies, Inc.*/#ifndef __IMX258_LIB_H__
#define __IMX258_LIB_H__#include "sensor_lib.h"
#include "eeprom_lib.h"
#include "pdaf_api.h"
#include "pdaf_camif_api.h"
#define SENSOR_MODEL "imx258"/* IMX258 Regs */
#define IMX258_DIG_GAIN_GR_ADDR       0x020E
#define IMX258_DIG_GAIN_R_ADDR        0x0210
#define IMX258_DIG_GAIN_B_ADDR        0x0212
#define IMX258_DIG_GAIN_GB_ADDR       0x0214
#define IMX258_EXP_RATIO_ADDR         0x0222
#define IMX258_ABS_GAIN_R_WORD_ADDR   0x0B90
#define IMX258_ABS_GAIN_B_WORD_ADDR   0x0B92/* IMX258 CONSTANTS */
#define IMX258_MAX_INTEGRATION_MARGIN   20/* STATS DATA TYPE */
#define IMX258_CSI_PD_ISTATS            0x2F#define IMX258_DATA_PEDESTAL            0x40 /* 10bit value */#define IMX258_MIN_AGAIN_REG_VAL        0 /* 1.0x */
#define IMX258_MAX_AGAIN_REG_VAL        480 /* 16.0x */#define IMX258_MIN_DGAIN_REG_VAL        256 /* 1.0x */
#define IMX258_MAX_DGAIN_REG_VAL        256 /* 1.0x */#define IMX258_MAX_DGAIN_DECIMATOR      256/* IMX258 FORMULAS */
#define IMX258_MIN_AGAIN    (512 / (512 - IMX258_MIN_AGAIN_REG_VAL))
#define IMX258_MAX_AGAIN    (512 / (512 - IMX258_MAX_AGAIN_REG_VAL))#define IMX258_MIN_DGAIN    (IMX258_MIN_DGAIN_REG_VAL / 256)
#define IMX258_MAX_DGAIN    (IMX258_MAX_DGAIN_REG_VAL / 256)#define IMX258_MIN_GAIN     IMX258_MIN_AGAIN * IMX258_MIN_DGAIN
#define IMX258_MAX_GAIN     IMX258_MAX_AGAIN * IMX258_MAX_DGAIN/* uncomment FLIP_MIRROR macro toenable flip and mirror in sensor readoutchange bayer patternload pdaf flip and mirror header
*/
//#define FLIP_MIRROR
#define START_REG_ARRAY \
{ \{0x0100, 0x01, 0x00}, \
}#define STOP_REG_ARRAY \
{ \{0x0100, 0x00, 0x00}, \
}#define GROUPON_REG_ARRAY \
{ \{0x0104, 0x01, 0x00}, \
}#define GROUPOFF_REG_ARRAY \
{ \{0x0104, 0x00, 0x00}, \
}// 初始化 寄存器配置
#define INIT0_REG_ARRAY \
{ \/* External Clock Settings */ \{0x0136, 0x18, 0x00}, \{0x0137, 0x00, 0x00}, \/* Global Settings */ \{0x3051, 0x00, 0x00}, \......  //配置一系烈的寄存器{0x3006, 0x00, 0x00}, \{0x3007, 0x00, 0x00}, \
}#ifndef FLIP_MIRROR#define FLIP_MIRROR_SETTING {{0x0101, 0x00, 0x00}}
#else#define FLIP_MIRROR_SETTING {{0x0101, 0x03, 0x00}}
#endif
// 分辨率0 寄存器配置
#define RES0_REG_ARRAY \
{ \/* Mode A1: 4208x3120 Full 30fps */ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \......  //配置一系烈的寄存器{0x0818, 0x00, 0x00}, \{0x0819, 0x47, 0x00}, \
}
// 分辨率1 寄存器配置
#define RES1_REG_ARRAY \
{\/* (Reg-10)Mode: Full 16:9 30 fps */ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \/* Clock Settings */ \{0x0301, 0x05, 0x00}, \{0x0303, 0x02, 0x00}, \......  //配置一系烈的寄存器{0x0818, 0x00, 0x00}, \{0x0819, 0x47, 0x00}, \
}
// 分辨率2 寄存器配置
#define RES2_REG_ARRAY \
{ \/* Mode: 2100x1560 2x2 binning 30 fps */ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \......  //配置一系烈的寄存器{0x0819, 0x47, 0x00}, \{0x3031, 0x00, 0x00}, \
}
// 分辨率3 寄存器配置
#define RES3_REG_ARRAY \
{ \/* Mode: 2100x1176 60 fps */ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \......  //配置一系列的寄存器{0x0819, 0x47, 0x00}, \{0x3031, 0x00, 0x00}, \
}
// 分辨率4 寄存器配置
#define RES4_REG_ARRAY \
{ \/* Mode: 1400x784 90 fps*/ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \......  //配置一系列的寄存器{0x0819, 0x47, 0x00}, \{0x3031, 0x00, 0x00}, \
}
// 分辨率5 寄存器配置
#define RES5_REG_ARRAY \
{ \/* Mode: 1400x760 120 fps*/ \/* Output Format Settings */ \{0x0112, 0x0A, 0x00}, \{0x0113, 0x0A, 0x00}, \......  //配置一系列的寄存器{0x0819, 0x47, 0x00}, \{0x3031, 0x00, 0x00}, \
}/* Sensor Handler */
static sensor_lib_t sensor_lib_ptr =
{.sensor_slave_info ={.sensor_name = SENSOR_MODEL,          // "imx258".slave_addr = 0x20,                      // 7位地址0x20, 010 0000, 对应的8位地址为0100 0000, 0x40.i2c_freq_mode = SENSOR_I2C_MODE_FAST,.addr_type = CAMERA_I2C_WORD_ADDR,.sensor_id_info ={.sensor_id_reg_addr = 0x0016,.sensor_id = 0x0258,},.power_setting_array ={.power_setting_a ={{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_RESET,.config_val = GPIO_OUT_LOW,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VANA,.config_val = GPIO_OUT_HIGH,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VANA,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VDIG,.config_val = GPIO_OUT_HIGH,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VDIG,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VIO,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VAF,.config_val = GPIO_OUT_HIGH,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_CLK,.seq_val = CAMERA_MCLK,.config_val = 24000000,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_RESET,.config_val = GPIO_OUT_HIGH,.delay = 12,},},.size = 9,.power_down_setting_a ={{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_RESET,.config_val = GPIO_OUT_LOW,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_CLK,.seq_val = CAMERA_MCLK,.config_val = 0,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VIO,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VDIG,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VDIG,.config_val = GPIO_OUT_LOW,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_VREG,.seq_val = CAMERA_VANA,.config_val = 0,.delay = 0,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VANA,.config_val = GPIO_OUT_LOW,.delay = 1,},{.seq_type = CAMERA_POW_SEQ_GPIO,.seq_val = CAMERA_GPIO_VAF,.config_val = GPIO_OUT_LOW,.delay = 1,},},.size_down = 8,},},.sensor_output ={.output_format = SENSOR_BAYER,.connection_mode = SENSOR_MIPI_CSI,.raw_output = SENSOR_10_BIT_DIRECT,
#ifndef FLIP_MIRROR.filter_arrangement = SENSOR_RGGB,
#else.filter_arrangement = SENSOR_BGGR,
#endif},.output_reg_addr ={.x_output = 0x034C,.y_output = 0x034E,.line_length_pclk = 0x0342,.frame_length_lines = 0x0340,},.exp_gain_info ={.coarse_int_time_addr = 0x0202,.global_gain_addr = 0x0204,.vert_offset = IMX258_MAX_INTEGRATION_MARGIN,},.aec_info ={.min_gain = IMX258_MIN_GAIN,.max_gain = IMX258_MAX_GAIN,.max_analog_gain = IMX258_MAX_AGAIN,.max_linecount = 65525 - IMX258_MAX_INTEGRATION_MARGIN,},.sensor_num_frame_skip = 2,.sensor_num_HDR_frame_skip = 2,.sensor_max_pipeline_frame_delay = 2,.sensor_property ={.pix_size = 1.12, /* um */.sensing_method = SENSOR_SMETHOD_ONE_CHIP_COLOR_AREA_SENSOR,.crop_factor = 5.78,},.pixel_array_size_info ={.active_array_size ={.width = 4208,.height = 3120,},.left_dummy = 8,.right_dummy = 8,.top_dummy = 8,.bottom_dummy = 8,},.color_level_info ={.white_level = 1023,.r_pedestal = IMX258_DATA_PEDESTAL,.gr_pedestal = IMX258_DATA_PEDESTAL,.gb_pedestal = IMX258_DATA_PEDESTAL,.b_pedestal = IMX258_DATA_PEDESTAL,},.start_settings ={.reg_setting_a = START_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},.stop_settings ={.reg_setting_a = STOP_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},.groupon_settings ={.reg_setting_a = GROUPON_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},.groupoff_settings ={.reg_setting_a = GROUPOFF_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},.dualcam_master_settings ={.reg_setting_a = DUALCAM_MASTER_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,.size = 8,},.embedded_data_enable_settings ={.reg_setting_a = {},.addr_type = 0,.data_type = 0,.delay = 0,},.embedded_data_disable_settings ={.reg_setting_a = {},.addr_type = 0,.data_type = 0,.delay = 0,},.test_pattern_info ={.test_pattern_settings ={{.mode = SENSOR_TEST_PATTERN_OFF,.settings ={.reg_setting_a ={{0x0600, 0x0000, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,}},{.mode = SENSOR_TEST_PATTERN_SOLID_COLOR,.settings ={.reg_setting_a ={{0x0600, 0x0001, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,},},{.mode = SENSOR_TEST_PATTERN_COLOR_BARS,.settings ={.reg_setting_a ={{0x0600, 0x0002, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,},},{.mode = SENSOR_TEST_PATTERN_COLOR_BARS_FADE_TO_GRAY,.settings ={.reg_setting_a ={{0x0600, 0x0003, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,},},{.mode = SENSOR_TEST_PATTERN_PN9,.settings ={.reg_setting_a ={{0x0600, 0x0004, 0x00},},.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_WORD_DATA,.delay = 0,},},},.size = 5,.solid_mode_addr ={.r_addr = 0x0602,.gr_addr = 0x0604,.gb_addr = 0x0608,.b_addr = 0x0606,},},.init_settings_array ={.reg_settings ={{.reg_setting_a = INIT0_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},{.reg_setting_a = FLIP_MIRROR_SETTING,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},},.size = 2,},.res_settings_array ={.reg_settings ={/* Res 0 */{.reg_setting_a = RES0_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 1 */{.reg_setting_a = RES1_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 2 */{.reg_setting_a = RES2_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 3 */{.reg_setting_a = RES3_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 4 */{.reg_setting_a = RES4_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},/* Res 5 */{.reg_setting_a = RES5_REG_ARRAY,.addr_type = CAMERA_I2C_WORD_ADDR,.data_type = CAMERA_I2C_BYTE_DATA,.delay = 0,},},.size = 6,},.out_info_array ={.out_info ={ /* Res 0 */{.x_output = 4208,.y_output = 3120,.line_length_pclk = 5352,.frame_length_lines = 3224,.op_pixel_clk = 480000000,.binning_factor = 1,.min_fps = 7.500,.max_fps = 30.04,.mode = SENSOR_DEFAULT_MODE,.offset_x = 0,.offset_y = 0,.scale_factor = 1.000,.is_pdaf_supported = 1,.data_rate = 1296000000ULL * 4},/* Res 1 */{.x_output = 4208,.y_output = 2352,.line_length_pclk = 5352,.frame_length_lines = 2852,.op_pixel_clk = 458400000,.binning_factor = 1,.min_fps = 7.500,.max_fps = 30.03,.mode = SENSOR_DEFAULT_MODE,.offset_x = 0,.offset_y = 384,.scale_factor = 1.000,.is_pdaf_supported = 1,.data_rate = 1296000000ULL * 4},/* Res 2 */{.x_output = 2100,.y_output = 1560,.line_length_pclk = 5352,.frame_length_lines = 2851,.op_pixel_clk = 458400000,.binning_factor = 2,.min_fps = 7.500,.max_fps = 30.04,.mode = SENSOR_DEFAULT_MODE,.offset_x = 0,.offset_y = 0,.scale_factor = 1.000,.is_pdaf_supported = 0,.data_rate = 1296000000ULL * 4},/* Res 3*/{.x_output = 2100,.y_output = 1176,.line_length_pclk = 5352,.frame_length_lines = 1424,.op_pixel_clk = 458400000,.binning_factor = 2,.min_fps = 7.500,.max_fps = 60.14,.mode = SENSOR_HFR_MODE | SENSOR_DEFAULT_MODE,.offset_x = 0,.offset_y = 384,.scale_factor = 1.000,.is_pdaf_supported = 0,.data_rate = 1296000000ULL * 4},/* Res 4 */{.x_output = 1400,.y_output = 784,.line_length_pclk = 5352,.frame_length_lines = 948,.op_pixel_clk = 458400000,.binning_factor = 2,.min_fps = 7.500,.max_fps = 90.18,.mode = SENSOR_HFR_MODE,.offset_x = 0,.offset_y = 384,.scale_factor = 1.000,.is_pdaf_supported = 0,.data_rate = 1296000000ULL * 4},/* Res 5 */{.x_output = 1400,.y_output = 760,.line_length_pclk = 5352,.frame_length_lines = 828,.op_pixel_clk = 480000000,.binning_factor = 2,.min_fps = 7.500,.max_fps = 120.47,.mode = SENSOR_HFR_MODE,.offset_x = 0,.offset_y = 384,.scale_factor = 1.000,.is_pdaf_supported = 0,.data_rate = 1296000000ULL * 4},},.size = 6,},.csi_params ={.lane_cnt = 4,.settle_cnt = 0xB,.is_csi_3phase = 0,},.exposure_func_table ={.sensor_calculate_exposure = sensor_calculate_exposure,.sensor_fill_exposure_array = sensor_fill_exposure_array,},.meta_data_out_info_array ={.meta_data_out_info ={{/* set the meta half size which it should be to overcome the isp bug */.width = 80,.height = 1920,.stats_type = PD_STATS,.dt = IMX258_CSI_PD_ISTATS,},},.size = 1,},.sensor_capability = 0,.awb_func_table ={.sensor_fill_awb_array = 0,.awb_table_size = 0,},.parse_RDI_stats ={.parse_VHDR_stats = NULL,},.rolloff_config ={.enable = FALSE,.full_size_info ={.full_size_width = 0,.full_size_height = 0,.full_size_left_crop = 0,.full_size_top_crop = 0,},},.adc_readout_time = 0,.sensor_num_fast_aec_frame_skip = 0,.noise_coeff = {.gradient_S = 3.738032e-06,.offset_S = 3.651935e-04,.gradient_O = 6.396835e-11,.offset_O = -2.968624e-04,},.pdaf_config = {
#ifndef FLIP_MIRROR#include "imx258_pdaf.h"
#else#include "imx258_pdaf_flip_mirror.h"
#endif},
};#endif /* __IMX258_LIB_H__ */

2.probe流程

hal层函数 module_sensor_init()

hal层代码位于 \vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\module\module_sensor.c

//@\vendor\qcom\proprietary\mm-camera\mm-camera2\media-controller\modules\sensors\module\module_sensor.c
mct_module_t *module_sensor_init(const char *name)
{....../* module_sensor_probe_sensors */ret = sensor_init_probe(module_ctrl);/* find all the actuator, etc with sensor */ret = module_sensor_find_other_subdev(module_ctrl);/* Init sensor modules */ret = mct_list_traverse(module_ctrl->sensor_bundle, module_sensors_subinit,NULL);/* intiialize the eeprom */ret = mct_list_traverse(module_ctrl->sensor_bundle, module_sensor_init_eeprom,module_ctrl->eebin_hdl);/* Create chromatix manager */ret = mct_list_traverse(module_ctrl->sensor_bundle, module_sensor_init_chromatix, module_ctrl->eebin_hdl);/* Initialize dual cam stream mutex */pthread_mutex_init(&module_ctrl->dual_cam_mutex, NULL);}

hal层函数 sensor_init_probe()

在 sensor_init_eebin_probe()中,我们可以看出,知道camera 数量后,在for循环中,依次调用 sensor_probe()函数初始化每个camera,我们当前代码中有三个camera,这面就会调用三次sensor_probe()

/** sensor_init_probe: probe available sensors**  @module_ctrl: sensor ctrl pointer**  Return: 0 for success and negative error on failure**  1) Find sensor_init subdev and it*  2) Open EEPROM subdev and check whether any sensor library*  is present in EEPROM*  3) Open sensor libraries present in dumped firware location*  4) Check library version of EEPROM and dumped firmware*  5) Load latest of both*  6) Pass slave information, power up and probe sensors*  7) If probe succeeds, create video node and sensor subdev*  8) Repeat step 2-8 for all sensor libraries present in*  EEPROM*  9) Repeat step 6-8 for all sensor libraries present in*  absolute path**/boolean sensor_init_probe(module_sensor_ctrl_t *module_ctrl)
{......ret = sensor_init_eebin_probe(module_ctrl, sd_fd);......RETURN_ON_FALSE(sensor_init_xml_probe(module_ctrl, sd_fd));
}static boolean sensor_init_eebin_probe(module_sensor_ctrl_t *module_ctrl,int32_t sd_fd)
{SLOW("Enter");bin_ctl.cmd = EEPROM_BIN_GET_NUM_DEV;bin_ctl.ctl.q_num.type = EEPROM_BIN_LIB_SENSOR;bin_ctl.ctl.q_num.num_devs = 0;eebin_interface_control(module_ctrl->eebin_hdl, &bin_ctl);num_devs = bin_ctl.ctl.q_num.num_devs;SLOW("num_devs:%d", num_devs);for (i = 0; i < num_devs; i++ ) {bin_ctl.cmd = EEPROM_BIN_GET_DEV_DATA;bin_ctl.ctl.dev_data.type = EEPROM_BIN_LIB_SENSOR;bin_ctl.ctl.dev_data.num = i;rc = eebin_interface_control(module_ctrl->eebin_hdl, &bin_ctl);if (rc < 0)continue;ret = sensor_probe(module_ctrl,sd_fd,bin_ctl.ctl.dev_data.name,bin_ctl.ctl.dev_data.path,NULL,FALSE,FALSE);if (ret == FALSE) {SINFO("failed: to load %s", bin_ctl.ctl.dev_data.name);}}SLOW("Exit");return TRUE;
}

虽然前面也有 sensor_probe ,但正常流程中,我们走的不是eebin ,
而是通过 sensor_init_xml_probe(module_ctrl, sd_fd) 来解析
vendor/qcom/proprietary/mm-camera/mm-camera2/media-controller/modules/sensors/configs/sdm660_camera.xml 文件,
通过 xml 中 配置的sensor name 和 subdev name,来下发参数。

详细如下:

->首先拼凑 sdm660_camera.xml 的字符串路径
->odm 公司如果要自已定制路径的话,也可以通过 属性 persist.vendor.camera.customer.config 来配置。
->开始解析 sdm660_camera.xml文件中的 CameraConfigurationRoot 节点。
->通过 CameraModuleConfig 的数量可以知道 ,当前支持多少个camera。
->解析每个camera 的信息,并且在 sensor_probe[]数组中检查当前sensor 是否已经probe 过了。
->根据xml 中解析的结果,调用 sensor_probe 开始正式probe。
->当所有xml 中的项都遍历完成后,关闭xml。


static boolean sensor_init_xml_probe(module_sensor_ctrl_t *module_ctrl, int32_t sd_fd)
{// 首先拼凑 sdm660_camera.xml 的字符串路径/* Create the xml path from data partition */snprintf(config_xml_name, BUFF_SIZE_255, "%s%s", CONFIG_XML_PATH, CONFIG_XML);// odm 公司如果要自已定制路径的话,也可以通过 属性 persist.vendor.camera.customer.config 来配置if (access(config_xml_name, R_OK)) {SHIGH(" read fail (non-fatal) %s. Trying from system partition",config_xml_name);if (csidtg_enable) {/* Create the CSIDTG xml path from system partition */snprintf(config_xml_name, BUFF_SIZE_255, "%s%s", CONFIG_XML_SYSTEM_PATH, CSIDTG_CONFIG_XML);} else {property_get("persist.vendor.camera.customer.config", custom_xml_name, CONFIG_XML);/* Create the xml path from system partition */snprintf(config_xml_name, BUFF_SIZE_255, "%s%s",CONFIG_XML_SYSTEM_PATH, custom_xml_name);}}SHIGH("reading from file %s", config_xml_name);// 开始解析 sdm660_camera.xml文件中的 CameraConfigurationRoot 节点/* Get the Root pointer and Document pointer of XMl file */ret = sensor_xml_util_load_file(config_xml_name, &docPtr, &rootPtr, "CameraConfigurationRoot");// 通过 CameraModuleConfig 的数量可以知道 ,当前支持多少个camera/* Get number of camera module configurations */num_cam_config = sensor_xml_util_get_num_nodes(rootPtr, "CameraModuleConfig");SLOW("num_cam_config = %d", num_cam_config);xmlConfig.docPtr = docPtr;xmlConfig.configPtr = &camera_cfg;// 解析每个camera 的信息,并且在 sensor_probe[]数组中检查当前sensor 是否已经probe 过了for (i = 0; i < num_cam_config; i++) {nodePtr = sensor_xml_util_get_node(rootPtr, "CameraModuleConfig", i);RETURN_ON_NULL(nodePtr);xmlConfig.nodePtr = nodePtr;ret = sensor_xml_util_get_camera_probe_config(&xmlConfig, "CameraModuleConfig");if (slot_probed[camera_cfg.camera_id]) {SHIGH("slot %d already probed", camera_cfg.camera_id);continue;}// 根据xml 中解析的结果,调用 sensor_probe 开始正式proberc = sensor_probe(module_ctrl,sd_fd,camera_cfg.sensor_name,NULL,&xmlConfig,FALSE,FALSE);} else {slot_probed[camera_cfg.camera_id] = TRUE;}}// 关闭xml 文件
XML_PROBE_EXIT:sensor_xml_util_unload_file(docPtr);return ret;
}

hal层函数 sensor_probe() 下发 CFG_SINIT_PROBE

进入 sensor_probe()函数:
在函数中可以看出,首先会调用 sensor_load_library()加载vendor 中camera sensor 的库文件。
接着通过 IOCTRL 向通过下发 CFG_SINIT_PROBE消息,通知驱动层作probe 初始化。

/** sensor_probe: probe available sensors*  @fd: sensor_init fd*  @sensor_name: sensor name*  Return: TRUE for success and FALSE for failure*  1) Open sensor library*  2) Pass slave information, probe sensor*  3) If probe succeeds, create video node and sensor subdev is*  created in kernel**/
static boolean sensor_probe(module_sensor_ctrl_t *module_ctrl, int32_t fd, const char *sensor_name, char *path, struct xmlCameraConfigInfo *xmlConfig, boolean is_stereo_config, boolean bypass_video_node_creation)
{/* Load sensor library */rc = sensor_load_library(sensor_name, sensor_lib_params, path);....../* Pass slave information to kernel and probe */memset(&cfg, 0, sizeof(cfg));cfg.cfgtype = CFG_SINIT_PROBE;cfg.cfg.setting = slave_info;if (ioctl(fd, VIDIOC_MSM_SENSOR_INIT_CFG, &cfg) < 0) {SINFO("[%s]CFG_SINIT_PROBE failed",sensor_name);ret = FALSE;goto ERROR;}if (cfg.probed_info.session_id == 0 && FALSE == bypass_video_node_creation) {SINFO("[%s] probe failed.", sensor_name);ret = FALSE;goto ERROR;}SHIGH("[%s] probe succeeded: session_id(%d) entity_name(%s)",sensor_name, cfg.probed_info.session_id, cfg.entity_name);......
}

Kernel Ioctl 函数 msm_sensor_init_subdev_ioctl()

上层IOCTRL 命令下发到kernerl 中,进入msm_sensor_init_subdev_ioctl()中,接着转发到msm_sensor_driver_cmd()中,调用 msm_sensor_driver_probe()函数..

// @\kernel\msm-4.4\drivers\media\platform\msm\camera_v2\sensor\msm_sensor_init.c
static long msm_sensor_init_subdev_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
{switch (cmd) {case VIDIOC_MSM_SENSOR_INIT_CFG:rc = msm_sensor_driver_cmd(s_init, arg);break;}
}/* Static function definition */
static int32_t msm_sensor_driver_cmd(struct msm_sensor_init_t *s_init, void *arg)
{switch (cfg->cfgtype) {case CFG_SINIT_PROBE:mutex_lock(&s_init->imutex);s_init->module_init_status = 0;rc = msm_sensor_driver_probe(cfg->cfg.setting,&cfg->probed_info,cfg->entity_name);mutex_unlock(&s_init->imutex);if (rc < 0)pr_err("%s failed (non-fatal) rc %d", __func__, rc);break;case CFG_SINIT_PROBE_DONE:s_init->module_init_status = 1;wake_up(&s_init->state_wait);break;case CFG_SINIT_PROBE_WAIT_DONE:msm_sensor_wait_for_probe_done(s_init);break;return rc;
}

probe函数 msm_sensor_driver_probe()

从上层开始下发probe 命令,至此正式开始probe 初始化 camera,代码如下:

->初始化并分配 slave_info 内存
->将上层下发的 slave_info保存在 slave_info32 中
->将 slave_info32 中的信息保存到 slave_info中。
->打印 slave info 信息
->通过camera id 获取到对应的 camera sensor ctrol 信息,也就是对应的camera 的dts 信息。
->检测sensor 是否已经probe 过了,如果不是,直接跳过if 进行probe
->获取camera的power settting
->初始化 msm_camera_slave_info 结构体变量 camera_info ,用于保存 camera 的信息
->配置camera i2c 相关信息
->往s_ctrl 中填充 上下电相关信息
->解析该camera 中所有外设 dts 节点信息 "qcom,eeprom-src"、"qcom,actuator-src"、"qcom,led-     flash-src"
->调用 sensor_power_up()给sensor 上电,开始probe sensor ,上电时调用 ->msm_sensor_check_id(),然后调用msm_sensor_match_id()检测 sensor id 是否区配。
->创建对应的 /dev/videox 节点 及 /dev/mediax 的节点
->probe 成功后下电
->更新s_ctrl 结构体信息

// @ kernel\msm-4.4\drivers\media\platform\msm\camera_v2\sensor\msm_sensor_driver.c
int32_t msm_sensor_driver_probe(void *setting, struct msm_sensor_info_t *probed_info, char *entity_name)
{struct msm_sensor_ctrl_t            *s_ctrl = NULL;struct msm_camera_cci_client        *cci_client = NULL;struct msm_camera_sensor_slave_info *slave_info = NULL;struct msm_camera_slave_info        *camera_info = NULL;// 1. 初始化并分配 slave_info 内存/* Allocate memory for slave info */slave_info = kzalloc(sizeof(*slave_info), GFP_KERNEL);if (is_compat_task()) {// 2. 将上层下发的 slave_info保存在 slave_info32 中struct msm_camera_sensor_slave_info32 *slave_info32 =kzalloc(sizeof(*slave_info32), GFP_KERNEL);copy_from_user((void *)slave_info32, setting, sizeof(*slave_info32));// 3. 将 slave_info32 中的信息保存到 slave_info中。strlcpy(slave_info->actuator_name, slave_info32->actuator_name, sizeof(slave_info->actuator_name));strlcpy(slave_info->eeprom_name, slave_info32->eeprom_name, sizeof(slave_info->eeprom_name));strlcpy(slave_info->sensor_name, slave_info32->sensor_name, sizeof(slave_info->sensor_name));strlcpy(slave_info->ois_name, slave_info32->ois_name, sizeof(slave_info->ois_name));strlcpy(slave_info->flash_name, slave_info32->flash_name, sizeof(slave_info->flash_name));slave_info->addr_type = slave_info32->addr_type;slave_info->camera_id = slave_info32->camera_id;slave_info->i2c_freq_mode = slave_info32->i2c_freq_mode;slave_info->sensor_id_info = slave_info32->sensor_id_info;slave_info->slave_addr = slave_info32->slave_addr;slave_info->module_id_info =  slave_info32->module_id_info;slave_info->power_setting_array.size = slave_info32->power_setting_array.size;slave_info->power_setting_array.size_down = slave_info32->power_setting_array.size_down;slave_info->power_setting_array.size_down = slave_info32->power_setting_array.size_down;slave_info->power_setting_array.power_setting = compat_ptr(slave_info32->power_setting_array.power_setting);slave_info->power_setting_array.power_down_setting = compat_ptr(slave_info32->power_setting_array.power_down_setting);slave_info->sensor_init_params = slave_info32->sensor_init_params;slave_info->output_format =slave_ info32->output_format;kfree(slave_info32);  // 保存完毕合释放 slave_info32 内存。} else
#endif{if (copy_from_user(slave_info,(void *)setting, sizeof(*slave_info))) {pr_err("failed: copy_from_user");rc = -EFAULT;goto free_slave_info;}}// 4. 打印 slave info 信息/* Print slave info */CDBG("camera id %d Slave addr 0x%X addr_type %d\n", slave_info->camera_id, slave_info->slave_addr, slave_info->addr_type);CDBG("sensor_id_reg_addr 0x%X sensor_id 0x%X sensor id mask %d", slave_info->sensor_id_info.sensor_id_reg_addr, slave_info->sensor_id_info.sensor_id,slave_info->sensor_id_info.sensor_id_mask);CDBG("power up size %d power down size %d\n",slave_info->power_setting_array.size,slave_info->power_setting_array.size_down);CDBG("position %d",slave_info->sensor_init_params.position);CDBG("mount %d",slave_info->sensor_init_params.sensor_mount_angle);// 5. 通过camera id 获取到对应的 camera sensor ctrol 信息,也就是对应的camera 的dts 信息。/* Extract s_ctrl from camera id */s_ctrl = g_sctrl[slave_info->camera_id];CDBG("s_ctrl[%d] %pK", slave_info->camera_id, s_ctrl);// 6. 检测sensor 是否已经probe 过了,如果不是,直接跳过if 进行probeif (s_ctrl->is_probe_succeed == 1) {/** Different sensor on this camera slot has been connected* and probe already succeeded for that sensor. Ignore this* probe */......}// 7. 获取camera的power setttingrc = msm_sensor_get_power_settings(setting, slave_info,&s_ctrl->sensordata->power_info);// 8. 初始化 msm_camera_slave_info 结构体变量 camera_info ,用于保存 camera 的信息camera_info = kzalloc(sizeof(struct msm_camera_slave_info), GFP_KERNEL);s_ctrl->sensordata->slave_info = camera_info;/* Fill sensor slave info */camera_info->sensor_slave_addr = slave_info->slave_addr;camera_info->eeprom_slave_addr = slave_info->module_id_info.module_slave_id;camera_info->eeprom_module_reg_addr = slave_info->module_id_info.module_id_reg_addr;camera_info->eeprom_module_id =  slave_info->module_id_info.module_id;camera_info->eeprom_master_id = slave_info->module_id_info.master_id;camera_info->sensor_id_reg_addr =slave_info->sensor_id_info.sensor_id_reg_addr;camera_info->sensor_id = slave_info->sensor_id_info.sensor_id;camera_info->sensor_id_mask = slave_info->sensor_id_info.sensor_id_mask;s_ctrl->sensor_i2c_client->addr_type = slave_info->addr_type;if (s_ctrl->sensor_i2c_client->client)s_ctrl->sensor_i2c_client->client->addr =camera_info->sensor_slave_addr;// 9. 配置camera i2c 相关信息。cci_client = s_ctrl->sensor_i2c_client->cci_client;cci_client->cci_i2c_master = s_ctrl->cci_i2c_master;cci_client->sid = slave_info->slave_addr >> 1;cci_client->retries = 3;cci_client->id_map = 0;cci_client->i2c_freq_mode = slave_info->i2c_freq_mode;// 10. 往s_ctrl 中填充 上下电相关信息 /* Parse and fill vreg params for powerup settings */rc = msm_camera_fill_vreg_params(s_ctrl->sensordata->power_info.cam_vreg,s_ctrl->sensordata->power_info.num_vreg,s_ctrl->sensordata->power_info.power_setting,s_ctrl->sensordata->power_info.power_setting_size);/* Parse and fill vreg params for powerdown settings*/rc = msm_camera_fill_vreg_params(s_ctrl->sensordata->power_info.cam_vreg,s_ctrl->sensordata->power_info.num_vreg,s_ctrl->sensordata->power_info.power_down_setting,s_ctrl->sensordata->power_info.power_down_setting_size);CSID_TG:/* Update sensor, actuator and eeprom name in*  sensor control structure */s_ctrl->sensordata->sensor_name = slave_info->sensor_name;s_ctrl->sensordata->eeprom_name = slave_info->eeprom_name;s_ctrl->sensordata->actuator_name = slave_info->actuator_name;s_ctrl->sensordata->ois_name = slave_info->ois_name;s_ctrl->sensordata->flash_name = slave_info->flash_name;/** Update eeporm subdevice Id by input eeprom name*/// 11. 解析该camera 中所有外设节点信息 "qcom,eeprom-src"、"qcom,actuator-src"、"qcom,led-flash-src"rc = msm_sensor_fill_eeprom_subdevid_by_name(s_ctrl);   =====> src_node = of_parse_phandle(of_node, "qcom,eeprom-src", i);/** Update actuator subdevice Id by input actuator name*/rc = msm_sensor_fill_actuator_subdevid_by_name(s_ctrl);=====> src_node = of_parse_phandle(of_node, "qcom,actuator-src", 0);rc = msm_sensor_fill_ois_subdevid_by_name(s_ctrl);rc = msm_sensor_fill_flash_subdevid_by_name(s_ctrl);=====> src_node = of_parse_phandle(of_node, "qcom,led-flash-src", 0);// 12. 调用 sensor_power_up() 给sensor 上电,开始probe sensor ,上电时调用 msm_sensor_check_id(),然后调用msm_sensor_match_id()检测sensor id 是否区配。/* Power up and probe sensor */rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);==================>@ \kernel\msm-4.4\drivers\media\platform\msm\camera_v2\sensor\msm_sensor.cfor (retry = 0; retry < 3; retry++) {/* session is secure */s_ctrl->sensor_i2c_client->i2c_func_tbl =&msm_sensor_secure_func_tbl;rc = msm_camera_power_up(power_info, s_ctrl->sensor_device_type, sensor_i2c_client);rc = msm_sensor_check_id(s_ctrl);========> rc = msm_sensor_match_id(s_ctrl);<=======if (rc < 0) {msm_camera_power_down(power_info,s_ctrl->sensor_device_type, sensor_i2c_client);msleep(20);continue;} else {break;}}<==================// 13. 创建对应的 /dev/videox 节点 及 /dev/mediax 的节点pr_err("%s probe succeeded", slave_info->sensor_name);/** Create /dev/videoX node, comment for now until dummy /dev/videoX* node is created and used by HAL*/if (s_ctrl->sensor_device_type == MSM_CAMERA_PLATFORM_DEVICE)rc = msm_sensor_driver_create_v4l_subdev(s_ctrl);// 14. probe 成功后下电/* Power down */s_ctrl->func_tbl->sensor_power_down(s_ctrl);rc = msm_sensor_fill_slave_info_init_params(slave_info,s_ctrl->sensordata->sensor_info);rc = msm_sensor_validate_slave_info(s_ctrl->sensordata->sensor_info);/* Update sensor mount angle and position in media entity flag */is_yuv = (slave_info->output_format == MSM_SENSOR_YCBCR) ? 1 : 0;mount_pos = ((s_ctrl->is_secure & 0x1) << 26) | is_yuv << 25 |(s_ctrl->sensordata->sensor_info->position << 16) |((s_ctrl->sensordata->sensor_info->sensor_mount_angle / 90) << 8);s_ctrl->msm_sd.sd.entity.flags = mount_pos | MEDIA_ENT_FL_DEFAULT;/*Save sensor info*/s_ctrl->sensordata->cam_slave_info = slave_info;// 15. 更新s_ctrl 结构体信息msm_sensor_fill_sensor_info(s_ctrl, probed_info, entity_name);/** Set probe succeeded flag to 1 so that no other camera shall* probed on this slot*/s_ctrl->is_probe_succeed = 1;return rc;
}

3.camx-chi框架probe 流程 

Camx 刚接触的时候对于这个xml 一脸懵逼,实际上和mm-camera差不多就是以xml node节点的方式标准化了driver相关的code,exposure 和 gain的逻辑实现还是在同级目录的cpp中,并且将 xml 的解析工作放在了 out/target/<product>/gen/STATIC_LIBERARIES/libcamxgenerated_intermediates/generated/ 中主要是包含了:

g_chromatix : tuning 相关xml的解析code
g_facedetection :人脸检测相关xml的解析code
g_parser :主要的解析manager 流程图中的 imageSensorModuleDataManager 的 初始化调到了,此目录下的paramtersetmanager.cpp 的 LoadBinaryParameters() 再根据type不同进行各个sub module xml 的读取。
g_sensor:camera sensor xml 解析code,包括:actuator, eeprom, flash, moduleconfig, ois ,sensor, sensormodule, eebin主要看此目录下的 camxsenordriver.cpp ,主要功能把 sensor driver xml 的各个节点内容全都 load 一遍。看懂了这里剩下的就是 xml 的填空工作啦。

详细的加载过程流程图:

camx 的sensor probe 主要流程:

camera 的 probe success 主要需要 xml 中 salveAddress 、sensorIdRegAddr 、sensorID 和 powerUpSequence 这个4个参数(当然还有一个前提是你的 kenrel 的i2c clock power gpio等配置的没有问题),这时候还用不到 initsetting 等等其他参数,毕竟你sensor 还没有读到正确寄存器值,详细过程见流程图。

参考链接:

【高通SDM660平台】(2) --- Camera Kernel 驱动层代码逻辑分析_CielleeX的博客-CSDN博客

​​​​​​【高通SDM660平台 Android 10.0】(10) --- Camera Sensor lib 与 Kernel Camera Probe 代码分析_CielleeX的博客-CSDN博客

高通camera驱动 camx read xml 和 probe 流程 和 sensor I2C读写的波形图 (三)_shangbolei的博客-CSDN博客_camera probe流程

Camera Probe 代码分析相关推荐

  1. 【高通SDM660平台 Android 10.0】(10) --- Camera Sensor lib 与 Kernel Camera Probe 代码分析

    [高通SDM660平台 Android 10.0]Camera Sensor lib 与 Kernel Camera Probe 代码分析 一.libmmcamera_imx258.so 代码分析 1 ...

  2. 【高通SDM660平台 Android 10.0】(12) --- Camera Chromatix 代码分析

    [高通SDM660平台 Android 10.0]Qcom Camera Daemon 代码分析 一.chromatix_imx258_lc898217xc 目录 1.1 例:imx258_lc898 ...

  3. Android MTK Camera驱动代码分析

    一.Camera调用过程:      imgsensor起到承上启下的作用,在系统起来时会创建整个camera驱动运行的环境,其中主要的文件和函数如下框图所示,先设备挂载时会调用注册platform设 ...

  4. qualcomm的camera马达驱动代码分析

    前言: 主要给大家介绍基于高通平台的camera马达驱动的编写过程,此过程会涉及到手机对焦功能实现的原理以及如何通过I2C子系统实现数据传输等过程. 一.手机自动对焦原理 手机自动对焦功能是通过将摄像 ...

  5. Linux stmac网卡代码分析----probe

    probe 主要分析一下驱动的主要框架,必要地方细致分析下 文件位置: drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c 从文件的最后看起: modul ...

  6. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

  7. pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

  8. 模块加载过程代码分析1

    一.概述 模块是作为ELF对象文件存放在文件系统中的,并通过执行insmod程序链接到内核中.对于每个模块,系统都要分配一个包含以下数据结构的内存区. 一个module对象,表示模块名的一个以null ...

  9. MTK6589下传感器框架结构和代码分析以及传感器的参数指标

    MTK6589下传感器框架结构和代码分析以及传感器的参数指标 作者:韩炜彬  中国当代著名嵌入式研究专家 一.      模块框架 1)配置 路径:Alps/mediatek/config/$(pro ...

  10. VINS-Mono代码分析与总结(完整版)

    VINS-Mono代码分析总结 参考文献 1 VINS-Mono: A Robust and Versatile Monocular Visual-Inertial State Estimator, ...

最新文章

  1. L1-006 连续因子
  2. 深入浅析Python 函数注解与匿名函数
  3. 构建良好的敏捷团队氛围
  4. C++ number of positive divisors计算正除数的实现算法(附完整源码)
  5. WinSock三种选择I/O模型
  6. 针对新手的Java EE7和Maven项目–第6部分
  7. python如何实时捕捉cmd显示_如何从Python脚本中捕获Python解释器和/或CMD.EXE的输出? -问答-阿里云开发者社区-阿里云...
  8. java死锁怎么用jvm调试_jvm 内存dump、gc查看、线程死锁,jmap、jstack、jstat
  9. python高斯核函数_机器学习:SVM(核函数、高斯核函数RBF)
  10. C语言的考试系统,C语言考试系统.doc
  11. C语言之一个有趣的关机程序
  12. 英语口语智能测试软件,口语易英语口语智能评测系统(英语口语训练软件)V6.91 最新版...
  13. python学习笔记——类与对象、常用函数
  14. C语言:设备管理系统
  15. 多级延迟效果器:D16 Group Tekturon for Mac()
  16. 使用ALLMAPS进行辅助组装得到准染色体水平基因组
  17. CSR8675模组,支持蓝牙APTX
  18. Android win10 平板 省电,小编解答win10系统Mobile设置更省电的图文办法
  19. EJB初探(二)为什么需要EJB
  20. Tomcat的部署学习

热门文章

  1. 数字图像处理(21): 图像金字塔(高斯金字塔 与 拉普拉斯金字塔)
  2. cocos creator 打包apk_Cocos Creator Android打包 apk
  3. 无法定位链接器!请检查 tools\link.ini 中的配置是否正确。 易语言5.9版本 静态编译
  4. AIR是什么?.air文件如何打开?flex如何运行air文件
  5. Java UDP 客户端服务器程序示例
  6. 汉字转拼音(同音异形)-工具
  7. java数据透视表_Java 创建 Excel 数据透视表
  8. delphi调用https
  9. 如何查看java安装成功_如何查看java是否安装成功
  10. 《乔布斯传.神一样的传奇》读后感