0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于DWC_ether_qos的以太网驱动开发-描述符链表介绍

嵌入式USB开发 来源:嵌入式USB开发 作者:嵌入式USB开发 2023-08-30 09:39 次阅读

本文转自公众号欢迎关注

一.描述符概述

1.0 前言

对于DWC Ethernet QoS驱动的编写来说,初始化完成之后,核心操作就是DMA的描述符链表配置(linked list of descriptors)。DMA根据描述符链表自动在FIFO和用户指定的缓存之间搬运数据。对于熟悉新思的IP的用户来说,这种套路会有似曾相识的感觉,没错新思的大部分高速IP的数据流都是这么处理的,比如在DWC2 USB的IP中就是Scatter/Gather DMA,叫法不一样,实现和思想基本是一样的。这种方式可以解放CPU,使用DMA根据描述符链表搬运数据,对于高速数据流的流式处理有利,相对单个描述符的DMA,链表式描述符一次可以处理更多数据更高效,且能够实现环形不间断流式处理。

参考手册《21 Descriptors》

1.1描述符类型

Normal Descriptor: 描述要传输的数据包和其控制信息。包含两个缓冲区和两个地址指针,这种设计以实现较大的灵活性,支持不同的内存管理方案。

Context Descriptor: 描述要传输的数据包的控制信息。

注意:单个数据包可以使用的描述符数量没有限制,虽然这里没有限制,但是受限于Ring_Length寄存器,描述符链表实际最多只能配置为0x3FF即1024个描述符。

1.2描述符结构

描述链表整体看是一个环形结构即到了描述符的末尾可以绕回.

图片

有一些寄存器对该环形描述符进行定义

1.2.1描述符的颗粒(间隙)

收发都是一样的

图片

上述描述Descriptor n本身的大小是固定的即RDES0~RDES3,4个WORD(根据不同的总线宽度和大小端,有不同的layout,但是其大小总是4个WORD大小,见后面说明).

还支持描述符之间有间隙,间隙的单位根据总线宽度而定,即32,64,128位总线宽度分别对应 Word, Dword, Lword为单位,寄存器DMA_CH(#i)_Control的DSL位域即用于描述该间隙。

再次提醒注意,这里的单位是根据总线宽度而定,不是固定为WORD。

图片

图片

比如这里DSL=0,则表示描述符之间没有间隙,

设置为1,如果是32位总线则间隙为1 WORD。

图片

1.2.2描述符的个数

收发分别由如下寄存器指定

DMA_CH(#i)_TxDesc_Ring_Length

DMA_CH(#i)_RxDesc_Ring_Length

图片

图片

1.2.3描述符的首末地址

1)发由以下寄存器决定:

基地址

DMA_CHi_Tx_Control的ST=0,即TX停止时才能修改以下寄存器。

DMA_CH(#i)_TxDesc_List_HAddress 发送描述符链表基地址的高位,只有40,48位地址模式才使用。

DMA_CH(#i)_TxDesc_List_Address 发送描述符链表基地址的低位,必须根据总线宽度按照Word, Dword,Lword对齐,DMA会自动根据总线宽度忽略低位。

尾地址

DMA_CH(#i)_TxDesc_Tail_Pointer 发送描述符链表尾地址,必须根据总线宽度按照Word, Dword,Lword对齐。

这里为什么没有高位寄存器了呢,因为不需要了,高位和DMA_CH(#i)_TxDesc_List_HAddress一样。

2)收由以下寄存器决定 :

基地址

DMA_CH(#i)_RX_Control 的SR=0,即RX停止时才能修改以下寄存器。

DMA_CH(#i)_RxDesc_List_HAddress 接收描述符链表基地址的高位,只有40,48位地址模式才使用。

DMA_CH(#i)_RxDesc_List_Address

接收描述符链表基地址的低位,必须根据总线宽度按照Word, Dword,Lword对齐,DMA会自动根据总线宽度忽略低位。

尾地址

DMA_CH(#i)_RxDesc_Tail_Pointer接收描述符链表尾地址,必须根据总线宽度按照Word, Dword,Lword对齐。

这里为什么没有高位寄存器了呢,因为不需要了,高位和DMA_CH(#i)_RxDesc_List_HAddress一样。

1.2.4当前处理的Buffer地址

以下只读寄存器可以调试使用,确认当前处理的描述符对应的Buffer地址,reset时这些寄存器会清零。

发送Buffer

DMA_CH(#i)_Current_App_TxBuffer_H 地址高位

DMA_CH(#i)_Current_App_TxBuffer 地址低位

接收Buffer

DMA_CH(#i)_Current_App_RxBuffer_H

DMA_CH(#i)_Current_App_RxBuffer

需要有收发数据才会更新当前处理的Buffer地址。

1.2.5当前描述符指针

以下只读寄存器可以调试使用,确认当前处理的描述符,reset时这些寄存器会清零。

发送

DMA_CH(#i)_Current_App_TxDesc

接收

DMA_CH(#i)_Current_App_RxDesc

Current寄存器是什么时候更新的呢,测试可以知道是写Base寄存器时更新

图片

进一步测试可知是在DMA停止,即DMA_CH(#i)_RX_Control的SR为0时写DMA_CH(#i)_RxDesc_List_Address 时Current寄存器会自动设置为DMA_CH(#i)_RxDesc_List_Address的值。如果SR=1则不会。

TX也类似。在DMA工作之后,该寄存器更新为当前正在处理的描述符。

1.3描述符的内存布局

描述符的大小总是4x4字节的,但是其布局和总线宽度和大小端有关。

且必须根据总线宽度Word, DWord,或 LWord 对齐。

三种总线宽度,2种大小端模式一共有6种组合

32位的大端和小端

图片

64位小端

图片

64位大端

图片

128位小端

图片

128位大端

图片

1.4描述链表的工作过程

1.4.1环形结构

图片

前面介绍的描述符首末地址,当前描述符指针和描述符个数这几个寄存器决定了链表的行为。

DMA可以处理的描述符范围是:[Base,Tail)

注意[]表示包括本身,()表示不包括本身,即包括Base寄存器对应的描述符,不包括Tail寄存器对应的描述符。

当前描述符指针则从Base到Tail-1的位置遍历,当Current=Tai时DMA停止工作。

同时还受描述符个数寄存器限制,

如果描述个数设置为N,则Current到Base~N-1的位置之后会绕回到Base,即以N个为单位回环,这里假设Tail是在N个描述符之后的,如果在之前则回环之前就Current=Tail停止了。

1.4.2停止条件:

Current=Tail

或者Current的位置没有就绪的描述符,即不是Owned by DMA的描述符。

所以Tail至少要大于base才能传输。

1.4.3重启条件

重启条件即保证current处的描述符就绪,且current%N

写Tail寄存器时会触发一次硬件的重启条件检测,来检测上述条件。

所以停止了之后读写 都需要写Tail寄存器才能重启

1.4.4几种情况分析

Tail 指向 N-1位置之后,此时current不可能达到tail,因为到N-1时就绕回了,

所以停止条件只能是current处的描述符未就绪,即不是Owned by DMA。

此时current不断回环遍历,只要软件能保证current处的描述符一直就绪,DMA就一直传输处理,形成了不间断的持续流处理。

图片

Tail刚好指向N-1位置或者更向前

则当current=current后停止。

或者current处的描述符未就绪即停止。

此时没法形成持续的流,因为current到了tail之后就会停止。

图片

1.4.5驱动的设计

为了充分利用上述描述符的回环模式,能够连续不断的收发,需要保证DMA处理完之前就更新好后续描述符。使得DMA一直有描述符能处理,不至于current处描述符未就绪而导致停止,且tail设置为在N个描述符之后,这样current始终不会因为=tail而停止。

要保证连续不断的流,需要软件准备描述符的速度大于等于DMA处理描述符的速度。

即current处始终有描述符可以处理,所以软件准备好的描述符在current及其之后,需要软件维护一个变量index记录当前软件准备好的描述到了哪。

即current追赶index。

当index>current时,[current,index)之间是已经准备好的描述符待DMA处理的,[index,Tail)

[base,current)这两部分是DMA已经处理完,软件需要更新的描述符。

图片

当index<=current时,[index,current)是DMA已经处理完,软件需要更新的描述符。

[current,Tail),[Base,index)这两部分是DMA未处理的部分。

图片

所以驱动处理流程如下

初始化时先尽可能多的填充好描述符,对于接收可以初始化所有描述符为接收状态,对于发送当然刚开始可能并不需要发送很多数据,那么就需要发送多少就准备多少描述符。

然后接收中断中处理DMA已经接收完的描述符,应用处理完对应的数据后再将这些描述符设置为接收状态。

对于发送则查询哪些描述符DMA已经发送完就可将其更新为发送状态进行发送。

比如如下开始准备了n个描述符

图片

然后启动DMA传输,

此时有两种情况,一种是硬件处理DMA比如软件更新描述符块,还有一种是相反。

后者软件总是在current追不上index,即软件更新描述符速度大于硬件处理描述符速度

一段时间后可能就是如下所示

图片

而前者软件准备的慢则current会追上index此时DMA会停止,软件需要重新准备描述符并重新配置Tail来重启DMA。

具体的驱动代码后面再详讲。

1.5总结

以上介绍了描述符链表,尤其需要了解环形链表的工作模式何时启动,何时停止,软件和硬件如何配合使用环形链表。以及相关寄存器的值的含义和何时更新。了解以上机制后后面就可以开始编写驱动代码进行收发。下回再详讲。

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    4982

    文章

    18281

    浏览量

    288465
  • 以太网
    +关注

    关注

    40

    文章

    5076

    浏览量

    166238
  • 寄存器
    +关注

    关注

    30

    文章

    5028

    浏览量

    117731
  • 驱动
    +关注

    关注

    11

    文章

    1717

    浏览量

    84345
  • dma
    dma
    +关注

    关注

    3

    文章

    535

    浏览量

    99021
收藏 人收藏

    评论

    相关推荐

    基于DWC_ether_qos以太网驱动开发-MAC帧格式介绍

    本文转自公众号,欢迎关注 基于DWC_ether_qos以太网驱动开发-MAC帧格式介绍 (qq.com) 一.前言   在
    的头像 发表于 08-30 09:23 1281次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-MAC帧格式<b class='flag-5'>介绍</b>

    基于DWC_ether_qos以太网驱动开发-MDIO驱动编写与测试

    本文转自公众号欢迎关注 基于DWC_ether_qos以太网驱动开发-MDIO驱动编写与测试 一.前言
    的头像 发表于 08-30 09:37 2273次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-MDIO<b class='flag-5'>驱动</b>编写与测试

    基于DWC_ether_qos以太网驱动开发-数据流验证过程

    转自公众号欢迎关注 https://mp.weixin.qq.com/s/klrHhaLMM_0W3FGVwHXFkA 基于DWC_ether_qos以太网驱动开发-数据流验证过程
    的头像 发表于 08-31 08:41 1166次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-数据流验证过程

    基于DWC_ether_qos以太网驱动开发-收发驱动编写与调试

    本文转自公众号,欢迎关注 基于DWC_ether_qos以太网驱动开发-收发驱动编写与调试 (qq.com) https://mp.wei
    的头像 发表于 09-05 08:47 1364次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-收发<b class='flag-5'>驱动</b>编写与调试

    基于DWC_ether_qos以太网驱动开发-无OS环境移植LWIP

    本文转自公众号欢迎关注 基于DWC_ether_qos以太网驱动开发-无OS环境移植LWIP (qq.com) https://mp.weixin.qq.com
    的头像 发表于 09-06 08:40 804次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-无OS环境移植LWIP

    基于DWC_ether_qos以太网驱动开发-LWIP的堆管理介绍

    本文转自公众号欢迎关注 基于DWC_ether_qos以太网驱动开发-LWIP的堆管理介绍 (qq.com) https://mp.wei
    的头像 发表于 09-08 08:40 766次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-LWIP的堆管理<b class='flag-5'>介绍</b>

    基于DWC_ether_qos以太网驱动开发-RTOS环境移植LWIP与性能测试

    本文转自公众号,欢迎关注 基于DWC_ether_qos以太网驱动开发-RTOS环境移植LWIP与性能测试 (qq.com) https://mp.weixin.qq.com
    的头像 发表于 09-11 11:20 1095次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-RTOS环境移植LWIP与性能测试

    基于DWC_ether_qos以太网驱动开发-LWIP在PC上进行开发调试

    本文转自公众号欢迎关注 基于DWC_ether_qos以太网驱动开发-LWIP在PC上进行开发调试 (qq.com) https://mp
    的头像 发表于 09-11 08:40 1105次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-LWIP在PC上进行<b class='flag-5'>开发</b>调试

    UBL UBOOT 描述符

       在DM368的开发包目录下/psp/flash-utils/DM36x/GNU:执行make 可以省成UBL:ubl_DM36x_nand.bin ;我想问的是如何添加UBL 的描述符?烧写到
    发表于 06-21 08:48

    以太网数据帧的发送描述符队列是什么意思?

    这个描述符是什么呀,类似linux系统的文件描述符
    发表于 05-26 06:15

    以太网描述符ETH_DMATxDesc_OWN异常

    stm32 以太网发送一段时间后发送描述符状态一直为DMA拥有,造成以太网发送停止,发送过程中什么原因会造成描述符一直为DMA拥有;(发送接收同时进行,接收为中断接收)`&a
    发表于 07-07 14:08

    设计软件核心以太网服务质量数据手册免费下载

    本文描述Synopsys设计软件核心以太网服务质量DWC以太网QoS核心5.10A。DWC
    发表于 10-23 08:00 15次下载
    设计软件核心<b class='flag-5'>以太网</b>服务质量数据手册免费下载

    基于DWC_ether_qos以太网驱动开发-包过滤

    以太网上数据非常多,如果所有数据都接收交给软件去处理软件负载会非常重,所以一般只需要接收发给自己的数据即可
    的头像 发表于 09-02 09:19 826次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-包过滤

    基于DWC_ether_qos以太网驱动开发-软复位介绍与问题案例

    一般模块都会有软复位的功能,软复位在驱动编写中很重要。一般初始化时执行软复位使得模块进入确定的初始状态以提高可靠性,异常时也可以重新初始化来恢复,所以软复位在驱动中一般是必须要做的动作。
    的头像 发表于 09-02 09:17 888次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-软复位<b class='flag-5'>介绍</b>与问题案例

    基于DWC_ether_qos以太网驱动开发-描述符格式介绍

    前面我们介绍描述符链表的工作模式,重点是了解环形链表是如何环形的,以及相关的寄存器。驱动编写就需要更进一步,了解
    的头像 发表于 09-04 14:14 927次阅读
    基于<b class='flag-5'>DWC_ether_qos</b>的<b class='flag-5'>以太网</b><b class='flag-5'>驱动</b><b class='flag-5'>开发</b>-<b class='flag-5'>描述符</b>格式<b class='flag-5'>介绍</b>