APP下载

基于SCM601 平台的MCU-LCD Linux 驱动设计

2021-03-12贾天有任获荣李兆刚

软件导刊 2021年2期
关键词:缓冲区模组内核

贾天有,任获荣,李兆刚

(1.西安电子科技大学通信工程学院;2.西安电子科技大学机电工程学院,陕西西安 710000;3.浙江万胜智能科技股份有限公司,浙江 杭州 310012)

0 引言

在嵌入式主流LCD 屏中,主要包括两大类硬件接口,一种是常见的RGB 接口,另一种是MCU 接口[1]。RGBLCD 一般连接在处理器集成的LCD 控制器上,显存由系统内存充当,常用于显示视频或动画;MCU-LCD 针对早期内存较小、资源受限的单片机而设计,一般通过并口、SPI 等方式与处理器连接。MCU-LCD 显存内置在LCD 模组内部,常用于显示静止图片[2]。MCU-LCD 由于其价格低的优点,在嵌入式设备中仍然大量使用。范林涛等[3]提出SPI 接口的MCU-LCD 与Framebuffer 结合的LCD 驱动开发方法,该方法占用引脚资源较少,但也存在一些缺点:传输距离较近、抗干扰能力较差且不能在应用层控制LCD 以刷新。本文针对这些问题,提出基于并口的MCU-LCD 驱动程序,该驱动程序提供定时刷新帧缓冲区和应用层控制刷新帧缓冲区两种方式,可以通过应用层控制方式快速将信息显示在电子屏上,而对于非紧急数据的显示则采用定时器定时刷新方式,提升了驱动灵活性。MCU-LCD 和RGB-LCD 对比如表1 所示。

Table 1 Comparison of MCU-LCD and RGB-LCD表1 MCU-LCD 与RGB-LCD 对比

1 硬件接口

1.1 MCU-LCD 液晶模组

ST75161 是点阵型液晶模组,分辨率大小为160×160像素,可配置为单色或者4 级灰度两种工作模式,该芯片可以通过8 位并行接口(8080 系列或6800 系列)、SPI 或IIC 接口直接连接到微处理器。本文针对并行8080 接口作介绍,I8080 总线是Intel 提出的一种总线[4],Intel 总线的控制线有4 根:RD 读使能、WR 写使能、A0(数据/命令选择,1:数据,0:命令)、CSB 片选。数据和命令都通过D[7:0](双向数据线)传输,通过A0 的高低电平判断传输的是数据还是控制命令,A0 为低电平表明传输的是控制命令,A0 为高电平表明传输的是数据。

1.2 EBI 接口

SCM601 芯片是智芯微发布的一款以ARM926EJ-S[5]为内核的工业级SOC,最高主频300MHz,SOC 集成了EBI(外部总线,External Bus Interface)接口[6],SCM601 外部总线接口支持访问外部并行接口设备,如SRAM 和外部I/O设备,支持8 bit/16 bit 数据总线宽度,支持8080 和6800 模式的接口信号,支持最高5 SRAM 和外部I/O 设备,支持可编程访问周期。本文通过EBI 接口与ST75161 液晶模组连接。配置EBI 接口相关寄存器的值,使EBI 工作于并行8080 模式,调整EBI 总线读/写时序,匹配外接的ST75161液晶时序规格。为操作外接的LCD 模块,将EBI 的A0 地址线与LCD 侧的A0(数据/命令选择,1:数据,0:命令)相连,这样LCD 成为只有两个可访问地址的外部设备,访问两个地址中的低地址表示MCU 和LCD 之间传输的是命令,访问两个地址中的高地址表示MCU 和LCD 之间传输的是数据。通过以上配置,便可以通过EBI 接口向LCD 发送控制命令或数据以实现对LCD 的操作。采用并行8080接口时接线方式如图1 所示。

2 Linux 帧缓冲

Fig.1 Parallel 8080 interface wiring method图1 并行8080 接口接线方式

