Linux下的幀緩衝lcd應用編程及Framebuffer驅動程式模型

來源:互聯網
上載者:User

一、Linux的幀緩衝裝置

幀緩衝(framebuffer)是 Linux 為顯示裝置提供的一個介面,把顯存抽象後的一種裝置,他允許上層應用程式在圖形模式下直接對顯示緩衝區進行讀寫操作。這種操作是抽象的,統一的。使用者不必關心物理顯存的位置、換頁機制等等具體細節。這些都是由Framebuffer 裝置驅動來完成的。幀緩衝驅動的應用廣泛,在 linux 的案頭系統中,Xwindow 伺服器就是利用幀緩衝進行視窗的繪製。尤其是通過幀緩衝可顯示漢字點陣,成為 Linux漢化的唯一可行方案。

幀緩衝裝置對應的裝置檔案為/dev/fb*,如果系統有多個顯示卡,Linux 下還可支援多個幀緩衝裝置,最多可達 32 個,分別為/dev/fb0 到/dev/fb31,而/dev/fb 則為當前預設的幀緩衝裝置,通常指向/dev/fb0。當然在嵌入式系統中支援一個顯示裝置就夠了。幀緩衝裝置為標準字元裝置,主裝置號為29,次裝置號則從0到31。分別對應/dev/fb0-/dev/fb31。

通過/dev/fb,應用程式的操作主要有這幾種:

1.讀/寫(read/write)/dev/fb:相當於讀/寫螢幕緩衝區。例如用 cp /dev/fb0 tmp 命令可將當前螢幕的內容拷貝到一個檔案中,而命令 cp tmp > /dev/fb0 則將圖形檔案tmp直接顯示在螢幕上。

2.映射(map)操作:由於 Linux 工作在保護模式,每個應用程式都有自己的虛擬位址空間,在應用程式中是不能直接存取物理緩衝區地址的。為此,Linux 在檔案操作 file_operations 結構中提供了 mmap 函數,可將檔案的內容映射到使用者空間。對於幀緩衝裝置,則可通過映射操作,可將螢幕緩衝區的物理地址映射到使用者空間的一段虛擬位址中,之後使用者就可以通過讀寫這段虛擬位址訪問螢幕緩衝區,在螢幕上繪圖了。

3.I/O控制:對於幀緩衝裝置,對裝置檔案的 ioctl操作可讀取/設定顯示裝置及螢幕的參數,如解析度,顯示顏色數,螢幕大小等等。ioctl 的操作是由底層的驅動程式來完成的。

 

在應用程式中,操作/dev/fb的一般步驟如下:

1.開啟/dev/fb裝置檔案。

2.用 ioctl 操作取得當前顯示螢幕的參數,如螢幕解析度,每個像素點的位元數。根據螢幕參數可計算螢幕緩衝區的大小。

3.將螢幕緩衝區映射到使用者空間(mmap)。

4.映射後就可以直接讀寫螢幕緩衝區,進行繪圖和圖片顯示了。

典型程式段如下:

 

#include <linux/fb.h> int main() {int fbfd = 0; struct fb_var_screeninfo vinfo; struct fb_fix_screeninfo finfo; long int screensize = 0; /*開啟裝置檔案*/ fbfd = open("/dev/fb0", O_RDWR); /*取得螢幕相關參數*/ ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo);ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo); /*計算螢幕緩衝區大小*/ screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; /*映射螢幕緩衝區到使用者地址空間*/ fbp=(char*)mmap(0,screensize,PROT_READ|PROT_WRITE,MAP_SHARED, fbfd, 0); /*下面可通過 fbp指標讀寫緩衝區*/ ……/*釋放緩衝區,關閉裝置*/munmap(fbp, screensize);close(fbfd);}

二、ioctl操作

ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)

擷取fb_var_screeninfo結構的資訊,在linux/include/linux/fb.h定義。

ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)

擷取fb_fix_screeninfon結構的資訊。在linux/include/linux/fb.h定義。

fbfd為裝置檔案號。

三.mmap函數

功能描述:

mmap函數是unix/linux下的系統調用

mmap將一個檔案或者其它對象映射進記憶體。檔案被映射到多個頁上,如果檔案的大小不是所有頁的大小之和,最後一個頁不被使用的空間將會清零。munmap執行相反的操作,刪除特定地址地區的對象映射。

