V4L2视频驱动大致完成,剩下工作配合调试并修正驱动。主要基于图形显示,稳定程度及抓图速度进行了改进。通过启动内核的打印信息和输入命令之后的打印信息来判断整个流程是否出现了问题,同时可用示波器测量观察是否有数据通过,来判断是哪个芯片上面出现了问题。比如通过打印一些控制寄存器的值,并联系芯片的厂家还配合这些时间参数的设置。整个产品的目的医疗用途,是通过高清摄像头(CMV4000,2048*2048)拍摄皮肤,并将图片在手机屏幕一样的终端显示出来,用于医生的研究。通过CMV4000抓取到的数据,FPGA不断的对CMV4000发出req,缓冲区收到一个数据就对cpu发出一个中断IRQ。在FPGA和TC358746转换芯片的数据转换,通过MIPI口传送给CPU,I2C总线用于控制,并将数据传输给应用层APK处理并显示出来。驱动是从简单的做起,比如先设置640*480之后成功了再设置2048*2048观察结果;先将一个像素的显示设置为8bit,亦能正常显示,但不是很清晰,有黑点,总体流程结束后,可以换为10bit,照出的图像太黑了,就从取低8位修改为取高8位。速度方面主要针对FPGA的性能及通道配置、MIPI传输速度、并口、CPU接收能力等来提高。通过设置设置FPGA发入的数据为循环发入,就可以通过Ultraedit来查看接收到的数据是否有丢失了1帧。观察发现只能接收到奇数位数据或只能接收到偶数位数据,说明判断数据丢失了一半,通过示波器观察MIPI口发现并无数据丢失,发现是CPU驱动方面的问题。后联系厂商得出FPGA的一些参数设置存在问题,经过修改发现发出的数据都能完整的接收得到,可以通过抓取图片的时间来查看,原来是丢失数据时200秒抓10帧,而不丢失数据时候是100秒抓10帧。可以提高抓图的速率,但是发现速度并未明显提高还是在每秒抓3帧左右,说明瓶颈在其他地方。
apk上面无法运行设置摄像头参数的命令,只能通过在内核启动的时候,往里面添加脚本,在脚本中存放那些需要执行的命令,同时将这个脚本放入内核启动时的一系列执行序列中,是一个文件。同时,需注意需要将该脚本文件的权限修改。并注意复制该脚本的时候系统会默认修改权限,且不同目录的权限MASK不一样。
对某些代码进行注释的时候,对多行代码同时进行注释时,采用#if 0 和#endif的方式来进行注释的方式更为保险。编译的时候看屏幕出错时候立即按ctl+c然后针对报错信息进行修改代码,然后再继续编译。
6.24
拿到新焊的3个4460板子,启动后肯定是会有一些乱码的,因为新来的板子不会有u-boot和内核文件系统的。需要自己先通过TF卡(micro SD卡)来先将u-boot烧写进去,有了u-boot,之后便使用u-boot的fastboot来进行进一步的烧写了。其中有一块板子不能正常启动,和正常启动的板子的log相对比,发现有EMMC卡不能正常初始化,说明了是EMMC卡的问题,发现该B板和A板和C板的EMMC的型号不一致,认定是现在的内核不能很好的支持这款EMMC,所以通过beyond compare来对比现在的内核和之前的内核中相关的代码,来修改现在的内核重新烧写。那么该板最终就能正常启动。
6.25
对APK设计了测试用例,使用了EXCEL表格,首先需要针对大功能比如抓图、PLAYBACK中的图像的显示,再对各个大功能中的小功能进行了细化,并写出对小功能的确定的方法。对pandaboard的烧写要注意烧写的binaries要最新的版本,其中pandaboard官网上面的对pandaboard的u-boot、kernel的已经不再更新了,该项目由linaro来负责更新。去linaro下载最新的版本即可通过先对SD卡进行分区,一个是boot区,用于存放MLO、u-boot、kernel。另一个是文件系统区用于存放文件系统。将sd卡插入pandaboard中上电即可自动启动。
6.27
TF卡即为micro SD卡。
对该板子的SD卡热插拔功能进行测试,先试了现在的内核发现插拔SD卡没有反应,再烧写那三块板子的image文件,重新进行了实验。kernel可以进行备份,比如通过mv kernel kernel-xxx,然后mv kernel-xqw-exposure-test kernel,就是实现多任务不干扰,随时替换kernel文件夹然后进行编译烧写测试。
为了确保烧写和编译是对的,在probe函数下加了/* Init controls */
printk("HenryDbg::v4l2 ctrls----------------->\n");
再查找启动LOG中有没有该句话打印出来。
printk("HenryDbg::v4l2 ctrls::V4L2_CID_EXPOSURE = %d------------------>\n", V4L2_CID_EXPOSURE);
打印时增加对核心参数的打印,亦是一种很好的方法。
测试案例的编写不能依赖于串口,因为有的时候没有串口来辅助。最好能添加一下重复的次数。下次更新测试案例了,就不要重复覆盖了该excel,应当使用v1.1等标记,因为不同测试案例对应着不同的版本。另外使用的测试结果,最好能另外存放一个表格,防止过多的测试次数,不便于观察。
yavta /dev/video0 -l > log.log
/system/bin/sh: cannot create log.log: Read-only file system
如果乱码太多的话,把结果保存进log中,最后再通过cat log.log查看。
6.28
[ 8.496917] HenryDebug::cmv4000_probe--------->
[ 8.501953] HenryDbg::v4l2 ctrls::V4L2_CID_EXPOSURE = 9963793------------------>
[ 8.510101] HenryDbg::cmv4000_s_ctrl enter------------------>
[ 8.516387] HenryDbg::cmv4000_s_ctrl::V4L2_CID_PIXEL_RATE------------->
[ 8.524108] HenryDbg::cmv4000_s_ctrl enter------------------>
[ 8.530426] HenryDbg::cmv4000_s_ctrl::V4L2_CID_EXPOSURE------------->
至上而下的分析问题,从应用层的yavta.c中的list control函数开始分析,再往下是内核中的v4l2_ioctl.c 和 v4l2_controls.c文件最低层是cmv4000.c。分别在各个文件对应的位置中添加了打印语句,从中分析了到了 v4l2_controls.c中的函数,能执行到该函数,因为该函数的第一个打印执行了,但是之后的打印并未被打印出来,说明第二条打印之前的地方就是问题所在。因此对这几个判定参数进行分析,将各个参数拆开进行单独的判定每个参数实现一个打印,就能得知最终哪个参数的问题而导致了这个函数执行的退出了。
7.3
Read the relevant documents in the document directory , it explains how the functions and the entire framework work in detail.
My next step is read all the relevant codes in the media/video/ , master the technological process of the video and the control.
We usually add a debug infomation either before or after a judgement statement .
in the case of if ,else if ,else ,we usually add a debug infomation in each of the judgement statement,so we can make sure which way the kernel choosed.
7.5 LOG of capture the frame
[ 665.567443] OMAP4 ISS CSI2a output: VIDIOC_QBUF
[ 665.572570] HenryDebug::__video_do_ioctl tp4------>
[ 665.577880] HenryDebug::__video_do_ioctl tp5------>
[ 665.583251] HenryDebug::iss_video_qbuf------->
[ 665.588165] vb2: qbuf of buffer 1 succeeded
[ 665.594909] HenryDebug::__video_do_ioctl tp6------>
[ 665.600311] OMAP4 ISS CSI2a output: VIDIOC_QBUF 00:00:00.00000000 index=1, type=vid-cap, flags=0x00000000, field=0, sequence=0, memory=mmap
[ 665.614105] OMAP4 ISS CSI2a output: bytesused=0, offset/userptr=0x00000000, length=4194304
[ 665.623138] OMAP4 ISS CSI2a output: timecode=00:00:00 type=0, flags=0x00000000, frames=0, userbits=0x00000000
[ 665.636016] OMAP4 ISS CSI2a output: VIDIOC_DQBUF
[ 665.641174] HenryDebug::__video_do_ioctl tp7------>
[ 665.646545] HenryDebug::__video_do_ioctl tp8------>
[ 665.651885] HenryDebug::iss_video_dqbuf------->
[ 665.656829] HenryDebug::vb2_dqbuf-------------->
[ 665.661895] HenryDebug::vb2_dqbuf tp1-------------->
[ 665.667297] HenryDebug::vb2_dqbuf tp2-------------->
[ 665.674682] HenryDebug::vb2_dqbuf tp3-------------->
[ 665.680084] vb2: dqbuf: Returning done buffer
[ 665.684844] HenryDebug::vb2_dqbuf tp4-------------->
[ 665.690277] HenryDebug::vb2_dqbuf tp5-------------->
[ 665.695648] vb2: dqbuf of buffer 2, with state 3
[ 665.700714] HenryDebug::__video_do_ioctl tp9------>
[ 665.706024] OMAP4 ISS CSI2a output: VIDIOC_DQBUF 00:11:01.00342529 index=2, type=vid-cap, flags=0x00000005, field=0, sequence=62, memory=mmap
[ 665.722076] OMAP4 ISS CSI2a output: bytesused=4194304, offset/userptr=0x00800000, length=4194304
[ 665.731628] OMAP4 ISS CSI2a output: timecode=00:00:00 type=0, flags=0x00000000, frames=0, userbits=0x00000000
[ 665.776947] MeterDebug omap4iss_csi2_isr------->
[ 665.781890] MeterDebug csi2_isr_ctx------->
[ 665.786376] MeterDebug csi2_isr_buffer------->
[ 665.791107] vb2: Done processing on buffer 1, state: 2
[ 665.796600] CSIA_IRQ
When we do not have the command cp,we can use the cat to copy the file to root directory,so the file is moved from the flash to the ram,we can easily get the file through the qq steward.But first of all,we should turn the root directory to a readable and writeable directory.
mount -o remount,rw /
7.8
最上面是应用层yavta.c,然后再yavta.c中调用了V4L2的相关IO控制,进入了内核的第一个函数是v4l2-ioctl.c,该函数里面定义了V4L2中的所有IO控制的命令,但是对于具体的设备需要实现哪些命令,那在第三步的iss_video.c中,我们按需要用到什么命令直接在该处中定义了相应的控制函数,因此我们可以得知相应的v4l2-ioctl.c的定义的实现是在iss_video.c中的具体的函数中的实现。当然最底层的函数是cmv4000.c。
输入了yavta /dev/video0 -l > log.log可以有效的排除驱动的输出,之后再用cat log.log查看结果:
root@android:/ # cat log.log
Device /dev/video0 opened.
Device `OMAP4 ISS CSI2a output' on `media' is a video capture device.
--- User Controls (class 0x00980001) ---
control 0x00980901 `Contrast' min 0 max 255 step 1 default 123 current 123.
control 0x00980911 `Exposure' min 0 max 4096 step 1 default 2048 current 2048.
--- Image Processing Controls (class 0x009d0001) ---
control 0x009d0902 `Pixel Rate' min 0 max 0 step 1 default 0 current 96000000.
3 controls found.
Video format: (00000000) 0x0 (stride 0) buffer size 0
7.10
yavta -w `Exposure' 2048
设置曝光控制的方法,注意是`Exposure'而不是‘Exposure’。
修改曝光控制的正确办法:
yavta /dev/video0 -w '0x00980911 0x4096'
注意电脑的输入有三种,分别是:DVI,HDMI,VGA。各种输入线的端口外形不一样。且有可能遇见该linux主机碰见不支持其显示器的分辨率的情况。
YUYV与RGB24
RGB是一种颜色的表示法,计算机中一般采用24位来存储,每个颜色占8位。YUV也是一种颜色空间,为什么要出现YUV,主要有两个原因,一个是为了让彩色信号兼容黑白电视机,另外一个原因是为了减少传输的带宽。YUV中,Y表示亮度,U和V表示色度,总之它是将RGB信号进行了一种处理,根据人对亮度更敏感些,增加亮度的信号,减少颜色的信号,以这样“欺骗”人的眼睛的手段来节省空间。YUV到RGB颜色空间转换关系是:
R = Y + 1.042*(V-128); G = Y - 0.34414*(U-128) - 0.71414*(V-128); B = Y + 1.772*(U-128);
YUV的格式也很多,不过常见的就是422、420等。YUYV就是422形式,简单来说就是,两个像素点P1、P2本应该有Y1、U1、V1和Y2、U2、V2这六个分量,但是实际只保留Y1、U1、Y2、V2。
图1 YUYV像素