Zynq-Linux移植学习笔记(二十六)——PCIE端节点通过DMA访问内存失败问题解决

1、背景介绍

局部硬件简图如下:

局部硬件简图

如上图所示,ZYNQ中使用了AXI_PCIE IP核,作为PCIE RC节点,交换芯片作为PCIE EP节点,两者之间通过PCIE总线相连。ZYNQ通过PCIE配置交换芯片,实现路由配置和转发等功能。

2、问题描述
Linux启动后能枚举到交换芯片,也可以通过PCIE命令读写交换芯片寄存器,但交换芯片在每次上电时需要启动DMA引擎从ZYNQ端的DDR获取描述符,这时发现ARM能给出ACK信号,但却没有数据返回,导致DMA引擎取数失败。

3、解决思路
首先可以确认这种情况下是PCIE的EP访问RC,由于ZYNQ已经实现了RC对EP的正确读写,不可能去向正常而回向异常,可以确认链路应该不存在问题。

通过盛科SDK给出的信息发现DMA引擎去取描述符的地址如下:

如上图所示,交换芯片是从DDR物理地址0x3f100000的地方取描述符,由于我们的DDR是1GB(0x0-0x3fffffff),这个地址是在含在DDR物理区间内的。其实通过Linux启动打印信息可以发现操作系统启动时已经专门给dma预留了一段从0x3f000000起始的16MB连续空间,盛科交换芯片申请的一大块连续DMA内存正是从这段空间分出来的,这也是DMA物理地址是0x3f100000的原因。

现在可以确认交换芯片DMA访问的地址是正确的。此时既然取不到数据,一种情况是通过PCIE无法访问该地址,另一种情况是通过PCIE访问该地址是被映射到了内存区域之外。

经过排查,发现在AXI_PCIE IP核的配置中有下面这一项。

这里的PCIE:BARS就是通过PCIE能访问的内存大小,很显然,这里的配置需要和DDR实际大小一样才行,之前这里配置的是512MB,而0x3f100000明显是512MB空间之外,所以导致DMA引擎访问这段地址出错,取不到数据。这里改成1GB后问题解决。

4、结论
PCIE IP核需要将PCIE:BARS空间大小配置和DDR大小一样,这样PCIEEP通过DMA引擎访问DDR空间时不会发生访问出错情况。

文章来源:Felven的博客
注:本文为授权转载文章,如需转载请联系作者授权