您的位置:首页 > 其它

mmap将物理地址映射到用户空间

2016-07-08 09:04 369 查看
1. 申请空间

void *virt_mem = kzalloc(PAGE_SIZE, GFP_KERNEL);

2. 驱动层----->> 实现file_operation接口的.mmap方法

int led_drv_mmap(struct file *filp, struct vm_area_struct *vma)
{
//  vma是一个信息体, 用户提供mmap的请求

// 参数1, vma信息载体
//参数2,用户空间的虚拟起始位置
// 参数3, 物理地址
unsigned long addr;

if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
return -EINVAL;

addr = virt_to_phys(led_dev->virt_mem);

vma->vm_flags |= VM_IO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);

if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) {
printk(KERN_ERR "%s: io_remap_pfn_range failed\n",
__func__);
return -EAGAIN;
}

return 0;

}

3. 用户层的掉用
fd = open("/dev/led0", O_RDWR);

// mmap
int len = PAGE_SIZE;
//返回值为映射上来的物理地址
char *mmap_addr = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);

//往里面写点值
memcpy(mmap_addr,str,strlen(str));

sleep(1);

//读取数据
read(fd, rbuf, 64);
printf("rbuf = %s\n", rbuf);


2. 字符串或中文在屏幕的位置显示行数,
参数1:x轴坐标     参数2:y轴坐标     参数3:显示内容的大小    参数4:显示的内容
void Display_character(unsigned int x,unsigned int y,unsigned int len,unsigned char *string)
{
int k, xx;
unsigned char qh,wh;
const unsigned char *mould;
unsigned int length =len;

printf("length =%d\n",length);
for(k=0,xx=x;k<length-1;k++)
{
if(string[k]&0x80)   //中文字符
{
qh =string[k]-0xa0;         //区号
wh =string[k+1]-0xa0;       //位号
mould =&__CHS[((qh-1)*94+wh-1)*32];
Draw_Text16(4+xx,y,0x0000ff,mould);
xx+=16;
k++;
}
else
{
mould =&__ASCII[string[k]*16];
Draw_ASCII(4+xx,y,0xff0000,mould);
xx+=8;
}
}
}

3.获取到lcd屏的 vinfo.xres *vinfo.yres*vinfo.bits_per_pixel/8物理空间大小,并映射到应用层
static int init_lcd(char *dev_name)
{
int framebuffer_fd;
/*1.打开帧缓冲设备*/
framebuffer_fd =open(dev_name,O_RDWR);
if(framebuffer_fd<0)
{
printf("Error: failed open framebuffer device!\n");
return -1;
}

/*2.获取固定参数*/
if(ioctl(framebuffer_fd,FBIOGET_FSCREENINFO,&finfo))
{
printf("Error:failed get the framebuffer device`s fix informations!\n");
return -1;
}

/*3.获取可变参数*/
if(ioctl(framebuffer_fd,FBIOGET_VSCREENINFO,&vinfo))
{
printf("Error:failed get the framebuffer device`s var informations!\n");
return -1;
}

printf("xres =%ld\n",vinfo.xres);
printf("yres =%ld\n",vinfo.yres);
screensize =(vinfo.xres *vinfo.yres*vinfo.bits_per_pixel/8);
printf("screensize =%ld\n",screensize);

/*5.映射*/
framebuffer_ptr =(char *)mmap(  NULL,//如果此值为NULL,则表示用内核来自动给你分配一块虚拟空间
screensize,        //空间大小
PROT_READ|PROT_WRITE,//权限
MAP_SHARED,        //是否可以共享
framebuffer_fd,        //文件描述符
0);            //从哪个地方开始
if(framebuffer_ptr<0)
{
printf("Error:failed to mmap device mem!\n");
return -1;
}
memset(framebuffer_ptr,0,screensize);
printf("framebuffer_ptr is mmaped ok!\n");
return framebuffer_fd;
}

4. 对图片文件的操作
/*1.打开一副图片*/
pic_fd =open(argv[2],O_RDWR);
printf("pic_fd=%d\n",pic_fd);

/*2.获取图片大小*/
len =lseek(pic_fd, 0, SEEK_END);
printf("len =%ld\n",len);

buffer =(char *)malloc(len);

lseek(pic_fd, 0, SEEK_SET);
/*3.读取图片数据*/
read(pic_fd,buffer,len);

5.如果要显示一张图片
图片文件--读取数据--解析图片数据--------数据转换成RGB565--------------- LCD屏需要什么数据(RGB)
void draw_bmp(char *bmpfi
b45e
lename, unsigned short *fb)
{
unsigned char * bmpdata;
int ret;

ret = bmp_read_file(bmpfilename, &bmpdata);
if (ret)
{
printf("read bmpfile error.\n");
}
printf("bmpread0000000!!!!\n");
bmp2fb16_rgb565(bmpdata, fb);
printf("bm2fb1600000000000!!!!\n");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: