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

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 *bmpfilename, 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");
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值