S3C2440是应用十分广泛且适用于嵌入式系统的一款嵌入式处理器。winCE 5.0/6.O是微软公司开发的一款专用于嵌入式系统的实时操作系统。其模块化设计使开发人员可以根据需求定制设备。目前,国内大部分OEM商都提供了对S3C2440的camera接口在WinCE5.O/6.0下的驱动支持。遗憾的是,目前国内OEM商提供的驱动仅限于对几款微型摄像头(如ov9650等)的驱动支持。当用户采用CCD摄像头作为图像采集的前端设备时,原来的驱动已经不能使用了,而CCD摄像头因其优越的性能,在监控领域扮演着主力军角色。本文从分析S3C2440的camera接口特性出发,详细介绍当摄像设备为CCD摄像头时,在WinCE 5.O/6.0操作系统环境下开发camera驱动的形式、方法和主要的驱动代码。
1 camera接口特性
S3C2440处理器有一个专用的camera接口(CAMIF),该接口支持ITU-R BT.601/656 YCbCr 8位数据格式视频数据输入,最大输入视频图像大小为4 096×4 096像素。视频输入后分两个通道逐帧保存图像数据,一个为预览通道(即P通道),另一个为编解码通道(即C通道)。两个通道均通过DMA方式将一帧图像保存到系统内存SDRAM中,在系统内存中共开辟了4组帧图像缓冲,从而保证了用户应用程序在读取帧图像数据时不影响另一帧图像数据写入。其特性如下:
◆支持ITU-R BT.601/656 YCbCr 8位数据格式视频数据输入,并可调整Y、Cb、Cr三个信号的顺序,以适应不同的视频信号源;
◆具有DZI功能,相当于数码变焦;
◆C通道输出图像最大为4 096×4 096像素;
◆P通道输出图像最大为640×480像素;
◆P通道输出图像格式可配置为RGBl6或GRB24;
◆C通道输出图像格式可配置为YCbCr 4:2:2或YCbCr 4:2:0:
◆输出图像可X方向镜像翻转、Y方向镜像翻转,或180°旋转;
◆DMA数据传输,4组帧图像缓冲,2个对应的中断处理,保证视频实时采集;
◆2个通道不同图像数据格式输出,便于用户程序开发。
CAMIF对外接口信号定义如下:
CAMPCLK输入的视频像素同步时钟。
CAMVSYNC输入的视频帧同步时钟。
CAMHREF输入的视频行同步时钟。
CAMDATA[7:0] 输入的视频8位数据。
CAMCLKOUT输出的时钟,用于外接的没有独立时钟的camera芯片的主时钟。当外接的camera芯片有独立的时钟时,该信号可不用。
CAMRESET输出的软件复位信号,可对外接的camera芯片进行复位。
信号的时序图如图1所示。
使用CAMIF时,必须对CAMIF相关寄存器进行正确配置,下面介绍主要寄存器的配置原理。
CAMRCFMT 选择输入视频信号源格式寄存器
①选择输入视频信号源为ITU-R BT.601 YCbCr 8位数据格式,或ITU-R BT.656 YCbCr 8位数据格式。
②选择输入视频信号源水平像素大小和垂直像素大小,一定要和外接的camera设备分辨率一致。
③选择输入视频信号Ycbcr信号顺序,一定要和外接camera信号的实际顺序一致。
CIWDOFST 从输入信号中截取中心部分的图像寄存器
原理是:从输入信号中截取中心部分的图像输出到大小不变的输出图像缓冲中,从而实现对图像的放大或缩小。
①配置该寄存器允许缩放或不允许缩放。
②X方向图像放大或缩小控制,原理是截切掉左部和右部的图像像素数。
③Y方向图像放大或缩小控制,原理是截切掉上部和下部的图像像素数。
CIGCTRL 全局控制寄存器
通过该寄存器对外接的camera进行复位,即控制CAMRESET信号的电平高低。
CICOTRGFMT C通道输出图像格式及大小配置寄存器
①可将C通道输出图像格式配置为YCbCr 4:2:2或YCbCr 4:2:0格式。
②可设置C通道输出图像X方向像素数。
③可设置C通道输出图像Y方向像素数。
④可设置C通道输出图像X方向镜像。
⑤可设置C通道输出图像Y方向镜像。
⑥可设置C通道输出图像180°旋转。
CIPRTRGFMT P通道输出图像大小配置寄存器
①可设置P通道输出图像X方向像素数。
②可设置P通道输出图像Y方向像素数。
③可设置P通道输出图像X方向镜像。
④可设置P通道输出图像Y方向镜像。
⑤可设置P通道输出图像180°旋转。
CICOSTATUS和CIPRSTATUS 状态寄存器
CICOSTATUS反映C通道数据的写入状态,即4组缓冲的哪一组;CIPRSTATUS反映P通道数据的写入状态,即4组缓冲的哪一组。用户程序采集图像数据时,应根据状态寄存器当前状态,决定从哪一组读出数据。
此外,CICOYSAl~CICOYSA4分别为C通道第1~4帧Y信号数据缓冲起始地址寄存器;CICOCBSAl~CICOCBSA4分别为C通道第1~4帧Cb信号数据缓冲起始地址寄存器;CICOCRSAl~CICOCRSA4分别为C通道第1~4帧Cr信号数据缓冲起始地址寄存器;CIPRCLRSAl~CIPRCLRSA4分别为P通道第1~4帧RGB信号数据缓冲起始地址寄存器。
2 WinCE下的驱动开发 目前,我国市场上的CCD摄像头只有模拟视频输出接口,显然它不能和S3C2440的camera接口直接连接,硬件上需要增加一块解码芯片。解码芯片把CCD的模拟信号解码为BT.601/656 YUV4:2:2格式信号,这个信号和CAMIF信号是匹配的,因此解码芯片输出就可以直接连接到S3C2440的camera接口。典型的解码芯片为SAA7113,接口电路如图2所示。 如果想简化硬件电路和驱动代码,也可以根据需求向生产商定制CCD摄像头,要求生产商生产的CCD摄像头直接按照ITU-R BT.601/656格式输出视频信号。具有这种接口的CCD摄像头就可以直接和S3C2440的camera接口连接,接口电路如图3所示。 两种情况的驱动代码开发过程基本上是相同的。区别是:前者需要S3C2440通过I2C总线对解码芯片SAA7113的相关寄存器进行配置,而后者则不需要。下面以前者为例介绍驱动的开发方法。2.1 配置解码芯片SAA7113 SAA7113是NXP公司推出的视频解码系列芯片,在很多视频产品(如电视卡、MPEG2、MPEG4)中都有应用。SAA7113的主要作用是把输入模拟视频信号解码成标准的BT.656 YUV4:2:2数字信号,相当于一种A/D器件。它兼容全球各种视频标准,在我国应用时必须根据我国视频标准来配置内部寄存器。 对SAA7113配置需要通过I2C总线进行,分配S3C2440的GPIO的E15模拟I2C的SDA线,E14模拟I2C的SCL线。OEM商提供的原驱动是针对手机摄像头ov9650开发的,二者的配置原理和过程是相同的,但配置内容不同,输出图像的格式也不同。ov9650输出的图像是逐行扫描的,SAA7 113输出的图像则是隔行扫描的。由图1可知,CAMIF是逐帧输入的,所以必须把SAA3117的场同步信号VS作为CAMIF的帧同步信号CAMSYNC,输出图像是逐场保存的。配置内容为: ①复位SAA3117。 ②模拟通道选择。 ③配置亮度、色度、对比度、自动增益控制量。 ④将RTSl引脚配置为场同步信号VS,将RTSO信号配置为行同步信号HREF,信号极性应分别与图1中CAMVSYNC和CAMHREF信号极性一致。 ⑤配置图像宽度为720像素。 ⑥配置帧图像高度为576像素,一帧图像分奇偶两场分时输出,每场图像高度为288像素。 ⑦配置数据格式为BT.656 YCbCr 4:2:2 8位格式输出。注意,数据口的信号顺序为CB0 Y0 CR0 Y1 CBlY2…CR359 Y719。 ⑧时钟采用24.576 MHz的独立时钟,此时LLC的频率为27 MHz,场频为50Hz,帧频为25 Hz。2.2 为CAMlF分配DMA内存空间 因为S3C2440从camera接口采集到的视频数据是以DMA机制写到内存的,所以必须为C通道和P通道分别分配逻辑内存(即DMA缓冲区)。Win CE有两种分配DMA缓冲区的方法:使用CEDDK函数和使用winCE内核函数。建议使用CEDDK函数:
注意:C通道和P通道应分别分配。分配成功后,应将4组YCbCr信号的起始地址与分配给C通道的DMA缓冲区地址关联起来,将4组RGB信号的起始地址与分配给P通道的DMA缓冲区地址关联起来。格式不同时,关联的空间大小是不同的。如果C通道格式为YCbCr4:2:2,图像宽度为CoDstWidtlh,图像高度为CoDstHeight,分配的DMA地址为CoFrameBuffer,则二者的关联关系为:
这样分配的目的是,保证每一组YCbCr信号的地址空间是连续的,便于用户程序开发。
如果P通道格式为RGBl6,图像宽度为PrDstWidth,图像高度为PrDstHeight,分配的DMA地址为PrFrame Buffer,则二者的关联关系为:
如果P通道格式为RGB24,图像宽度为PrDstWidth,图像高度为PrDstHeight,分配的DMA地址为PrFrame Buffer,则二者的关联关系为:
2.3 配置CAMIF相关寄存器
①把输入视频信号宽度配置为720像素,高度配置为288像素;
②把输入视频信号格式配置为BT.656 YCbcr 4:2:2格式;
③把输入视频信号顺序配置为CbYCr;
④根据用户的LCD显示终端的分辨率配置P通道的图像宽度、高度像素和格式;
⑤根据用户对图像的处理需求来配置C通道的图像宽度、高度像素和格式;
⑥配置C通道的缩放系数;
⑦配置P通道的缩放系数;
⑧把C通道的DMA地址配置给4组起始地址寄存器;
⑨把P通道的DMA地址配置给4组起始地址寄存器。
2.4 创建camera流式驱动接口函数
WinCE下的硬件驱动程序大多采用流式驱动来开发,因为它有一个一致的接口函数供用户调用。此处,把接口函数命名为:CAM_Close()、CAM_Deinit()、CAM_Init()、CAM IOControl()、CAM()pen()、CAM PowerDown()、CAM_PowerUp()、CAM_Read()、CAM_Seek()和CAM-_Write()。
(1)CAM_Init()函数
该函数在驱动程序每次被设备管理器加载时调用。其实现的功能如下:
配置SAA7113,分配C通道、P通道的DMA内存空间,根据输入信号源属性和输出图像、预览图像属性配置CAMIF寄存器。
创建一个事件CameraEvent,使用WinCE内核函数InterruptInitialize(SYSINIR_CAM,CameraEvent,NULL,O)把该事件与camera的逻辑中断号SYSINIR_CAM关联起来,即当中断发生时激活该事件。
创建一个中断服务线程。在该线程内用WaitForSintgleObjcet(CameraEvent,INFINITE)函数阻塞线程,并等待CameraEvent激活。把预览视频图像的功能放到CameraEyent激活之后完成,即把P通道缓冲区的内容拷贝到显示终端。最后,用InterruptDone(SYSINIR_CAM)函数结束本次中断处理。
(2)CAM_IOControl()函数
可以说,该函数才真正是用户程序与驱动程序联系的主要通道,用户程序对camera接口的控制及数据采集均是通过该函数完成的。其主要功能有:
①打开/关闭P通道或C通道输出。
②修改配置参数。
③控制输出图像的放大或缩小。
④如果需要RGB数据,则读取P通道缓冲区内容;
如果需要YCbCr数据,则读取C通道缓冲区内容。注意,读取之前要根据状态寄存器CICOSTATUS或CIPRSTATUS的当前状态,确定访问哪一组缓冲区。
(3)CAM_Deinit()函数
当卸载本驱动时,该函数负责释放分配的内存空间和资源。
(4)CAM_Open()函数
该函数内部并没有具体的功能代码,只是当用户程序使用CreateFile(TEXT(“CAMl:”),GENERIC_READ|GENERIC WRITE,O,NULL,OP-EN_EXISTING,O,O)函数打开camera驱动时调用该函数,并返回一个文件句柄。基于该句柄用户才能进行后续操作。
(5)CAM_Close()函数
该函数内部并没有具体的功能代码,只有当用户程序使用CloseFile(hfile)函数关闭camera驱动时才调用该函数,并释放之前返回的文件句柄。其他接口函数没用赋予其具体功能。
结语
按照上述方法开发的驱动代码,连同其他驱动已在PB5.O环境下编译通过,生成的内核文件在原硬件平台下成功运行,P通道视频图像流畅,C通道图像质量较高。该方法弥补了目前国内在WinCE 5.O/6.O操作系统环境下CCD摄像头无法连接到S3C2440的camera接口的缺陷,为工程技术人员设计嵌入式图像采集系统时提供了一种有效手段。