Camera FAQ
串口读写 Sensor 寄存器
【读 Sensor 寄存器命令示例】
1)cd /sys/devices/gc2053_mipi(进入目标 Sensor 节点目录)
2)echo 16 > addr_width; echo 8 > data_width(输入目标 Sensor 寄存器地址/数据位宽,请查阅 datasheet 获取)
3)echo 1 > read_flag(read_flag:读写控制节点,使能为1表示后续操作为读动作,使能为0表示后续操作为写动作)
4)echo 30350021 > cci_client(“30350021”:表示读取0x3035【目标寄存器地址】,在 read_flag = 1 情况下,写入值0021为无效状态)
5)cat read_value(打印上一步操作的结果:寄存器值)
【写 Sensor 寄存器命令示例】
1)cd /sys/devices/gc2053_mipi(进入目标 Sensor 节点目录)
2)echo 16 > addr_width; echo 8 > data_width(输入目标 Sensor 寄存器地址/数据位宽,请查阅 datasheet 获取)
3)echo 0 > read_flag(read_flag:读写控制节点,使能为1表示后续操作为读动作,使能为0表示后续操作为写动作)
4)echo 36510021 > cci_client (“36510021”:0x3651【目标寄存器地址】,0x0021【将要写入的寄存器值】,在 read_flag = 0 情况下,写入值为0x0021)
5)cat read_value
TWI 通讯异常
主控读写 Sensor 寄存器都是通过 TWI 来完成的,所以在调试 Sensor 时经常会遇到 TWI 通讯异常,如下:
TWI 被占用
TWI 被占用一般是 TWI 配置有冲突导致的,需要检查当前方案 Sensor 所使用的 TWI 在 uboot.dts 和 sysconfig.fex 是否也配置上了,需要将其注释掉,如下是 TWI4 被占用的打印:
sysconfig.fex 和 uboot.dts 修改如下,将 TWI4 配置注释掉:
TWI 通讯异常
如图 TWI 通讯异常的打印,如果出现 TWI 通讯异常,建议先从几个方面进行排查:
-
检查 board.dts 当前方案 Sensor 所使用的 TWI 引脚配置是否正确,是否被其他模块使用。
-
检查 board.dts 当前方案 Sensor 的 TWI 地址是否正确。
-
TWI SCK SDA 引脚硬件上是否有接上拉电阻。
-
检查 Sensor 驱动的上电时序(sensor_power 函数)是否有问题,如果上电时序没有问题,需要用万用表量一下 Sensor 三路供电 IOVDD、DVDD 和 AVDD 是否符合 Sensor 硬件设计指南上的需求,IOVDD 一般是 1.8V, DVDD 一般是 1.2V,AVDD 一般是 2.8V。
-
检查 board.dts 当前方案 Sensor 的 MCLK 引脚配置是否有冲突,如果配置没有问题,需要使用示波器量一下 Sensor 端 MCLK 是否有输出以及频率是否正确,是否与 Sensor 驱动配置的一样。
-
检查 board.dts 当前方案 Sensor 的 PWDN 和 RESET 引脚配置是否有冲突,如下,当前方案 Sensor 使用的 PE11 引脚与音频模块有冲突,需要将其注释掉。
TWI 读出来的寄存器值异常
如果 TWI 通讯没有出现异常,但是主控端读取到 Sensor 寄存器值都为0,则需要检查一下 Sensor 驱动配置的 TWI 数据位宽和地址位宽是否与 Sensor datasheet 说明一样,见 Sensor TWI 数据位宽和地址位宽章节说明。同时,检查一下 Sensor 三路供电 IOVDD、
DVDD 和 AVDD 是否正常。
select timeout 不出图
主控将 Sensor 初始化配置写进 Sensor 之后,一般 Sensor 就会有数据输出,如果出现[ISP_ERR]video_wait_buffer, line: 488,video8 select timeout!
,则表示当前 Video 节点所在的 Sensor 是没有数据给到主控端,或者是给过来数据是有问题的。
出现 select timeout 的打印可以从以下几点定位问题:
检查 SOC MIPI 寄存器状态
MIPI-Parser 寄存器
在 sample_virvi 运行起来之后,连续抓取 parser 寄存器,以 V821 平台为例,检查 0x45820034 (MIPI1:0x45821034)是否有寄存器值刷新,这个寄存器值表示 SoC 收到图像的宽高信息,可以快速判断 SOC 是否收到图像数据,抓取寄存器指令如下:
MIPIA检查 0x45820034
寄存器,MIPIB检查 0x45821034
寄存器。
- MIPIA/MIPI0:
cd /sys/class/sunxi_dump && echo 0x45820000, 0x45820200 > dump; cat dump
- MIPIB/MIPI1:
cd /sys/class/sunxi_dump && echo 0x45821000, 0x45821200 > dump; cat dump
MIPI-PHY 寄存器
检查 MIPIA:0x45810100(MIPIB:0x45810200)的 bit[0] 是否使能,这个 bit 表示 phy_en,检查 MIPIA:0x458101f0 (MIPIB:0x458102f0) 的 bit[19:16] 和 bit[0:3] 状态,如果状态一直处于 3(0011),则表示没有收到 Sensor 的图像数据,如果寄存器值状态处于 3-5 之间切换,则表示有收到图像数据
获取 V821 PHY 寄存器状态指令如下:
-
MIPIA/MIPI0:
cd /sys/class/sunxi_dump && echo 0x45810100, 0x458101ff > dump; cat dump
-
MIPIB/MIPI1:
cd /sys/class/sunxi_dump && echo 0x45810200, 0x458102fc > dump; cat dump
MIPI-PAYLOAD 寄存器
在通路运行起来之后,连续抓取 MIPI-PAYLOAD 寄存器,以 V821 平台 MIPI0 为例,检查 0x45811118 寄存器值(MIPI1检查:0x45811518 寄存器值)检查[31:07]的 ERR PD 标志位是否被置位,如果 ERR PD 被置位,需要检查 MIPI 波形是否正常,抓取寄存器指令如下:
MIPIA检查 0x45811118 寄存器,MIPIB检查 0x45811518 寄存器。
- MIPIA/MIPI0:
cd /sys/class/sunxi_dump && echo 0x45811000, 0x458111ff > dump; cat dump
- MIPIA/MIPI1:
cd /sys/class/sunxi_dump && echo 0x45811400, 0x458115ff > dump; cat dump
通过上述查看寄存器的方式,可以先初步判断一下是否是 Sensor 端没有发送数据过来,与此同时,可以使用示波器量一下 Sensor 端的 mipi data
和 mipi clk
引脚是否有波形,如果没有量到波形,则需要检查一下 Sensor 驱动的初始化配置是否与 Sensor 原厂提供初始化配置一致,同时需要将问题反馈给 Sensor 原厂。如果初步检查 Sensor 有发送数据,且 SoC MIPI 状态有在轮转,那么可以尝试调节 MIPI Clk Delay 寄存器。
调节 MIPI Clk Delay 寄存器
确定 clk delay 范围
PS:需要在边跑应用出图的同时来调试,尽可能在边预览图像边调试,方便判断调整后图像是否还存在花屏、异常横/竖线等异常现象。 第一步,连续多次抓取 MIPI PAYLOAD 寄存器,检查bit【7-12】等异常中断标志位是否被置起,以此来判断 MIPI 状态是否异常。
平台 | MIPIA | MIPIB |
---|---|---|
V821 | 0x45811118 | 0x45811518 |
// MIPIA
cd /sys/class/sunxi_dump && echo 0x45811118 0xffffffff > write // 清除中断标志位
cd /sys/class/sunxi_dump && echo 0x45811000, 0x458111ff > dump; cat dump
// MIPIB
cd /sys/class/sunxi_dump && echo 0x45811518 0xffffffff > write // 清除中断标志位
cd /sys/class/sunxi_dump && echo 0x45811400, 0x458115ff > dump; cat dump
第二步,如图所示,bit【24:20】是 clk lane0 的软件设定延时值,起到延时采样的作用,适当调整这个参数可以使得 SoC 与 Sensor 的时序更加匹配。
平台 | MIPIA | MIPIB |
---|---|---|
V821 | 0x45810118 | 0x45810218 |
// MIPIA PHYA 读指令
cd /sys/class/sunxi_dump && echo 0x45810100, 0x458101ff > dump; cat dump
// PHYA 0x45810118 寄存器写指令
cd /sys/class/sunxi_dump && echo 0x45810118 0x00000000 > write
// MIPIB PHYB 读指令
cd /sys/class/sunxi_dump && echo 0x45810200, 0x458102fc > dump; cat dump
// PHYB 0x45810218 寄存器写指令
cd /sys/class/sunxi_dump && echo 0x45810218 0x00000000 > write
第三步,保持 clk dly 为 0x0,步进递增延时值,同时检查步骤一是否出现异常状态。例如设置 clk dly 等于 0x0,步进递增至0x9 时,MIPI状态满足步骤一(即 MIPI 状态寄存器值异常),那么 clk dly 适用的的范围为【0x0,0x8】,最佳值是取这个范围的中间也就是 0x4。
Sensor 驱动配置 clk delay
将调试出来的 clk delay 值配置到 Sensor 驱动。
// 请配置在 sensor_init 函数中
static int sensor_init(struct v4l2_subdev *sd, u32 val)
{
int ret;
struct sensor_info *info = to_state(sd);
sensor_dbg("sensor_init\n");
/*Make sure it is a target Sensor */
ret = sensor_detect(sd);
if (ret) {
sensor_err("chip found is not an target chip.\n");
return ret;
}
info->focus_status = 0;
info->low_speed = 0;
info->width = 1280;
info->height = 720;
info->hflip = 0;
info->vflip = 0;
info->gain = 0;
info->exp = 0;
info->deskew = 0x4; // 配置 clk delay 参数
info->tpf.numerator = 1;
info->tpf.denominator = 20; /* 30fps */
return 0;
}
翻转失效或图像异常
翻转失效
在调用水平或垂直方向进行翻转,API 已返回成功后,画面延迟生效或者概率性失效,大部分 Sensor 在设置翻转寄存器到生效需要一小段时间,可以在设置寄存器后加一点点小延时来规避,也可以通过回读寄存器来大致估摸需要的延时时长,或者在代码中添加回读机制,保证翻转寄存器被更新到后才执行其它操作,如下:
// gc2083垂直翻转示例
data_type sensor_flip_status; //定义私有全局变量,用于记录当前翻转状态
static int sensor_s_vflip(struct v4l2_subdev *sd, int enable)
{
unsigned int iic_addr;
data_type get_value;
data_type set_value;
data_type value_0015;
data_type value_0d15;
int times_out = 3;
int eRet;
if (!(enable == 0 || enable == 1)) {
sensor_err("Invalid parameter!!!\n");
return -1;
}
sensor_i2c_addr_get(sd, &iic_addr);
get_value = sensor_flip_status & 0x03;
if (enable)
set_value = get_value | 0x02;
else
set_value = get_value & 0xFD;
sensor_write(sd, 0x0015, set_value);
sensor_write(sd, 0x0d15, set_value);
do {
/* write repeatly */
sensor_write(sd, 0x0015, set_value); //覆写寄存器
sensor_write(sd, 0x0d15, set_value);
eRet = sensor_read(sd, 0x0015, &value_0015); //回读寄存器
eRet = sensor_read(sd, 0x0d15, &value_0d15);
sensor_print("[V] eRet:%d, value_0015 = 0x%x, value_0d15 = 0x%x, times_out:%d\n", eRet, value_0015, value_0d15, times_out);
usleep_range(10000, 30000);
times_out--;
} while ((value_0015 != set_value) && (value_0d15 != set_value) && (times_out >= 0)); //通过覆写和回读,确认寄存器已被更新
if ((times_out < 0) && ((value_0d15 != set_value) || (value_0015 != set_value))) {
sensor_err("set vflip failed, please set more times!!!\n"); //寄存器未能被更新到,上报异常
return -1;
} else {
sensor_flip_status = set_value;
}
sensor_print("vflip current_switch_choice : 0x%x, set_value : 0x%x, sensor_flip_status = 0x%x, , value_0015 = 0x%x, value_0d15 = 0x%x\n",iic_addr, set_value, sensor_flip_status, value_0015, value_0d15);
return 0;
}
如果寄存器未被正常更新,则上报异常,具体问题也可以咨询 Sensor 原厂翻转寄存器设置时,是否有其它相关联寄存器需要同步设置(如切页、组写等),同时,检查驱动中是否有其它操作翻转寄存器的代码,是否存在同时使用的冲突。
自动降帧常见问题
调整的帧率与预期不符
有以下几种可能性:
1.sensor_win_sizes 中的 VTS、HTS、PCLK 信息填写不正确,VTS、HTS 需要按照 Sensor 初始化寄存器列表里的值来进行填写,PCLK 可以通过 Sensor 原厂获取(或自行计算)后填写,注意三者要满足公式,这三个关键信息是会交由 ISP 计算实际的曝光时间的,如果填写不准确会间接导致曝光时间有误差,进而导致降帧时帧率产生误差。
PCLK = HTS * VTS * FPS
2.更新 VTS、HTS 寄存器的方法有误,寄存器的读写方式需要严格按照规格书描述来操作(也可以直接询问 Sensor 原厂),注意大部分寄存器会区分高低位信息分别更新两个寄存器,需要留意写入的值是否符合预期,可以在更新寄存器后,使用 sensor_read 函数回读打印确认,并实时查看 VI 结点信息来检查。
3.检查 ISP 效果的最大曝光时间设置是否与预期不符,如目标是自动降帧至 10fps,但最大曝光时间又限制在 1/20s,那么不会触发自动降帧策略,当然也存在当前照度可能还未到要降帧延长曝光时间的时候;
设置帧率之后,Sensor 不出图
有以下几种可能性:
-
回退驱动中帧率调整的相关代码,检查出图稳定性,是否真的是帧率改动导致的不出图。
-
确保 VTS、HTS 寄存器更新成功,设置的值也符合预期;如果确定寄存器值符合预期,那么可以咨询 Sensor 原厂该 Sensor 在调整帧率时是否有其它注意事项,如 VTS 偏移量限制等。