dma控制器

DMA---直接存储器访问

霸气de小男生 提交于 2020-03-12 13:37:22
一、DMA简介 DMA传输实现高速数据移动过程无需任何CPU操作控制。 DMA控制器是独立于Cortex_M4内核的。 STM32F407共有2个DMA控制器,DMA1只有外设到存储器和存储器到外设的传输模式,DMA2具有外设到存储器、存储器到外设以及存储器到存储器的传输模式。 传输模式: 1》外设到存储器(P--->M):把外设数据寄存器内容转移到指定的内存空间。 2》存储器到外设(M--->P):把特定存储区内容转移到外设的数据寄存器中。 3》存储器到存储器(M--->M):把一个指定的存储区内容拷贝到另一个存储区空间。 二、功能框图 (1)外设通道选择 每个DMA控制器具有8个数据流,每个数据流对应8个外设通道,每个通道对应不同的DMA请求。 外设通道选择要解决的主要问题是决定哪一个外设作为该数据流的源地址或者目标地址。 每个外设请求都占用一个数据流通道,相同外设请求可以占用不同数据流通道。 (2)仲裁器 仲裁器用来管理判断哪个数据流的优先级高。 仲裁器管理数据流方法分为两个阶段:第一阶段数据软件阶段,在配置数据流时可以通过寄存器设定它的优先级别,可以设置为非常高、高、中和低四个级别。第二阶段数据硬件阶段,如果两个或两个以上数据流软件设置优先级一样,则它们优先级取决于数据流编号,编号越低优先级越高,比如数据流2优先级高于数据流3。 (3)FIFO

总线主控DMA

给你一囗甜甜゛ 提交于 2020-02-17 18:30:38
DMA都是主控总线的,这里的总线主控DMA是指设备本身具备DMA功能,而无需使用系统DMA控制器。 总线主控DMA的设备,有两种基本的DMA方式 基于包的DMA传输 使用公共缓冲区的传输 基于包的DMA传输一般是这样的过程: IRP到达Dispacher Dispacher分配一个通道 AllocateAdapterChannel ,这个例程会在一个合适的时候调用它的一个回调函数 回调函数内部会根据IRP的MDL得到内核虚拟地址,接着 MapTransfer ,调用会得到物理地址,这个物理地址是指总线相关的物理地址 得到物理地址后,一般是写入硬件寄存器,并且通知启动DMA传输 真正的DMA传输就开始了 这种方式的DMA是可以直接把硬件的数据DMA到应用层的,效率相当高。另外DDK文档说明了一些Cache的控制,以及映射寄存器(x86是软件模拟的)的一些关系。需要仔细推敲和理解 使用公共缓冲区的传输是比较简单的: 在StartDevice时, AllocateCommonBuffer 得到一个公共缓冲区,这个缓冲区是物理连续的,有时候是会失败的。如果失败,那么StartDevice应该返回STATUS_INSUFFICIENT_RESOURCES. 和基于包的一样,IRP到达Dispacher,Dispacher直接使用缓冲区域地址编程硬件就可以启动DMA了

STM32F4x系列的DMA配置

不想你离开。 提交于 2020-02-15 20:47:28
以SPI2 为例,将存储器中的数据,通过DMA方式搬运到外设,DMA配置步骤: 1、选择DMA1还是DMA2:通过图1可查看到SPI2是在DMA1表里,所以选择DMA1。   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE); 2、选择数据流:该配置应该放在所有信息配置完在使能。   DMA_Cmd(DMAX_StreamY, ENABLE);   其中X = 1、2,Y=0、1…7,有两个DMA,分别是DMA1和DMA2,每个DMA控制器有又有8个数据流。   问题1:一个外设怎么知道选哪个数据流呢?   答:先查看参考手册,找到DMA1/2请求映射表,如下图1、2 图1 图2   比如现在用到外设SPI2_TX(存储器的数据搬运到外设,所以得找发送) ,选择数据流4。   DMA_Cmd(DMA1_Stream4, ENABLE); 3、通道选择,有8个通道,不是随便选择的,得查看图1和图2,SPI2外设所对应的通道0。   DMA_InitStructure.DMA_Channel = DMA_Channel_0; 4、设置外设基地址。   DMA_InitStructure.DMA_PeripheralBaseAddr = 0Xxxxx;    问题2:怎么知道当前选用外设的基地址?看人家例子都是写好了的,到时换其他外设

STM32使用DMA控制器试验总结

偶尔善良 提交于 2020-02-11 14:32:57
在使用串口DMA试验过程中,遇到了一些问题,通过试验找到了问题所在,也对DMA的应用有了新的认识,仅以此分享给大家,不足之处请多多指教。 DMA初始化 // 串口对应的DMA请求通道 # define USART_TX_DMA_CHANNEL DMA1_Channel4 # define USART_TX_DMA_IRQ DMA1_Channel4_IRQn # define USART_TX_DMA_IRQHandler DMA1_Channel4_IRQHandler // 外设寄存器地址 # define USART_DR_ADDRESS (USART1_BASE+0x04) // 一次发送的数据量 # define SENDBUFF_SIZE 250 /** * @brief USARTx TX DMA 配置,内存到外设(USART1->DR) * @param 无 * @retval 无 */ void USARTx_DMA_Config ( void ) { DMA_InitTypeDef DMA_InitStructure ; DMA_DeInit ( USART_TX_DMA_CHANNEL ) ; // 开启DMA时钟 RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_DMA1 , ENABLE ) ; // 设置DMA源地址

linux DMA接口

淺唱寂寞╮ 提交于 2020-02-09 22:49:04
1.两种DMA映射类型 1.1. 一致性DMA映射(Consistent DMA mappings ) 主要用于映射长时间使用的区域。 CPU和DMA controller不需要考虑cache的影响。 这里的consistent实际上是coherent的概念,不能保证consistent,也就是说需要memory barrier来保证memory order。 1.2 流式DMA映射(streaming DMA mapping) 主要用于一次性DMA传输,传输完成后就会释放。 2.指定DMA设备的寻址范围 include/linux/dma-mapping.h 1 // 用于一致性内存映射的映射范围 2 static inline int dma_set_coherent_mask(struct device *dev, u64 mask) 3 // 用于流式内存映射的映射范围 4 static inline int dma_set_mask(struct device *dev, u64 mask); 3.DMA映射接口 3.1一致性DMA接口 分配较大DMA buffer 1 // dev DMA控制器设备 2 // size 要分配的DMA buffer大小 3 // dma_handle 返回DMA buf的物理地址 4 // flag 分配标志 5 // 返回值 DMA

Linux 内存管理一

别来无恙 提交于 2020-01-31 11:03:20
疫情在家,整理下以前的学习笔记, 作为linux 三个最重要的部分之一(进程,io,内存),内存管理是非常重要的,是深入理解linux各个部分的基础,linux的内存管理与其他rtos的内存管理不一样,他是一个“富” os,也就是支持很多的应用同时跑,还需要支持应用之间的内存隔离。Linux 内存不仅仅用于内存,比如作为硬盘的补充,硬盘本身也可以作为内存来使用。 硬件原理和分页管理 只要我们打开了MMU之后,CPU只能看到虚拟地址,最终这个虚拟地址通过MMU根据页表查询到对应的硬件地址。比如要访问虚拟地址0x1234560,其中0x560 是页内偏移, 0x1234 是页号, 比如查到0x1234 对应的物理地址是1G,CPU访问0x1234560 的时候,实际访问的是1G+0x560 的地址。 物理地址是页表下面的一个数值,所以物理地址本质上是一个整数,而不是指针。地址是以*p访问到的,其实从linux中物理地址的数据类型也可以看出来 页表除了可以查虚拟地址对应的物理地址以外,还承担了一项非常重要的权限管理(RWX),RWX指读写执行权限,对linux安全非常重要,比如代码段映射为只读读加可执行,那么无论是应用还是内核里面的任何错误行为都不会改写代码段,只要一改写硬件就会发生page fault,软件的错误行为就会被硬件拦截,硬件里面还可以管理另外一个重要的权限

计算机组成:输入输出系统

老子叫甜甜 提交于 2020-01-29 18:22:09
输入输出系统 通道可以看做是DMA的升级版,通道有自己的控制器甚至是存储器、内存 通道可以执行由通道指令编写的程序,由操作系统完成 如果使用通道,就不是连接接口了,而是连接设备管理器 I/O处理机可以使用微处理器甚至直接使用和主处理器相同的处理器来做,当然这就不是家用电脑的范畴了,强大的I/O处理机甚至在没有IO工作时,可以作为主机的处理器来使用 I/O和主机的连接方式 统一编址:将io地址看成内存地址的一部分。这种方式实现了io和内存的统一不需要单独的io指令,CPU指令集相对简单,如果内存空间比较大(eg.64位)可以采用这种方式 单独编址: 串行速度慢,但是适合长距离传输 不便于增删设备 外部设备输出的数据可以先缓存到io接口,进行数据格式的转换等操作再输入主机 便于增删设备、采用标准接口,可移植性强 信息传送的控制方式 CPU直接对IO进行管理 缺点就是广为人知的,浪费CPU DMA请求:向CPU申请占用一个存取周期的总线控制权从而将外部设备的数据加载到内存中,这个周期内CPU不能使用总线对内存进行访问,但是这段时间CPU依然可以正常使用(由于CPU会预先取一部分指令,这段时间不能访问内存有可能影响不大) 外部设备简介 主观图像:用户绘制的图像,由点线面构成,就是简单的那种 客观图像:eg.GUI A:模拟信号 D:数字信号 IO接口 为什么使用接口 主机可能使用并行传输

