嵌入式Lee

文章数:196 被阅读:578672

账号入驻

基于DWC2的USB驱动开发-抽丝剥茧再论SETUP完成标志DOEPINTn.SetUp

最新更新时间:2023-07-26
    阅读数:

前言

https://www.elecfans.com/outside?redirect=https://mp.weixin.qq.com/s/gm5OAutfnYv6H_5Ce8GEqA 一文中我们介绍了控制传输,中断相关寄存器 , 尤其是 DOEPINTn.XferCompl DOEPINTn.SetUp DOEPINTn.StsPhseRcvd 几个状态的组合非常重要,因为由他们可以确定当前控制传输处于什么阶段。前文我们对此进行了介绍,但是个人觉得讲的还不够透彻,原理还没有讲清楚,知其然知其所以然是我们一开始就强调的,所以针对这个几个标志位我们再次更详细的介绍,先来介绍最关键的 DOEPINTn.SetUp

DOEPINTn.SetUp

Setup DOEPINTn 寄存器中的一个标志,用于表示 Setup 阶段是否完成。

我们这里可能要问 DIEPINTn 为什么没有 SetUp 标志,因为 Setup 总是 HOST->DEV 的,所以总是 OUT 传输,所以总是对应 OUT 端点的, IN 端点的寄存器不可能有。这里强调一下我们一定要多问为什么,先思考猜测,然后再从手册规格书中查找答案,只有这样才能加深理解, USB 开发中这是很重要的,当然任何技术性的工作这一点都重要。

我们从寄存器的描述中也可以看到,该位表示 SetUP 阶段完成,并且只有控制 OUT 端点有。

还有个信息是本次控制传输没有连续的 SETUP ,意味着软件可以开始解析 SETUP 8 字节的内容以决定下一步要干嘛了。如果有连续的 SETUP 则是最后一个 SETUP 完成才能进行。


那么究竟 SETUP 完成对应的一个什么状态呢 ? 硬件是怎么知道 SETUP 阶段完成的呢?主机和设备判断 SETUP 完成有什么区别吗 ? 我们会抛出一连串问题,如果能抛出这些问题说明你很适合做底层和驱动开发 !

后面我们会抽丝剥茧,从原理到实践,从猜测到手册中求证,一层层剖析。

这里我们要回顾下控制传输,

我们从规格书中的拓扑图可以看到,控制传输的 SETUP 阶段过程如下

或者换个表达方式如下

或者从 USB 分析仪抓包数据来看,更形象。

SETUP 阶段对应 3 个包 :SETUP 令牌包; DATA0 的数据包,始终是 HOST->DEV ;设备的响应 ACK

这里顺便提一下, SETUP 的数据始终使用 DATA0; 而设备要么正常接收并接受 ACK ,要么接收错误或者没接收到不响应,只有这两种情况,不能接收了不接受而 NAK 或者 STALL 等。

这里还顺便提一下接收和接受的概念区别。接收通常指的物理层数据正确接收到了,而接受则指的软件能够处理,或者说愿意处理。 接收了也可能不接受。

这里协议层面我们可以看到 SETUP 阶段完成的标志是,设备 ACK 响应了。

如下所示

仔细思考下,这里只是协议上的定义,也就是对应的总线上的数据,至于 SETUP 完不完成是要由参与者 HOST DEV 去确定的,换句话说总线上的状态并不意味参与者就是这个状态了,因为参与者还要正确接收到总线上的数据才算。

对于主机接收到了设备发送的 ACK 那么主机认为 SETUP 阶段完成,如果设备发了 ACK 但是主机没收到呢?那么主机认为 SETUP 没完成,会认为本次失败,从头发 SETUP 包重来。

同样的对于设备来说将 ACK 发送到总线上去后,设备并不知道 HOST 接收没接收到,设备并不知道主机的状态。所以主机和设备对 SETUP 完成的状态确认存在不同步。

那怎么办呢 ? 设备并不知道主机认为 SETUP 完成了没有,因为设备并不知道主机收没收到 ACK 。就好比子非鱼安知鱼之乐,有点绕了。

其实也没什么办法,设备确实现在不知道主机是不是认为 SETUP 完成了,但是设备可以根据主机下一步的行动来确定。因为主机如果接收到了 ACK ,认为 SETUP 完成了那么主机下一步就会发 IN 或者 OUT 令牌进入数据阶段 ( 或者状态阶段 ) ,否则则会重发 SETUP 重新进入 SETUP 阶段。

设备可以据此来进行判断,如果收到了主机的 IN 或者 OUT 令牌,则确认主机认为 SETUP 已经完成了,于是设备也知道 SETUP 完成了,这里设备和主机判断 SETUP 完成的时间点是不一样的,这就是协议定义和实际判定存在的区别。所以对于协议设计一定要考虑这种区别,协议设计了要考虑如何实现,也就一直强调的理论要结合实践,对于驱动编写更需要考虑从这些细节。

以上恭喜你从头开始推导出了设备判断 SETUP 完成的原理,那么回到上面的标志位 DOEPINTn.SetUp 即表示 SETUP 阶段完成, DWC2 控制也是这么判断的吗?所谓英雄所见略同, DWC2 控制器还真是这么判断的。

上面寄存器的描述中只提了该标志的含义,并没提其具体置位的原理和时机,实际编程指导手册中是有说明的。

如下位置,手册就进行了说明当, SETUP 令牌之后,接收到了 IN OUT 令牌则置位 DOEPINTn.SetU ,和我们推导的完全一致。

为什么是 IN OUT 呢,因为控制传输可能是控制写,控制读,还可能无数据阶段的控制传输,所以后面要不就是 IN 数据或者 OUT 数据或者 IN 状态,如下所示

控制写

控制读

无数据阶段的控制传输

驱动编写注意事项

从上面可以看到设备是延迟才能确认 SETUP 完成的,也就是在 SETUP 后设备收到了主机发的 IN OUT 之后才确认,中断也是在此时产生。

对于控制写,上面设备确认 SETUP 完成产生中断,中断服务函数开始去解析 8 字节的 SETUP 内容,来确定数据阶段要干嘛,后面数据阶段是 IN 还是 OUT 或者还是没有数据阶段直接状态阶段,其实是数据阶段 ( 状态阶段 ) 已经启动,设备延迟了。

此时中断服务函数还未执行,软件还没根据解析准备 IN 或者 OUT 描述符,所以此时对于这个 IN 或者 OUT ,硬件只能自动 NAK ,如下所描述 :

所以这种情况下,中断服务函数中进行了解析,并知道要准备 OUT 描述进行接收时,设置 EPEna=1 时还要同时设置 CNAK=1 ,清除硬件的自动 NAK 状态,让硬件根据 OUT 描述符去接收数据。

对于控制读后面是 IN 数据阶段,或者无数据阶段的控制传输后面是 IN 状态,也是类似的。

总结

以上对 DOEPINTn.SetUp 进行了详细的解析,因为它太重要了, SETUP 阶段是控制传输的核心,因为只有 SETUP 完成才能去解析 8 字节的内容,才能决定后续干嘛,对于驱动编写接收到 8 字节的 SETUP 数据是第一个关键步。以上也可以看出一定要从原理上去理解,这也是驱动编写的重要原则,必须知其然知其所以然,精确的知道各个时间点的各个时间,以及其条件等,注意精确两个字。



最新有关嵌入式Lee的文章

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: TI培训

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved