歡迎您光臨本站 登入註冊首頁

概述

   驅動程序,就是讓硬體正常工作的一段程序.拋開操作系統而言,各種外設的驅動程序的編寫都是大同小異,所不同的只是驅動程序在整個系統中的位置,以及與應用程序和內核之間的調……

    驅動程序,就是讓硬體正常工作的一段程序.拋開操作系統而言,各種外設的驅動程序的編寫都是大同小異,所不同的只是驅動程序在整個系統中的位置,以及與應用程序和內核之間的調用關係.筆者在深圳天喜投資有限公司參與VOIP項目時,曾經接觸過多種LCD(包括點陣型和字元型),也寫過一個小的GUI,只能顯示漢字以及畫簡單的直線、圓等等.在這個GUI中,應用程序直接調用LCD驅動程序的API,無需通過操作系統內核(nucleus).以這種方式編寫驅動固然簡單,但是不能達到標準化、規範化的目的,只能憑一己之力做一些較為簡單的應用.相反,如果能充分利用開放源碼的優勢,在已有的代碼基礎上開發出自己的圖形界面,就可以大大縮短開發時問.
    近幾年,隨著Linux技術的興起,uClinux在嵌入式領域逐漸佔有了重要的地位.uClinux驅動程序的結構和標準Linux驅動程序的結構類似,不同的只是uClinux不支持內存管理單元.因此,為了充分利用uClinux的優勢,驅動程序必須按照uClinux的方式來寫.Microwindows是一個著名的開放式源碼的嵌入式GUI軟體,目的是把圖形視窗環境引入到運行uClinux的小型設備上.而實現這一切的基礎即為Framebuffer.開發者只需實現LCD的Framebuffer驅動,即可完成像Windows中的桌面圖形界面,Framebuffer使得一切都變得那麼簡單.

1 底層LCD驅動機制
1.1 硬體平台
    S3C44B0X是三星公司基於ARM 核心的一款MCU,集成了多種外圍設備,其中包括LCD控制器.LCD控制器的功能是產生顯示驅動信號,驅動LCD顯示器.用戶只需要通過讀寫一系列的寄存器,完成配置和顯示控制.LCD控制器通過DMA將顯存中的數據傳入顯示板的Driver IC來顯示圖形.S3C44B0X中的LCD控制器可支持單色/彩色LCD顯示.最高只能支持8 b的STN(Super Twisted Nematic)顯示.配置LCD控制器重要的一步是指定顯示緩衝區,顯示的內容就是從緩衝區中讀出的,其大小由屏幕解析度和顯示顏色數決定.在文中,筆者採用的是優龍G35I顯示面板,在240×320解析度下提供4級灰度顯示.

1.2 Framebuffer的實現機制
    在uCLinux中,Framebuffer是一種能夠提取圖形的硬體設備,是用戶進入圖形界面的很好介面.Framebuffer是顯存抽象后的一種設備,它允許上層應用程序在圖形模式下直接對顯示緩衝區進行讀寫操作.這種操作是抽象的,統一的.用戶不必關心物理顯存的位置、換頁機制等等具體細節.這些都是由Framebuffer設備驅動來完成的.有了Framebuffer,用戶的應用程序不需要對底層的驅動深入了解就能夠做出很好的圖形.
    對於用戶而言,它和/dev下面的其他設備沒有什麼區別,用戶可以把Framebuffer看成一塊內存,既可以向這塊內存中寫人數據,也可以從這塊內存中讀取數據.顯示器將根據相應指定內存塊的數據來顯示對應的圖形界面.而這一切都由LCD控制器和相應的驅動程序來完成.
    Framebuffer的顯示緩衝區位於uClinux中核心態地址空間,而在uClinux中,每個應用程序都有自己的虛擬地址空間,在應用程序中是不能直接訪問物理緩衝區地址的.為此,uClinux在文件操作file_operations結構中提供了mmap函數,可將文件的內容映射到用戶空間.對於幀緩衝設備,則可通過映射操作,將屏幕緩衝區的物理地址映射到用戶空間的一段虛擬地址中,之後用戶就可以通過讀寫這段虛擬地址訪問屏幕緩衝區,在屏幕上繪圖.Framebuffer中內存塊分佈如圖1所示.
 
圖1 內存塊分布圖

