Linux驱动技术技术之一:DMA编程

    DMA      即Direct Memory Access,是一种允许外设直接存取内存数据而没有     CPU      参与的技术,当外设对于该块内存的读写完成之后,DMAC通过中断通知CPU,这种技术多用于对数据量和数据传输速度都有很高要求的外设控制,如显示设备等。

DMA和Cache一致性

我们知道,为了提高系统运行效率,现代的CPU都采用多级缓存结构,其中就包括使用多级Cache技术来缓存内存中的数据来缓解CPU和内存速度差异问题。在这种前提下,显而易见,如果DMA内存的数据已经被Cache缓存了,而外设又修改了其中的数据,这就会造成Cache数据和内存数据不匹配的问题,即DMA与Cache的一致性问题。为了解决这个问题,最简单的办法就是禁掉对DMA内存的Cache功能,显然,这会导致性能的降低

虚拟地址 VS 物理地址 VS 总线地址

在有MMU的计算机中,CPU看到的是虚拟地址,发给MMU后转换成物理地址,虚拟地址再经过相应的     电路   转换成总线地址,就是外设看到的地址。所以,DMA外设看到的地址其实是总线地址。     Linux   内核提供了相应的A     PI   来实现三种地址间的转换:

//虚拟->物理virt_to_phys()//物理->虚拟ioremap()//虚拟->总线virt_to_bus()//总线->虚拟bus_to_virt()

DMA地址掩码

DMA外设并不一定能在所有的内存地址上执行DMA操作,此时应该使用DMA地址掩码

int dma_set_mask(struct device *dev,u64 mask);

比如一个只能访问24位地址的DMA外设,就使用dma_set_mask(dev,0xffffff)

编程流程

下面是在内核程序中使用DMA内存的流程:

 Linux驱动技术技术之一:DMA编程_设计制作_测量仪表

一致性DMA

如果在驱动中使用DMA缓冲区,可以使用内核提供的已经考虑到一致性的API:

/** * request_dma - 申请DMA通道 * On cert     ai   n platforms, we have to alloca     te   an interrupt as well... */int request_dma(unsigned int chan, const char *device_id);/** * 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 memory for a device for perfor     mi   ng DMA. This func     ti   on * 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, gfp_t flag)//申请PCI设备的DMA缓冲区void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)//释放DMA缓冲区void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle )//释放PCI设备的DMA缓冲区void pci_free_consistent()/** * free_dma - 释放DMA通道 * On certain platforms, we have to free interrupt as well... */void free_dma(unsigned int chan);

流式DMA

如果使用应用层的缓冲区建立的DMA申请而不是驱动中的缓冲区,可能仅仅使用kmalloc等函数进行申请,那么就需要使用流式DMA缓冲区,此外,还要解决Cache一致性的问题。

/** * request_dma - 申请DMA通道 * On certain platforms, we have to allocate an interrupt as well... */int request_dma(unsigned int chan, const char *device_id);//映射流式DMAdma_addr_t dma_map_single(struct device *dev,void *buf, size_t size, enum dma_dat     adi   rec  TI on direc  TI on);//驱动获得DMA拥有权,通常驱动不该这么做void dma_sync_single_for_cpu(struct device *dev,dma_addr_t dma_handle_t bus_addr,size_t size, enum dma_data_direc  TI on direc  TI on);//将DMA拥有权还给设备void dma_sync_single_for_device(struct device *dev,dma_addr_t dma_handle_t bus_addr,size_t size, enum dma_data_direction direction);//去映射流式DMAdma_addr_t dma_unmap_single(struct device *dev,void *buf, size_t size, enum dma_datadirection direction);/** * free_dma - 释放DMA通道 * On certain platforms, we have to free interrupt as well... */void free_dma(unsigned int chan);

93
167
0
76

相关资讯

  1. 1、电流传感器研发商星成电子新三板挂牌上市2977
  2. 2、华澜微新一轮融资到位资金2.4亿元,用于开发高端核心控制器芯片4989
  3. 3、2022年全球可穿戴设备市场总出货量将达2亿1234
  4. 4、美商务部对中兴通讯暂时部分解禁4448
  5. 5、NVIDIA推出CUDA-XAI加速库,面向GPU加速数据科学4890
  6. 6、phonearena报道称,消费者对iPhone11S的期待相当之高156
  7. 7、情感互动为人机交互提供更好的协作方式2369
  8. 8、深迪半导体发布新一代高性能小尺寸磁传感器ST480MS819
  9. 9、人们如何如何防备网络传播误信息1267
  10. 10、光电传感器的特性及市场1047
全部评论(0)
我也有话说
0
收藏
点赞
顶部