开启辅助访问
 找回密码
 立即注册

STM32系列通用USB全速设备接口(USB)

rainsea 回答数0 浏览数373
相关专栏:
相关文章:
推荐几本学习STM32书籍:
<hr/>1、 USB简介

USB外设实现了USB2.0全速总线和APB1总线间的接口。
USB外设支持USB挂起/恢复操作,可以停止设备时钟实现低功耗。
2、USB全速设备接口(USB)

小容量产品是指闪存存储器容量在16K至32K字节之间的STM32F101xx、STM32F102xx和 STM32F103xx微控制器。
中容量产品是指闪存存储器容量在64K至128K字节之间的STM32F101xx、STM32F102xx和 STM32F103xx微控制器。
大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控 制器。
互联型产品是指STM32F105xx和STM32F107xx微控制器。
本章描述的模块适用于增强型STM32F103xx和USB型STM32F102xx系列。
3、USB主要特征


  • 符合USB2.0全速设备的技术规范
  • 可配置1到8个USB端点
  • CRC(循环冗余校验)生成/校验,反向不归零(NRZI)编码/解码和位填充
  • 支持同步传输
  • 支持批量/同步端点的双缓冲区机制
  • 支持USB挂起/恢复操作
  • 帧锁定时钟脉冲生成
注: USB和CAN共用一台专用的512字节的SRAM存储器用于数据的发送和接收,因此不能同时使用 USB和CAN(共享的SRAM被USB和CAN模块互斥地访问)。USB和CAN可以同时用于一台应用 中但不能在同一台时间使用。



图1 USB设备框图

4、USB功能描述

USB模块为PC主机和微控制器所实现的功能之间提供了符合USB规范的通信链接。PC主机和 微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被USB外 设直接访问。这块专用数据缓冲区的大小由所使用的端点数目和每个端点最大的数据分组大小 所决定,每个端点最大可使用512字节缓冲区,最多可用于16个单向或8个双向端点。USB模块 同PC主机通信,根据USB规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处 理。整个传输的格式由硬件完成,其中包括CRC的生成和校验。
每个端点都有一台缓冲区描述块,描述该端点使用的缓冲区地址、大小和需要传输的字节数。 当USB模块识别出一台有效的功能/端点的令牌分组时,(如果需要传输数据并且端点已配置)随 之发生相关的数据传输。USB模块通过一台内部的16位寄存器实现端口与专用缓冲区的数据交 换。在所有的数据传输完成后,如果需要,则根据传输的方向,发送或接收适当的握手分组。 在数据传输结束时,USB模块将触发与端点相关的中断,通过读状态寄存器和/或者利用不同的 中断处理程序,微控制器可以确定:

  • 哪个端点需要得到服务
  • 产生如位填充、格式、CRC、协议、缺失ACK、缓冲区溢出/缓冲区未满等错误时,正在进 行的是哪种类型的传输。
USB模块对同步传输和高吞吐量的批量传输提供了特殊的双缓冲区机制,在微控制器使用一台 缓冲区的时候,该机制保证了USB外设总是可以使用另一台缓冲区。
在任何不需要使用USB模块的时候,通过写控制寄存器总可以使USB模块置于低功耗模式 (SUSPEND模式)。在这种模式下,不产生任何静态电流消耗,同时USB时钟也会减慢或停止。 通过对USB线上数据传输的检测,可以在低功耗模式下唤醒USB模块。也可以将一特定的中断 输入源直接链接到唤醒引脚上,以使系统能立即恢复正常的时钟系统,并支持直接启动或停止 时钟系统。
4.1、USB功能模块描述
USB模块实现了标准USB接口的所有特性,它由以下部分组成:

  • 串行接口控制器(SIE):该模块包括的功能有:帧头同步域的识别,位填充,CRC的产生和 校验,PID的验证/产生,和握手分组处理等。它与USB收发器交互,利用分组缓冲接口提 供的虚拟缓冲区存储局部数据。它也根据USB事件,和类似于传输结束或一台包正确接收 等与端点相关事件生成信号,例如帧首(Start of Frame),USB复位,数据错误等等,这些 信号用来产生中断。
  • 定时器:本模块的功能是产生一台与帧开始报文同步的时钟脉冲,并在3ms内没有数据传输 的状态,检测出(主机的)全局挂起条件。
  • 分组缓冲器接口:此模块管理那些用于发送和接收的临时本地内存单元。它根据SIE的要求 分配合适的缓冲区,并定位到端点寄存器所指向的存储区地址。它在每个字节传输后,自 动递增地址,直到数据分组传输结束。它记录传输的字节数并防止缓冲区溢出。
  • 端点相关寄存器:每个端点都有一台与之相关的寄存器,用于描述端点类型和当前状态。 对于单向和单缓冲器端点,一台寄存器就可以用于实现两个不同的端点。一共8个寄存器, 可以用于实现最多16个单向/单缓冲的端点或者7个双缓冲的端点或者这些端点的组合。例 如,可以同时实现4个双缓冲端点和8个单缓冲/单向端点。
  • 控制寄存器:这些寄存器包含整个USB模块的状态信息,用来触发诸如恢复,低功耗等 USB事件。
  • 中断寄存器:这些寄存器包含中断屏蔽信息和中断事件的记录信息。配置和访问这些寄存 器可以获取中断源,中断状态等信息,并能清除待处理中断的状态标志。
注意: 端点0总是作为单缓冲模式下的控制端点。
USB模块通过APB1接口部件与APB1总线相连,APB1接口部件包括以下部分:

  • 分组缓冲区:数据分组缓存在分组缓冲区中,它由分组缓冲接口控制并创建数据结构。应 用软件可以直接访问该缓冲区。它的大小为512字节,由256个16位的字构成。
  • 仲裁器:该部件负责处理来自APB1总线和USB接口的存储器请求。它通过向APB1提供较 高的访问优先权来解决总线的冲突,并且总是保留一半的存储器带宽供USB完成传输。它 采用时分复用的策略实现了虚拟的双端口SRAM,即在USB传输的同时,允许应用程序访问 存储器。此策略也允许任意长度的多字节APB1传输。
  • 寄存器映射单元:此部件将USB模块的各种字节宽度和位宽度的寄存器映射成能被APB1寻 址的16位宽度的内存集合。
  • APB1封装:此部件为缓冲区和寄存器提供了到APB1的接口,并将整个USB模块映射到 APB1地址空间。
  • 中断映射单元:将可能产生中断的USB事件映射到三个不同的NVIC请求线上:(1)、USB低优先级中断(通道20):可由所有USB事件触发(正确传输,USB复位等)。固件在处 理中断前应当首先确定中断源。(2)、USB高优先级中断(通道19):仅能由同步和双缓冲批量传输的正确传输事件触发,目的是 保证最大的传输速率。(3)、USB唤醒中断(通道42):由USB挂起模式的唤醒事件触发。
5、编程中需要考虑的问题

5.1、通用USB设备编程
这一部分描述了实现USB设备功能的应用程序需要完成的任务。除了介绍一般的USB事件中应 该采取的操作外,还着重介绍了双缓冲端点和同步传输的操作。这些相关的操作都是由USB模 块初始化,并由以下几节所描述的USB事件所驱动。
5.2、系统复位和上电复位
发生系统复位或者上电复位时,应用程序首先需要做的是提供USB模块所需要的时钟信号,然后清除复位信号,使程序可以访问USB模块的寄存器。复位之后的初始化流程如下所述:
首先,由应用程序激活寄存器单元的时钟,再配置设备时钟管理逻辑单元的相关控制位,清除复位信号。
其次,必须配置CNTR寄存器的PDWN位用以开启USB收发器相关的模拟部分,这点需要特别的处理。此位能打开为端点收发器供电的内部参照电压。由于打开内部电压需要一段启动时间(数据手册中的tSTARTUP),在此期间内USB收发器处于不确定状态,所以在设置CNTR寄存器的 PDWN后必需等待一段时间之后,才能清除USB模块的复位信号(清除CNTR寄存器上的FRES 位),和ISTR寄存器的内容,以便在使能其他任何单元的操作之前清除未处理的假中断标志。
最后,应用程序需要通过配置设备时钟管理逻辑的相应控制位来为USB模块提供标准所定义的 48MHz时钟。
当系统复位时,应用程序应该初始化所有需要的寄存器和分组缓冲区描述表,使USB模块能够 产生正常的中断和完成数据传输。所有与端点无关的寄存器需要根据应用的需求进行初始化(比 如中断使能的选择,分组缓冲区地址的选择等)。接下来按照USB复位处理(参见下段)。
USB复位(RESET中断)
发生USB复位时,USB模块进入前面章节中描述过的系统复位状态:所有端点的通信都被禁止 (USB模块不会响应任何分组)。在USB复位后,USB模块被使能,同时地址为0的默认控制端点 (端点0)也需要被使能。这可以通过配置USB_DADDR寄存器的EF位,EP0R寄存器和相关的分 组缓冲区来实现。在USB设备的枚举阶段,主机将分配给设备一台唯一的地址,这个地址必须 写入USB_DADDR寄存器的ADD[6:0]位中,同时配置其他所需的端点。
当复位中断产生时,应用程序必需在中断产生后的10ms之内使能端点0的传输。
分组缓冲区的结构和用途
每个双向端点都可以接收或发送数据。接收到的数据存储在该端点指定的专用缓冲区内,而另一台缓冲区则用于存放待发送的数据。对这些缓冲区的访问由分组缓冲区接口模块实现,它提出缓冲区访问请求,并等待确认信息后返回。为防止产生微控制器与USB模块对缓冲区的访问冲突,缓冲区接口模块使用仲裁机制,使APB1总线的一半周期用于微控制器的访问,另一半保证USB模块的访问。这样,微控制器和USB模块对分组缓冲区的访问如同对一台双端口SRAM 的访问,即使微控制器连续访问缓冲区,也不会产生访问冲突。
USB模块使用固定的时钟,此时钟被USB标准定义为48MHz。APB1总线的时钟可以大于或者小于这个频率。
注意: 为满足USB数据传输率和分组缓冲区接口的系统需求,APB1总线时钟的频率必须大于8MHz,以避免数据缓冲区溢出或不满
每个端点对应于两个分组缓冲区(一般一台用于发送,另一台用于接收)。这些缓冲区可以位于整个分组存储区的任意位置,因为它们的地址和长度都定义在缓冲区描述表中,而缓冲区描述表也同样位于分组缓冲区中,其地址由寄存器确定。
缓冲区描述表的每个表项都关联到一台端点寄存器,它由4个16位的字组成,因此缓冲区描述表的起始地址按8字节对齐(寄存器的最低3位总是“000”)。第21.5.3节详细介绍缓冲区描述表表项。 如果是非同步非双缓冲的单向端点,只需要一台分组缓冲区(即发送方向上的分组缓冲区)。
其他未用到的端点或某个未使用的方向上的缓冲区描述表项可以用于其他用途。同步和双缓冲批量端点有特殊的分组缓冲区处理方法。下图描述了缓冲区描述表项和分组缓冲区区域的关系。



图2 分组缓冲区对应的缓冲区描述表项定位

不管是接收或是发送,分组缓冲区都是从底部开始使用的。USB模块不会改变超出当前分配到的缓冲区区域以外的其他缓冲区的内容。如果缓冲区收到一台比自个大的数据分组,它只会接收最大为自身大小的数据,其他的丢掉,即发生了所谓的缓冲区溢出异常。
端点初始化
初始化端点的第一步是把适当的值写到ADDRn_TX或ADDRn_RX寄存器中,以便USB模块能找到要传输的数据或准备好接收数据的缓冲区。USB_EpnR寄存器的EP_TYPE位确定端点的基本类型,EP_KIND位确定端点的特殊特性。作为发送方,需要设置USB_EpnR寄存器的STAT_TX 位来使能端点,并配置COUNTn_TX位决定发送长度。作为接收方,需要设置STAT_RX位来使 能端点,并且设置BL_SIZE和NUM_BLOCK位,确定接收缓冲区的大小,以检测缓冲区溢出的 异常。对于非同步非双缓冲批量传输的单向端点,只需要设置一台传输方向上的寄存器。一旦 端点被使能,应用程序就不能再修改USB_EpnR寄存器的值和ADDRn_TX / ADDRn_RX, COUNTn_TX / COUNTn_RX所在的位置,因为这些值会被硬件实时修改。当数据传输完成时, CTR中断会产生,此时上述寄存器可以被访问,并重新使能新的传输。
IN分组(用于数据发送)
当接收到一IN令牌分组时,如果接收到的地址和一台配置好的端点地址相符合的话,USB模块 将会根据缓冲区描述表的表项,访问相应的ADDRn_TX和COUNTn_TX寄存器,并将这些寄存 器中的数值存储到内部的16位寄存器ADDR和COUNT(应用程序无法访问)中。此时,USB模块 开始根据DTOG_TX位发送DATA0或DATA1分组,并访问缓冲区(请参考’分组缓冲区的结构和用 途’段落)。在IN分组传输完毕之后,从缓冲区读到的第一台字节将被装载到输出移位寄存器中, 并开始发送。最后一台数据字节发送完成之后,计算好的CRC将被发送。如果收到的分组所对应的端点是无效的,将根据USB_EpnR寄存器上的STAT_TX位发送NAK或STALL握手分组而不发送数据。
ADDR内部寄存器被用作当前缓冲区的指针,COUNT寄存器用于记录剩下未传输的字节数。USB总线使用低字节在先的方式传输从缓冲区中读出的数据。数据从ADDRn_TX指向的数据分组缓冲区开始读取,长度为COUNTn_TX/2个字。如果发送的数据分组为奇数个字节,则只使用最后一台字的低8位。
在接收到主机响应的ACK后,USB_EpnR寄存器的值有以下更新:DTOG_TX位被翻转, STAT_TX位为’10’,使端点无效,CTR_TX位被置位。应用程序需要通过USB_ISTR寄存器的EP_ID和DIR位识别产生中断的USB端点。CTR_TX事件的中断服务程序需要首先清除中断标志位,然后准备好需要发送的数据缓冲区,更新COUNTn_TX为下次需要传输的字节数,最后再设置STAT_TX位为’11’(端点有效),再次使能数据传输。当STAT_TX位为’10’时(端点为NAK状态),任何发送到该端点的IN请求都会被NAK,USB主机会重发IN请求直到该端点确认请求有效。上述操作过程是必需遵守的,以避免丢失紧随上一次CTR中断请求的下一台IN传输请求。
OUT分组和SETUP分组(用于数据接收)
USB模块对这两种分组的处理方式基本相同;对SETUP分组的特殊处理将在下面关于控制传输部分详细说明。当接收到一台OUT或SETUP 分组时,如果地址和某个有效端点的地址相匹配,USB模块将访问缓冲区描述表,找到与该端点相关的ADDRn_RX和COUNTn_RX寄存器,并将ADDRn_RX 寄存器的值保存在内部 ADDR 寄存器中。同时, COUNT 会被被复位,从 COUNTn_RX 中读出的 BL_SIZE 和 NUM_BLOCK 的值用于初始化内部 16 位寄存器 BUF_COUNT,该寄存器用于检测缓冲区溢出(所有的内部寄存器都不能被应用程序访问)。USB 模块将随后收到的数据按字方式组织(先收到的为低字节),并存储到ADDR指向的分组缓冲区中。同时,BUF_COUNT值自动递减,COUNT值自动递增。当检测到数据分组的结束信号时, USB模块校验收到CRC的正确性。如果传输中没有任何错误发生,则发送ACK握手分组到主机。即使发生CRC错误或者其他类型的错误(位填充,帧错误等),数据或是会被保存到分组缓冲区中,至少会保存到发生错误的数据点,只是不会发送ACK分组,并且USB_ISTR寄存器的ERR位将会置位。在这种情况下,应用程序通常不需要干涉处理,USB模块将从传输错误中自动恢复,并为下一次传输做好准备。如果收到的分组所对应的端点没有准备好,USB模块将根据USB_EpnR寄存器的STAT_RX位发送NAK或STALL分组,数据将不会被写入接收缓冲区。
ADDRn_RX的值决定接收缓冲区的起始地址,长度由包含CRC的数据分组的长度(即有效数据长度+2)决定,但不能超过BL_SIZE和NUM_BLOCK所定义的缓冲区的长度。如果接收到的数据分组的长度超出了缓冲区的范围,超过范围的数据不会被写入缓冲区,USB模块将报告缓冲区发生溢出,并向主机发送STALL握手分组,通知此次传输失败,也不产生中断。
如果传输正确完成,USB模块将发送ACK握手分组,内部的COUNT寄存器的值会被复制到相应的 COUNTn_RX 寄存器中, BL_SIZE 和 NUM_BLOCK 的值保持不变,也不需要重写。 USB_EpnR寄存器按下列方式更新:DTOG_RX位翻转,STAT_RX=10(NAK)使端点无效, CTR_RX位置位(如果CTR中断已使能,将触发中断)。如果传输过程中发生了错误或者缓冲区溢 出,前面所列出的动作都不会发生。CRT中断发生时,应用程序需要首先根据USB_ISTR寄存 器的EP_ID和DIR位识别是哪个端点的中断请求。在处理CTR_RX中断事件时,应用程序首先要 确定传输的类型(根据USB_EPnR寄存器的SETUP位),同时清除中断标志位,然后读相关的缓 冲区描述表表项指向的COUNTn_RX寄存器,获得此次传输的总字节数。处理完接收到的数据 后,应用程序需要将USB_EpnR中的STAT_RX位置成’11’,使能下一次的的传输。当STAT_RX 位为’10’时(NAK),任何一台发送到端点上的OUT请求都会被NAK,PC主机将不断重发被NAK的分组,直到收到端点的ACK握手分组。以上描述的操作次序是必需遵守的,以避免丢失紧随上一台CTR中断的另一台OUT分组请求。
控制传输
控制传输由3个阶段组成,首先是主机发送SETUP分组的SETUP阶段,然后是主机发送零个或多个数据的数据阶段,最后是状态阶段,由与数据阶段方向相反的数据分组构成。SETUP传输只发生在控制端点,它非常类似于OUT分组的传输过程。使能SETUP传输除了需要分别初始化 DTOG_TX位为’1’,DTOG_RX位为’0’外,还需要设置STAT_TX位和STAT_RX位为10(NAK), 由应用程序根据SETUP分组的相应字段决定后面的传输是IN或是OUT。控制端点在每次发生CTR_RX中断时,都必须检查USB_EpnR寄存器的SETUP位,以识别是普通的OUT分组或是 SETUP分组。USB设备应该能够通过SETUP分组中的相应数据决定数据阶段传输的字节数和方向,并且能在发生错误的情况下发送STALL分组,拒绝数据的传输。因此在数据阶段,未被使用到的方向都应该被设置成STALL,并且在开始传输数据阶段的最后一台数据分组时,其反方向的传输仍设成NAK状态,这样,即使主机立刻改变了传输方向(进入状态阶段),仍然可以保持为等待控制传输结束的状态。在控制传输成功结束后,应用程序可以把NAK变为VALD,如果控制传输出错,就改为STALL。此时,如果状态分组是由主机发送给设备的,那么STATUS_OUT 位(USB_EPnR寄存器中的EP_KIND)应该被置位,只有这样,在状态传输过程中收到了非零长度的数据分组,才会产生传输错误。在完成状态传输阶段后,应用程序应该清除STATUS_OUT 位,并且将STAT_RX设为VALID表示已准备好接收一台新的命令请求,STAT_TX则设为NAK, 表示在下一台SETUP分组传输完成前,不接受数据传输的请求。
USB规范定义SETUP分组不能以非ACK握手分组来响应,如果SETUP分组传输失败,则会引发下一台SETUP分组。因此,以NAK或STALL分组响应主机的SETUP分组是被禁止的。
当STAT_RX位被设置为’01’(STALL)或’10’(NAK)时,如果收到SETUP分组,USB模块会接收分组,开始分组所要求的数据传输,并回送ACK握手分组。如果应用程序在处理前一台CTR_RX事件时USB模块又收到了SETUP分组(即CTR_RX仍然保持置位),USB模块会丢掉收到的SETUP分组,并且不回答任何握手分组,以此来模拟一台接收错误,迫使主机再次发送SETUP分组。这样做是为了避免丢失紧随一次CTR_RX中断之后的又一台SETUP分组传输。
5.3、双缓冲端点
USB标准不仅为不同的传输模式定义了不同的端点类型,而且对这些数据传输所需要的系统要求做了描述。其中,批量端点适用于在主机PC和USB设备之间传输大批量的数据,因为主机可以在一帧内利用尽可能多的带宽批量传输数据,使传输效率得到提高。然而,当USB设备处理前一次的数据传输时,又收到新的数据分组,它将回应NAK分组,使PC主机不断重发同样的数据分组,直到设备在可以处理数据时回应ACK分组。这样的重传占用了很多带宽,影响了批量传输的速率,因此引入了批量端点的双缓冲机制,提高数据传输率。
使用双缓冲机制时,单向端点的数据传输将使用到该端点的接收和发送两块数据缓冲区。数据翻转位用来选择当前使用到两块缓冲区中的哪一块,使应用程序可以在USB模块访问其中一块缓冲区的同时,对另一块缓冲区进行操作。例如,对一台双缓冲批量端点进行OUT分组传输时,USB模块将来自PC主机的数据保存到一台缓冲区,同时应用程序可以对另一台缓冲区中的 数据进行处理(对于IN分组来说,情况是一样的)。
因为切换缓冲区的管理机制需要用到所有4个缓冲区描述表的表项,分别用来表示每个方向上的两个缓冲区的地址指针和缓冲区大小,因此用来实现双缓冲批量端点的USB_EpnR寄存器必需配置为单向。所以只需要设定STAT_RX位(作为双缓冲批量接收端点)或者STAT_TX位(作为双缓冲批量发送端点)。如果需要一台双向的双缓冲批量端点,则须使用两个USB_EpnR寄存器。
为尽可能利用双缓冲的优势,达到较高的传输速率,双缓冲批量端点的流量控制流程与其他端点的稍有不同。它只在缓冲区发生访问冲突时才会设置端点为NAK状态,而不是在每次传输成功后都将端点设为NAK状态。
DTOG位用来标识USB模块当前所使用的储存缓冲区。双缓冲批量端点接收方向的缓冲区由 DTOG_RX(USB_EpnR寄存器的第14位)标识,而双缓冲批量端点发送方向的缓冲区由 DTOG_TX(USB_EpnR寄存器的第6位)标识。同时,USB模块也需要知道当前哪个缓冲区正在 被应用程序使用,以避免发生冲突。由于USB_EpnR寄存器中有2个DTOG位,而USB模块只使用其中的一位来标识硬件所使用的缓冲区,因此,应用程序可使用另一位来标识当前正在使用哪个缓冲区,这个新的标识被称为SW_BUF位。下表列出了双缓冲批量端点在实现发送和接收操作时,USB_EPNR寄存器的DTOG位和SW_BUF位之间的关系。



