打印

【在线等!】ARM DMA与I2S外设握手bug 调过DMA请进(采纳,48分)

[复制链接]
4087|17
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
arm_debug_yj|  楼主 | 2013-6-30 11:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
【功能描述】
        用ARM 的DMA来搬外设(I2S)FIFO的数据到SDRAM去,实现录音功能

【配置描述】
1、I2S配置
使能I2S收命令时,I2S会输出时钟(示波器看正常),I2S那边就会有采样率为44.1KSa/s的数据源源不断填入I2S的接受FIFO中,I2S的DMA请求配置是当FIFO(大小为32字)满一半的时候,也就是当I2S接收FIFO中数据超过16个字的时候,触发DMA传输请求;
2、DMA这边配置为传输宽度为字(32bit,一般与外设的fifo的宽度相同),采用突发传输模式(8个字),每次传输大小为I2S的半个FIFO容量(16字),源地址是I2S接收FIFO的输出口,源地址不变;目的地址是SDRAM,地址递增;源地址为硬件握手接口,目的地址为软件握手接口

【bug  描述】
理论上说,配置好DMA并使能后,只有当外设的DMA传输请求过来时,DMA获得总线控制权后才会回外设一个ACK,然后启动DMA传输,DMA的传输率应该是44.1K/16(I2S每更新16个数据请求一次DMA传输),但是本实验里,DMA配置好后,使能之后,DMA就开始去I2S接收FIFO那里搬东西了,DMA的搬移频率远比I2S 接收FIFO数据更新频率(44.1KHz)快,就会导致I2S接收FIFO每采集到一个新数据(比如数据A),在下一个数据B来临之前也就是在接下去的1/44.1ms这段时间里,DMA一直读那个相同的数据A,导致SDRAM中一大片一大片的数据是重复的

【酬谢】哪位有类似经历或者有**思路的告知一下,本人只剩48分,全部奉上

相关帖子

沙发
huangxz| | 2013-6-30 12:28 | 只看该作者
没说是什么器件的啊

使用特权

评论回复
板凳
arm_debug_yj|  楼主 | 2013-6-30 13:04 | 只看该作者
huangxz 发表于 2013-6-30 12:28
没说是什么器件的啊

ARM9微控制器

使用特权

评论回复
地板
jlass| | 2013-7-1 10:27 | 只看该作者
明显是DMA的参数没配对,收发的速度应该配成和IIS的收发同步,也就是说配成iis每收到一个数据触发一次DMA的传输,而不是直接配置一个固定的速度。

使用特权

评论回复
5
airwill| | 2013-7-1 12:16 | 只看该作者
DMA 跑得太快了啦. 说明 DMA 的配置有问题

使用特权

评论回复
6
arm_debug_yj|  楼主 | 2013-7-2 14:20 | 只看该作者
jlass 发表于 2013-7-1 10:27
明显是DMA的参数没配对,收发的速度应该配成和IIS的收发同步,也就是说配成iis每收到一个数据触发一次DMA的 ...

DMA是根据外设的请求才会去搬移数据的,请求一次搬一次,而I2S采集的数据源是codec芯片过来的音频数据,该数据的采样率是44.1kHz,也就是说每过一个1/44.1 毫秒,I2S 的接收FIFO中多了一个数据,当I2S接收FIFO中数据达到16时,I2S会发送DMA请求给DMA(I2S仓库满一半了,叫DMA来搬东西啦),DMA收到I2S的请求后会申请总线控制权,获得总线控制权后会回I2S一个ACK,I2S收到ACK后会释放DMA请求,DMA开始传输,DMA 的传输速度很快,一下子就把I2S FIFO中的16个数据搬走了,完成后,按道理DMA会在那里等待下一次请求的到来,问题就出在这里,它没有等待,一直在搬

使用特权

评论回复
7
arm_debug_yj|  楼主 | 2013-7-2 14:23 | 只看该作者
airwill 发表于 2013-7-1 12:16
DMA 跑得太快了啦. 说明 DMA 的配置有问题

DMA的速度肯定比外设要快的,就是让I2S FIFO中的数据积累到一定阈值的时候,发请求给DMA一次性搬走,使得I2S fifo中的数据量处于正常水平,一超过阈值就叫DMA来搬,如此反复

使用特权

评论回复
8
jlass| | 2013-7-2 14:25 | 只看该作者
arm_debug_yj 发表于 2013-7-2 14:20
DMA是根据外设的请求才会去搬移数据的,请求一次搬一次,而I2S采集的数据源是codec芯片过来的音频数据, ...

DMA有循环搬移和只搬移一次的选择,你是不是选成循环搬移了

使用特权

评论回复
9
arm_debug_yj|  楼主 | 2013-7-2 14:34 | 只看该作者
jlass 发表于 2013-7-2 14:25
DMA有循环搬移和只搬移一次的选择,你是不是选成循环搬移了

您说的是BURST TRANSFER吗

使用特权

评论回复
10
jlass| | 2013-7-2 14:39 | 只看该作者
本帖最后由 jlass 于 2013-7-2 14:41 编辑
arm_debug_yj 发表于 2013-7-2 14:34
您说的是BURST TRANSFER吗

应该不是,印象中叫auto ***
当然,不同的芯片叫法可能不一样。但意思就是“传输完成后,自动重新开始”

使用特权

评论回复
11
arm_debug_yj|  楼主 | 2013-7-2 14:40 | 只看该作者
jlass 发表于 2013-7-2 14:39
应该不是,印象中叫auto ***

我用的这款芯片DMA寄存器中好像没有这个选项

使用特权

评论回复
12
jlass| | 2013-7-2 14:49 | 只看该作者
arm_debug_yj 发表于 2013-7-2 14:40
我用的这款芯片DMA寄存器中好像没有这个选项

这只是一个思考方向的建议。

毕竟你用的是什么芯片也没写,DMA的配置项有什么也没写,只从你的描述上看出DMA传输完成以后没有停止的问题。
从另一个角度也可以考虑可能DMA并没有完成一次传输(比如DMA的传输数据量配置的过多了)

使用特权

评论回复
13
arm_debug_yj|  楼主 | 2013-7-2 14:51 | 只看该作者
jlass 发表于 2013-7-2 14:39
应该不是,印象中叫auto ***
当然,不同的芯片叫法可能不一样。但意思就是“传输完成后,自动重新开始” ...

您说的应该是地址自动重载吧,这个没有使能

使用特权

评论回复
评论
jlass 2013-7-2 14:52 回复TA
是的 
14
arm_debug_yj|  楼主 | 2013-7-2 15:27 | 只看该作者
jlass 发表于 2013-7-2 14:49
这只是一个思考方向的建议。

毕竟你用的是什么芯片也没写,DMA的配置项有什么也没写,只从你的描述上看 ...

按照您这个建议把每次DMA传输的大小改的小一点,很遗憾现象还是一样的,

使用特权

评论回复
15
arm_debug_yj|  楼主 | 2013-7-2 15:34 | 只看该作者
jlass 发表于 2013-7-2 14:49
这只是一个思考方向的建议。

毕竟你用的是什么芯片也没写,DMA的配置项有什么也没写,只从你的描述上看 ...

DMA的详细配置如下;
1、源地址为I2S的RX FIFO(地址不变),目的地址为SDRAM(0x61100000),地址自增加
2、传输宽度为32bits,一般与外设的FIFO宽度相同
3、burst transfer 长度为8*32bits
4、DMA每次传输16*32bits(I2S的fifo大小为32*32bits,半满即16个字就触发DMA传输)
5、源地址为硬件握手接口,目的地址为软件握手接口

使用特权

评论回复
16
xinzha| | 2013-7-2 22:10 | 只看该作者
1、你可以查一下当数据低于水线之后,FIFO有没有把DMA请求线真的释放。
2、你可以用软件的方式触发DMA在两块内存间搬数据,如果没问题说明DMA控制器正常。
3、FIFO空了继续去读,很有可能产生underflow错误,不知道这种FIFO是否处理好了。
4、如果是I2S自动触发DMA搬运,软件如何知道哪里是数据,哪里不是,并且DMA控制器怎么知道写数据的边界在哪儿?

使用特权

评论回复
17
happydaysxw| | 2014-2-14 15:20 | 只看该作者
你好,我配置了DMA的触发深度为8,但是却无法触发,求指教

使用特权

评论回复
18
jiang60023453| | 2014-2-15 23:30 | 只看该作者
借贵贴求问:
s3c2440 使用IIS模式+uda1341,看网上资料裸机操作是这样:
#define IISFIFO (*(volatile unsigned int *)0x55000010)
IISFIFO=(buffer[2*i+count])+(buffer[2*i+1+count]<<8);

我在linux下这样操作:使用映射配置,IISCON IISMOD 时钟都通过映射配置
(volatile unsigned long *) IISFIFO;
IISFIFO=(volatile unsigned long *)ioremap(0x55000010,4);
*IISFIFO=(buffer[2*i+count])+(buffer[2*i+1+count]<<8);
和裸机效果应该是一样的??,可是linux下IISFIFO却没有数据,没有声音.可是网上看那样写的童鞋都可以,手上没有JTAG用不了裸机调试。。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

33

帖子

0

粉丝