2 底層LCD驅動介面
2.1 Linux下設備驅動程序
    在Linux中,大部分的設備驅動都寫成模塊的形式,但嵌入式系統是針對具體應用的,一般都不需要這一功能.因此,uClinux的驅動程序都是直接編譯到內核中.
    Linux將設備分為最基本的兩大類,字元設備和塊設備.字元設備是以單個位元組為單位進行順序讀寫操作,通常不使用緩衝技術,如滑鼠等,驅動程序實現比較簡單;而塊設備則是以固定大小的數據塊進行存儲和讀寫,如硬碟、軟盤等.為提高效率,系統對於塊設備的讀寫提供了緩存機制,由於涉及緩衝區管理,調度,同步等問題,實現起來比字元設備複雜得多.
    Linux的設備管理是和文件系統緊密結合的,各種設備都以文件的形式存放在/dev目錄下,稱為設備文件口].應用程序可以打開,關閉,讀寫這些設備文件,完成對設備的操作,就象操作普通的數據文件一樣.為了管理這些設備,系統為設備編了號,每個設備號又分為主設備號和次設備號.主設備號用來區分不同種類的設備,而次設備號用來區分同一類型的多個設備.對於常用設備,Linux有約定俗成的編號.
    Linux的特點之一,是為所有的文件,包括設備文件,提供了統一的操作函數介面,struct file_operations.
     結構體中的成員為一系列的介面函數,如用於讀/寫的read/write函數,用於控制的ioctl等.打開一個文件就是調用這個文件file_operations中的open操作.不同類型的文件有不同的file_operations成員函數.如普通的磁碟數據文件,介面函數完成磁碟數據塊讀寫操作;而對於各種設備文件,則最終調用各自驅動程序中的I/O函數進行具體設備的操作.這樣,應用程序根本不用考慮操作的是設備還是普通文件,可一律當作文件處理,具有非常清晰統一的I/O介面.

2.2 Framebuffer設備驅動
    在uCLinux中,由於外設的種類繁多,操作方式也各不相同.對於LCD的驅動,uCLinux採用幀緩衝設備,幀緩衝設備對應的設備文件為/dev/fb*,如果系統有多個顯示卡,uCI inux還支持多個幀緩衝設備,分別為/dev/fbO到/dev/fb31,而/dev/fb則為當前預設的幀緩衝設備,通常指向/dev/fb0.當然在嵌入式系統中支持一個顯示設備就夠了.幀緩衝設備為標準字元設備,主設備號為29,次設備號則從0到31.分別對應/dev/fb0-/dev/fb31.Framebuffer設備在很大程度上依靠了下面的3個數據結構,在fb.h中聲明.
Struct fb_var_screeninfo
Struct fb_fix_screeninfo
Struct fb_info
    第1個結構是用來描述圖形卡的特性的.通常是被用戶設置的.第2個結構定義了圖形卡的硬體特性,是不能改變的,用戶選定了LCD控制器和顯示器后,那麼它的硬體特性也就定下來了.第3個結構定義了當前圖形卡Framebuffer設備的獨立狀態,一個圖形卡可能有兩個Framebuffer,在這種情況下,就需要兩個fb_info結構.這個結構是惟一內核空間可見的.

2.3 Framebuffer驅動程序的實現
    應用程序通過內核對Framebuffer的控制,主要有下面3種方式.
1)讀/寫/dev/fb 相當於讀/寫屏幕緩衝區.
2)映射(map)操作 通過映射操作,可將屏幕緩衝區的物理地址映射到用戶空問的一段虛擬地址中,之後用戶就可以通過讀寫這段虛擬地址訪問屏幕緩衝區,在屏幕上繪圖.
3)I/O控制 對於幀緩衝設備,設備文件的ioctl操作可讀取/設置顯示設備及屏幕的參數,如解析度、顯示顏色數、屏幕大小等等.ioctl的操作是由底層的驅動程序來完成的.
    因此,Framebuffer驅動要完成的工作已經是很少了,只需分配顯存的大小、初始化LCD控制寄存器、設置修改硬體設備相應的var信息和fix信息.
    幀緩衝設備屬於字元設備,採用“文件層一驅動層”的介面方式.在文件層次上,uClinux為其定義了