图3 双缓冲批量端点缓冲区标识定义

USB模块当前使用的缓冲区由DTOG位标识,而应用程序所使用的缓冲区由SW_BUF位标识,这两个位的标识方式相同,下表描述了这种标识方式。



图4 双缓冲批量端点的缓冲区使用标识

注(1):端点处于NAK状态
可以通过以下方式设置一台双缓冲批量端点:

  • 将USB_EPnR寄存器的EP_TYPE位设为’00’,定义端点为批量端点
  • 将USB_EPnR寄存器的EP_KIND位设为’1’,定义端点为双缓冲端点
应用程序根据传输开始时用到的缓冲区来初始化DTOG和SW_BUF位;这需要考虑到这两位的数据翻转特性。设置好DBL_BUF位之后,每完成一次传输后,USB模块将根据双缓冲批量端点的流量控制操作,并且持续到DBL_BUF变为无效为止。每次传输结束,根据端点的传输方向,CTR_RX位或CTR_TX位将会置为’1’。与此同时,硬件将设置相应的DTOG位,完全独立于软件来实现缓冲区交换机制。DBL_BUF位设置后,每次传输结束时,双缓冲批量端点的STAT位的取值不会像其他类型端点一样受到传输过程的影响,而是一直保持为’11’(有效)。但是,如果在收到新的数据分组的传输请求时,USB模块和应用程序发生了缓冲区访问冲突(即DTOG和SW_BUF为相同的值,见表154),状态位将会被置为’10’(NAK)。应用程序响应CTR中断时,首先要清除中断标志,然后再处理传输完成的数据。应用程序访问缓冲区之后,需要翻转SW_BUF位,以通知USB模块该块缓冲区已变为可用状态。由此,双缓冲批量传输的NAK分组的数目只由应用程序处理一次数据传输的快慢所决定:如果数据处理的时间小于USB总线上完成一次数据传输的时间,则不会发生重传,此时,数据的传输率仅受限于USB主机。
应用程序也可以不考虑双缓冲批量端点的特殊控制流程,直接在相应USB_EPnR寄存器的STAT位写入非’11’的任何状态,在这种情况下,USB模块将按照写入的状态执行流程而忽略缓冲器实际的使用情况。
5.4、同步传输
USB标准定义了一种全速的需要保持固定和精确的数据传输率的传输方式:同步传输。同步传输一般用于传输音频流、压缩的视频流等对数据传输率有严格要求的数据。一台端点如果在枚举时被定义为“同步端点”,USB主机则会为每个帧分配固定的带宽,并且保证每个帧正好传送一台IN分组或者OUT分组(由端点传输方向确定分组类型)。为了满足带宽要求,同步传输中没有出错重传;这也就意味着,同步传输在发送或接收数据分组之后,无握手协议,即不会发送ACK分组。同样,同步传输只传送PID(分组ID)为DATA0的数据包, 而不会用到数据翻转机制。
通过设置USB_EPnR寄存器EP_TYPE为’10’,可以使其成为同步端点。同步端点没有握手机制,根据USB标准中的说明,USB_EPnR寄存器的STAT_RX位和STAT_TX位分别只能设成’00’ (禁止)和’11’(有效)。同步传输通过实现双缓冲机制来简化软件应用程序开发,它同样使用两个缓冲区,以确保在USB模块使用其中一块缓冲区时,应用程序可以访问另外一块缓冲区。
USB模块使用的缓冲区根据不同的传输方向,由不同的DTOG位来标识。(同一寄存器中的DTOG_RX位用来标识接收同步端点,DTOG_TX位用来标识发送同步端点),见下表。



图5 同步端点的缓冲区使用标识

与双缓冲批量端点一样,一台USB_EPnR寄存器只能处理同步端点单方向的数据传输,如果要求同步端点在两个传输方向上都有效,则需要使用两个USB_EPnR寄存器。
应用程序需要根据首次传输的数据分组来初始化DTOG位;它的取值还需要考虑到DTOG_RX或DTOG_TX两位的数据翻转特性。每次传输完成时,USB_EPnR寄存器的CTR_RX位或CTR_TX位置位。与此同时,相关的DTOG位由硬件翻转,从而使得交换缓冲区的操作完全独立于应用程序。传输结束时,STAT_RX或STAT_TX位不会发生变化,因为同步传输没有握手机制,所以不需要任何流量控制,而一直设为’11’(有效)。同步传输中,即使OUT分组发生CRC错误或者缓冲区溢出,本次传输仍被看作是正确的,并且可以触发CTR_RX中断事件;但是,发生CRC错误时硬件会设置USB_ISTR寄存器的ERR位,提醒应用程序数据可能损坏。
5.5、挂起/恢复事件
USB标准中定义了一种特殊的设备状态,即挂起状态,在这种状态下USB总线上的平均电流消耗不超过500uA。这种电流限制对于由总线供电的USB设备至关重要,而自供电的设备则不需要严格遵守这样的电流消耗限制。USB主机以3毫秒内不发送任何信号标志进入挂起状态。通常情况下USB主机每毫秒会发送一台SOF,当USB模块检测到3个连续的SOF分组丢失事件即可判定主机发出了挂起请求,接着它会置位SB_ISTR寄存器的SUSP位,以触发挂起中断。USB设备进入挂起状态之后,将由“唤醒”序列唤醒。所谓的“唤醒”序列, 可以由USB主机发起,也可以由USB设备本身触发;但是,只有USB主机可以结束“唤醒”序列。被挂起的USB模块必须至少还具备检测RESET信号的功能,它会将其当作一次正常的复位操作来执行。
实际的挂起操作过程对于不同的USB设备来说是不同的,因为需要不同的操作来降低电源消耗。下面描述了一起典型的挂起操作,重点介绍应用程序如何响应USB模块的SUSP信号。

  • 将USB_CNTR寄存器的FSUSP置为’1’,这将使USB模块进入挂起状态。USB模块一旦进入挂起状态,对SOF的检测立刻停止,以避免在USB挂起时又发生新的SUSP事件。
  • 消除或减少USB模块以外的其他模块的静态电流消耗。
  • 将USB_CNTR寄存器的LP_MODE位置为’1’,这将消除模拟USB收发器的静态电流消耗,但仍能检测到唤醒信号。
  • 可以选择关闭外部振荡器和设备的PLL,以停止设备内部的任何活动。
当设备处于挂起状态时发生USB事件,该设备会被唤醒,并需要调用“唤醒”例程来恢复系统时钟,和USB数据传输。如果唤醒设备的是USB复位操作,则应该保证唤醒的过程不要超过10毫秒(参见“USB协议规范”)。USB模块处于挂起状态时,唤醒或复位事件需要清除 USB_CNTR寄存器的LP_MODE位。即使唤醒事件可以立刻触发一台WKUP中断事件,但由于恢复系统时钟需要比较长的延迟时间,处理WKUP中断的中断服务程序必须非常小心;为了减短系统唤醒的时间,建议将唤醒代码直接写在挂起代码后面,这样就可以在系统时钟重启后迅速进入唤醒代码中执行。为防止或减少ESD等干扰意外地唤醒系统(从挂起模式退出是一台异步事件),在挂起过程中数据线被过滤,滤波宽度大约为70nS。
下面是唤醒操作的过程:启动外部振荡器和设备的PLL(此项可选)。

  • 清零USB_CNTR寄存器的FSUSP位。
  • USB_FNR寄存器的RXDP和RXDM位可以用来判断是指什么触发了唤醒事件,如下图6所示,它还同时列出了各种情况软件应该采取的操作。如果需要的话,可以通过检测这两位变成’10’(代表空闲总线状态)的时间来知道唤醒或复位事件的结束。此外,在复位事件结束时,USB_ISTR寄存器的RESET位被置为’1’,如果RESET中断被使能,就会产生中断。此中断应该按正常的复位操作处理。



图6 唤醒事件检测

设备可能不是被与USB模块相关的事件唤醒的(例如一台鼠标的移动可唤醒整个系统)。在这种情况下,先将USB_CNTR寄存器的RESUME位置为’1’,然后在1ms-15ms之间再把它清为0可以启动唤醒序列(这个间隔可以用ESOF中断来实现,该中断在内核正常运行时每1ms发生一次)。RESUME位被清零后,唤醒过程将由主机PC完成,可以利用USB_FNR寄存器的RXDP和 RXDM位来判断唤醒是否完成。
注意: 只有在USB模块被设置为挂起状态时(设置USB_CNTR寄存器的FSUSP位为’1’),才可以设置RESUME位。
6、USB寄存器描述

USB模块的寄存器有以下三类:

  • 通用类寄存器:中断寄存器和控制寄存器
  • 端点类寄存器:端点配置寄存器和状态寄存器
  • 缓冲区描述表类寄存器:用来确定数据分组存放地址的寄存器
缓冲区描述表类寄存器的基地址由USB_BTABLE寄存器指定,所有其他寄存器的基地址则为USB模块的基地址0x4000 5C00。由于APB1总线按32位寻址,因此所有的16位寄存器的地址都是按32位字对齐的。同样的地址对齐方式也用于从0x4000 6000开始的分组缓冲存储区。
可以用半字(16位)或字(32位)的方式操作这些外设寄存器。

6.1 通用寄存器
这组寄存器用于定义USB模块的工作模式,中断的处理,设备的地址和读取当前帧的编号。
6.1.1 USB控制寄存器(USB_CNTR)
地址偏移:0x40
复位值:0x0003


位15 -CTRM:正确传输(CTR)中断屏蔽位 (Correct transfer interrupt mask)

  • 0:正确传输(CTR)中断禁止
  • 1:正确传输(CTR)中断使能,在中断寄存器的相应位被置1时产生中断。
位14 -PMAOVRM:分组缓冲区溢出中断屏蔽位 (Packet memory area over / underrun interrupt mask)

  • 0:PMAOVR中断禁止
  • 1:PMAOVR中断使能,在中断寄存器的相应位被置1时产生中断。
位13 -ERRM:出错中断屏蔽位 (Error interrupt mask)

  • 0:出错中断禁止
  • 1:出错中断使能,在中断寄存器的相应位被置1时产生中断。
位12 -WKUPM:唤醒中断屏蔽位 (Wakeup interrupt mask)

  • 0:唤醒中断禁止
  • 1:唤醒中断使能,在中断寄存器的相应位被置1时产生中断。
位11 -SUSPM:挂起中断屏蔽位 (Suspend mode interrupt mask)

  • 0:挂起(SUSP)中断禁止
  • 1:挂起(SUSP)中断使能,在中断寄存器的相应位被置1时产生中断。
位10 -RESETM:USB复位中断屏蔽位 (USB reset interrupt mask)

  • 0:USB RESET中断禁止
  • 1:USB RESET中断使能,在中断寄存器的相应位被置1时产生中断。
位9 -SOFM:帧首中断屏蔽位 (Start of frame interrupt mask)

  • 0:SOF中断禁止
  • 1:SOF中断使能,在中断寄存器的相应位被置1时产生中断。
位8 -ESOFM:期望帧首中断屏蔽位 (Expected start of frame interrupt mask)

  • 0:ESOF中断禁止
  • 1:ESOF中断使能,在中断寄存器的相应位被置1时产生中断。
位7~位5 保留
位4 -RESUME:唤醒请求 (Resume request)
设置此位将向PC主机发送唤醒请求。根据USB协议,如果此位在1ms到15ms内保持有效,主 机将对USB模块实行唤醒操作。
位3 -FSUSP:强制挂起 (Force suspend)
当USB总线上保持3ms没有数据通信时,SUSP中断会被触发,此时软件必需设置此位。

  • 0:无效
  • 1:进入挂起模式,USB模拟收发器的时钟和静态功耗仍然保持。如果需要进入低功耗状态(总 线供电类的设备),应用程序需要先置位FSUSP再置位LP_MODE。
位2 -LP_MODE:低功耗模式 (Low-power mode)
此模式用于在USB挂起状态下降低功耗。在此模式下,除了外接上拉电阻的供电,其他的静态 功耗都被关闭,系统时钟将会停止或者降低到一定的频率来减少耗电。USB总线上的活动(唤醒 事件)将会复位此位(软件也可以复位此位)。

  • 0:非低功耗模式
  • 1:低功耗模式