Framebuffer 是出现在Linux2.2.xx 内核中的一种驱动程序接口[7]。Linux 抽象出Framebuffer 设备供用户态进程实现直接写屏,用户可以将Framebuffer 看成是显示内存的一个映像,将其映射到用户地址空间后,就可以直接进行读写操作,而写操作可以直接反应在屏幕上。这种操作是抽象的、统一的,用户不必关心物理显存的位置、换页机制等具体细节,这些都由Framebuffer 设备驱动完成[8]。

2.1 Framebuffer 关键结构体

fb_info 结构体:帧缓冲设备最关键的一个数据结构是fb_info 结构体,其中包含了关于帧缓冲设备属性和操作的完整描述[9],结构体定义如下:

本处只列出部分较为重要的成员,其中fb_var_screen⁃info 记录用户可以修改的显示器控制器参数,包括屏幕分辨率和每个像素的比特数等;fb_fix_screeninfo 记录用户不能修改的显示控制器参数;fb_ops 为帧缓冲操作函数集;screen_base 为帧缓冲的虚拟地址[10]。

fb_var_screeninfo 结构体:用于记录帧缓冲设备的可修改记录[11]。结构体定义如下:

其中,xres 为屏幕的水平像素数,yres 为屏幕的垂直像素数,bits_per_pixel 定义每个像素由多少个bit 表示[12]。

fb_fix_screeninfo 结构体:记录了帧缓冲设备不可修改的记录[13]。结构体定义如下:

其中,id 是字符串标识,smem_start 是帧缓冲内存的开始地址,type 标识LCD 设备类型,line_length 指一行的长度(以字节为单位)。

2.2 驱动实现

基于Framebuffer 的LCD 驱动是字符设备,主设备号固定为29[14],次设备号从0 到31,符合Linux 驱动框架,驱动可独立编写为一个模块,能够动态加载到内核或动态从内核卸载,Linux 中通过module_init()和module_exit()分别声明驱动的入口和出口函数st75161_i80_init()、st75161_i80_exit()。

入口函数st75161_i80_init()实现以下功能:①分配一个fb_info 结构体;②初始化该结构体中的固定和可变参数,即根据 ST75161 液晶模组的硬件特性填充fb_var_screeninfo 结构体和fb_fix_screeninfo 结构体,初始化fb_ops 结构体。调用dma_alloc_writecombine()申请一段连续的物理内存区域作为显存空间,函数返回值为申请的帧缓存内存起始位置的虚拟地址[15];③参考SCM601 芯片手册,配置EBI 相关寄存器使EBI 接口工作于并行8080模式并设置读写时序;④背光引脚设置,初始化st75161 液晶;⑤向内核注册fb_info 结构体[16];⑥MCU-LCD 不同于RGB-LCD,不具备自动刷新帧缓冲区的功能,因此需要手动刷新,将显示缓冲区中的数据显示在屏幕上,本文通过在内核中添加定时器周期性刷新和在应用层通过ioctl()系统调用函数控制刷新两种方式相结合,共同控制帧缓冲区的刷新。

部分关键代码如下:

其中,initialization_ST75161()为ST75161 液晶模组初始化函数,该函数根据液晶模组官方手册中的初始化时序编写。

出口函数st75161_i80_exit()实现以下功能:①注销fb_info 结构体;②关闭st75161 液晶显示及背光;③注销用于刷新帧缓冲区的定时器;④释放硬件资源。

部分关键代码如下:

2.3 编译驱动

编写Makefile 文件,将编写的驱动编译成模块。Make⁃file 文件如下:

执行make 命令,将生成驱动模块ST75161_lcd.ko。

3 验证测试

3.1 应用程序

将编译生成的ST75161_lcd.ko 模块,使用insmod 命令动态加载进Linux 内核,在文件系统中生成一个设备文件/dev/fb0,在应用程序中,操作/dev/fb0 表现为对LCD 设备的操作。

