zoukankan      html  css  js  c++  java
  • Android平台上PMEM的使用及Platform设备注册(一)

    Android中PMEM驱动程序是物理内存的驱动程序,可用于分配物理内存。PMEM在camera和video系统中频繁使用。下面,简单记录一下PMEM的使用方法。另外,由于PMEM设备做为Platform设备存在,所以我们将对Platform设备做以简单描述。

    一、PMEM的使用

    使用PMEM需要包含如下几个头文件:

    #include <sys/ioctl.h>

    #include <binder/MemoryHeapBase.h>

    #include <binder/MemoryHeapPmem.h>

    #include <linux/android_pmem.h>

     

    定义如下几个数据结构:

    #define PMEM_DEV "/dev/pmem0" //PMEM设备的路径

    #define kBufferCount 3 //申请的buffer数目

    sp<MemoryBase> mBuffers[kBufferCount];//存储PMEM buffer的数组

    int mBuffersPhys[kBufferCount];//存储PMEM buffer的物理地址

    int8 *mBuffersVirt[kBufferCount]; //存储PMEM buffer的逻辑地址

    sp<MemoryHeapBase> masterHeap;

    sp<MemoryHeapPmem>  mPreviewHeap;

     

    下面,我们分配3个大小为mPreviewFrameSize的buffer,同时获取每个buffer的物理地址和逻辑地址,将3个buffer放入数组mBuffers中。具体代码如下:

        Int mem_size = kBufferCount  * mPreviewFrameSize;  

    masterHeap = new

                MemoryHeapBase(PMEM_DEV,mem_size,MemoryHeapBase::NO_CACHING);

        mPreviewHeap = new MemoryHeapPmem(masterHeap,MemoryHeapBase::NO_CACHING);

            if (mPreviewHeap->getHeapID() >= 0) {

                mPreviewHeap->slap();

                masterHeap.clear(); 

                struct pmem_region region;

               int fd_pmem = 0;

              fd_pmem = mPreviewHeap->getHeapID(); 

          ::ioctl(fd_pmem,PMEM_GET_PHYS,&region);//获取物理地址

          for(int i = 0; i  < kBufferCount; i++){

            mBuffersPhys[i] = region.offset + i * mPreviewFrameSize;   

    mBuffersVirt[i] = (int8 *)mPreviewHeap->getBase() + i * mPreviewFrameSize;

            mBuffers[i] = new MemoryBase(mPreviewHeap,  i * mPreviewFrameSize, mPreviewFrameSize);

            ssize_t offset;

            size_t size;

            mBuffers[i]->getMemory(&offset, &size);

            LOGD("Preview buffer %d: offset: %d, size: %d.", i, offset, size);

          }

         }

      else LOGE("Camera preview heap  error: could not create master heap!");

     

    mPreviewFrameSize:一帧的大小,即byte数;

    MemoryHeapBase::NO_CACHING:表示该区域不会被cache;

    ::ioctl(fd_pmem,PMEM_GET_PHYS,&region);获取被分配的区域对应的物理地址;

    mBuffersPhys[i] = region.offset + i * mPreviewFrameSize;获取每个buffer对应的物理地址;

    mBuffersVirt[i] = (int8 *)mPreviewHeap->getBase() + i * mPreviewFrameSize;获取每个buffer对应的逻辑地址;

    mBuffers[i] = new MemoryBase(mPreviewHeap,  i * mPreviewFrameSize, mPreviewFrameSize);被分配区域对应的每个buffer的信息;

    mBuffers[i]->getMemory(&offset, &size);获取每个buffer的offset和大小;

     

    由于将PMEM做为Platform设备,下面将对Platform设备做以简单描述。

     

    二、Platform设备

    Linux 2.6的设备驱动模型中,我们关心总线、设备和驱动这3个实体,总线将设备和驱动绑定。在系统每注册一个设备的时候,会寻找与之匹配的驱动;相反的,在系统每注册一个驱动的时候,会寻找与之匹配的设备,而匹配由总线完成。

    一个现实的Linux设备和驱动通常都需要挂接在一种总线上,对于本身依附于PCIUSBI2 CSPI等的设备而言,这自然不是问题,但是在嵌入式系统里面,SoC系统中集成的独立的外设控制器、挂接在SoC内存空间的外设等确不依附于此类总线。基于这一背景,Linux发明了一种虚拟的总线,称为platform总线,相应的设备称为platform_device,而驱动成为platform_driver

    Linux platform. driver机制和传统的device driver 机制(通过driver_register函数进行注册)相比,一个十分明显的优势在于platform机制将设备本身的资源注册进内核,由内核统一管理,在驱动程序中使用这些资源时通过platform. device提供的标准接口进行申请并使用。这样提高了驱动和资源管理的独立性,并且拥有较好的可移植性和安全性(这些标准接口是安全的)

    下面,我们介绍几个重要的数据结构。
    platform_device结构体用来描述设备的名称、资源信息等。该结构被定义在

    /kernel/include/linux/platform_device.h中。

       struct platform_device {

       const char * name;    //设备名

       int     id;           //设备编号

       struct device dev;  

       u32     num_resources;  //设备使用资源的数目

       struct resource  * resource;  //设备使用资源

    };

    下面来看一下platform_device结构体中最重要的一个成员struct resource * resourcestruct resource被定义在include/linux/ioport.h中,定义原型如下:

    struct resource {

        resource_size_t start;  //资源起始地址

        resource_size_t end;    //资源结束地址

        const char *name;     

        unsigned long flags;    //资源类型

        struct resource *parent, *sibling, *child;

    };

    注:struct resource结构中我们通常关心startendflags3个字段,分别标明资源的开始值、结束值和类型,flags可以为IORESOURCE_IOIORESOURCE_MEMIORESOURCE_IRQIORESOURCE_DMA等。startend的含义会随着flags而变更,如当flagsIORESOURCE_MEM时,startend分别表示该platform_device占据的内存的开始地址和结束地址;当flagsIORESOURCE_IRQ时,startend分别表示该platform_device使用的中断号的开始值和结束值,如果只使用了1个中断号,开始和结束值相同。对于同种类型的资源而言,可以有多份,譬如说某设备占据了2个内存区域,则可以定义2IORESOURCE_MEM资源。

    下面,我们以PMEM设备为例,对Platform设备的注册流程做以描述。

    (待续)

  • 相关阅读:
    偶数求和
    POJ2002Squares
    学习笔记之ulimit
    LeetCode 345. Reverse Vowels of a String
    LeetCode 343. Integer Break
    LeetCode 292. Nim Game
    LeetCode 338. Counting Bits
    LeetCode 344. Reverse String
    [ZZ]良好的编码习惯
    学习笔记之Linux Shell脚本教程:30分钟玩转Shell脚本编程
  • 原文地址:https://www.cnblogs.com/nsnow/p/3831555.html
Copyright © 2011-2022 走看看