位1 -PDWN:断电模式 (Power down)
此模式用于彻底关闭USB模块。当此位被置位时,不能使用USB模块。

  • 0:退出断电模式
  • 1:进入断电模式
位0 -FRES:强制USB复位 (Force USB Reset)

  • 0:清除USB复位信号
  • 1:对USB模块强制复位,类似于USB总线上的复位信号。USB模块将一直保持在复位状态下 直到软件清除此位。如果USB复位中断被使能,将产生一台复位中断。
6.1.2 USB中断状态寄存器(USB_ISTR)
地址偏移:0x44
复位值:0x0000


此寄存器包含所有中断源的状态信息,以供应用程序确认产生中断请求的事件。
寄存器的高8位各表示一台中断源。当相关事件发生时,这些位被硬件置位,如果USB_CNTR寄存器上的相应位也被置位,则会产生相应的中断。中断服务程序需要检查每个位,在执行必要的操作后必需清除相应的状态位,不然中断信号线一直保持为高,同样的中断会再次被触发。如果同时多个中断标志被设置,也只会产生一台中断。
应用程序可以使用不同的方式处理传输完成中断,以减少中断响应的延迟时间。端点在成功完成一次传输后,CTR位会被硬件置起,如果USB_CNTR上的相应位也被设置的话,就会产生中断。与端点相关的中断标志和USB_CNTR寄存器的CTRM位无关。这两个中断标志位将一直保持有效,直到应用程序清除了USB_EpnR寄存器中的相关中断挂起位(CTR位是个只读位)。 USB模块有两路中断请求源:

  • 高优先级的USB IRQ:用于高优先级的端点(同步和双缓冲批量端点)的中断请求,并且该中断不能被屏蔽。
  • 低优先级USB IRQ:用于其他中断事件,可以是低优先级的不可屏蔽中断,也可以是由 USB_ISTR寄存器的高8位标识的可屏蔽中断。
对于端点产生的中断,应用程序可以通过DIR寄存器和EP_ID只读位来识别中断请求由哪个端点产生,并调用相应的中断服务程序。
用户在处理同时发生的多个中断事件时,可以在中断服务程序里检查USB_ISTR寄存器各个位的顺序来确定这些事件的优先级。在处理完相应位的中断后需要清零该中断标志。完成一次中断服务后,另一中断请求将会产生,用以请求处理剩下的中断事件。
为了避免意外清零某些位,建议使用加载指令,对所有不需改变的位写’1’,对需要清除的位写’0’。对于该寄存器,不建议使用读出-修改-写入的流程,因为在读写操作之间,硬件可能需要设置某些位,而这些位会在写入时被清零。
下面详细描述每个位:
位15 -CTR:正确的传输 (Correct transfer)
此位在端点正确完成一次数据传输后由硬件置位。应用程序可以通过DIR和EP_ID位来识别是哪个端点完成了正确的数据传输。 此位应用程序只读。
位14 -PMAOVR:分组缓冲区溢出 (Packet memory area over / underrun)
此位在微控制器长时间没有响应一台访问USB分组缓冲区请求时由硬件置位。USB模块通常在以下情况时置位该位:在接收过程中一台ACK握手分组没有被发送,或者在发送过程中发生了比特填充错误,在以上两种情况下主机都会要求数据重传。在正常的数据传输中不会产生 PMAOVR中断。由于失败的传输都将由主机发起重传,应用程序就可以在这个中断的服务程序中加速设备的其他操作,并准备重传。但这个中断不会在同步传输中产生(同步传输不支持重传)因此数据可能会丢失。
此位应用程序可读可写,但只有写0有效,写1无效。
位13 -ERR:出错 (Error)
在下列错误发生时硬件会置位此位。

  • NANS:无应答。主机的应答超时。
  • CRC:循环冗余校验码错误。数据或令牌分组中的CRC校验出错。
  • BST:位填充错误。PID,数据或CRC中检测出位填充错误。
  • FVIO:帧格式错误。收到非标准帧(如EOP出目前错误的时刻,错误的令牌等)。
USB应用程序通常可以忽略这些错误,因为USB模块和主机在发生错误时都会启动重传机制。 此位产生的中断可以用于应用程序的开发阶段,可以用来监测USB总线的传输质量,标识用户可能发生的错误(链接线松,环境干扰严重,USB线损坏等)。 此位应用程序可读可写,但只有写0有效,写1无效。
位12 -WKUP:唤醒请求 (Wakeup)
当USB模块处于挂起状态时,如果检测到唤醒信号,此位将由硬件置位。此时CTLR寄存器的 LP_MODE位将被清零,同时USB_WAKEUP被激活,通知设备的其他部分(如唤醒单元)将开始 唤醒过程。
此位应用程序可读可写,但只有写0有效,写1无效。
位11-SUSP:挂起模块请求 (Suspend mode request)
此位在USB线上超过3ms没有信号传输时由硬件置位,用以指示一台来自USB总线的挂起请求。USB复位后硬件立即使能对挂起信号的检测,但在挂起模式下(FSUSP=1)硬件不会再检测挂起信号直到唤醒过程结束。
此位应用程序可读可写,但只有写0有效,写1无效
位10 -RESET:USB复位请求 (USB reset request)
此位在USB模块检测到USB复位信号输入时由硬件置位。此时USB模块将复位内部协议状态机,并在中断使能的情况下触发复位中断来响应复位信号。USB模块的发送和接收部分将被禁止,直到此位被清除。所有的配置寄存器不会被复位,除非应用程序对他们清零。这用来保证在复位后USB传输还可以立即正确执行。但设备的地址和端点寄存器会被USB复位所复位。
此位应用程序可读可写,但只有写0有效,写1无效
位8 -ESOF:期望帧首标识位 (Expected start of frame)
此位在USB模块未收到期望的SOF分组时由硬件置位。主机应该每毫秒都发送SOF分组,但如 果USB模块没有收到,挂起定时器将触发此中断。如果连续发生3次ESOF中断,也就是连续3 次未收到SOF分组,将产生SUSP中断。即使在挂起定时器未被锁定时发生SOF分组丢失,此 位也会被置位。
此位应用程序可读可写,但只有写0有效,写1无效。
位7~位5 保留
位4 -DIR:传输方向 (Direction of transaction)
此位在完成数据传输产生中断后由硬件根据传输方向写入。

  • 如果DIR=0,相应端点的CTR_TX位被置位,标志一台IN分组(数据从USB模块传输到PC主机) 的传输完成。
  • 如果DIR=1,相应端点的CTR_RX位被置位,标志一台OUT分组(数据从PC主机传输到USB模 块)的传输完成。如果CTR_TX位同时也被置位,就标志同时存在挂起的OUT分组和IN分组。 应用程序可以利用该信息访问USB_EPnR位对应的操作,它表示挂起中断传输方向的信息。
  • 该位为只读。
位3~0 -EP_ID[3~0]:端点ID (Endpoint Identifier)
此位在USB模块完成数据传输产生中断后由硬件根据请求中断的端点号写入。如果同时有多个端点的请求中断,硬件写入优先级最高的端点号。端点的优先级按以下方法定义:同步端点和双缓冲批量端点具有高优先级,其他的端点为低优先级。如果多个同优先级的端点请求中断,则根据端点号来确定优先级,即端点0具有最高优先级,端点号越小,优先级越高。应用程序可以通过上述的优先级策略顺序处理端点的中断请求。该位为只读
6.1.3 USB帧编号寄存器(USB_FNR)
地址偏移:0x48
复位值:0x0XXX,X代表未定义数值


位15 -RXDP:D+状态位 (Receive data + line status)
此位用于观察USB D+数据线的状态,可在挂起状态下检测唤醒条件的出现。
位14 -RXDM:D-状态位 (Receive data - line status)
此位用于观察USB D-数据线的状态,可在挂起状态下检测唤醒条件的出现。
位13 -LCK:锁定位 (Locked)
USB模块在复位或唤醒序列结束后会检测SOF分组,如果连续检测到至少2个SOF分组,则硬件会置位此位。此位一旦锁定,帧计数器将停止计数,一直等到USB模块复位或总线挂起时再恢复计数。
位12~位11 -LSOF[1~0]:帧首丢失标志位 (Lost SOF)
当ESOF事件发生时,硬件会将丢失的SOF分组的数目写入此位。如果再次收到SOF分组,引脚会清除此位。
位10~位0 -FN[10~0]:帧编号 (Frame number)
此部分记录了最新收到的SOF分组中的11位帧编号。主机每发送一台帧,帧编号都会自加,这对于同步传输非常有意义。此部分发生SOF中断时更新。
6.1.4 USB设备地址寄存器(USB_DADDR)
地址偏移:0x4C
复位值:0x0000


位7 -EF:USB模块使能位 (Enable function)
此位在需要使能USB模块时由应用程序置位。如果此位为0,USB模块将停止工作,忽略所有寄存器的设置,不响应任何USB通信。
位6~位0 -ADD[6~0]:设备地址 (evice address)
此位记录了USB主机在枚举过程中为USB设备分配的地址值。该地址值和端点地址(EA)必需和USB令牌分组中的地址信息匹配,才能在指定的端点进行正确的USB传输。
6.1.5 USB分组缓冲区描述表地址寄存器(USB_BTABLE)
地址偏移:0x50
复位值:0x0000


位15~位3 -BTABLE[15~3]:缓冲表 (Buffer table)
此位记录分组缓冲区描述表的起始地址。分组缓冲区描述表用来指示每个端点的分组缓冲区地 址和大小,按8字节对齐(即最低3位为000)。每次传输开始时,USB模块读取相应端点所对应 的分组缓冲区描述表获得缓冲区地址和大小信息。
位2~位0 保留位,由硬件置为0

6.2 端点寄存器
端点寄存器的数量由USB模块所支持的端点数目决定。USB模块最多支持8个双向端点。每个USB设备必须支持一台控制端点,控制端点的地址(EA位)必需为0。不同的端点必需使用不同的端点号,否则端点的状态不定。每个端点都有与之对应的USB_EpnR寄存器,用于存储该端点的各种状态信息。
6.2.1 USB 端点n寄存器(USB_EPnR), n=[0..7]
地址偏移:0x00至0x1C
复位值:0x0000


当USB模块收到USB总线复位信号,或CTLR寄存器的FRES位置位时,USB模块将会复位。该寄存器除了CTR_RX和CTR_TX位保持不变以处理紧随的USB传输外,其他位都被复位。每个端点对应一台USB_EPnR寄存器,其中n为端点地址,即端点ID号。
对于此类寄存器应避免执行读出-修改-写入操作,因为在读和写操作之间,硬件可能会设置某些位,而这些位又会在写入时被修改,导致应用程序错过相应的操作。因此,这些位都有一台写入无效的值,建议用Load指令修改这些寄存器,以免应用程序修改了不需要修改的位。
位15 -CTR_RX:正确接收标志位 (Correct Transfer for reception)
此位在正确接收到OUT或SETUP分组时由硬件置位,应用程序只能对此位清零。如果CTRM位已置位,相应的中断会产生。收到的是OUT分组或是SETUP分组可以通过下面描述的SETUP位确定。以NAK或STALL结束的分组和出错的传输不会导致此位置位,因为没有真正传输数据。
此位应用程序可读可写,但只有写0有效,写1无效
位14 -DTOG_RX:用于数据接收的数据翻转位 (Data Toggle, for reception transfers)
对于非同步端点,此位由硬件设置,用于标记希望接收的下一台数据分组的Toggle位 (0=DATA0,1=DATA1)。在接收到PID(分组ID)正确的数据分组之后,USB模块发送ACK握手分组,并翻转此位。对于控制端点,硬件在收到SETUP分组后清除此位。 对于双缓冲端点,此位还用于支持双缓冲区的交换(请参考21.4.3双缓冲端点)。 对于同步端点,由于仅发送DATA0,因此此位仅用于支持双缓冲区的交换(请参考21.4.4同步 传输)而不需进行翻转。同步传输不需要握手分组,因此硬件在收到数据分组后立即设置此位。
应用程序可以对此位进行初始化(对于非控制端点,初始化是必需的),或者翻转此位用于特殊用途。
此位应用程序可读可写,但写0无效,写1可以翻转此位
位13~位12 -STAT_RX[1~0]:用于数据接收的状态位 (Status bits, for reception transfers)
具体的定义请参考下表
此位用于指示端点当前的状态,表157列出了端点的所有状态。当一次正确的OUT或SETUP数据传输完成后(CTR_RX=1),硬件会自动设置此位为NAK状态,使应用程序有足够的时间在处理完当前传输的数据后,响应下一台数据分组。 对于双缓冲批量端点,由于使用特殊的传输流量控制策略,因此根据使用的缓冲区状态控制传 输状态(请参考21.4.3双缓冲端点)。对于同步端点,由于端点状态只能是有效或禁用,因此硬件不会在正确的传输之后设置此位。如果应用程序将此位设为STALL或者NAK,USB模块响应的操作是未定义的。
此位应用程序可读可写,但写0无效,写1翻转此位
位11 -SETUP:SETUP分组传输完成标志位 (Setup transaction completed)
此位在USB模块收到一台正确的SETUP分组后由硬件置位,只有控制端点才使用此位。在接收完成后(CTR_RX=1),应用程序需要检测此位以判断完成的传输是否是SETUP分组。为了防止中断服务程序在处理SETUP分组时下一台令牌分组修改了此位,只有CTR_RX为0时,此位才可以被修改,CTR_RX为1时不能修改。 此位应用程序只读
位10~位9 -EP_TPYE[1~0]:端点类型位 (Endpoint type)
具体的定义请参考下表
所有的USB设备都必需包 含一台地址为0的控制端点,如果需要可以有其他地址的控制端点。只有控制端点才会有SETUP传输,其他类型的端点无视此类传输。SETUP传输不能以NAK或STALL分组响应,如果控制端点在收到SETUP分组时处于NAK状态,USB模块将不响应分组,就会出现接收错误。如果控制端点处于STALL状态,SETUP分组会被正确接收,数据会被正确传输,并产生一台正确传输完成的中断。控制端点的OUT分组安装普通端点的方式处理。批量端点和中断端点的处理方式非常类似,仅在对EP_KIND位的处理上有差别。
位8 -EP_KIND:端点特殊类型位 (Endpoint kind)
具体的定义请参考下表

  • DBL_BUF:应用程序设置此位能使能批量端点的双缓冲功能。
  • STATUS_OUT:应用程序设置此位表示USB设备期望主机发送一台状态数据分组,此时,设备对于任何长度不为0的数据分组都响应STALL分组。此功能仅用于控制端点,有利于提供应用程序对于协议层错误的检测。如果STATUS_OUT位被清除,OUT分组可以包含任意长度的 数据。
位7 -CTR_TX:正确发送标志位 (Correct transfer for transmission)
此位由硬件在一台正确的IN分组传输完成后置位。如果CTRM位已被置位,会产生相应的中 断。应用程序需要在处理完该事件后清除此位。在IN分组结束时,如果主机响应NAK或STALL 则此位不会被置位,因为数据传输没有成功。
此位应用程序可读可写,但写0有效,写1无效。
位6 -DTOG_RX:发送数据翻转位 (Data Toggle, for transmission transfers)
对于非同步端点,此位用于指示下一台要传输的数据分组的Toggle位(0=DATA0, 1=DATA1)。在一台成功传输的数据分组后,如果USB模块接收到主机发送的ACK分组,就会 翻转此位。对于控制端点,USB模块会在收到正确的SETUP PID后置位此位。对于双缓冲端点,此位还可用于支持分组缓冲区交换。对于同步端点,由于只传送DATA0,因此该位只用于支持分组缓冲区交换。由于同步传输不需要握手分组,因此硬件在接收到数据分组后即设置该位。应用程序可以初始化该位(对于非控制端点,初始化此位时必需的),也可以设置该位用于特殊用途。
此位应用程序可读可写,但写0无效,写1翻转此位。
位5~位4 -STAT_TX[1~0]:用于发送数据的状态位 (Status bits, for transmission transfers)
具体的定义请参考下表
应用程序可以翻转这些位来初始化 状态信息。在正确完成一次IN分组的传输后(CTR_TX=1),硬件会自动设置此位为NAK状态, 保证应用程序有足够的时间准备好数据响应后续的数据传输。对于双缓冲批量端点,由于使用特殊的传输流量控制策略,是根据缓冲区的状态控制传输的状态的。对于同步端点,由于端点的状态只能是有效或禁用,因此硬件不会在数据传输结束时改变端点的状态。如果应用程序将此位设为STALL或者NAK,则USB模块后续的操作是未定义的。
此位应用程序可读可写,但写0无效,写1翻转此位
位3~位0 -EA[3~0]:端点地址 (Endpoint address)
应用程序必需设置此4位,在使能一台端点前为它定义一台地址。



接收状态编码



端点类型编码



端点特殊类型定义



发送状态编码

6.3 缓冲区描述表
虽然缓冲区描述表位于分组缓冲区内,但仍可将它看作是特殊的寄存器,用以配置USB模块和微控制器内核共享的分组缓冲区的地址和大小。由于APB1总线按32位寻址,所以所有的分组缓冲区地址都使用32位对齐的地址,而不是USB_BTABLE寄存器和缓冲区描述表所使用的地址。
以下介绍两种地址表示方式:

  • 一种是应用程序访问分组缓冲区时使用的
  • 另一种是相对于USB 模块的本地地址。
供应用程序使用的分组缓冲区地址需要乘以2才能得到缓冲区在微控制器中的真正地址。分组缓冲区的首地址为0x4000 6000。下面将描述与USB_EPnR寄存器相关的缓冲区描述表。
6.3.1 发送缓冲区地址寄存器 n(USB_ADDRn_TX)
地址偏移:[USB_BTABLE] + n×16
USB本地地址:[USB_BTABLE] + n×8


位15~位1 -ADDRn_TX[15~1]:发送缓冲区地址 (Transmission buffer address)
此位记录了收到下一台IN分组时,需要发送的数据所在的缓冲区起始地址。
位0 因为分组缓冲区的地址必须按字对齐,所以此位必须为’0’。
6.3.2 发送数据字节数寄存器 n(USB_COUNTn_TX)
地址偏移:[USB_BTABLE] + n×16 + 4
USB本地地址:[USB_BTABLE] + n×8 + 2


位15~位10
由于USB模块支持的最大数据分组为1023个字节,所以USB模块忽略这些位。
位9~位0 COUNTn_TX[9:0]: 发送数据字节数 (Transmission byte count)
此位记录了收到下一台IN分组时要传输的数据字节数。
注: 双缓冲区和同步IN端点有两个USB_COUNTn_TX,寄存器:分别为USB_COUNTn_TX_1和 USB_COUNTn_TX_0,内容如下:


6.3.3 接收缓冲区地址寄存器 n(USB_ADDRn_RX)
地址偏移:[USB_BTABLE] + n×16 + 8
USB本地地址:[USB_BTABLE] + n×8 + 4


位15~位1 -ADDRn_RX[15~1]:接收缓冲区地址 (Reception buffer address)
此位记录了收到下一台OUT或者SETUP分组时,用于保存数据的缓冲区起始地址。
位0 因为分组缓冲区的地址按字对齐,所以此位必需为’0’。
6.3.4 接收数据字节数寄存器 n(USB_COUNTn_RX)  
地址偏移:[USB_BTABLE] + n×16 + 12
USB本地地址:[USB_BTABLE] + n×8 + 6


该寄存器用于存放接收分组时需要使用到的两个参数。高6位定义了接收分组缓冲区的大小,以便USB模块检测缓冲区的溢出。低10位则用于USB模块记录实际接收到的字节数。由于有效位数的限制,缓冲区的大小由分配到的存储区块数表示,而存储区块的大小则由所需的缓冲区大小决定。缓冲区的大小在设备枚举过程中定义,由端点描述符的参数maxPacketSize表述。(具体信息请参考”USB 2.0协议规范”)
位15 -BL_SIZE:存储区块的大小 (Block size)
此位用于定义决定缓冲区大小的存储区块的大小。

  • 如果BL_SIZE=0,存储区块的大小为2字节,因此能分配的分组缓冲区的大小范围为2-62个 字节。
  • 如果BL_SIZE=1,存储区块的大小为32字节,因此能分配的分组缓冲区的大小范围为32-512 字节,符合USB协议定义的最大分组长度限制。
位14~位10 -NUM_BLOCK[4~0]:存储区块的数目 (Number of blocks)
此位用以记录分配的存储区块的数目,从而决定最终使用的分组缓冲区的大小。具体详情看下表
位9~位0 -COUNTn_RX[9~0]:接收到的字节数 (Reception byte count)
此位由USB模块写入,用以记录端点收到的最新的OUT或SETUP分组的实际字节数。



分组缓冲区大小的定义

注: 双缓冲区和同步IN端点有两个USB_COUNTn_RX寄存器:分别为USB_COUNTn_RX_1和 USB_COUNTn_TX_0,内容如下:


6.4 USB寄存器映像



USB寄存器映像和复位值



USB寄存器映像和复位值
使用道具 举报
| 来自广东 用Deepseek满血版问问看
当贝投影