通过命令
#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.