您尚未登录。

楼主 #1 2020-04-25 00:28:20

Quotation
会员
注册时间: 2018-10-04
已发帖子: 289
积分: 271.5

调通F1C100s的SPI DMA

1. 初步调通SPI DMA,成果喜人。
SPI Tx和Rx都用上DMA,接示波器看CLK信号。当通过寄存器设置SPI速率设为100MHz的时候,CLK信号实际能跑到96MHz。SPI速率设为50MHz的时候,实际CLK为49.xMHz。
(用XBoot不管怎么设速率,实际的只能到25MHz。一方面是没用DMA,一方面是XBoot的代码不够优化。)

2. 实验用DMA加持的SPI驱动ST7789串口屏。240x240分辨率、RGB565,SPI跑满50MHz,屏幕帧率可以到54。非常满意了。
实验时是用杜邦线接的屏,也许走线好一点的话还能支持更高速率。我现在是只能跑到50MHz了,多1M显示就开始乱了。

3. 实验DMA做内存拷贝,结果如下。DMA拷贝内存,速度并没比memcpy快多少。
有几个参数能影响DMA拷贝速度:1) DMA的种类,用NDMA还是DDMA;2) data width 3) burst length。
而memcpy速度受CPU主频影响(一点点)。

拷贝128KB数据比较:
memcpy 2.4ms(640MHz主频)
DDMA 1.9ms(data width = 32-bit,burst length = 4)
NDMA 2.6ms(data width = 32-bit,burst length = 4)
DDMA拷贝内存最快能到memcpy的1.25倍。

另外,发现DDMA拷贝较大的数据会出错,比如拷贝1MB数据,第一次成功,第二次就从1020KB开始数据不正确了。可能是缓存的原因,待研究。

离线

楼主 #7 2020-04-26 17:09:13

Quotation
会员
注册时间: 2018-10-04
已发帖子: 289
积分: 271.5

Re: 调通F1C100s的SPI DMA

Quotation 说:

另外,发现DDMA拷贝较大的数据会出错,比如拷贝1MB数据,第一次成功,第二次就从1020KB开始数据不正确了。可能是缓存的原因,待研究。

这个问题是简单的cache问题,从另一个帖子里@armstrong 的回复明白了。正确invalidate和clean缓存后就没有传输错误了。DDMA一次可以传16M,NDMA一次可以256KB(文档上说是128KB)。

离线

楼主 #8 2020-04-26 17:16:52

Quotation
会员
注册时间: 2018-10-04
已发帖子: 289
积分: 271.5

Re: 调通F1C100s的SPI DMA

泡在妞里的Feel 说:

666,DMA部分的代码可否分享一下。

现在还有点玄学问题没有解决,以后解决了再分享……
代码里有时候多一行少一行无关代码,显示屏就花屏了。可能是时序的问题,也可能是字节对齐的问题,还没弄明白。

另外,我是很想分享代码,但是代码混在项目里,要分享出来还得抠,抠出来又不能直接跑。
要是全志有一套像STM32那样的标准库,分享资料会更方便。

离线

楼主 #9 2020-04-26 17:24:38

Quotation
会员
注册时间: 2018-10-04
已发帖子: 289
积分: 271.5

Re: 调通F1C100s的SPI DMA

泡在妞里的Feel 说:

求赐教,这两个寄存器是什么功能?
https://whycan.cn/files/members/1964/test.png

Wait State意思不知道。

Burst Length大约是每次传输数据,在总线上连续传几个“Data Width”那么大的数据。
对于从内存到内存,Burst Length设为4直接就可以用。
对于从内存到外设或外设到内存的DMA,如果Burst Length设为4,外设的FIFO一般有trigger level也要对应改。比如trigger level默认为1,表示FIFO里只要有1个数据就发送DRQ,让DMA来拷走。当Burst Length为4,trigger level也要>=4。
反过来,如果是从内存到外设拷数据的,FIFO的trigger level需要 <= (FIFO总长度 - 4)。

离线

楼主 #10 2020-04-26 17:29:19

Quotation
会员
注册时间: 2018-10-04
已发帖子: 289
积分: 271.5

Re: 调通F1C100s的SPI DMA

ntmusic 说:

水一贴,DMA结合操作系统才能比较好发挥优势,在等待DMA传输结束时CPU可以很方便的切换出去做别的事情,而裸机则一般要通过设置状态结合中断来使用,程序结构也会变得奇奇怪怪,若使用查询等待的话可能还不如直接使用CPU操作来的快,因为CPU一般拥有总线最高优先权

确实,有OS抽象出线程或task的概念会方便使用。不过如果代码写得巧,裸奔也清爽的:D。
比如把中断封装成回调,用C++的lambda写回调实在很方便。

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn