修复nanopi2的SPI无法使用50MHZ传输的问题(S5P4418)

3 篇文章 0 订阅
3 篇文章 0 订阅

一.问题背景

在使用nanopi2进行连接一个SPI接口的2.8寸TFT彩屏,在使用过程中发现了两个问题,第一个问题是友善提供的linux3.4内核SPI默认没使用DMA传输。第二个问题是 DMA传输会出现超时 ,超时还会导致linux内核发生崩溃。
在这里插入图片描述
在这里插入图片描述

通过debugfs可以看到SPI的DMA传输发生了堵塞:
在这里插入图片描述

 本人使用的TFT屏是2.8寸的分别率是 240x320 ,色彩深度是RGB565,每 个像素点2个字节,一帧图像是153600字节,大约153KB,如果不使用DMA传输,发现即使使用50MHZ,4418传输一帧图像仍然需要160毫秒左右,如果使用DMA一帧大概25毫秒,因此需要做到40HZ刷新率,必须要使用DMA!!!

附上nanopi2的内核源码的github:

https://github.com/friendlyarm/linux-3.4.y.git

在这里插入图片描述
编译内核的方法:

make nanopi2_linux_defconfig
make uImage
详情请参考维基: https://wiki.friendlyelec.com/wiki/index.php/NanoPi_M2/zh

点击此处进入维基: https://wiki.friendlyelec.com/wiki/index.php/NanoPi_M2/zh

 经过反复阅读代码,发现代码并无逻辑问题,编码测试发现核心的BUG出现在SPI上,在高速DMA传输过程中,会导致SPI的接收FIFO出现数据丢失,比如通过SPI传输5000字节,SPI的MOSI发送完毕这5000字节,MISO收到的数据理论也是5000字节,但是DMA把MISO数据搬到内存过程有概率不及时,从而导致RX FIFO堆满出现了溢出,最后导致DMA无法从RX FIFO搬出指定长度的数据,接收DMA中断就无法产生,进而SPI主机驱动的回调函数也无法被调用,从底层到顶层一步步阻塞,最后挤压的DMA请求导致linux内核崩溃。
原因大概率是ARM处理器的DMA和SPI控制器相性问题所致,属于硬件问题吧,因此仅能通过软件弥补,保护内核不崩溃,对于显示屏确保MOSI数据流正常,就算得上可靠了!!

二.启用SPI的DMA传输

 默认从git中克隆下来的内核,友善官方是禁用了SPI主机驱动中DMA功能,需要自己来打开。
打开DMA方式如下:

2.1 修改cfg_main.h 文件

arch/arm/plat-s5p4418/nanopi2/include/cfg_main.h

在这里插入图片描述
把cfg_main.h 文件中传输方式改成2,默认内核支持轮询,中断,DMA,传输,其中DMA传输最快对CPU负荷最低,时钟源频率改成100MHZ,最低2分频,即SPI传输最高可以得到50MHZ。

具体可以参考SPI的章节,时钟源最大100MHZ,主机模式下SPI最大50MHZ。
在这里插入图片描述

2.2 make menuconfig 配置SPI

Device Drivers —>
 [*] SPI support —>
在这里插入图片描述
修改上面的菜单,以SPI2总线为例子勾选中port 2,和使用DMA模式传输。

2.3 修改SPI主机驱动代码

主机驱动

drivers/spi/spi-pl022.c

在这里插入图片描述
把上图的触发条件改成下图所示:

在这里插入图片描述
注意:由于S5P4418的SPI外设固定是以4字节为突发传输长度,这个是不能修改的,因此SPI必须以4字节为一次DMA突发传输,比如用户希望用DMA传输3个字节将会导致DMA控制器和SPI不协调出错。

由于DMA支持分散形式的链表传输,因此DMA单次传输长度理论上是不限的,因为我们一帧图像大概也是接近200KB,所以我们需要删除少于4096的条件。

2.4 增加设备驱动的代码

上面步骤过后主机驱动已经修改完成了,对于设备驱动(如显示屏)就不展示了,比如我用的一个st7789的显示屏。

三.修改DMA控制器驱动程序

 经过反复的裸机程序测试,定位到主要是DMA驱动的中断出现异常,因此修改了S5P4418内核中的DMA驱动程序。

四.效果

使用DMA传输图像SPI总线上是很紧凑的,字节和字节的间隙大概40ns如下图:
在这里插入图片描述

使用中断或轮询的方式的SPI总线是很疏松,字节和字节的间隙大概25us,甚至50us不等,而且消耗CPU:
在这里插入图片描述
因为在50MHZ主频下传输4个字节仅大概需要760ns,如下图所示,又因SPI中断模式是每发送4个字节中断一次,每760ns让CPU响应并处理一次中断,这样是不可能的,所以响应不及时往往导致数据不能及时填入发送FIFO,导致发送数据疏松。
在这里插入图片描述
在50MHZ的SPI下中断模式发送最终必然导致发送效果不尽人意,因此DMA模式下可以大大降低CPU中断的触发,提高传输效率。

 修改前,使用DMA传输,每5帧左右就会导致内核崩溃或者卡死,修改后,本人经过2天晚上测试,一晚上跑20万帧,一点问题都没有,S5P4418 SOC还是挺强了,但是对于低速的SPI外设需要用到全双工,尽量控制主频在20MHZ下使用DMA收发都能正常,超过40M通常无法保证接收正常,但可以保证发送是正常的!!!

五.补丁包和补丁包的使用

 由于修改的过程比较复杂,很多老哥可能看不懂,或者跟不上,下面给出最简单的修复步骤,附件中会提供补丁包

克隆内核源码:

git clone https://github.com/friendlyarm/linux-3.4.y.git
cp 0001-Fixed-__spi_sync-timeout-when-using-50MHZ-and-DMA.patch linux-3.4.y

将补丁包0001-Fixed-__spi_sync-timeout-when-using-50MHZ-and-DMA.patch下载到内核源码目录下:

补丁包下载链接: https://download.csdn.net/download/weixin_43536180/87364903

在这里插入图片描述
使用补丁包:

git am < 0001-Fixed-__spi_sync-timeout-when-using-50MHZ-and-DMA.patch

查看是否生成新的提交:

git log

在这里插入图片描述
重新编译内核

make nanopi2_linux_defconfig
make uImage

编译后会生成新的uImage 镜像文件!!

更新内核到nanopim2开发板:

mount mount /dev/mmcblk0p1 /mnt/
拷贝新镜像到开发,有些时候更新的是uImage.hdmi,因为默认不接LCD屏幕是启动这个HDMI显示的内核!!
cp uImage /mnt/uImage

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值