智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 27011|回复: 54
打印 上一主题 下一主题

[讨论] K60 的 DMA 部分

  [复制链接]

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
跳转到指定楼层
1#
发表于 2013-2-16 11:45:43 | 显示全部楼层 回帖奖励 |倒序浏览 |阅读模式
请问一下野火的DMA驱动里面的一些问题吗,一直在看数据手册的DMA部分,全是英文,看的真的不是很懂,好多纠结。

    源地址和目的地址的区别是啥啊,当数据来临时是目的地址进行相应的增加吗?如果我的目的地址和源地址设定为0X0003,通道每次传输字节数为4个字节,那DMA转换结束后,目的地址是会变成0X007吗?
    主循环和副循环是怎么区分的呢?如果的我的主循环次数为3,那就上面的例子,是不是指总共会造成12个字节的传输呢,最后的目的地址和源地址是什么啊?
    当前和起始主循环次数是什么意思啊,为什么主循环结束后要恢复源地址呢?
    DMA总共有16个通道,一个通道用来采集编码器的脉冲个数,另一个用来保存ADC对8个传感器的直接采样值(也就是说没有检波电路,>20KHz进行采样,我是电磁组的),这两个交替工作,能实现吗?


   DMA_NBYTES_MLNO(CHn) =   DMA_NBYTES_MLNO_NBYTES(BYTEs); // 通道每次传输字节数,这里设置为BYTEs个字节。注:值为0表示传输4GB */


    DMA_CITER_ELINKNO(CHn)  = DMA_CITER_ELINKNO_CITER(count); //当前主循环次数
    DMA_BITER_ELINKNO(CHn)  = DMA_BITER_ELINKYES_BITER(count);//起始主循环次数

/* 配置 DMA 传输结束后的操作 */
    DMA_SLAST(CHn)      =   0;                              //调整  源地址的附加值,主循环结束后恢复  源地址
    DMA_DLAST_SGA(CHn)  =   (u32)( (cfg & 0x20) == 0 ? (-count)  : 0 ); //调整目的地址的附加值,主循环结束后恢复目的地址或者保持地址

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
2#
 楼主| 发表于 2013-2-16 13:12:34 | 显示全部楼层
本帖最后由 yangkuanqaz8598 于 2013-2-16 13:32 编辑
suebillt 发表于 2013-2-16 12:29
不懂,昨天看到触发源那边就晕了,不知槽为何物


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
3#
 楼主| 发表于 2013-2-16 13:14:59 | 显示全部楼层
suebillt 发表于 2013-2-16 12:29
不懂,昨天看到触发源那边就晕了,不知槽为何物

不知道槽是不是可以理解为DMA需要采集数据的数据源呢.....槽是个很神奇的名词
回复 支持 反对

使用道具 举报

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
4#
 楼主| 发表于 2013-2-16 13:30:36 | 显示全部楼层
suebillt 发表于 2013-2-16 13:23
DMA可以软件触发,也可以IO电平触发,我只是困惑exti那部分初始化的时候定义了IO的外部中断触发DMA,但是 ...

楼上能不能给个例程附件看下勒,我这只有野火的DMA驱动,
回复 支持 反对

使用道具 举报

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
5#
 楼主| 发表于 2013-2-16 14:01:37 | 显示全部楼层
suebillt 发表于 2013-2-16 13:40
我就是看的野火的,就是不知道PTB8 被宏定义在哪,找不到

PTB8啊,它在GPIO_CFG.H里面,是一个PTxn的枚举。
只不过这个触发源的配置看不懂,加上这source[5-0]是怎么对应触发源的,我找不到呢

/* 配置 DMA 触发源 */
    DMAMUX_CHCFG_REG(DMAMUX_BASE_PTR, CHn) = (0
            | DMAMUX_CHCFG_ENBL_MASK                        /* Enable routing of DMA request */
            //| DMAMUX_CHCFG_TRIG_MASK                        /* Trigger Mode: Periodic   PIT周期触发传输模式   通道1对应PIT1,必须使能PIT1,且配置相应的PIT定时触发 */
            | DMAMUX_CHCFG_SOURCE((ptxn >> 5) + DMA_Port_A) /* 通道触发传输源:     */

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
6#
 楼主| 发表于 2013-2-16 17:24:31 | 显示全部楼层
qurrer 发表于 2013-2-16 16:57
不懂

一起学习,一起研究{:soso_e113:}
回复 支持 反对

使用道具 举报

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
7#
 楼主| 发表于 2013-2-17 00:25:13 | 显示全部楼层
本帖最后由 yangkuanqaz8598 于 2013-2-17 00:32 编辑
suebillt 发表于 2013-2-16 14:05
英文资料太复杂,没看懂,刚刚看这个知道了通道源那部分

看了你给的资料后,我貌似懂了点东西,说出看下理解的对不对~

       对于主循环的理解:你需要传输多少次数据,传输的次数值存储在主循环计器DMA_CITER_ELINKNO(CHn)的CITER中,每次传输完数据之后,CITER的值就会自动减一,一旦主循环计数器的CITER的值减到0,则DMA传输完毕后,TCDn_CSR[DONE]置1,如果允许,可以向CPU申请中断,读走这部分数据(比如我们要对一个传感器的电压值,采集100次,则应该将主循环的次数就设定为100,也就是DMA_CITER_ELINKNO(CHn)的CITER的数值设定为100)。

      对于目的地址的理解:当DMA存储数据的时候,也就是每次数据传输之后,目的地址会自动加上DMA_DOFF(CHn)这个目的地址偏移量的值。
如果偏移量为0时,每次传输数据之后目的地址不会发生变化,这样一来,如果有多次数据的传输(也就是主循环的次数),则就会造成对上次数据的更新覆盖( DMA_count_init()就是这样,只不过其实它并没有利用存储在COUNTSADDR这个地址的数据值,而是利用DMA_CITER_ELINKNO(CHn)的CITER值在每次数据传输传输完成之后,值会自动减一,从而达到累加计数的目的)。
如果DMA_DOFF(CHn)等于BYTEn(每次DMA传输字节数),这样以来,如果有多次数据的传输,那数据在内存里面的地址就会变成连续的储存,而不会造成对上次数据的覆盖。
DMA_SLAST(CHn)和DMA_DLAST_SGA(CHn)分别为当DMA传输结束后(主循环结束后),对于源地址和目的地址的最终偏移调整值。如果其值都为0,则下次需要DMA传输数据的时候,则此次数据组将会覆盖上次的数据组。(对于AD采样的话,应该可以理解为,如果我先对1号传感器采集100个数据,数据依次经过DMA存储在内存中,形成这次的数据组。当我们读走这个数据组之后,我们又需要对2号传感器采集100个数据,这100个数据就会覆盖上次的数据,从而形成此次的数据组。这样以来我们应该可以定义一个 ADC_result[100] 用来存储每次传感器的100数据)
所以对于目的地址,我的理解就是,目的地址就是每次DMA收到数据后,这个数据在内存中的存储位置。


      而对于源地址,简单理解可以通过内存中数据的复制这类问题来理解。比如通过设定一些配置参数后,DMA按照设定好的顺序从0x1000(源地址)取出数据,在将此数据复制到0X2000(目的地址)中,这样就实现了内存中数据的复制,并且不需要CPU的干预也就是所DMA就是将源地址的数据经过设定好的规律直接搬移到目的地址(但是此时数据总线是被DMA在利用,所以数据进行复制的时候,CPU并不能对内存进行访问,所以才有什么数据总线的分时复用吧,纯属于个人理解)。
下面我们把它简单应用在ADC采样的问题上,因为一个AD采样,其采样的结果保存在数据结果寄存器(ADCx_Rn)中,并且此结果寄存器在内存中肯定是映射一个地址。因此,我们就可以把DMA的源地址设定为这个地址,这样一来,就可以把AD的采样数据就可以通过DMA直接保存在内存中。并且如果每次读取源地址的数据之后,源地址的偏移值为0,换句话说就是源地址一直保持不变,依旧指向AD采样的结果值,这样下次AD的采样值就也可以不断的保存在相应的目的地址中了。而对应的,我们只要把目的地址偏移量设定为1,也就说每次储存数据之后,目的地址会加一,这样一来,AD的采样值在内存中就会以地址连续的方式存储了。
K60是32位单片机,所以其内存中的一个地址就可以保存4个字节(32位)的数据,由于AD的数据精度可以选择为8bit、10bit、12bit、16bit,但是对于一个结果整体而言,其任然是以32位的形式存储,所以源数据宽度也就应该设定为4个字节,目的数据宽度也应该与之匹配,也设定为4个字节,否则数据的传输就会出现错误了。假如源数据宽度为1个字节,源地址为0X1000,那么源地址里面的数据就会分为4个字节,分别进过四次读取之后,再交给目的地址。这样一来,一个完整的数据就会被拆为4个数据,这样数据传输就出错了。


       对于触发源的理解:Trigger(触发源)和 Peripheral Request 一起构成了DMA Request (数据采集的控制信号)

DMA有三种工作模式:无效模式、正常模式、和周期触发模式。
周期触发模式:触发源是PIT(周期定时器中断),这种模式仅仅适用与DMA Channel 0 -- DMA Channel 3。
正常工作模式:触发源是由DMAMUX_CHCFG_REG的SOURCE[0:5]决定的,它们之间的映射关系野火的ADC驱动中DMA_sources枚举已经定义好了。触发源包含很多,有UART、SPI、ADC、FTM、PDB、CPM、I2C、IO口触发,以及 Always On(一直使能,DMA Request完全由Peripheral Request决定,但是这个Peripheral Request,我不知道它是怎么来的,从这里我就开始理解不清楚了) 。其中看到例程中用的最多是IO口触发了,这个比较好理解。但是触发源还可以ADCn等触发,这个我也不理解了。




这就是我理解的东西了,我说的肯定有地方理解不到位,要是有错误的话,希望你也提醒我下,免得我一直错下去,哈哈~~     欢迎继续讨论


补充内容 (2013-2-17 09:01):
DMA选择了触发源之后,其触发源还是需要进行相应的配置。比如DMA_Source选择了IO口触发之后,对应IO口就应该做开启时钟,输出方向设定为输入,以及配置为触发模式,输入上拉或者下拉之类的.......

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
8#
 楼主| 发表于 2013-2-17 10:20:42 | 显示全部楼层
yangkuanqaz8598 发表于 2013-2-17 00:25
看了你给的资料后,我貌似懂了点东西,说出看下理解的对不对~

       对于主循环的理解:你需要传输多 ...

有没有大神能给指点的啊,在触发源这边还是不理解啊,很徘徊这个DMA_Source到底是触发源还是源地址啊.....
回复 支持 反对

使用道具 举报

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
9#
 楼主| 发表于 2013-2-17 12:24:35 | 显示全部楼层
suebillt 发表于 2013-2-17 11:47
触发源是在这个寄存器设置的DMAMUX_CHCFG_SOURCE(),不是源地址,表格中PA是49,PB50,以此类推

嗯,那这样一来,他这个Source[0:5]里面可以选择的ADC和UART,这两个触发怎么理解呢。ADC触发会是指一旦采样结束,就触发DMA吗,它是考ADC的转换结束标志位来触发的吗,我就是不懂在这个里。
回复 支持 反对

使用道具 举报

10

主题

105

帖子

0

精华

高级会员

Rank: 4

积分
619
威望
289
贡献
138
兑换币
184
注册时间
2012-12-13
在线时间
96 小时
10#
 楼主| 发表于 2013-2-17 16:53:17 | 显示全部楼层
本帖最后由 yangkuanqaz8598 于 2013-2-17 16:54 编辑
suebillt 发表于 2013-2-17 12:56
IO的触发是外部中断中设置的DMA触发,我想ADC也是由中断触发DMA

对于IO口而言,它的触发如果是依靠外部中断的话,那在外部中断函数里面不是应该有相应的软件触发DMA代码吗?但是野火的驱动里面并没有编写啊。我觉得IO口触发的话,应该仅仅就是设定IO口为触发模式,DMA为IO口触发,这两种外设模式就好了吧。


或者你的意思是指,DMA的IO触发,是因为DMA利用了IO口的中断信号,从而触发DMA数据传输的。要是这样理解的话,DMA的ADC触发,就也可以理解为DMA利用了ADC的转换结束的中断信号来触发DMA数据传输的喽,是这个意思吗


回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

关于我们|联系我们|小黑屋|亿加合和智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-5-5 15:24 , Processed in 0.082224 second(s), 25 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表