linux 简单的DMA例程

Deadly 提交于 2020-01-20 03:05:20
一个简单的使用 DMA 例子 示例:下面是一个简单的使用DMA进行传输的驱动程序,它是一个假想的设备,只列出DMA相关的部分来说明驱动程序中如何使用DMA的。 函数dad_transfer是设置DMA对内存buffer的传输操作函数,它使用流式映射将buffer的虚拟地址转换到物理地址,设置好DMA控制器,然后开始传输数据。 int dad_transfer(struct dad_dev *dev, int write, void *buffer, size_t count) { dma_addr_t bus_addr; unsigned long flags; /* Map the buffer for DMA */ dev->dma_dir = (write ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); dev->dma_size = count; //流式映射,将buffer的虚拟地址转化成物理地址 bus_addr = pci_map_single(dev->pci_dev, buffer, count, dev->dma_dir); dev->dma_addr = bus_addr; //DMA传送的buffer物理地址 //将操作控制写入到DMA控制器寄存器,从而建立起设备 writeb(dev->registers.command

《Linux Device Drivers》第十五章 内存映射和DMA——note

微笑、不失礼 提交于 2020-01-20 03:04:37
简单介绍 很多类型的驱动程序编程都须要了解一些虚拟内存子系统怎样工作的知识 当遇到更为复杂、性能要求更为苛刻的子系统时,本章所讨论的内容迟早都要用到 本章的内容分成三个部分 讲述mmap系统调用的实现过程 讲述怎样跨越边界直接訪问用户空间的内存页 讲述了直接内存訪问(DMA)I/O操作,它使得外设具有直接訪问系统内存的能力 Linux的内存管理 地址类型 Linux是一个虚拟内存系统,这意味着用户程序所使用的地址与硬件使用的物理地址是不等同的 有了虚拟内存,在系统中执行的程序能够分配比物理内存很多其它的内存,甚至一个单独的进程都能拥有比系统物理内存很多其它的虚拟地址空间 以下是一个Linux使用的地址类型列表 用户虚拟地址 这是在用户空间程序所能看到的常规地址 物理地址 该地址在处理器和系统内存之间使用 总线地址 该地址在外围总线和内存之间使用,通常它们与处理器使用的物理地址同样 内核逻辑地址 内核逻辑地址组成了内核的常规地址空间 在大多数体系架构中。逻辑地址和与其相关联的物理地址不同,只在它们之间存在一个固定的偏移量 kmalloc返回的内存就是内核逻辑地址 内核虚拟地址 和内核逻辑地址的同样之处在于。它们都将内核空间的地址映射到物理地址上 内核虚拟地址与物理地址的映射不必是线性的一对一的 全部的逻辑地址都是内核虚拟地址。可是非常多内核虚拟地址不是逻辑地址

DMA

耗尽温柔 提交于 2020-01-12 04:28:07
DMA有3种实现方式:内存->内存;内存->外设;外设->内存 (外设->内存的DMA属于ADC) stm32有俩个DMA控制器: DMA1:7通道 DMA2:5通道,只存在于大容量(256K-512K)和互联型产品(f105和f107系列) rbt6开发板属于中容量,标准型,只有DMA1; 由图可知,内存->外设的方式,只能使用对应的通道,不能使用其他的。 而内存->内存的方式,可以使用所有的通道。 DMA一次可以传输2^16个字节的数据 那么,如果多个通道请求到来,应该怎么办? 这时,需要DMA的仲裁器进行仲裁: 1.首先,判断DMA通道x配置寄存器(DMA_CCRx)的PL位; 2.其次,如果PL位相同,判断通道的编号,编号越小,优先级越高。(同时,DMA1的优先级大于DMA2) typedef struct { uint32_t DMA_PeripheralBaseAddr;//外设地址 uint32_t DMA_MemoryBaseAddr; //存储器地址 uint32_t DMA_DIR; //传输方向 //这三个成员共同决定了内存->外设;外设->内存这俩种传输模式 uint32_t DMA_BufferSize; //传输的数量,单位由外设和存储器数据宽度决定 uint32_t DMA_PeripheralInc; //外设地址是否递增 uint32_t DMA