对于应用程序而言,framebuffer 驱动和其它设备并无区别,用户可以将它看成是一块内存,可以向这块内存读写数据。Framebuffer 的显示缓冲区位于内核空间,应用程序可以将此空间映射到应用空间,在应用程序进行操作[18]。

应用层操作/dev/fb0 一般步骤如下:①使用系统调用函数open()打开/dev/fb0 设备文件;②使用系统调用函数ioctl()取得LCD 屏的重要参数,如屏幕分辨率、每个像素点的比特数,并根据这些参数计算屏幕缓冲区大小;③使用系统调用函数mmap()将屏幕缓冲区映射到用户空间;④读写映射后的空间,进行绘图、显示等操作;⑤释放资源,关闭设备文件。

应用程序操作/dev/fb0 流程如图2 所示。

Fig.2 Process of application operation/dev/fb0图2 应用程序操作/dev/fb0 流程

分别编写基本图形绘制函数、汉字显示函数和位图显示函数对驱动程序进行测试。

(1)绘制基本图形。画点函数是图形绘制的基础,将液晶屏左上角定义为坐标原点,横向为x 轴,纵向为y 轴,根据具体像素点的(x,y)坐标向帧缓冲区写入数据,将(x,y)位置画点,矩形和圆形绘制依据相关算法调用画点函数依次绘制。

(2)位图显示。BMP 位图文件可分为文件头、信息头和图像数据3 个部分,其中文件头占14 字节,信息头占40字节[19],分别用两个结构体表示文件头和信息头:

打开图片文件后,先根据文件头中的文件类型判断是否为BMP 图片,如果是,则读取信息头和文件头获取图片的其它信息,最后根据BMP 图片宽度和高度将位图信息复制到帧缓冲区,位图信息即可显示。

(3)ASCII 字符和汉字显示。简体中文汉字编码常采用GB2312 编码,一个汉字使用两个字节编码,高字节称为区码,低字节称为位码[20]。本文使用16×16 格式汉字库和8×16 格式字符库,使用以下方法即可获得具体汉字的字模:

ADD=[(区码-0xa1)x 0x5e+(位码-0xa1)]x 0x20;

从字符库中获取字模较简单,8×16 字符库中,每个字符占用16 字节,具体字符的字模信息在字符库中的偏移量等于字符对应的ASCII 值与每个字符占用字节数的乘积[21]。根据字符和汉字的字模信息,即可将具体字符和汉字加以显示。

3.2 LCD 显示测试结果

测试程序在基于SCM601 的集中器平台上运行,在屏幕上绘制矩形和圆形,同时对BMP 格式单色图片进行显示和汉字显示。测试效果如图3—图5 所示。

Fig.3 Geometry drawing图3 几何图形绘制

Fig.4 Graphic display图4 图形显示

Fig.5 Character and text display图5 字符和文字显示

4 结语

本文基于Framebuffer 机制设计MCU-LCD Linux 驱动程序,并编写测试程序以验证其功能。基于这种方式开发的驱动很好地解决了Linux 内核对MCU-LCD 的支持,为移植嵌入式中流行的Qt 和MINGUI 提供了基础。但该方法控制帧缓冲区刷新频率的定时器周期为500ms,该时间可能不是帧缓冲区刷新最优时间值,需进一步调试修改。

猜你喜欢

缓冲区模组内核
强化『高新』内核 打造农业『硅谷』
光学薄膜技术及在背光模组中的应用研究
基于嵌入式Linux内核的自恢复设计
Linux内核mmap保护机制研究
浅谈石墨烯材料在LED路灯模组中的应用及该模组的设计
嫩江重要省界缓冲区水质单因子评价法研究
关于超薄LED背光模组设计探讨
关键链技术缓冲区的确定方法研究
一种大面积OLED模组均匀调光技术研究
地理信息系统绘图缓冲区技术设计与实现