在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
查看: 4146|回复: 5

帧缓冲设备驱动的基本原理和框架

[复制链接]
发表于 2006-9-30 16:34:17 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?注册

x
长期以来,常见的掌上电脑(PDA)等小型手持式设备上,由于硬件条件的限制,我们看到的显示器件通常是单色LCD,用户界面也非常简单,几乎看不到PC机上美观整齐的图形界面(GUI)支持。因为早期嵌入式处理器的速度有限,在处理图形和多媒体数据方面显得力不从心。
随着高性能嵌入式处理器的普及和硬件成本的不断降低,尤其是ARM系列处理器的推出,嵌入式系统的功能也越来越强。在多媒体应用的推动下,彩色LCD也越来越多地应用到了嵌入式系统中,如新一代掌上电脑(PDA)多采用TFT显示器件,支持彩色图形界面,图片显示和视频媒体播放。掌上电脑(PDA)的操作系统有微软Window CE,PalmOS等。而Linux做为开放源代码的操作系统也在市场中占据了一席之地。由于Linux成本低廉,任何人都可以得到其源代码并在其基础上进行开发,成为各家厂商极力发展的操作系统,加上其核心小,潜力可观。
  在应用需求的推动下,Linux下也出现了许多图形界面软件包,如MiniGUI、Trolletech公司的Embedded QT等,其图形界面及开发工具与Windows CE不相上下。在图形软件包的开发和移植工作中都牵涉到底层LCD的驱动问题。笔者参与了一个很有代表性的项目,是基于ARM9的PDA系统的开发,用的是Motorola公司龙珠系列的MC9328MX1。软件采用Linux 2.4.18平台,编译器为gcc的ARM交叉编译器。在移植QT的过程中牵涉到了底层驱动的开发,本文就对相关问题作一探讨。
  
  硬件平台
  MC9328MX1(以下简称MX1)是Motorola公司基于ARM核心的第一款MCU,主要面向高端嵌入式应用。内部采用ARM920T内核,并集成了SDRAM/Flash,LCD,USB,蓝牙,多媒体闪存卡(MMC/SD, Memory Stick),CMOS摄像头等控制器。
  LCD控制器的功能是产生显示驱动信号,驱动LCD显示器。用户只需要通过读写一系列的寄存器,完成配制和显示控制。MX1中的LCD控制器可支持单色/彩色LCD显示器。支持彩色TFT时,可提供4/8/12/16位颜色模式,其中16位颜色模式下可以显示64k种颜色。配置LCD控制器重要的一步是指定显示缓冲区,显示的内容就是从缓冲区中读出的,其大小由屏幕分辨率和显示颜色数决定。在本例中,笔者采用的是夏普LQ035Q2DD54 TFT 显示模块,在240×320分辨率下可提供16位彩色显示。
  
  Linux下的设备驱动
  Linux将设备分为最基本的两大类,字符设备和块设备。字符设备是以单个字节为单位进行顺序读写操作,通常不使用缓冲技术,如鼠标等,驱动程序实现比较简单;而块设备则是以固定大小的数据块进行存储和读写的,如硬盘,软盘等。为提高效率,系统对于块设备的读写提供了缓存机制,由于涉及缓冲区管理,调度,同步等问题,实现起来比字符设备复杂得多。
  Linux的设备管理是和文件系统解密结合的,各种设备都以文件的形式存放在/dev目录下,称为设备文件。应用程序可以打开,关闭,读写这些设备文件,完成对设备的操作,就象操作普通的数据文件一样。为了管理这些设备,系统为设备编了号,每个设备号又分为主设备号和次设备号。主设备号用来区分不同种类的设备,而次设备号用来区分同一类型的多个设备。对于常用设备,Linux有约定俗成的编号,如硬盘主设备号是3。
  Unix / Linux的特点之一,是为所有的文件,包括设备文件,提供了统一的操作函数接口,定义如下:
  struct file_operations {
  struct module *owner;
  loff_t (*llseek) (struct file *, loff_t, int);
  ssize_t (*read) (struct file *, char *, size_t, loff_t *);
  ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
  int (*readdir) (struct file *, void *, filldir_t);
  unsigned int (*poll) (struct file *, struct poll_table_struct *);
  int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
  int (*mmap) (struct file *, struct vm_area_struct *);
  int (*open) (struct inode *, struct file *);
  int (*flush) (struct file *);
  int (*release) (struct inode *, struct file *);
  int (*fsync) (struct file *, struct dentry *, int datasync);
  int (*fasync) (int, struct file *, int);
  int (*lock) (struct file *, int, struct file_lock *);
  ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
  ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
  ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
  unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
  };
  结构体中的成员为一系列的接口函数,如用于读/写的read/ write函数,用于控制的ioctl等。打开一个文件就是调用这个文件file_operations中的open操作。不同类型的文件有不同的file_operations成员函数。如普通的磁盘数据文件,接口函数完成磁盘数据块读写操作;而对于各种设备文件,则最终调用各自驱动程序中的I/O函数进行具体设备的操作。这样,应用程序根本不用考虑操作的是设备还是普通文件,可一律当作文件处理,具有非常清晰统一的I/O接口。所以file_operations是文件层次的I/O接口。
  但是,由于外设的种类繁多,操作方式也各不相同。如声音设备驱动要使用DMA通道,显示设备驱动要提供对显存的操作,硬盘驱动要处理复杂的缓冲区结构,网络设备驱动和socket联系紧密。如果file_operations中的函数都让驱动程序的开发人员来写,则就要处理大量的细节,几乎是不可能的。为了解决设备多样性的问题,Linux采用了特殊情况特殊处理的办法,为不同设备定义好了文件层次file_operations结构中的接口函数,其中处理了大多数设备相关的操作,如各种缓冲区的申请和释放等等,而具体操作底层硬件的一小部分则留给开发人员。所以Linux另外提供一个文件层到底层驱动程序的接口,通常为一个结构体,其中包含成员变量和函数指针。不同的设备驱动有不同的结构体。这样,一方面保证了文件层I/O接口file_operations的一致性,另一方面驱动程序的开发人员也不用了解太多细节,只专注于硬件相关的I/O操作就可以了。例如,一个有代表性的特殊设备是声音设备,其文件层的file_operations定义如下:
  struct file_operations oss_sound_fops = {
  owner: THIS_MODULE,
  llseek: sound_lseek,
  read: sound_read,
  write: sound_write,
  poll: sound_poll,
  ioctl: sound_ioctl,
  mmap: sound_mmap,
  open: sound_open,
  release: sound_release,
  };
  其中的sound_read,sound_write等函数Linux都已提供,处理了与声音设备相关的许多细节,如DMA的申请,释放和操作等。而文件层到驱动程序的接口为audio_driver结构,其中包含底层操作函数。文件层的sound_read,sound_write会在需要时调用audio_driver中的函数。开发人员只要编写audio_driver中的函数就可以了。这样,最大程度地减小了驱动开发的工作量。下面我们将看到,Linux为显示设备提供的帧缓冲驱动也是这种“文件层 - 驱动层”的接口方式。
发表于 2006-10-5 11:56:35 | 显示全部楼层
支持啊,期待你的下文
另外想请教一些问题:
我现在用的是ARM9开发板+ARM-LINUX操作系统,操作系统里带有LCD的驱动程序,并且支持多种类型的TFT和STN液晶屏,现在我想把一块自己的12位TFT液晶屏接到开发板上,但我不知道文该怎么修改操作系统的配置,以支持我自己的液晶
在编译内核的时候,运行menuconfig 可以选择液晶屏的尺寸,如320*240、640*480等,也可以选择帧缓冲区的格式如2/4/8/16bit等,但怎样选择STN或TFT呢,它们的驱动信号完全不一样啊
如蒙赐教,不胜感激啊
发表于 2006-11-24 22:01:30 | 显示全部楼层
谢谢,不错
发表于 2006-11-25 16:58:25 | 显示全部楼层
不错!
坚持底层技术路线
发表于 2006-12-12 12:59:58 | 显示全部楼层
很好,期待下文
发表于 2012-10-13 01:08:07 | 显示全部楼层
thanks
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

小黑屋| 手机版| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2025-2-2 02:49 , Processed in 0.037843 second(s), 10 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表