范林涛 王骜
(1河北远东通信系统工程有限公司,河北石家庄050200)(2云南大学信息学院,云南昆明650091)
基于OMAPL138平台的串口LCD Linux驱动设计
范林涛1王骜2
(1河北远东通信系统工程有限公司,河北石家庄050200)(2云南大学信息学院,云南昆明650091)
简要介绍了OMAPL138及串口LCD,设计并实现了一款基于OMAPL138平台的串口LCD的Linux驱动,介绍了OMAPL138平台及串口LCD的配置方式以及串口LCD驱动使用的关键技术—FrameBuffer、DMA与SPI,描述了驱动的基本架构和运行流程,最后从理论计算和实际使用方面验证了设计的可用性。
OMAPL138驱动串口LCD FrameBuffer DMA SPI
OMAPL138是美国德州仪器(TI)推出全新DSP+ARM工业处理器,这款芯片也是业界功耗最低的浮点数字信号处理器DSP+ARM9处理器,大大降低了双核通讯的开发难度,可充分满足工业应用的高能效、连通性设计对高集成度外设、更低热量耗散以及更长电池使用寿命的需求[1]。
在嵌入式应用中,OMAPL138的DSP核负责运行复杂的算法,ARM核负责控制与运算无关的外设,如显示屏、键盘和指示灯等。嵌入式应用的显示屏通常采用LCD,LCD与ARM连接的方式分为串口和并口2种[2]。串口方式是使用SPI(Serial Peripheral Interface)接口对数据进行串行进行传输,串口连接方式的主要优点是占用引脚少、PCB布线方便和抗干扰能力强;缺点是速度较慢且占用一个标准SPI接口。并口连接方式使用16根并口数据线及其他相关控制线将ARM与LCD相连,数据采用并行方式传输,并口连接方式的优点是传输速度快、直接操作显存、显示效果好和OMAPL138集成了并口的LCD控制器;缺点是占用资源多、传输距离近和抗干扰能力较差,在不以显示效果为主的嵌入式应用中,串口LCD是具有明显优势的。
实现串口LCD的Linux驱动需要使用3种关键技术:FrameBuffer、DMA及SPI。
2.1FrameBuffer
Framebuffer是一个标准的图像/视频输出设备,将基于不同硬件架构的图像/视频设备抽象成一种内存映射设备,屏蔽了底层硬件架构的差异,使应用开发人员仅需关注图片或图像本身,而不需要针对不同的底层硬件设备进行适配,提高了程序的可移植性[3]。Linux系统中的Framebuffer驱动框架如图1所示。
图1 FrameBuffer驱动程序结构图
Linux程序分为用户空间及内核空间2个层次,在FrameBuffer驱动程序里,fbmem.c定义了面向应用程序的高层操作,包括FrameBuffer设备的读写、内存映射及IO控制等函数,这些操作与具体硬件设备无关。向下一级使用xxx-fb.c,xxx表示具体的硬件设备,例如OMAPL138属于Davinci架构,其FrameBuffer驱动名为da8xx-fb.c。这个驱动主要是针对struct fb_info结构体的操作,例如注册与注销,这个结构体定义了帧缓冲设备的属性和操作的完整集合,主要包括针对硬件设备的具体操作fb_ops、固定参数fix及可变参数var等,每个帧设备都有一个fb_info结构体[4]。
2.2DMA
在FrameBuffer的应用中,底层硬件驱动需要周而复始的将显存内容刷新到底层硬件设备中,为了大大减轻CPU负担,这种持续不间断的大量数据搬移的工作,应当使用DMA控制器来处理。
OMAPL138使用增强型DMA控制器EDMA3[5],可以将内存划分为3个维度,如图2所示,第一维度称为Array,长度为ACNT字节,第二维度称为Frame,由BCNT个Array组成,第三维度由CCNT个Frame组成。
采用EDMA3的AB同步传输模式,每一个DMA事件触发传送ACNT×BCNT个数据,即传输一个Frame。使用的LCD为160×128像素点,每个像素点使用16 bits表示,一副图像为160×128×2=40 960 Bytes。将ACNT设置为20 480(最大值为32 768),BCNT设置为2,CCNT设置为1,表示每次传输完成后,回到帧缓冲的起始内存开始新一轮传输。
针对每个外设接口的接收和发送,OMAPL138均分配一个传输通道,使用SPI1与LCD相连,SPI1的发送通道是19,需要在分配DMA通道的函数edma_alloc_channel()中,对通道进行正确的设置。EDMA3还需要对传输的源地址和目的地址进行设置,源地址设置为帧缓冲请求的首地址,目的地址设置为SPI1的写数据寄存器SPIDAT0,物理地址为0x01F0E038。
2.3SPI
SPI是一种高速全双工同步通信总线,以主从方式工作,这种模式通常有一个主设备和一个或多个从设备,在LCD驱动中,OMAPL138作为主控设备,LCD作为从属设备,连接的引脚分别是时钟信号线SCLK、片选信号线CS及主机输出线SDO[6]。
在SPI使用之前,首先需要按照LCD手册对SPI时序的要求,对SPI寄存器的相应比特位进行正确的配置,包括SPI的使能、分频、位宽、片选、极性、相位及传输间延时等参数。例如在LCD的配置阶段,需要将SPI设置为8位传输模式,而在LCD的数据传输阶段,需要将SPI设置为16位传输模式,LCD要求SPI传输速率不超过14 MHz,进入SPI控制器的时钟频率约为153 MHz,需要将分频设置为11以下。为降低SPI时钟对于PCB其他电路的影响,可以在保证显示效果的前提下,尽量降低SPI时钟,可以将分频设置为16,将SPI时钟速率控制在10 MHz以下。
LCD的Linux驱动,符合Linux驱动的架构,模块的初始化module_init()函数调用da8xx_fb_init()函数,该函数主要实现以下2个功能:
①注册struct spi_driver类型的SPI设备驱动,spi_driver主要包含SPI的probe()和remove()函数,用于SPI对DMA的开启及释放;
②注册struct platform_driver类型的FrameBuffer平台设备驱动,platform_driver包含了对FrameBuffer的probe()、remove()、suspend()及resume()等函数,用于FrameBuffer的相关操作。
操作系统运行起来后,运行到加载LCD的驱动的阶段,将会执行LCD驱动最主要的一个函数,即FrameBuffer的probe()函数fb_probe(),其执行流程如图3所示。
图3 fb_probe()执行流程图
FrameBuffer的probe()函数用于执行以下任务:
①分配平台设备资源:为FrameBuffer平台设备申请资源,请求内存空间并将SPI寄存器物理地址重定向到此内存空间;
②分配FrameBuffer:使用framebuffer_alloc()函数生成一个fb_info结构的数据空间;
③填充fb_info:初始化fb_info结构中固定和可变的内存参数,定义fb_ops结构体,主要是ioctl()函数,用于应用程序与FrameBuffer设备进行控制信息交互,例如获取其固定及可变信息、设置屏幕开启、关闭及亮度等信息,注意,ioctl()函数的执行首先要停止DMA,操作完成后再开启DMA,防止DMA控制器和ARM操作冲突;
④注册FrameBuffer:使用register_framebuffer()函数;
⑤配置DMA:为SPI的发送分配19通道并及发送缓冲区;
⑥配置并开启LCD显示:按照LCD手册,对LCD的寄存器进行配置,步骤依次是:复位LCD→设置晶振→设置内存写入模式→设置RGB驱动电流→设置RGB预充电时间→设置显示长宽及偏移→讲写入模式设置为RAM模式等待DMA写入图像数据→打开显示。
fb_probe()函数执行完毕后,操作系统将执行SPI的probe()函数,在这个函数里面将DMA开启,至此正式向LCD中写入图像数据。
设备正式运行时,显示屏上出现FrameBuffer初始值代表的图像,说明FrameBuffer、DMA及SPI正常工作。使用示波器测量SPI的SCLK引脚,调节示波器的测量宽度旋钮,可见时钟的发送是不间断的,说明DMA在周而复始的运行,不断地将图像数据写入SPI,每个SPI数据为16 bits,如图4所示。将测量宽度旋钮旋至每格2 μs,使用测量功能测量10个SPI数据,左边测量线Ax=-8.436 μs,右边测量线Bx=8.547 μs,Δx=16.983 μs,1/Δx=58.8 824 118 kHz,测量范围内共有16×10=160个点,因此SPI时钟频率为160/Δx/1000=9.4 MHz。
图4 LCD的SPI时钟时序图
每帧图像点数为160×128×16=327 680个,在上述时钟频率下,每秒钟帧刷新速率为9.4×1 000 000/327 680=28.75帧,大于电影每秒24帧的刷新速率,满足了LCD使用的理论需求,如果需要更大的刷新速度,可以适当提高SPI的时钟速率。
编写测试程序,打开LCD驱动生成的设备/dev/fb0,使用ioctl()函数获取LCD的固定及可变参数,例如屏幕的尺寸和像素深度等信息;使用mmap()函数根据获取的LCD属性,申请图像缓存并映射FrameBuffer;向图像缓存等时间间隔的写入不同图像,使用人眼观察,在图像切换时,不能观察出图像刷新时的变换过程,满足了实际使用的需求。
串口LCD在速率上只有并口LCD的1/16,但是在有些嵌入式应用中,在满足数据或图像显示的基础上,不算其他控制引脚,串口LCD比并口LCD节省13根数据引脚,除了在PCB上布线复杂度极大下降,这些引脚还可以复用为其他功能,可以充分的利用有限的引脚资源。在这种情况下,串口LCD仍然具有广阔的使用空间。
[1]岳仁超,孙建东,刘晓铭.基于OMAPL138智能台区终端的设计[J].自动化与仪器仪表,2014(5):44-45,49.
[2]张伽伟,周安栋,罗勇.ARM11嵌入式系统Linux下LCD的驱动设计[J].液晶与显示,2011,26(5):660-664.
[3]梁小鸥,谭珏.基于Framebuffer的MCU-LCD驱动设计[J].微型机与应用,2014,33(17):37-39.
[5]艾纯明,欧阳斌林.应用EDMA3实现视频数据格式转换[J].中国科技信息,2012(7):106-107.
[6]杨美刚,李小文.SPI接口及其在数据交换中的应用[J].通信
技术,2007(11):385-387.
Design and Implementation of Serial LCD Linux Driver Based on OMAPL138 Platform
FAN Lin-tao1,WANG Ao2
(1 Hebei Far-east Communication System Engineering Co.,Ltd,Shijiazhuang Hebei 050200,China)(2 School of Information Science and Engineering,Yunnan University,Kunming Yunnan 650091,China)
In embedded applications,the serial LCD simple wiring,easy programming can meet the practical needs of the embedded device and have broad potential applications.This paper designs and implements a serial LCD Linux driver based on OMAPL138 platform,introduces OMAPL138 platforms and serial LCD configuration.The key technologies of serial LCD are analyzed,such as FrameBuffer,DMA and SPI.The basic structure and operation of the driving process are described,and the design availability is verified based on theoretical calculations and actual uses.
OMAPL138;serial LCD;FrameBuffer;DMA;SPI
TP334.3
A
1008-1739(2015)14-42-3
定稿日期:2015-06-26