介绍rk平台针对cif链路出现的mipi错误以及断流的复位操作

文章详细阐述了Rockchip平台中CIF模块的定时器设置和复位操作。通过配置rockchip,cif-monitor属性,可以检测数据异常并自动复位。在3588平台,可通过宏定义ROCKCHIP_CIF_USE_MONITOR启用复位机制。关键函数包括rkcif_reset_watchdog_timer_handler、rkcif_detect_reset_event和rkcif_init_reset_work,分别用于重置看门狗定时器、检测复位事件和初始化复位工作。复位操作涉及rkcif_do_start_stream、rkcif_monitor_reset_event等,根据监测模式决定触发条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.定时器timer的setup

        经常看到vicap数据发生异常时,在rkcif_mipi_lvds节点下面配置该属性rockchip,cif-monitor 来进行检测异常并复位,驱动是在该文件中进行解析设置drivers\media\platform\rockchip\cif\dev.c;该属性需要在dts中配置,是针对1126,3568,3399等平台;3588平台复位机制使能,就不用去修改dts,直接把这个宏定义打开就行ROCKCHIP_CIF_USE_MONITOR;以下以3588平台为例

        上面箭头的描述如下,也都在drivers\media\platform\rockchip\cif目录下的Kconfig文件中定义了;这个也就是356x平台中rockchip,cif-monitor里面的参数index0-index4;

 

         当然这些宏定义也可以在rockchip_defconfig文件中进行添加 如下所示

 

         timer定时器相关的3个函数如下:

1.rkcif_reset_watchdog_timer_handler 重置看门狗定时器处理程序

2.rkcif_detect_reset_event 检测复位事件

        该函数里面要知道这两个变量last_buf_wakeup_cnt和buf_wake_up_cnt,这个是用来判断数据是否一直走,是否断流用的。所以该函数的实现如下;如果断流的话,buf_wake_up_cnt是不会在增加的,即last_buf_wakeup_cnt = buf_wake_up_cnt;

if (timer->last_buf_wakeup_cnt[stream->id] < stream->buf_wake_up_cnt && check_cnt == 0) {
............
}
else if (timer->last_buf_wakeup_cnt[stream->id] == stream->buf_wake_up_cnt) {  //断流了
............
v4l2_info(&dev->v4l2_dev,"do reset work due to frame end is stopped, run_cnt:%d\n", timer->run_cnt);
}

        针对监测的三种模式,其中HOTPLUG和CONTINUE模式都是调用is_reset = rkcif_is_csi2_err_trigger_reset(即引起复位的原因),为true的话,则调用rkcif_init_reset_work(timer); 而TRIGGER即协议层的报错处理调用timer->is_csi2_err_occurred;为true的话,则调用rkcif_init_reset_work(timer);

3.rkcif_init_reset_work(timer)函数主要实现如下:

for (i = 0; i < dev->num_channels; i++) {
stream = &dev->stream[i];
if (stream->state == RKCIF_STATE_STREAMING)
timer->last_buf_wakeup_cnt[stream->id] = stream->buf_wake_up_cnt;
	}

        理解4种监测模式的具体含义,如下表:

 

2.复位的操作

        摄像头开启出流调用rkcif_do_start_stream,然后该函数里面会调rkcif_monitor_reset_event函数;

        rkcif_monitor_reset_event 调用rkcif_is_triggered_monitoring,该函数的作用是先判断定时器的监测模式,如果是CONTINUE或HOTPLUG,那么当满足如下条件时,定时器被触发;

if (stream->frame_idx >= timer->triggered_frame_num)
/*triggered_frame_num 这个就是从哪一帧起开始检测,默认为0,
即开启数据流时就开始检测;*/

        如果监测模式是TRIGGER,那么就会调用该函数rkcif_is_csi2_err_trigger_reset(timer); 判断两次报错的时间diff_time是否大于等于err_time_interval(发现错误后继续监视的超时,单位(ms)),是的话,定时器触发 is_triggered = true;

if (timer->csi2_err_triggered_cnt >= 1) {
	cur_time = ktime_get_ns();
	diff_time = cur_time - timer->csi2_first_err_timestamp;
	diff_time = div_u64(diff_time, 1000000);
	if (diff_time >= timer->err_time_interval) {
		is_triggered = true;
		v4l2_info(&dev->v4l2_dev, "trigger reset for time out of csi err\n");
		goto end_judge;
			}

         接下来就完成定时器的启动

1.
timer->is_triggered = rkcif_is_triggered_monitoring(dev); 
...........
2.
cycle = fps * timer->frm_num_of_monitor_cycle;
timer->cycle = msecs_to_jiffies(cycle);
...........
timer->run_cnt = 0;
timer->is_running = true;
timer->is_buf_stop_update = false;
...........
3.
timer->timer.expires = jiffies + timer->cycle;
mod_timer(&timer->timer, timer->timer.expires); 
//启动定时器,不加这句的话,定时器不工作,不会调用rkcif_reset_watchdog_timer_handler。

rkcif_detect_reset_event会调用函数rkcif_init_reset_work
执行工作队列schedule_work(&dev->reset_work.work),去调用
rkcif_reset_work实现复位->rkcif_do_reset_work->rkcif_monitor_reset_event;
在rkcif_do_reset_work中通过ioctl调用sensor驱动的RKMODULE_SET_QUICK_STREAM
ret = v4l2_subdev_call(p->subdevs[i], core, ioctl,RKMODULE_SET_QUICK_STREAM, &on);

cif复位成功后,会打印如下log:

v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "do rkcif reset successfully!\n");

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值