bsp和驱动的区别_Zynq SDK 驱动探求(四)数据从软件来到逻辑

09b19d88894bb1897eb7f3dc0891a564.png

对于一个希望能够达到软件定义,硬件加速的协议栈来说,打通软硬之间的任督二脉是最为重要的一环。本文通过搭建一个 AXI DMA 子系统,将 PS 中网卡驱动软件接收到的数据包发送给逻辑部分,建立起 PS 到 PL 的数据流。

搭建逻辑 DMA 子系统

e9d2fe892b74dad2db9cfd84d5ef8d5b.png

在 Vivado 的 Block Design 功能中通过拖动 IP 的方式建立一个 DMA传输子系统。DMA 子系统包括一个 AXI-DMA 和一个 AXI-FIFO。本文中的实验因为是把数据从 PS 端传输到 PL 端,所以只会用到接收 FIFO(但为了回环测试,所以又将接收 FIFO 的输出端连接到了 DMA 发送端(S2MM 对应于逻辑部分的发送端))。DMA IP 有多条总线通道,分别用于和 FIFO 以及 PS 连接,下图表示了 DMA 系统各部分的连接情况。

c384117c037cac5112d1f5644fc53cc9.png

在 IP 连接图上会看到很多的总线矩阵( interconnect ),DMA 和 PS 之间通过两个总线矩阵连接,不考虑这些总线矩阵,本质上的总线连接就如上图,蓝色的是逻辑部分,红色的是 PS 部分。红蓝之间共有 3 条总线与一条信号线连接。系统中真正使用的为接收 FIFO,发送 FIFO 暂未使用,用虚线表示。

信号线是中断控制线,DMA 产生的中断会由 PS 进行中断响应。AXI-Lite 是一条配置总线,PS 端对 DMA 的配置控制都会通过这条总线进行。剩下的是一对 AXI 总线,这对总线分别对应着发送接收的数据流通道。图中的发送是指 DMA 到 PS 的数据流向,在本实验中没有用到,使用的是接收是 PS 到 DMA 的数据流向。

DMA 的工作可以理解为将数据从 AXI 总线的形式转为 AXIS 的形式。AXI 是指 Memory Mapped 的数据,即数据有对应的内存地址,数据存储于存储介质(如 DDR,BRAM)或者寄存器(比如网络 MAC 的数据缓冲寄存器)中。在本实验中 MM 指的是从 PS 的 MAC 数据缓冲寄存器中搬用的网络数据包。

AXIS 总线对应的一般是对数据进行处理的逻辑部分,AXIS 总线在本实验中指的是接收 FIFO,此时的数据没有地址的概念,以数据流的形式出现,简单来说当 valid 信号线为 1 时, data 上的数据有效。FIFO 作为从机 (slave)接收数据,所以整个从 PS 到 PL 的传输过程称为 MM2S (Memory Mapped to Slave),PL 到 PS 的数据流则称为 S2MM 。

本实验中的 DMA 配置为简单模式,数据传输的 AXI 总线连接到 PS 的 HP_AXI 接口,控制用 AXI-Lite 连接到 PS 的 GP_AXI 接口。我们将在后续的文章中讨论 DMA 以及 PS 上的多种 AXI 接口。

AXI-DMA 外设驱动

AXI-DMA 属于我们在前文中说的,由 Xilinx 官方提供的逻辑 IP 外设。区别于 PS 系统中包括的 ps7_dma,DMA 在 Vivado 中是一个标准的 IP 核,所以官方有提供标准的外设驱动以及使用示例。

0ca0d36b5d14d720b10e93920d5acb95.png

这里我们同样化用 example 中的代码,封装成我们自己的功能函数。

我们使用的是简单模式,使用中断的例程 axi_dma_loop_test_bsp_xaxidma_example_simple_intr,首先看下例程的结构。例程中主要的函数分别是

main(void)

主函数中完成了对 DMA 的初始化,准备一份发送数据,放在数组缓冲区中,调用 DMA 的 XAxiDma_SimpleTransfer 函数发送,同时接收一份数据放到接收缓冲区中。因为硬件结构上为回环连接,发送的数据会被 DMA 接收,主函数会对发送接收的数据进行比较。

void TxIntrHandler(void *Callback)/void RxIntrHandler(void *Callback)

发送接收中断函数在 DMA 发送/接收后被调用,对当前置起的中断进行处理,如果没有错误发生,那么置起发送完成标志。这是一个全局变量,主程序在发送/接收中断完成后,对发送接收的数据进行比较。在正常的使用中,发送接收中断完成标志表示程序可以进行下一次发送/接收操作。

封装应用驱动函数

为了方便使用,我们以 example 的代码为基础,封装成自己的应用驱动

初始化 DMA 函数,在主函数初始化外设时调用。

int 

DMA 发送函数,封装了 XAxiDma_SimpleTransfer 函数。

int 

在 LwIP 中使用 DMA 驱动

在本文实验中,将 LwIP 和 DMA 子系统结合起来,将网卡驱动接收到的数据传输给逻辑部分。在 xilinx sdk 的 LwIP 例程的基础上,添加对于 AXI DMA 驱动的支持。

首先在主函数 main 中初始化平台时,初始化 DMA 。

1205e3fd046f813a3260e58387339a92.png

接下来修改网卡接收中断函数 emacps_recv_handler ,加入 DMA 发送函数 axidma_send_data 。在将数据包 pbuf 交付上层软件之前,先启动 DMA 传输,传输长度为数据包的长度。我们这里只传输数据包的 payload 部分,所以传入指向 payload 的指针。

7e35adb06f7eab13a950ab85ceb9cfd6.png

数据来了

DMA 开始传输后,数据就开始从 axis 接口进入接收 FIFO。可以使用 vivado 的 debug 功能设置触发电,观察到数据开始到来。我们可以把逻辑收到的数据和软件中 payload 指针指向的地址上的数据相比较,可以发现数据显然是一致的。但注意到此时传输给逻辑部分的数据也是按照主机字节序组织的。

50d10dbec29b051760ed608c931ab9b4.png

d1390e43e8a50e43f6957cdf1e73525b.png

对数据做些什么

目前初步的计划是在逻辑中进行计算数据的校验和,解析协议等操作,在 PS 需要这些操作的结果时,不需要在 PS 端再进行计算,只需要从寄存器中读取由逻辑部分计算完成的信息即可,以此实现减少 PS 端软件运算需求的目的。

结语

本文中简单介绍了 DMA 子系统的硬件搭建,DMA example 的介绍以及在 LwIP 网卡接收中断函数中添加 DMA 传输函数。介绍地比较简单,有兴趣的读者可以来进一步讨论。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值