Chinaunix首页 | 论坛 | 博客
  • 博客访问: 37710
  • 博文数量: 12
  • 博客积分: 500
  • 博客等级: 下士
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-21 17:12
文章分类
文章存档

2010年(12)

我的朋友

分类: LINUX

2010-07-09 10:28:22

DMA学习笔记

 

2010628星期一

DMA:direct memory access 是一种无须CPU参与就可以让外设与系统之间进行双向数据传输的硬件机制.

DMADMAC控制,在传输期间,CPU可以并发的执行其他任务.

 

需注意:

1:DMAcache一致性;

DMA针对内存中的地址有与cache有没有重叠区域.如果没有则相安无事.但是如果有重叠区域,就得考虑,因为并发的话,DMAcache就有可能从同一片内存中取数据,而取数据肯定会有时间先后的顺序.一旦cache取完了数据,但是DMA又对这一片内存空间进行了操作使得内存中的内容发生了改变,改变之前cache恰好还没有将没改变之前的内容传给CPU做处理.这样就会导致不一致性的错误.cache与内存中的数据一样就称之为一致,不一样就不一致.

       现在这个问题还没有找到恰当的方法去修改.这样的错误系统是不会报错的,而且很难检测出来,所以一般的解决办法就是让DMAcache不要使用同一片内存空间,做出这样的牺牲换取系统的正常稳定的工作.

 

内存分配了一致性区域(进行地址映射并保证一致性)

Void *dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *haddle,gfp_t gfp);

返回值:申请到的DMA缓冲区的虚拟地址

通过haddle返回缓冲区的总线地址(dma_addr_t是总线地址类型)

Void *dma_free_coherent()是与之对应的释放函数.

 

 

2010629星期二

Cache的不一致性,不仅仅发生在DMA的情况下,尤其是带MMU功能的ARM处理器,开启MMU之前,需要先置CACHE无效.TLB也是如此(TLB?)

 

  TLBTranslation lookaside buffer,即旁路转换缓冲,或称为页表缓冲;里面存放的是一些页表文件(虚拟地址到物理地址的转换表)。

  X86保护模式下的寻址方式:段式逻辑地址〉线形地址〉页式地址;

  页式地址=页面起始地址+页内偏移地址;

  对应于虚拟地址:叫page(页面);对应于物理地址:叫frame(页框);

  X86体系的系统内存里存放了两级页表,第一级页表称为页目录,第二级称为页表。

  TLBCPU里的一级、二级缓存之间不存在本质的区别,只不过前者缓存页表数据,而后两个缓存实际数据。()

 

 

DMA缓冲区 必须是物理上连续的内存空间

相关函数:

申请DMA缓冲区:

__get_dma_pages()__get_free_pages()/*内核中的函数*/的一个宏定义

或者dma_mem_alloc()

 

基于DMA的硬件使用的是总线地址并不是物理地址,

总线地址:从设备的角度看到的物理地址.

物理地址:CPU的角度看到的未经转换的内存地址.

 

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

 

内核提供了转换的函数进行总线地址<---->虚拟地址的转换

Virt_to_bus()bus_to_virt()

 

IOMMU: input/output memory management unit

IOMMU针对外设地址和内存地址之间的转换.(主要作用就是使得外设可以看到虚拟地址)

 

问题:SG:service guaide?分段中的缓冲区地址对外设变的连续?

()

 

DMA映射工作:

1:分配一片DMA缓冲区

2:为这片缓冲区产生设备可访问的地址.

 

注意:设备并不一定能在所有的内存地址上执行DMA操作,这时要执行地址掩码:

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

 

 

2010630星期三

DMA的流程

1:在使用DMA之前需要申请DMA通道

int request_dma(unsigned int dmanr,const char *device_id);//申请通道

void free_dma(unsigned int dmanr);//释放通道

 

Request_dma

初始化DMAC

申请DMA缓冲区

进行DMA传输

中断处理(如果有)

释放dma缓冲区

Free_dma()

在设备驱动模块加载或open()函数中进行

在设备驱动模块卸载或release()函数中进行

在读写及硬件操作时运行

看完了DMA的理论的东西之后,心里有很多的疑问:

1:如何将DMA集成到现在要用的nandflash驱动中去!

2:DMA中有很多的函数,分配连续的空间的函数中是随机分配的么?如何要从某个固定的起始地址开始分配,如何去做?

 

201071星期四

今天天气不错哦,多云````

如何实际运用DMA去做驱动```

1:DMA中有自己的一套中断方式``

1:要安装中断服务程序

2:申请DMA缓冲区

3:初始化DMA

4:进行DMA操作

5:引发中断进行中断处理程序

 

201076星期二

这中间发生了很多事情,老师又给我拷贝了一份dmac的文档,117页有的忙活了.

:桥要负责所存地址,数据及控制信号,同时要进行二次译码及选择相应的APB设备.

什么是握手信号:

什么是握手信号? 什么是握手协议?

RS -232
通行方式允许简单连接三线:TxRx和地线。但是对于数据传输,双方必须对数据定时采用使用相同的波特率。尽管这种方法对于大多数应用已经足够,但是对于接收方过载的情况这种使用受到限制。这时需要串口的握手功能。在这一部分,我们讨论三种最常用的RS-232握手形式:软件握手、硬件握手和 Xmodem


a
,软件握手:我们讨论的第一种握手是软件握手。通常用在实际数据是控制字符的情况,类似于GPIB使用命令字符串的方式。必须的线仍然是三根:Tx Rx和地线,因为控制字符在传输线上和普通字符没有区别,函数SetXModem允许用户使能或者禁止用户使用两个控制字符XONOXFF。这些字符在通信中由接收方发送,使发送方暂停。
例如:假设发送方以高波特率发送数据。在传输中,接收方发现由于CPU忙于其他工作,输入buffer已经满了。为了暂时停止传输,接收方发送XOFF,典型的值是十进制19,即十六进制13,直到输入buffer空了。一旦接收方准备好接收,它发送XON,典型的值是十进制17,即十六进制11,继续通信。输入buffer半满时,LabWindows发送XOFF。此外,如果XOFF传输被打断,LabWindows会在buffer达到75%和 90%时发送XOFF。显然,发送方必须遵循此守则以保证传输继续。

b
硬件握手:第二种是使用硬件线握手。和TxRx线一样,RTS/CTSDTR/DSR一起工作,一个作为输出,另一个作为输入。第一组线是RTS Request to Send)和CTSClear to Send)。当接收方准备好接收数据,它置高RTS线表示它准备好了,如果发送方也就绪,它置高CTS,表示它即将发送数据。另一组线是DTRData Terminal Ready)和DSRData Set Ready)。这些现主要用于Modem通信。使得串口和Modem通信他们的状态。例如:当Modem已经准备好接收来自PC的数据,它置高DTR线,表示和电话线的连接已经建立。读取DSR线置高,PC机开始发送数据。一个简单的规则是DTR/DSR用于表示系统通信就绪,而RTS/CTS用于单个数据包的传输。

LabWindows,函数SetCTSMode使能或者禁止使用硬件握手。如果CTS模式使能,LabWindows使用如下规则:
PC发送数据:
RS-232
库必须检测CTS线高后才能发送数据。

PC接收数据:
如果端口打开,且输入队列有空接收数据,库函数置高RTSDTR
如果输入队列90%满,库函数置低RTS,但使DTR维持高电平。
如果端口队列近乎空了,哭喊数置高RTS,但使DRT维持高电平。
如果端口关闭,库函数置低RTSDTR

c
XModem握手:最后讨论的握手叫做XModem文件传输协议。这个协议在Modem通信中非常通用。尽管它通常使用在Modem通信中, XModem协议能够直接在其他遵循这个协议的设备通信中使用。在LabWindows中,实际的XModem应用对用户隐藏了。只要PC和其他设备使用 XModem协议,在文件传输中就使用LabWindowsXModem函数。函数是XModemConfigXModemSend XModemReceive

XModem
使用介于如下参数的协议:start_of_dataend_of_dataneg_ackwait_delay start_delaymax_triespacket_size。这些参数需要通信双方认定,标准的XModem有一个标准的定义:然而,可以通过 XModemConfig函数修改,以满足具体需要。这些参数的使用方法由接收方发送的字符neg_ack确定。这通知发送方其准备接收数据。它开始尝试发送,有一个超时参数start_delay;当超时的尝试超过max_ties次数,或者收到接收方发送的start_of_data,发送方停止尝试。如果从发送方收到start_of_data,接收方将读取后继信息数据包。包中含有包的数目、包数目的补码作为错误校验、packet_size字节大小的实际数据包,和进一步错误检查的求和校验值。在读取数据后,接收方会调用wait_delay,然后想发送方发送响应。如果发送方没有收到响应,它会重新发送数据包,直到收到响应或者超过重发次数的最大值max_tries。如果一直没有收到响应,发送方通知用户传输数据失败。
由于数据必须以pack_size个字节按包发送,当最后一个数据包发送时,如果数据不够放满一个数据包,后面会填充ASCIINULL0)字节。这导致接收的数据比原数据多。在XModem情况下一定不要使用XON/XOFF,因为XModem发送方发出包的数目很可能增加到XON/OFF控制字符的值,从而导致通信故障。

 

给我的感觉 硬件握手就是收发双方遵循一种传输协议```必须双方都准备好,就算是握手成功了.

 

