Skip to main content

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-S100MIPI hostI2Cgpio_engpio_lpwm_mclk其他
RX0
可接 imx219 模组
0
4 lane
1SPI1_CSN0
gpio_number:502
可通过拨码开关进行选择
• LPWM0_DOUT0
gpio_number:456
• mclk 24Mhz
注意: imx219 模组本身外接 24M 晶振,所以不需要 SOC 端输出 mclk
RX1
可接 imx219 模组
1
4 lane
2SD_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_controlsensor 增益控制info:sensor 总线信息 mode:senosr 运行模式;linear/hdr/pwl again:sensor again 参数,最大4个 dgain:sensor dgain 参数,最大4个 gain_num:sensor gain 参数个数
aexp_line_controlsensor 曝光控制info:sensor 总线信息 mode:senosr 运行模式;linear/hdr/pwl line:sensor line 参数,最大4个 line_num:sensor line 参数个数
awb_controlsensor 端 awb 控制info:sensor 总线信息; mode:senosr 运行模式;linear/hdr/pwl rgain:sensor rgain bgain:sensor bgain grgain:sensor rrgain gbgain:sensor gbgain
userspace_controlhal 层各类控制开关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 的分辨率,帧率,数据格式进行配置。下面列出文件中需要单独配置的部分,其余部分可保持默认值,无需关注。

mipi 配置

字段描述
rx_enableMIPI 接收(RX) 设备使能,使能对应的 MIPI RX 端口,默认填 1。 注意 该字段不是配置 MIPI RX 端口号,只是使能 MIPI RX。
phy0: 代表 mipi dphy。
lanemipi lane 数,目前每一个 MIPI RX 默认支持 4 lane。
datatypemipi 输入的数据格式,与 sensor 配置保持一致。 常见的如下: RAW8:0x2A RAW10: 0x2B RAW12: 0x2C YUV422 8-bit: 0x1E
fps帧率,供计算 MIPI 一些配置使用,按照 sensor 输出帧率填写即可,可从 FAE 获取。
mipiclkmipi 总传输率 (所有 LANE),可从 FAE 获取,一般 FAE 提供 sensor init setting 时有描述。
width输入图像 宽度 piexl。
height输入图像 高度 piexl。
linelenthmipi linelenth, 根据 sensor 实际情况配置,可从sensor spec 寄存器读取,或者实际硬件测量。
framelenthmipi framelenth, 根据 sensor 实际情况配置,可从sensor spec 寄存器读取,或者实际硬件测量。
settlemipi settle, phy 的 settle 时间配置,可实际硬件测量。报 mipi phy 错时可调整, 0 - 120 范围。
channel_nummipi 虚拟通道 number,linear mode 填 1,HDR DOL2 mode 填 2。
channel_sel[MIPIHOST_CHANNEL_NUM]mipi 虚拟通道对应的 ipi channel。

camera sensor 配置

字段描述
name[CAMERA_MODULE_NAME_LEN]camera 模组名称,需要和 sensor lib名称对应,如:sensor 驱动名称为:libimx219.so,那么 name 为 imx219
addrsensor 设备地址,一般是 i2c 7位地址。
sensor_modesensor 工作模式: 1:NORMAL_M,linear 模式 2:DOL2_M,hdr 2帧合成1帧 3:DOL3_M,hdr 3帧合成1帧 4: DOL4_M,hdr 4帧合成1帧 5: PWL_M,hdr 模式 sensor 内部合成
gpio_enable是否使用 gpio 控制 camera sensor 的引脚,以满足 sensor 上下电的时序要求。如:使用 gpio 来控制 sensor XSHUTDN 引脚。注意:需要在 dts 中配置对应的 gpio number。 0: 不使用 gpio 来控制。 非 0: 使用 gpio 来控制 sensor,按照 bit 来使能 gpio 数量。 比如: 0x07 则代表使能 [a, b, c] 3 个 gpio。
gpio_level如果选择 gpio_enable_bit,则可以配置 gpio_level 来控制 sensor 引脚高低电平。某个 gpio bit 与 sensor 管脚高低电平关系如下: 0: 先输出低电平,sleep 1s (休眠时间可以在 sensor 驱动文件 power_on 函数中,通过 usleep 自行定义),再输出高电平。 1: 先输出高电平,sleep 1s,再输出低电平 比如:0x05 = 101,从 bit0 到 bit2 分别代表 gpio a 先输出高电平,再输出低电平,gpio b 先输出低电平,再输出高电平,gpio c 先输出高电平,再输出低电平。 注意:需要根据 sensor spec 上电时序来自定义。
fpssensor 帧率配置
widthsensor 出图宽度 pixel
heightsensor 出图高度 piexl
formatsensor mipi 数据类型,常见的如下: RAW8:0x2A RAW10: 0x2B RAW12: 0x2C YUV422 8-bit: 0x1E
extra_mode模组索引配置,部分 sensor 驱动中会用到
config_index功能配置,部分 sensor 驱动中会用到
calib_lnamesensor 效果库路径,默认路径为 /usr/hobot/lib/sensor
end_flag固定为 CAMERA_CONFIG_END_FLAG

