Linux 预留内存 DMA 使用心得

文章目录

    • 预留的内存如何配置
    • 使用申请
    • 映射内存给用户态使用
    • 内存释放

如何预留内存参考文档:
Linux Reserved Memory 预留内存
本文采用的是 上文的 “通过DMA API预留内存”的方式

预留的内存如何配置

通过命令

#cat /proc/iomem
7ff00000-7ff00fff : /dma@7ff00000
7ff00000-7ff00fff : /dma@7ff00000
7ff50000-7ff50fff : /hdlcd@7ff50000
7ff60000-7ff60fff : /hdlcd@7ff60000
7ff80000-7ff80fff : /uart@7ff80000
7ff80000-7ff80fff : /uart@7ff80000
7ff90000-7ff90fff : /i2s@7ff90000
7ffa0000-7ffa0fff : /i2c@7ffa0000
7ffc0000-7ffcffff : /ehci@7ffc0000
7ffd0000-7ffd0fff : /memory-controller@7ffd0000
80000000-dfffffff : System RAM
......

可以看到系统内存其中的一块为

80000000-dfffffff : System RAM

我选择从系统内存中的尾部分配512M内存
地址从0xC0000000 开始,长度为0x20000000
我的分配为:

 reserved-memory {
        //Reserved memory through DMA API 
        sample_reserved: buffer@0xC0000000 {
           compatible = "shared-dma-pool";
            no-map;
            reg = <0x0 0xC0000000 0x0 0x20000000>;
        };
  };

    sample@0x64000000{
        compatible = "test,sample";
        memory-region=<&sample_reserved>;
    };

系统启动后再次使用命令查看内存:

#cat /proc/iomem
7ff00000-7ff00fff : /dma@7ff00000
7ff00000-7ff00fff : /dma@7ff00000
7ff50000-7ff50fff : /hdlcd@7ff50000
7ff60000-7ff60fff : /hdlcd@7ff60000
7ff80000-7ff80fff : /uart@7ff80000
7ff80000-7ff80fff : /uart@7ff80000
7ff90000-7ff90fff : /i2s@7ff90000
7ffa0000-7ffa0fff : /i2c@7ffa0000
7ffc0000-7ffcffff : /ehci@7ffc0000
7ffd0000-7ffd0fff : /memory-controller@7ffd0000
80000000-bfffffff : System RAM

使用申请

如上文所述,通过以下代码来使用这一块的内存:

define ALLOC_SIZE (0x20000000)

/* Initialize reserved memory resources */
 int rc= 0;
 dma_addr_t dma_handle;
 void* vaddr;
  rc = of_reserved_mem_device_init(dev);
  if(rc) {
    dev_err(dev, "Could not get reserved memory\n");
    goto error1;
  }
 
  /* Allocate memory */ 
  dma_set_coherent_mask(dev, 0xFFFFFFFF);
  
  vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &dma_handle, GFP_KERNEL);
  dev_info(dev, "Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llX\n", (u64)lp->vaddr, lp->paddr);

其中 vaddr 是内核代码可以直接使用的虚拟地址。
dma_handle 是这一块内存区域的物理地址。

dma_alloc_coherent 介绍

/**
 * dma_alloc_coherent - allocate consistent memory for DMA
 * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
 * @size: required memory size
 * @handle: bus-specific DMA address
 *
 * Allocate some uncached, unbuffered memory for a device for
 * performing DMA.  This function allocates pages, and will
 * return the CPU-viewed address, and sets @handle to be the
 * device-viewed address.
 */
void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);

映射内存给用户态使用

sample_mmap(struct file *file, struct vm_area_struct *vma)
{
    struct sample_data *priv= file->private_data;
    return dma_mmap_coherent(priv->dev, vma, priv->vaddr,
            priv->dma_handle, priv->size);
}

dma_mmap_coherent介绍:

/**
 * dma_mmap_coherent - map a coherent DMA allocation into user space
 * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
 * @vma: vm_area_struct describing requested user mapping
 * @cpu_addr: kernel CPU-view address returned from dma_alloc_coherent
 * @handle: device-view address returned from dma_alloc_coherent
 * @size: size of memory originally requested in dma_alloc_coherent
 *
 * Map a coherent DMA buffer previously allocated by dma_alloc_coherent
 * into user space.  The coherent DMA buffer must not be freed by the
 * driver until the user space mapping has been released.
 */
int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
		void *cpu_addr, dma_addr_t handle, size_t size);

内存释放

 dma_free_coherent(dev, ALLOC_SIZE , vaddr , dma_handle);

dma_free_coherent介绍:

void
    dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
              dma_addr_t dma_handle)

Free a region of consistent memory you previously allocated.  dev,
size and dma_handle must all be the same as those passed into
dma_alloc_coherent().  cpu_addr must be the virtual address returned by
the dma_alloc_coherent().

Note that unlike their sibling allocation calls, these routines
may only be called with IRQs enabled.

你可能感兴趣的:(嵌入式Linux)