filed:字段,现场.

 

x = 0 7时,通道寄存器包含下列部分:

l        CFGx –通道x的配置寄存器

l        CTLx –通道x的控制寄存器

l        DARx –通道x的目的地址寄存器

l        DSRx –通道x的目的分散加载寄存器

l        DSTATx –通道x的目的状态寄存器

l        DSTATARx –通道x的目的状态地址寄存器

l        LLPx –通道x的链表指针寄存器

l        SARx –通道x的源地址寄存器

l        SGRx –通道x的源分散采集寄存器

l        SSTATx –通道x的源状态寄存器

l        SSTATARx –通道x的源状态地址寄存器

 

scatter/gather I/O

    scatter/gather方式是与block dma方式相对应的一种dma方式。

  

    dma传输数据的过程中,要求源物理地址和目标物理地址必须是连续的。但在有的计算机体系中,如IA,连续的存储器地址在物理上不一定是连续的,则dma传输要分成多次完成。

  

    如果传输完一块物理连续的数据后发起一次中断,同时主机进行下一块物理连续的传输,则这种方式即为block dma方式。

 

    scatter/gather方式则不同,它是用一个链表描述物理不连续的存储器,然后把链表首地址告诉dma masterdma master传输完一块物理连续的数据后,就不用再发中断了,而是根据链表传输下一块物理连续的数据,最后发起一次中断。 

 

    很显然scatter/gather方式比block dma方式效率高。

 

http://blog.csdn.net/zhoujunyi/archive/2007/12/06/1920110.aspx

 

 

中断寄存器:

1.Intblock 块传输中断

DMA向目的外设的块传输完成时,产生中断

2.IntDstTran 目的transaction完成中断

当位于目的端的握手接口(硬件或者软件握手接口)请求的single或者burst transaction中的最后的AHB传输完成后将产生中断

3.IntErr  错误中断

当在一个DMA传输中.AHB slave处在HRESP总线接收一个错误的响应时,将产生这个中断,DMA传输将取消,通道也禁用.

4.IntSrcTran transaction完成中断

当位于源端的握手接口(硬件或者软件握手接口)请求的single或者burst transaction中的最后的AHB传输完成后将产生中断

:如果操作的是内存 就应该忽略IntSrcTran/IntDstTran中断,因为对于内存来说.这里是没有”DMA transaction”概念的.

5.IntTfr  DMA传输完成中断

DMA向目的的外设传输完成时,会产生这个中断.

 

 

Raw :未经处理的

 