static struct file_operations fb_fops={
owner:THIS_MODULE,
read:fb_read,/*讀操作*/
write:fb_write,/*寫操作*/
ioctl:fb_ioctl,/*控制操作*/
mmap:fb_mmap,/* 映射操作*/
open:fb_open,/*打開操作*/
release:fb_release,/*關閉操作*/
};
    在uClinux中,由於幀緩衝設備是字元設備,應用程序需按文件的方式打開一個幀緩衝設備,如果打開成功,則可對幀緩衝設備進行讀、寫等操作.在上文中已經介紹了幀緩衝設備的地址空間問題,對於操作系統來說,讀、寫幀緩衝設備就是對物理地址空間進行數據讀寫.當然,對於應用程序來說,物理地址空間是透明的.由此可見,讀寫幀緩衝設備最主要的任務就是獲取幀緩衝設備在內存中的物理地址空間以及相應LCD的一些特性.
    圖2反映了應用程序如何寫幀緩衝設備來顯示圖形的全過程.
 
圖2 驅動程序實現框圖
    在了解了上面所述的概念后,編寫幀緩衝驅動的實際工作並不複雜,需要做如下工作.
1)編寫初始化函數 初始化函數首先初始化LCD控制器,通過寫寄存器設置顯示模式和顯示顏色數,然後分配I CD顯示緩衝區.在Linux可通過kmalloc函數分配一片連續的空間.筆者採用的LCD顯示方式為240×320,4位灰度.需要分配的顯示緩衝區為240×320×1/2=37.5k位元組,緩衝區通常分配在大容量的片外SDRAM 中,起始地址保存在LCD控制器寄存器中.最後是初始化一個fb_info結構,填充其中的成員變數,並調用register_framebuffer(&fb_info),將fb_info登記人內核.下面是初始化幀緩衝設備的程序代碼.
int __init s3c44b0xfb_init(void)
{
……
struct known_lcd_panels *p_lcd: //LCD Panel feature
/*Init LCD Controller*/
lcd_Init(p_lcd->bpp);
lcd_DispON();//Open LCD display
/* Init Framebuffer Parameter*/
fb_parameter_init(p_lcd);
memset(&fb_info.gen,0,sizeof(fb_info.gen));
/* Print some information */
printk("S3C44B0X framebuffer driver:Init ready ");
return 0;
)
2)編寫結構fb_info中函數指針fb_ops對應的成員函數 對於嵌入式系統的簡單實現,只需要下列3個函數就可以了.
struct fb_ops{
……
int(*fb_get_fix)(struct fb_fix_screeninfo *fix,int con,struct fb_info *info);
int(*fb_get_var)(struct fb_var_screeninfo *var,int con,struet fb_info *info);
int(*fb_set_var)(struet fb_var_screeninfo *var,int con,struct fb_info *info);
……
};
    struct fb_ops在include/linux/fb.h中定義.這些函數都是用來設置/獲取fb_info結構中的成員變數的.當應用程序對設備文件進行Ioctl操作時候會調用它們,例如,對於fb_get_fix(),應用程序傳入的是fb_fix_screeninfo結構,在函數中對其成員變數賦值,主要是smem_start(緩衝區起始地址)和smem_len(緩衝區長度),最終返回給應用程序.而fb_set_var()函數的傳入參數是fb_vat_screeninfo,函數中需要對xres,yres,和bits_per_pixel賦值.

3 在應用程序中使用Framebuffer設備
    uClinux通過設備文件來提供應用程序和設備驅動的介面.MicroWinows就是利用Frame_buffer的典型應用.
    Microwindows從原理上採用分層設計的方法,每個層次都完成特定的功能,並且能夠在不影響其他層次的基礎上針對不同的應用進行改編或者重寫.在最底層,顯示屏、滑鼠、觸摸屏等的驅動程序提供了與交互相關的硬體設備的訪問.在中間層,是一個精簡的圖形引擎,提供了劃線、區域填充、多邊形等多種基本的圖形功能.最上層為圖形應用程序提供了豐富的編程介面函數(API),通過這些介面函數可以定製桌面和窗口的外觀.目前,Microwindows提供兩套API介面,與Win32/WinCE基本兼容的API和採用X體系的Nano_XAPI.
    因此,為了將Microwindows 移植入S3C44B0X,只需更改與顯示屏相關的Framebuffer驅動程序.

4 結束語
    筆者在自己開發的S3C44B0X板上實現了uClinux以及Microwindows,為各種嵌入式應用提供了一個很好的開發平台.由於uCLinux是完全免費開放式源代碼,為嵌入式設備提供了更多的解決方案.熟悉圖形應用程序的用戶可以很快就在該系統上編寫出自己的圖形應用程序,在未來的嵌入式系統設計中,它的作用是無可限量的.


[admin via 研發互助社區 ] 基於Framebuffer 的LCD驅動程序的實現已經有2105次圍觀

http://cocdig.com/docs/show-post-42130.html