fb设备驱动1:fb设备的显像原理和步骤

lcd的显像原理:将DDR内存的一部分划分出来作为显存,显存与lcd显示屏幕之间做一个双向的映射,然后用户只需要将需要显示的内容放入显存之中,然后显存中的内容就会刷新到lcd的储存器中进行显示。

 

显存:在内核之中申请一块内存作为显存,由于内核空间和用户空间,也就是驱动和应用不能直接进行内容的复制,需要借助专门的接口函数copy_to_user和copy_from_user,而这两个函数的效率很慢,所以我们将在内核空间中申请的这块虚拟地址,而这个虚拟地址肯定会对应一块真实的物理地址,然后应用层mmap申请一段内存,进而进行虚拟地址映射,与我们之前显存对应的物理地址绑定,这样应用对于显存进行操作,驱动就可以将其显示在lcd上。

 

freamebuffer设备:

(1)由于lcd显示设备包括显示器的驱动器,显卡,以及各种不同位数的显示器,所以linux内核虚拟出来一个framebuffer设备向应用层提供一个统一的标准接口的显示设备(一般在/dev/fb0),应用可以使用open、read、write等对设备进行操作。

(2)fb设备是一个字符设备,他的设备框架自己创建了一个类/sys/class/graphic;

 

对于fb设备的简单操作:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

// 宏定义
#define FBDEVICE	"/dev/fb0"

#define WIDTH		1024	  //开发板的lcd显示屏的长宽
#define HEIGHT		600

#define WHITE		0xffffffff			
#define BLACK		0x00000000
#define RED			0xffff0000
#define GREEN		0xff00ff00			
#define BLUE		0xff0000ff			

#define GREENP		0x0000ff00			


// 函数声明
void draw_back(unsigned int width, unsigned int height, unsigned int color);
void draw_line(unsigned int color);


// 全局变量
unsigned int *pfb = NULL;


int main(void)
{
	int fd = -1, ret = -1;
	
	
	struct fb_fix_screeninfo finfo = {0};     
	struct fb_var_screeninfo vinfo = {0};	 
	
	// 第1步:打开设备
	fd = open(FBDEVICE, O_RDWR);
	if (fd < 0)
	{
		perror("open");
		return -1;
	}
	printf("open %s success.\n", FBDEVICE);
	
	// 第2步:获取设备的硬件信息
	ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	printf("smem_start = 0x%x, smem_len = %u.\n", finfo.smem_start, finfo.smem_len);
	
	ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
	printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
	printf("bpp = %u.\n", vinfo.bits_per_pixel);

	
	// 修改驱动中屏幕的分辨率
	vinfo.xres = 1024;
	vinfo.yres = 600;
	vinfo.xres_virtual = 1024;
	vinfo.yres_virtual = 1200;
	ret = ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	
	// 再次读出来检验一下
	ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	printf("修改过之后的参数:\n");
	printf("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
	printf("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
	printf("bpp = %u.\n", vinfo.bits_per_pixel);
	
	
	// 第3步:进行mmap
	unsigned long len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
	printf("len = %ld\n", len);
	pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
	if (NULL == pfb)
	{
		perror("mmap");
		return -1;
	}
	printf("pfb = %p.\n", pfb);
	
	draw_back(WIDTH, HEIGHT, WHITE);
	draw_line(RED);
	

	close(fd);
	
	return 0;
}



void draw_back(unsigned int width, unsigned int height, unsigned int color)
{
	unsigned int x, y;
	
	for (y=0; y


(1)打开fb设备:

fd = open(FBDEVICE, O_RDWR);

(2)获取lcd设备的具体参数如:分辨率信息:
 

ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);

其中 FBIOGET_FSCREENINFO 代表读取参数,FBIOPUT_VSCREENINFO 代表设置参数。

(3)应用申请内存,并进行虚拟地址映射:

pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

mmap函数的原型为:

void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);

第一个参数:想要映射的虚拟地址,第二个参数:映射的长度、第三个:映射内存的权限、第四个:打开的fb设备为文件描述符、第五个:映射的地址的偏移量。

在这里NULL表示使用系统分配的虚拟地址、PROT_READ | PROT_WRITE表示映射的地址可读可写、MAP_SHARED表示内存可被其他的进程共享打开使用、0表示偏移地址量为0.

(4)接着可以进行freambuffer显存内容的填充,之后就可以显示了。

 

End。。。。。。

 

 

你可能感兴趣的:(驱动开发)