单块(single-block)传输配置

 

1.       首先使能DmaCfgReg寄存器的Bit 0,将该位置1,来使能DMAC

2.       然后,选择一个目前没有使用的通道(channel),例如使用channel0

3.       通过写以下寄存器:ClearTfrClearBlockClearSrcTranClearDstTran,和ClearErr来清除上次DMA传输可能产生的中断。

4.       通过写入SAR0寄存器,来配置DMAC所要进行传输的源端的起始地址;通过写入DAR0寄存器,来配置DMAC所要进行传输的目的端的起始地址。

5.       接下来配置CTL0寄存器,注意CTL0寄存器中的几个关键field

l         BLOCK_TS:该field决定了DMA所要传输的BLOCK的大小,例如将该field配置为0x18,同时源端的位宽是64bit,则表示DMA将会从源端传输2464bit位宽的数据。

l         SMS:该field决定了源端位于DMA的哪个master端口,对于目前的系统架构,只有DDR2是位于DMAmaster1端口,其它设备位于DMAmaster2端口。

l         DMS:该field决定了目的端口是位于DMA的哪个master端口。

l         TT_FC:此field决定了此次传输的类型,是memorymemory传输,还是memoryperipheral传输,或者其它情况,可以参照对应的编码表来具体选择。

l         SINC:该field决定了源端传输数据的地址是递增,还是递减,或者不变。一般,外设的地址是不变的,memory的地址是递增,或者递减的。

l         DINC:该field决定了目的端传输数据的地址是递增,还是递减,或者不变。

l         SRC_TR_WIDTH:该field决定了源端的端口宽度,根据具体情况来确定。

l         DST_TR_WIDTH:该field决定了目的端的端口宽度,根据具体情况来确定。

l         由于此处是single block传输下的配置,CTL0寄存器中的LLP_SRC_EN,LLP_DST_EN fields要置0

l         如果希望中断使能,则在INT_EN中使能该位

6.       下面配置CFG0寄存器,有下面的一些关键field

l         DEST_PER:如果目的端是外设,则需要使用hardware handshaking interface,此处是该外设对应的hardware handshaking interface接口号,每个外设的接口号都是唯一的,互不相同的。至于外设具体接到哪个接口号上,需要根据具体的硬件连接来确定。

l         SRC_PER:如果源端是外设,则需要使用hardware handshaking interface,此处是该外设对应的hardware handshaking interface接口号,每个外设的接口号都是唯一的,互不相同的。至于外设具体接到哪个接口号上,需要根据具体的硬件连接来确定。

l         HS_SEL_SRC:如果源端是外设,且需要hardware handshaking interface的情况下,则该位需要置0,来使能hardware handshaking interface

l         HS_SEL_DST:如果目的端是外设,且需要hardware handshaking interface的情况下,则该位需要置0,来使能hardware handshaking interface

l         由于此处是single block传输下的配置,CFG0寄存器中的RELOAD_SRCRELOAD_DST fields要置0

l         寄存器中的其它fields可以选用默认值

7.       由于此处不需要使用LLP0寄存器,可以将LLP0寄存器全部置0

8.       如果希望产生中断,在使能CTL.INT_EN的基础上,将Mask寄存器(MaskBlock, MaskDstTran, MaskErr, MaskSrcTran, MaskTfr)中的屏蔽位不使能。

注意:

如果在DMA的传输中,通道的源端是memory的时候,应该屏蔽source transaction complete中断,即将MaskSrcTran寄存器的对应位屏蔽使能。

如果在DMA传输中,通道的目的端是memory的时候,应该屏蔽destination transaction complete中断,即将MaskDstTran寄存器的对应位屏蔽使能。

9.       最后配置ChEnReg,来使能channel0。注意其中的CH_EN_WE fieldCH_EN要对应,并通过写1来使能对应的channel.

 

 

阅读(5277) | 评论(0) | 转发(0) |
0

上一篇:O文件与ko文件的区别

下一篇:没有了

给主人留下些什么吧!~~