基於檔案的映射,在mmap和munmap執行過程的任何時刻,被對應檔的st_atime可能被更新。如果st_atime欄位在前述的情況下沒有得到更新,首次對映射區的第一個頁索引時會更新該欄位的值。用PROT_WRITE 和 MAP_SHARED標誌建立起來的檔案對應,其st_ctime 和 st_mtime

在對映射區寫入之後,但在msync()通過MS_SYNC 和 MS_ASYNC兩個標誌調用之前會被更新。

用法:

#include <sys/mman.h>void *mmap(void *start, size_t length, int prot, int flags,int fd, off_t offset);int munmap(void *start, size_t length); 

參數:

start:映射區的開始地址。

length:映射區的長度。

prot:期望的記憶體保護標誌,不能與檔案的開啟模式衝突。是以下的某個值,可以通過or運算合理地組合在一起

PROT_EXEC //頁內容可以被執行

PROT_READ //頁內容可以被讀取

PROT_WRITE //頁可以被寫入

PROT_NONE //頁不可訪問

flags:指定映射對象的類型,映射選項和映射頁是否可以共用。它的值可以是一個或者多個以下位的組合體

MAP_FIXED //使用指定的映射起始地址,如果由start和len參數指定的記憶體區重疊於現存的映射空間,重疊部分將會被丟棄。如果指定的起始地址不可用,操作將會失敗。並且起始地址必須落在頁的邊界上。

MAP_SHARED //與其它所有映射這個對象的進程共用映射空間。對共用區的寫入,相當於輸出到檔案。直到msync()或者munmap()被調用,檔案實際上不會被更新。

MAP_PRIVATE //建立一個寫入時拷貝的私人映射。記憶體地區的寫入不會影響到原檔案。這個標誌和以上標誌是互斥的,只能使用其中一個。

MAP_DENYWRITE //這個標誌被忽略。

MAP_EXECUTABLE //同上

MAP_NORESERVE //不要為這個映射保留交換空間。當交換空間被保留,對映射區修改的可能會得到保證。當交換空間不被保留,同時記憶體不足,對映射區的修改會引起段違例訊號。

MAP_LOCKED //鎖定映射區的頁面,從而防止頁面被交換出記憶體。

MAP_GROWSDOWN //用於堆棧,告訴核心VM系統,映射區可以向下擴充。

MAP_ANONYMOUS //匿名映射,映射區不與任何檔案關聯。

MAP_ANON //MAP_ANONYMOUS的別稱,不再被使用。

MAP_FILE //相容標誌,被忽略。

MAP_32BIT //將映射區放在進程地址空間的低2GB,MAP_FIXED指定時會被忽略。當前這個標誌只在x86-64平台上得到支援。

MAP_POPULATE //為檔案對應通過預讀的方式準備好頁表。隨後對映射區的訪問不會被頁違例阻塞。

MAP_NONBLOCK //僅和MAP_POPULATE一起使用時才有意義。不執行預讀,只為已存在於記憶體中的頁面建立頁表入口。

fd:有效檔案描述詞。如果MAP_ANONYMOUS被設定,為了相容問題,其值應為-1。

offset:被映射對象內容的起點。

 

返回說明:

成功執行時,mmap()返回被映射區的指標,munmap()返回0。失敗時,mmap()返回MAP_FAILED[其值為(void *)-1],munmap返回-1。errno被設為以下的某個值

EACCES:訪問出錯

EAGAIN:檔案已被鎖定,或者太多的記憶體已被鎖定

EBADF:fd不是有效檔案描述詞

EINVAL:一個或者多個參數無效

ENFILE:已達到系統對開啟檔案的限制

ENODEV:指定檔案所在的檔案系統不支援記憶體映射

ENOMEM:記憶體不足,或者進程已超出最大記憶體映射數量

EPERM:權能不足,操作不允許

ETXTBSY:已寫的方式開啟檔案,同時指定MAP_DENYWRITE標誌

SIGSEGV:試著向唯讀區寫入

SIGBUS:試著訪問不屬於進程的記憶體區

 

四、編程執行個體:

核心:linux-2.6.29.1

目標板:友善之臂mini2440

arm-linux-gcc-4.3.2

 下載 

==========================

Framebuffer驅動程式模型

  會向你展示目前的framebuffer裝置驅動的結構,最常用的是非標準驅動。很明顯他所處的層次最高,程式編寫是最容易的。理解了這個圖的,你已經很輕鬆的去完成一個fb驅動,比如給sa1100,s2410,s2440系列的ARM的LCD控制器寫驅動。

Color Map 剖析

在framebuffer驅動程式設計中,cmap這個東東太暈了。現在我要把他赤裸裸的剖析給大家:)

