1、什么是framebuffer
(1)很多人都会说操纵lcd显示就是操纵framebuffer,表面上来看是这样的。实际上是frambuffer就是linux内核驱动申请的一片内存空间,然后lcd内有一片sram,cpu内部有个lcd控制器,它有个单独的dma用来将frambuffer中的数据拷贝到lcd的sram中去 拷贝到lcd的sram中的数据就会显示在lcd上,LCD驱动和framebuffer驱动没有必然的联系,它只是驱动LCD正常工作的,比如有信号传过来,那么LCD驱动负责把信号转成显示屏上的内容,至于什么内容这就是应用层要处理的。
(2)framebuffer帧缓冲(简称fb)是linux内核中虚拟出的一个设备
(3)framebuffer向应用层提供一个统一标准接口的显示设备
(4)从驱动来看,fb是一个典型的字符设备,而且创建了一个类/sys/class/graphics
2、帧缓冲设备驱动的结构
3、framebuffer的使用步骤
(1)打开设备文件 /dev/fb0
(2)获取当前设备信息 #include
(3)mmap做映射
(4)填充framebuffer
1、驱动框架部分
2、驱动部分
3、如何分析
(1)经验
(2)分析menuconfig、Makefile、Kconfig等
(3)内核编译后检查编译结果中的.o文件
1、fbmem_init函数
(1)#ifdef MODULE
(2)fb_proc_fops和fb在proc文件系统中的表现
(3)register_chrdev注册fb设备
(4)class_create创建graphics类
(5)fbmem_exit的对应
2、fb_fops
(1)read/write/mmap/ioctl
(2)registered_fb和num_registered_fb
(3)struct fb_info
3、register_framebuffer和unregister_framebuffer
1、s3cfb.c
2、s3c_device_fb
3、probe函数分析
(1)struct s3c_platform_fb :这个结构体是fb的platform_data结构体,这个结构体变量就是platform设备的私有数据,这个数据在platform_device.device.platform_data中存储。在mach文件中去准备并填充这些数据,在probe函数中通过传参的platform_device指针取出来。
(2)struct s3cfb_global: 这个结构体主要作用是在驱动部分的2个文件(s3cfb.c和s3cfb_fimd6x.c)的函数中做数据传递用的。
5、
实验步骤:
1、打开设备
2、获取设备信息
(1)不可变信息FSCREENINFO,使用ioctl的FBIOGET_FSCREENINFO名
(2)可变信息VSCREENINFO,使用ioctl的FBIOGET_VSCREENINFO名
3、mmap做映射
做完了mmap后fb在当前进程中就已经就绪了,随时可以去读写LCD显示器了。
4、fb显示之刷背景和画横线
#include
#include
#include
#include
#include
#include
#include
// 宏定义
#define FBDEVICE "/dev/fb0"
#define WIDTH 1024
#define HEIGHT 600
#define WHITE 0xffffffff // test ok
#define BLACK 0x00000000
#define RED 0xffff0000
#define GREEN 0xff00ff00 // test ok
#define BLUE 0xff0000ff
#define GREENP 0x0000ff00 // 一样,说明前2个ff透明位不起作用
// 函数声明
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);
// 第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<height; y++)
{
for (x=0; x<width; x++)
{
*(pfb + y * WIDTH + x) = color;
}
}
}
//画线函数
void draw_line(unsigned int color)
{
unsigned int x, y;
for (x=50; x<600; x++)
{
*(pfb + 200 * WIDTH + x) = color;
}
}