vio 配置

字段1字段2字段3描述
VINcimmipi_en使能 mipi 接口
mipi_rxmipi rx 端口号
vc_indexmipi virtual index,mipi 虚拟通道,默认填写 0 即可
ipi_channelipi channel number,linear mode 为 1, hdr mode dol2 为 2
cim_isp_flybycim/sif online 到 isp。 0: sif offline 到 isp,数据经过 ddr。 1:sif online 到 isp,数据不经过 ddr。
input channelformatvin format,sensor 输出 format
widthsensor 输出分辨率 宽度 pixel
heightsensor 输出分辨率 高度 pixel
output channel / ddrddr_en数据是否 dump 到 DDR
wstride设置为 0,驱动会自动计算 wstride。
format下 ddr 时,设置的 sensor format
buffers_numcim/sif 下 ddr 的buffer number,设置为 1 - 6
flags一般在程序设置
HB_MEM_USAGE_CPU_READ_OFTEN | HB_MEM_USAGE_CPU_WRITE_OFTEN | HB_MEM_USAGE_CACHED
ISPbasehw_id 和 slot_idCIM 硬件直连 ISP 情况: hw_id 需要与 cim 的 rx_index 一一对应。 在sched_mode配置为1的情况下,CIM online ISP slot_id 取值0 ~ 3,与cim vc_index一一对应。 在sched_mode配置为2的情况下,slot_id 固定为0,cim vc_index可视sensor实际接入情况设置为0 ~ 3。 CIM DDR 连接 ISP 情况: hw_id 无限制,可视 sensor 实际接入情况和项目需要选择hw_id。 slot id只需从4开始到11即可。 注意:在多路压力场景下,采用CIM DDR的连接方式情况时,大分辨率的sensor通路连接尽量选择slot id取值较小的ISP通道上,可保证对sensor实时控制。
sched_modeISP的工作模式, 1: 表示manual,软件调度的方式, 2: 表示passthru模式,全online独占ISP的工作模式。
width输入图像高度
height输入图像宽度
frame_rate输入帧率,无实际效果
algo_state2a 的开关参数
output channelstream_output_mode 和 axi_output_modeisp 模式

板端运行程序

执行对应的测试程序

isp 图像预览

SDK 代码添加 tuning 程序

修改 /app/tuning_tool/scripts/tuning_menu.sh 文件,仿照已有的 sensor,进行添加。

ITEM_IMX219_RGGB="module:Raw10_IMX219_RDK-S100"
IMX219_RGGB_Raw10_IMX219_RDK-S100()
{
IDESC="imx219 rggb raw10 RDK-S100"
setup_case ${folder}/tuning_imx219_cim_isp_1080p
}

在 /app/tuning_tool/cfg/matrix 目录下建立 tuning_imx219_cim_isp_1080p 文件夹,并添加对应的 hb_j6dev.json mipi.json vpm_config.json 三个文件。

编译 SDK 系统代码,确保板端已经包含修改和添加的文件。

板端执行 tuning 程序

cd /app/utils/tuning_tool/scripts
.bash run_tuning.sh
# 按照交互页面提示,选择对应的 sensor

图像预览

打开 hbplayer,并设置网络地址(PC需要与板子可以ping通),点 apply 设置生效,并点 connect 则可以看到实时视频流。实时预览操作示意如图所示。

错误码

下面是 sensor 常见的错误码及简单的排查方向:

错误码定义排查方向
203HB_CAM_INIT_FAILsensor 初始化失败,一般可能 i2c 不通,配置的 sensor mode 不支持
205HB_CAM_START_FAILsensor 启动失败,一般可能 i2c 不通,配置的 sensor mode 不支持
207HB_CAM_I2C_WRITE_FAILsensor i2c 不通。
217HB_CAM_SENSOR_POWERON_FAILsensor 上电失败,可能是 sensor gpio 配置错误。
218HB_CAM_SENSOR_POWEROFF_FAILsensor 下电失败,可能是 sensor gpio 配置错误。

FAQ

control-tool 使用说明

进入tuning 目录,cd /app/tuning_tool/control_tool

按照交互界面提示,执行启动脚本 sh server_isp*_8000.sh,ISP 硬件具有两个 IP 核,每个核可以单独运行,若需要启动 isp 的控制则运行脚本 sh server_isp0_8000.sh.

启动方式如图所示。

脚本会自动识别板子ip, 默认检查eth1网卡ip地址。若需要修改为启动eth0 网卡,修改脚本eth_id=eth0。修改位置如图所示。

修改通信地址示意图