1. struct fb_cmap

/*顏色映射表*/struct fb_cmap {       __u32 start; /* First entry */       __u32 len; /* Number of entries */       __u16 *red; /* 紅色 */       __u16 *green; /*綠色*/       __u16 *blue; /*藍色*/       __u16 *transp; /* 透明度,允許 NULL */};

該結構在fb.h檔案中定義,在struct fb_ops結構中有兩個成員函數與其相關:

/*擷取顏色表*/int (*fb_get_cmap)(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);/*設定顏色表*/int (*fb_set_cmap)(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);

在struct fb_info結構中有變數:

struct fb_cmap cmap; /* Current cmap */

在fpgen基礎操作下提供:

extern intfbgen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);extern intfbgen_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);

在檔案/* drivers/video/fbcmap.c */中提供更多的cmap應用

 

extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp);extern void fb_copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);extern int fb_get_cmap(struct fb_cmap *cmap, int kspc,int (*getcolreg)(u_int, u_int *, u_int *, u_int *,u_int *, struct fb_info *),struct fb_info *fb_info);extern int fb_set_cmap(struct fb_cmap *cmap, int kspc,int (*setcolreg)(u_int, u_int, u_int, u_int, u_int,struct fb_info *),struct fb_info *fb_info);extern struct fb_cmap *fb_default_cmap(int len);extern void fb_invert_cmaps(void);

2. 通過檔案解析

在anakinfb.c檔案中,cmap

在stifb.c

本文介紹的裝置是位於/video目錄下面的anakinfb.c驅動程式。雖然我不清楚那個裝置的特性,但是從對程式的分析中我們仍然知道如何編寫一個frame buffer裝置驅動。

    本文是個標準的fb驅動。共221行,包含函數如下:

static int  anakinfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info) 31行 static int anakinfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,u_int transp, struct fb_info *info) 45行 static int anakinfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) 57行 static int anakinfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) 75行 static int anakinfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) 111行 static int anakinfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,     struct fb_info *info) 117行 static int anakinfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,     struct fb_info *info) 130行 static int anakinfb_switch_con(int con, struct fb_info *info) 147行 static int anakinfb_updatevar(int con, struct fb_info *info) 155行 static void anakinfb_blank(int blank, struct fb_info *info) 161行  int __init anakinfb_init(void) 178行

函數1,2是寄存器操作用。函數3,4,5,6,7是fb_ops函數。函數8用於切換控制台。函數9用於更新變數。函數10用於閃爍螢幕。函數11用於初始化裝置。

    很奇怪,對fb裝置的讀寫函數怎麼沒有!值得說明的是open,release,read,write,ioctl,mmap等函數的實現是由 fbmem.c檔案實現了。也就是說所有的fb裝置在給定了fb_info後,所有的操作都是一樣的。在明確的fb_info前提下,fbmem.c中的函數可以工作的很好。這樣大家應該感到非常輕鬆了吧,只要完成上述的幾個裝置相關的函數,frame buffer裝置的驅動就寫完了:) 
    系統的結構 

Stifb驅動模型

linux/drivers/video/stifb.c - Generic frame buffer driver for HP * workstations with STI (standard text interface) video firmware.

這個驅動程式和前面的anakin裝置完全不同,因為他不是採用標準的格式,而是根據 based on skeletonfb, which wasCreated 28 Dec 1997 by Geert Uytterhoeven也就是skeletonfb.c提供的架構完成的。

共230行,包含函數如下:

static int sti_encode_fix(struct fb_fix_screeninfo *fix, const void *par, struct fb_info_gen *info) 60行static int sti_decode_var(const struct fb_var_screeninfo *var,void *par, struct fb_info_gen *info) 71行static int sti_encode_var(struct fb_var_screeninfo *var, const void *par, struct fb_info_gen *info) 78行static void sti_get_par(void *par, struct fb_info_gen *info) 94行static void sti_set_par(const void *par, struct fb_info_gen *info) 99行static int sti_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info) 104行static int sti_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) 111行static void sti_set_disp(const void *par, struct display *disp, struct fb_info_gen *info) 118行static void sti_detect(void) 127行static int sti_blank(int blank_mode, const struct fb_info *info) 132行int __init stifb_init(void) 161行void stifb_cleanup(struct fb_info *info) 201行int __init stifb_setup(char *options) 208行

原文地址 http://www.dzkf.cn/html/qianrushixitong/2007/0429/2025_3.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.