嵌入式快速入门学习笔记-Framebuffer

介绍

在应用层与内核之间传递少量数据时,采用copy_from_usr,copy_to_usr。但是如果是传输图片这种大量数据时需使用mmap方法(在内核空间中申请一段内存作为显存,然后将这段内存的物理地址与应用层的地址进行映射)。

使用流程

1)打开设备文件/dev/fb0
2)获取设备信息——需要包含头文件#include <linux/fb.h>
3)mmap做映射
4)向framebuffer填充数据

#include <sys/mman.h>

void *mmap (void *addr, size_t length, int prot, int flags, int fd, off_t offset);
@addr 指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。
@len 映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起。
@prot 参数指定共享内存的访问权限。可取如下几个值的或:PROT_READ(可读) , PROT_WRITE (可写), PROT_EXEC (可执行), PROT_NONE(不可访问)。
@flags 由以下几个常值指定:MAP_SHARED , MAP_PRIVATE , MAP_FIXED,其中,MAP_SHARED , MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用。
@fd 即将映射到进程空间的文件描述字,一般为open()返回值,同时,fd可以指定为-1,此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间通信)。
@offset 一般设为0,表示从文件头开始映射, 代表偏移量。

应用层例程

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

//设备名宏定义
#define FBDEVICE	"/dev/fb0"

// 旧开发板
//#define WIDTH		800	
//#define HEIGHT		480
// 新开发板
#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透明位不起作用

//全局变量 指向mmap映射空间
unsigned int *pfb = NULL;

//背景填充函数
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;
	}
}

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);//FBIOGET_FSCREENINFO 获取不可变的硬件信息
	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);//FBIOGET_VSCREENINFO 获取可变的硬件信息
	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;
	//虚拟空间大小=1024*1200 ——> 双缓冲区
	vinfo.xres_virtual = 1024;
	vinfo.yres_virtual = 1200;
	ret = ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo);//FBIOPUT_VSCREENINFO 设定可变的硬件信息
	if (ret < 0)
	{
		perror("ioctl");
		return -1;
	}
	
	// 再次读出来检验一下
	ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);//FBIOGET_VSCREENINFO 获取可变的硬件信息
	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;//映射字节数=长*宽(实际长宽的两倍)*像素bit数/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;
}

gcc编译,烧录测试

修改内核显示logo

1、logo的png格式图片(图片分辨率不得大于屏幕分辨率),并将其命令为logo.png(目的在于方便pngtopnm指令)

2、在终端下执行以下命令

pngtopnm logo.png | ppmquant -fs 224 | pnmtoplainpnm > logo_x210_clut224.ppm

3、生成的ppm文件拷贝到/kernel/drivers/video/logo/目录下进行替换。

4、编译内核 make -j4

补充:

(1)修改fbmem.c的471行可以修改Logo显示在屏幕中间:

image.dx = (info->var.xres - logo->width)/2;
image.dy = (info->var.yres - logo->height)/2;

(2)如果图片显示不出来可能有以下原因:
 
a、内核里framebuffer的分辨率不对,可以在mach-x210.c的225行修改(1024 * 600);

b、只能在左上角显示,CONFIG_FRAMEBUFFER_CONSOLE宏可能被选中(该宏不需要勾选,可以现在.config里面查看,确定后,make menuconfig 去除Device Drivers -> Graphics support -> Console display driver support -> Framebuffer Console Support)

修改Boot开机logo

1、Boot显示开机logo的代码定位 uboot\drivers\video\logo.c
2、更改变量xboot_logo的赋值。

自制开机logo

1、下载GIMP(linux平台)
2、将准备的图片(分辨率不要太高)通过GMIP导出C文件
3、将导出的C文件代码替换xboot_logo的值。
补:目前还没有测试过GIMP生成C数组

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值