Camera点亮
范围
本章节概述了 RDK-S100 camera bring up 的过程,用于帮助读者快速了解并掌握 RDK-S100 camera 框架,如何快速的新增 camera 配置,并点亮 camera。
该部分内容以 RDK-S100 开发板 + imx219 camera 模组为例,进行配置讲解,其他硬件平台或者 camera 模组以实际情况为准。
准备工作
硬件资源:RDK-S100 开发板、camera 模组。
软件资源:系统 SDK、camera 驱动源码、sensor datasheet、sensor 的 initialize settings 等。
RDK-S100 开发板 camera 相关硬件资源如下:
RDK-S100 | MIPI host | I2C | gpio_en | gpio_lpwm_mclk | 其他 |
---|---|---|---|---|---|
RX0 可接 imx219 模组 | 0 4 lane | 1 | SPI1_CSN0 gpio_number:502 | 可通过拨码开关进行选择 • LPWM0_DOUT0 gpio_number:456 • mclk 24Mhz | 注意: imx219 模组本身外接 24M 晶振,所以不需要 SOC 端输出 mclk |
RX1 可接 imx219 模组 | 1 4 lane | 2 | SD_WPROT gpio_number:494 | 可通过拨码开关进行选择 • LPWM0_DOUT1 gpio_number:457 • mclk 24Mhz | 注意: imx219 模组本身外接 24M 晶振,所以不需要 SOC 端输出 mclk |
RX4 用于接 serdes | 4 4 lane | 3 | 暂无介绍 | 暂无介绍 | 解串器 max96712, addr: 0x29 poc: max20087, addr: 0x28 |
硬件连接示意图:
添加新 sensor 点亮步骤
RDK-S100 平台进行新硬件和新 camera 适配时,需要修改平台设备树 dts,camera 驱动库及相关配置文件即可,系统库一般无需改动。
dts 修改
sensor gpio 配置
确保新硬件使用的 sensor gpio 在 drobot-s100-pinctrl.dtsi --> pinctrl_video --> video_gpio节点中有配置,这样在开机启动时,系统才会将对应的 pin 设置为 gpio,用户程序方可以操作 pin。
vcon 是 RDK-S100 camera 用于管理 sensor 硬件相关的 dts 节点,如果 sensor 需要对应的时序才能正常启动,则需要在该节点中配置对应的 gpio。请根据硬件连接的实际情况配置,该相关信息可以从原理图及 pin list 中获取。
// dts: 在对应 vcon node 中设置 gpio,注意 vcon 端口号与 mipi rx 端口号 一 一对应
// vcon0 -- RX0
// ....
// vcon3 -- RX3
&vin_vcon0 {
bus = <2>;
gpio_poc = <0>;
gpio_des = <0>;
sensor_err = <0>;
//gpio_oth = <444 445>; // imx219 无需配置,所以这里是注释掉,为空
lpwm_chn = <0 1 2 3>;
rx_phy = <2 0>;
};
sensor i2c 配置
I2C bus number 需要在 dts vcon 中与 MIPI RX 端口进行绑定,请根据硬件连接的实际情况配置,该相关信息可以从原理图中获取。
// 在对应 vcon 中设置 i2c bus,如 RX0 设置 I2C2
&vin_vcon0 {
bus = <2>;
gpio_poc = <0>;
gpio_des = <0>;
sensor_err = <0>;
lpwm_chn = <0 1 2 3>;
rx_phy = <2 0>;
};
mclk 配置
RDK-S100 底座硬件暂时不支持 SOC 输出的 mclk 连接到 sensor 模组,目前只支持外带晶振的模组。
dts 修改验证
一般 dts 配置正确,硬件正确连接后,保证 sensor 供电及 mclk 正常 ,便可以使用 i2cdetect 检测到模组的 i2c 地址。 通过 echo 命令进行控制 sensor 上电或者 reset (注:该说明使用 imx219模组无需操作 gpio)
echo 502 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio502/direction
echo 1 > /sys/class/gpio/gpio502/value
echo 502 > /sys/class/gpio/unexport
使用 i2cdetect 检测 sensor i2c地址。如果检测到正确的地址,如下图所示,则表示 dts 配置正确,否则需要检查dts 配置。
![]() | ![]() |
---|
sensor 驱动文件添加
不同厂家的 sensor,都会搭配风格各异的 driver 和 setting。因此需要将原厂 sensor 驱动,转换成 RDK-S100 camera 驱动代码,并编译生成 so 库,然后将 so 库拷贝到设备的 /usr/hobot/lib/sensor/ 目录下。需要说明的是,在 mipi start 之前,必须保证 sensor 没有开流。
系统 SDK 目录 hobot-camera/drivers/sensor 下提供了 sensor 驱动模板文件 imx219_utility.c 以及适配过的其他 sensor 驱动,当添加新 camera sensor 支持时,可以仿照该部分文件进行修改。
#ifdef CAMERA_FRAMEWORK_HBN
SENSOR_MODULE_F(imx219, CAM_MODULE_FLAG_A16D8);
sensor_module_t imx219 = {
.module = SENSOR_MNAME(imx219),
#else
sensor_module_t imx219 = {
.module = "imx219",
#endif
.init = sensor_init,
.start = sensor_start,
.stop = sensor_stop,
.deinit = sensor_deinit,
.aexp_gain_control = sensor_aexp_gain_control,
.aexp_line_control = sensor_aexp_line_control,
.power_on = sensor_poweron,
.power_off = sensor_poweroff,
.userspace_control = sensor_userspace_control,
};
如上代码所示,RDK-S100 camera 框架下的 sensor 驱动接口包含在 sensor_module_t 的结构体中,文件名、结构体名和 module 字段要统一,例如文件名为 imx219_utility.c,那么结构体名和 module 字段要统一为 imx219。对于新 sensor 点亮,下列函数需要用户自行实现:
• init:sensor 初始化、setting 下发
• deinit:sensor 去初始化
• start:sensor 开流
• stop:sensor 关流
• power on: sensor 上电
• power off: sensor 下电
• aexp_gain_control: sensor gain 增益控制
• aexp_line_control: sensor line 曝光控制
• userspace_control: 用户回调功能开启控制
对于 3A 控制,系统支持驱动注册和应用层回调两种方式,默认使用应用层回调函数的方式,接口定义如下:
函数 | 功能 | 传入参数 |
---|---|---|
aexp_gain_control | sensor 增益控制 | info:sensor 总线信息 mode:senosr 运行模式;linear/hdr/pwl again:sensor again 参数,最大4个 dgain:sensor dgain 参数,最大4个 gain_num:sensor gain 参数个数 |
aexp_line_control | sensor 曝光控制 | info:sensor 总线信息 mode:senosr 运行模式;linear/hdr/pwl line:sensor line 参数,最大4个 line_num:sensor line 参数个数 |
awb_control | sensor 端 awb 控制 | info:sensor 总线信息; mode:senosr 运行模式;linear/hdr/pwl rgain:sensor rgain bgain:sensor bgain grgain:sensor rrgain gbgain:sensor gbgain |
userspace_control | hal 层各类控制开关 | port:sensor 端口号 enable:使能用户回调控制开关,默认全部关闭。 位定义: #define HAL_LINE_CONTROL 0x00000001 #define HAL_GAIN_CONTROL 0x00000002 #define HAL_AWB_CONTROL 0x00000004 |
如下代码是对 sensor 驱动主要结构体的初始化,需要根据每个 sensor 的实际情况来对应填写
// sensor 实际输出的宽度
turning_data->sensor_data.active_width = 1920;
// sensor 实际输出的高度
turning_data.sensor_data.active_height = 1080;
// 每秒多少曝光行,计算公式为1/每行时间或者(fps*vts),其中vts在不同sensor的里面的名字可能有所不同,
//可能是frame_length、vts等,但含义都是每帧的所含的总共行数,
//包括有效行和blanking。lines_per_second 亦可以理解成HMAX,需要注意的是有些sensor 无HMAX 概念
turning_data.sensor_data.lines_per_second = vts * sensor_info->fps;
// 短曝光最大曝光时间(短曝光每帧最大曝光行数),短曝光每帧最大曝光行数可以通过公式
//单帧曝光时间/单行曝光时间,
//即(1/fps)/(1/lines_per_second)
turning_data.sensor_data.exposure_time_max = vts;
// a_gain最大倍数,举一个例子,turning_data.sensor_data.analog_gain_max =126,
//最大倍率计算公式就是2^(X/32),其中X就是126,X这个值每一个sensor厂家不一样,
//需要从sensor手册或者sensor厂家查找得到;最大倍率也可以这样得到:先获取sensor最大增益,
//然后查找J5-ISP的增益表,得到对应的索引值,该索引值就是最大倍率。
turning_data.sensor_data.analog_gain_max = 109;
turning_data.sensor_data.digital_gain_max = 0;
//短曝光最小曝光时间(短曝光每帧最小曝光行数),
//每行的曝光时间可以用公式1秒/(帧率*(有效行+blank))即1/lines_per_second推算得出
turning_data.sensor_data.exposure_time_min = 1;
//长曝光最大曝光时间(长曝光每帧最 大曝光行数)
turning_data.sensor_data.exposure_time_long_max = vts;
// 填充 sensor 位宽data_width、bayer_start(RGGB pattern start (R/Gr/Gb/B))、
// bayer_pattern(RGGB/RCCC/RIrGB/RGIrB) 信息
sensor_data_bayer_fill(&turning_data.sensor_data, 10, (uint32_t)BAYER_START_R, (uint32_t)BAYER_PATTERN_RGGB);
// 填充 exposure_max_bit_width(pwl mode bits ) 信息
sensor_data_bits_fill(&turning_data.sensor_data, 12);
// setting stream ctrl
// 开流、关流
turning_data.stream_ctrl.data_length = 1;
// again lut表,fireware根据index索引lut表,查找sensor对应的寄存器值,lut表区分a_gain/d_gain,
// lut表格大小:again_lut[again_control_num][256], dgain_lut[dgain_control_num][256]
turning_data.normal.again_lut = malloc(256 * sizeof(uint32_t));
if (turning_data.normal.again_lut != NULL)
{
memset(turning_data.normal.again_lut, 0xff, 256 * sizeof(uint32_t));
memcpy(turning_data.normal.again_lut, imx219_gain_lut,
sizeof(imx219_gain_lut));
}
turning_data.normal.dgain_lut = malloc(256*sizeof(uint32_t));
if (turning_data.normal.dgain_lut != NULL) {
memset(turning_data.normal.dgain_lut, 0xff, 256*sizeof(uint32_t));
memcpy(turning_data.normal.dgain_lut, imx219_dgain_lut,
sizeof(imx219_dgain_lut));
}
• turning_data.sensor_data.active_width:sensor 实际输出的宽度。
• turning_data.sensor_data.active_height:sensor 实际输出的高度。
• turning_data.sensor_data.analog_gain_max:a_gain 最大倍数,举一个例子,turning_data.sensor_data.analog_gain_max =126,最大倍率计算公式就是2^(X/32),其中 X 就是 126,X这个值每一个 sensor 厂家不一样,需要从 sensor 手册或者 sensor 厂家查找得到。
• turning_data.sensor_data.digital_gain_max:d_gain 最大倍数。
• turning_data.sensor_data.exposure_time_min:短曝光最小曝光时间(短曝光每帧最小曝光行数),每行的曝光时间可以用公式1秒/(帧率*(有效行+blank))即1/lines_per_second推算得出。
• turning_data.sensor_data.exposure_time_max:短曝光最大曝光时间(短曝光每帧最大曝光行数),短曝光每帧最大曝光行数可以通过公式单帧曝光时间/单行曝光时间,即(1/fps)/(1/lines_per_second)。
• turning_data.sensor_data.exposure_time_long_max:长曝光最大曝光时间(长曝光每帧最大曝光行数),HDR sensor 会用到。
• turning_data.sensor_data.lines_per_second:每秒多少曝光行,计算公式为1/每行时间或者(fps*vts),其中vts在不同 sensor 的里面的名字可能有所不同,可能是frame_length、vts等,但含义都是每帧的所含的总共行数,包括有效行和 blanking 。lines_per_second 亦可以理解成HMAX,需要注意的是有些 sensor 无 HMAX 概念。
• turning_data.normal.again_lut:again lut 表,fireware 根据 index 索引 lut 表,查找 sensor 对应的寄存器值,lut 表区分 a_gain/d_gain,lut 表格大小:again_lut[again_control_num][256], dgain_lut[dgain_control_num][256]。
注意事项1:当某个 gain 值不存在时,该位填充 0xffffffff,分配 gain 时,程序会向下查找,直到可以查到可以分配的 gain,下发到 kernel 中的 lut 表需要是完成高低位转换,避免在 kernel 中进行,比如gain = 0x1234,写入寄存器 0x3012,0x3013,有些 sensor 在 0x3012 中写 0x12,有些 sensor 在 0x3013 中写 0x12,在 hal 中转换屏蔽该差异性;
注意事项2:lut 表示 [0,255] 共 256 gain 控制,转换公式为 2^(x/32),即实际的 gain 倍数为[2^(0/32),2^(255/32)], gain 的控制曲线为 log 类型,即任何一颗 sensor 的 gain 的控制被离散为 256 个控制点,原因是现在 3a 的控制算法给出 256 个控制点,给出更多的控制点并不会提高 gain 的控制精度
camera 在 mipi start 之前,需要保证 sensor 没有开流,在 camera sensor init settings 中进行更改。
static uint32_t imx219_linear_init_setting[] = {
....
// 0x0100,0x01, // 在 setting 最后不包含 开流 的配置
}
当 sensor 驱动和 setting 编写完成后,拷贝 *_utility.c 和 *_setting.h 到 SDK 对应目录中,并重新编译 SDK 生成 sensor 驱动库,生成文件位于 out/deploy/rootfs/usr/hobot/lib/sensor 中。
一般代码结构没有问题,即使 tuning_data 参数配置有不当的地方,框架也能正常加载 sensor驱动。如果 logcat 有 sensor so check 失败或者加载失败,则需要检查代码结构,是否按照 HBN 框架来编写。
用户程序
参考 SDK 已有的用户程序,包含 CIM、ISP 的参数配置,这些配置需要根据具体的 sensor 的分辨率,帧率,数据格式进行配置。下面列出文件中需要单独配置的部分,其余部分可保持默认值,无需关注。