Linux幀緩沖注冊OLED驅(qū)動(上)
1.幀緩沖Framebuff
在 linux 系統(tǒng)中 LCD 這類設(shè)備稱為幀緩沖設(shè)備,英文 frameBuffer 設(shè)備。
frameBuffer 是出現(xiàn)在 2.2.xx 內(nèi)核當(dāng)中的一種驅(qū)動程序接口。
幀緩沖( framebuffer)是 Linux 系統(tǒng)為顯示設(shè)備提供的一個接口,它將顯示緩沖區(qū)抽象,屏蔽圖像硬件的底層差異,允許上層應(yīng)用程序在圖形模式下直接對顯示緩沖區(qū)進行讀寫操作。用戶不必關(guān)心物理顯示緩沖區(qū)的具體位置及存放方式,這些都由幀緩沖設(shè)備驅(qū)動本身來完成。
用戶可以將 Framebuffer 看成是顯示內(nèi)存的一個映像, 將其映射到進程地址空間之后,就可以直接進行讀寫操作,而寫操作可以立即反應(yīng)在屏幕上。
幀緩沖驅(qū)動是字符類設(shè)備的一種,主設(shè)備號為29,生成的設(shè)備節(jié)點為/dev/fb*。
使用幀緩沖完成屏幕驅(qū)動注冊,應(yīng)用層只需調(diào)用open函數(shù)打開失敗,再通過ioctl函數(shù)獲取屏幕的參數(shù)信息,再調(diào)用mmap函數(shù)將屏幕顯存地址映射到進程空間,接下來對地址的寫入即是對屏幕的刷。
2.幀緩沖Framebuff應(yīng)用編程
幀緩沖應(yīng)用層編程步驟
打開LCD設(shè)備open(“/dev/fb0”,2);
獲取固定參數(shù)和可變參數(shù)ioctl;
將屏幕緩沖區(qū)映射到進程空間mmap;
實現(xiàn)屏幕最核心函數(shù)畫點函數(shù);
2.1 幀緩沖Framebuff設(shè)備節(jié)點
通過幀緩沖完成屏幕驅(qū)動注冊,會在/dev下生成設(shè)備節(jié)點,主設(shè)備號為29,注冊的一個設(shè)備驅(qū)動為/dev/fb0,第二個為/dev/fb1,依此類推,最大可以注冊32個設(shè)備。
2.2 固定參數(shù)
通過ioctl函數(shù),命令參數(shù)為FBIOGET_FSCREENINFO,固定參數(shù)結(jié)構(gòu)體為struct fb_fix_screeninfo。在固定參數(shù)可獲得的屏幕信息有:smem_len屏幕緩沖區(qū)大小、line_length一行的字節(jié)數(shù)。
#define FBIOGET_FSCREENINFO 0x4602 /*獲取屏幕固定參數(shù)*/
/*固定參數(shù)結(jié)構(gòu)體*/
struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
unsigned long smem_start; /* Start of frame buffer mem 屏幕物理地址 */
/* (physical address) */
__u32 smem_len; /* Length of frame buffer mem 屏幕緩沖區(qū)大小*/
__u32 type; /* see FB_TYPE_* */
__u32 type_aux; /* Interleave for interleaved Planes */
__u32 visual; /* see FB_VISUAL_* */
__u16 xpanstep; /* zero if no hardware panning */
__u16 ypanstep; /* zero if no hardware panning */
__u16 ywrapstep; /* zero if no hardware ywrap */
__u32 line_length; /* length of a line in bytes 一行的字節(jié)數(shù) */
unsigned long mmio_start; /* Start of Memory Mapped I/O */
/* (physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which */
/* specific chip/card we have */
__u16 capabilities; /* see FB_CAP_* */
__u16 reserved[2]; /* Reserved for future compatibility */
};
2.3 可變參數(shù)
??通過ioctl函數(shù),命令參數(shù)為FBIOGET_VSCREENINFO,固定參數(shù)結(jié)構(gòu)體為struct fb_fix_screeninfo。在固定參數(shù)可獲得的屏幕信息有:屏幕寬度xres、屏幕高度yres、顏色位數(shù)bits_per_pixel。
#define FBIOGET_VSCREENINFO 0x4600 /*獲取屏幕可變參數(shù)*/
/*可變參數(shù)結(jié)構(gòu)體*/
struct fb_var_screeninfo {
__u32 xres; /* visible resolution屏幕寬度 */
__u32 yres; /*屏幕高度*/
__u32 xres_virtual; /* virtual resolution */
__u32 yres_virtual;
__u32 xoffset; /* offset from virtual to visible */
__u32 yoffset; /* resolution */
__u32 bits_per_pixel; /* guess what 顏色位數(shù) */
__u32 grayscale; /* 0 = color, 1 = grayscale, */
/* >1 = FOURCC */
struct fb_bitfield red; /* bitfield in fb mem if true color, */
struct fb_bitfield green; /* else only length is significant */
struct fb_bitfield blue;
struct fb_bitfield transp; /* transparency */
__u32 nonstd; /* != 0 Non standard pixel format */
__u32 activate; /* see FB_ACTIVATE_* */
__u32 height; /* height of picture in mm */
__u32 width; /* width of picture in mm */
__u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
/* Timing: All values in pixclocks, except pixclock (of course) */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 colorspace; /* colorspace for FOURCC-based modes */
__u32 reserved[4]; /* Reserved for future compatibility */
};
2.4 將屏幕緩沖區(qū)映射到進空間
#include
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
函數(shù)功能: 將文件映射到進程空間
形參: addr --映射的虛擬地址,一般填NULL,有系統(tǒng)自行分配
???length --要映射的空間大小
???prot --PROT_READ可讀;PROT_WRITE可寫
???flags --MAP_SHARED可讀寫,讀寫內(nèi)容同步到文件;MAP_PRIVATE修改的內(nèi)容不會同步到文件
???fd --文件描述符
???offset --一般填0,表示映射整個文件
返回值: 成功返回映射的地址
???失敗返回-1
int munmap(void *addr, size_t length);
形參: addr --mamp函數(shù)返回值
???length --映射空間大小
2.5 幀緩沖獲取固定參數(shù)和可變參數(shù)示例
int main()
{
/*1.打開設(shè)備*/
int fd=open("/dev/fb0", 2);
if(fd<0)
{
printf("打開設(shè)備失敗n");
}
/*2.獲取固定參數(shù)*/
memset(&fb_fix,0, sizeof(fb_fix));
ioctl(fd,FBIOGET_FSCREENINFO,&fb_fix);
printf("屏幕緩存大小:%dn",fb_fix.smem_len);
printf("一行的字節(jié)數(shù):%dn",fb_fix.line_length);
/*3.獲取屏幕可變參數(shù)*/
memset(&fb_var,0, sizeof(fb_var));
ioctl(fd,FBIOGET_VSCREENINFO,&fb_var);
printf("屏幕尺寸:%d*%dn",fb_var.xres,fb_var.yres);
printf("顏色位數(shù):%dn",fb_var.bits_per_pixel);
/*4.將屏幕緩沖區(qū)映射到進程空間*/
lcd_p=mmap(NULL,fb_fix.smem_len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
close(fd);
if(lcd_p==(void *)-1)
{
printf("內(nèi)存映射失敗n");
return 0;
}
memset(lcd_p,0xff,fb_fix.smem_len);//將屏幕清空為白色
//取消映射
munmap(lcd_p,fb_fix.smem_len);
return 0;
}
/*畫點函數(shù)實現(xiàn)*/
static inline void LCD_DrawPoint(int x,int y,int c)
{
//獲取要繪制的點的地址
unsigned int *p= (unsigned int *)(lcd_p+y*fb_fix.line_length+x*fb_var.bits_per_pixel/8);
*p=c;//寫入顏色值
}
-
OLED
+關(guān)注
關(guān)注
119文章
6198瀏覽量
224087 -
Linux
+關(guān)注
關(guān)注
87文章
11292瀏覽量
209318
發(fā)布評論請先 登錄
相關(guān)推薦
評論