STM32F0实战:基于HAL库开发【4.6】
21.2 USB模块STM32F0072VBT6微控制器片内集成有符合USB2.0全速设备技术规范要求的USB模块通过该模块可以实现与PC主机的USB通信连接进一步拓展将该系列微控制器的应用范围。21.2.1 USB模块的结构STM32F072VBT6微控制器片内集成的USB模块可配置18个USB端点具有最多1024字节的专用包缓冲存储器其中256字节与CAN外设共享支持批量/同步端点的双缓冲区机制和USB挂起/恢复操作且支持USB 2.0电源管理和电池充电检测BCD在USB_DP线上嵌入了上拉电阻具备可编程的USB连接/断开能力。USB模块的主要特点见表21-5。USB模块能实现标准USB接口的所有功能其内部结构如图21-6所示。USB模块由以下部分组成。1.USB物理接口USB_PHY该模块提供了连接USB主机的电气接口。它包含差分模拟收发器、可控嵌入负载电阻连接到USB_DP线、电池充电检测BCD、多路复用的USB_DP和USB_DM线等。模拟收发器输出使能控制信号通过USB_NOE输出可用于驱动LED或为其他电路提供通信方向指示。2.串行接口引擎SIE该模块的功能有帧头同步域的识别、位填充、CRC的生成和校验、PID的验证/产生以及握手分组处理等。串行接口引擎与USB收发器交互利用分组缓冲接口提供的虚拟缓冲区存储中间数据并且根据USB事件、传输结束、包正确接收等与端点相关事件生成信号和触发中断。3.定时器其功能是产生一个与帧开始报文同步的时钟脉冲并且在3ms范围内如果没有检测到数据的传输将产生全局挂起事件。4.分组缓冲区接口用于管理分组缓冲区存储单元它根据SIE的要求分配合适的缓冲区并定位到端点寄存器所指向的存储区域。在每字节传输完成后自动递增地址直到数据分组传输结束。5.端点相关寄存器·端点寄存器每个端点都有一个与之相关的寄存器用于描述端点类型和当前状态。·控制寄存器包含USB模块的状态信息用来触发诸如恢复、低功耗等USB事件。·中断寄存器提供了中断标志和中断屏蔽功能配置和访问这些寄存器可以获取中断源、中断状态等信息并能清除待处理中断的状态标志。6.APB接口在图21-6中我们不难发现串行接口引擎SIE部分使用的是USB时钟48MHz而其余部分除了USB物理接口USB PHY以外使用的是PCLK时钟。USB模块通过APB接口部件与APB总线相连APB接口包括以下部分。·分组缓冲区由分组缓冲接口控制并且提供数据缓存应用软件可以直接访问该缓冲区。分组缓冲区的大小最多为1024字节由512个16位的半字构成。·仲裁器负责处理来自APB总线和USB模块的存储器请求。它通过向APB提供较高的访问优先权来解决总线冲突并且总是保留一半的存储器带宽供USB模块使用。它采用分时复用的策略实现了虚拟的双端口SRAM即在USB模块读取分组缓冲区时也同样允许应用程序访问。·寄存器映射单元将USB模块各种宽度的寄存器映射成能被APB总线寻址的16位宽度的存储器集合。·APB封装为分组缓冲区和寄存器提供了到APB总线的接口并将整个USB模块映射到APB地址空间上。·中断映射单元将产生中断的USB事件映射到NVIC请求线上。21.2.2 USB模块数据传输我们已经知道所谓端点就是一小片数据存储区域通过这一小片存储区域可以实现主机与USB模块之间的数据传送。USB模块的分组缓冲区恰恰是为端点提供的存储区域其大小最多为1024字节由512个16位的半字构成最多可用于16个单向或8个双向端点。为了便于理解USB模块与主机的数据传输我们有必要了解一下STM32F0系列微控制器的USB模块对于端点是如何定义的。以端点0为例其寄存器定义如图21-7所示。一个双向端点由以下六个部分来定义。·端点寄存器USB_EpnRn[0http://www.hzcourse.com/resource/readBook?path/openresources/teach_ebook/uncompressed/18006/OEBPS/Text/..7]用于描述和保存端点的状态信息。·缓冲区描述表用于配置USB模块和微控制器内核共享的分组缓冲区的地址和大小。·发送缓冲区地址寄存器USB_ADDRn_TX定义端点n发送缓冲区起始地址。·发送数据字节数寄存器USB_COUNTn_TX定义端点n发送缓冲区大小。·接收缓冲区地址寄存器USB_ADDRn_RX定义端点n接收缓冲区起始地址。·接收数据字节数寄存器USB_COUNTn_RX定义端点n接收缓冲区大小。当USB模块同PC主机通信时按照USB规范要求由USB模块实现令牌分组的检测、数据发送/接收、CRC的生成和校验、握手分组的处理等功能整个传输由硬件完成。端点使用的缓冲区大小和数量是动态的由主机根据传输的需要控制和改变。每个端点都有一个缓冲区描述表描述该端点使用的缓冲区地址、大小和需要传输的字节数。USB模块通过一个内部的16位寄存器软件不能访问实现端口与专用缓冲区的数据交换数据交换以有效的功能/端点的令牌分组开始并且以发送或接收适当的握手分组结束。在数据传输结束时USB模块将触发与端点相关的中断通过读状态寄存器或者利用不同的中断处理程序微控制器可以确定哪个端点需要得到服务或者在发生如位填充、缓冲区溢出等错误时做相应的处理。USB模块还对同步传输和高吞吐量的批量传输提供了特殊的双缓冲区机制即当微控制器使用一个缓冲区的时候保证USB外设总是可以使用另一个缓冲区。21.3 USB总线编程尽管使用STM32CubeMX软件提供的HAL库和中间件组件可以将USB编程难度降低但了解USB模块的运行过程和应用程序需要完成的具体功能对于USB模块的程序开发非常重要。以下我们将要对一般的USB事件、双缓冲端点和同步传输等过程应采取的软件操作做简要的说明。21.3.1 USB复位操作1.微控制器复位发生系统复位或者上电复位时应用程序需要为USB模块提供所需要的时钟信号然后清除复位信号使应用程序可以访问USB模块的寄存器。其次需要配置CNTR寄存器的PDWN位用以开启USB收发器相关的模拟部分打开为端点收发器供电的内部参考电压。之后应用程序需要为USB模块提供标准的48MHz时钟。当系统复位后应用程序应该初始化所有需要的寄存器和分组缓冲区描述表使USB模块能够产生正常的中断和完成数据传输。2.USB模块复位当USB模块收到USB总线复位信号或USB_CNTR寄存器的FRES位置位时USB模块将会复位。这时所有端点的通信都被禁止USB模块不会响应任何分组。USB复位后需要软件使能USB模块同时地址为0的默认控制端点端点0也需要被使能这些都可以通过配置USB_DADDR寄存器的EF位、EP0R寄存器和相关的分组缓冲区来实现。3.枚举阶段在USB设备的枚举阶段主机将分配给设备一个唯一的地址。该地址会写入USB_DADDR寄存器的ADD[60]位中同时配置其他所需的端点。当复位中断产生时应用程序必须在中断产生后的10ms之内使能端点0的传输。21.3.2 分组缓冲区每个双向端点都可以接收或发送数据。接收到的数据存储在该端点指定的专用缓冲区内而另一个缓冲区则用于存放待发送的数据。对这些缓冲区的访问由分组缓冲区接口模块实现它提出缓冲区访问请求并等待确认信息后返回。为防止微控制器与USB模块对缓冲区的访问冲突缓冲区接口模块使用仲裁机制使APB总线的一半周期用于微控制器的访问另一半保证USB模块的访问。这样微控制器和USB模块对分组缓冲区的访问如同对一个双端口SRAM的访问即使微控制器连续访问缓冲区也不会产生访问冲突。每个端点对应于两个分组缓冲区通常一个用于发送另一个用于接收。这些缓冲区可以位于整个分组存储区的任意位置它们的地址和长度都定义在缓冲区描述表中而缓冲区描述表也同样位于分组缓冲区中其地址由寄存器确定。缓冲区描述表的每个表项都关联到一个端点寄存器它由4个16位的字组成因此缓冲区描述表的起始地址按8字节对齐寄存器的最低3位总是“000”。如果是非同步非双缓冲的单向端点只需要一个分组缓冲区发送方向上的分组缓冲区。其他未用到的端点或某个未使用的方向上的缓冲区描述表项可以用于其他用途缓冲区描述表项和分组缓冲区的对应关系如图21-8所示。不管是接收还是发送分组缓冲区都是从底部开始使用的。USB模块不会访问超出当前分配到的缓冲区区域以外的其他缓冲区的内容。如果缓冲区收到一个比自己大的数据分组它只会接收最大为自身大小的数据其他的丢掉即发生了所谓的缓冲区溢出异常。21.3.3 端点初始化初始化端点的第一步是把适当的值写到ADDRn_TX或ADDRn_RX寄存器中以便USB模块能找到要传输数据的端点所对应的接收和发送数据缓冲区的位置。USB_EpnR寄存器的EP_TYPE位确定端点的基本类型EP_KIND位确定端点的特性。作为发送方需要设置USB_EpnR寄存器的STAT_TX位来使能端点并配置COUNTn_TX位决定发送长度。作为接收方需要设置STAT_RX位来使能端点并且设置USB_ADDRn_RX寄存器的BL_SIZE和NUM_BLOCK位确定接收缓冲区的大小。对于非同步非双缓冲批量传输的单向端点只需要设置一个传输方向上的寄存器即可。一旦端点被使能应用程序就不能再修改USB_EpnR寄存器的值和ADDRn_TX/ADDRn_RX、COUNTn_TX/COUNTn_RX所在的位置因为这些值会被硬件实时修改。当数据传输完成后CTR中断会产生此时上述寄存器可以被访问并重新使能新的传输。21.3.4 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请求都会被NAKUSB主机会重发IN请求直到该端点确认请求有效。上述操作过程是必须遵守的以避免丢失紧随上一次CTR中断请求的下一个IN传输请求。21.3.5 OUT和SETUP分组USB模块对这两种分组的处理方式基本相同。当接收到一个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中断发生时应用程序需要首先根据USB_ISTR寄存器的EP_ID和DIR位识别是哪个端点的中断请求。在处理CTR_RX中断事件时应用程序首先要根据USB_EpnR寄存器的SETUP位确定传输的类型同时清除中断标志位然后读相关的缓冲区描述表项指向的COUNTn_RX寄存器获得此次传输的总字节数。处理完接收到的数据后应用程序需要将USB_EpnR中的STAT_RX位置为“11”使能下一次的传输。当STAT_RX位为“10”时NAK任何一个发送到端点上的OUT请求都会被NAKPC主机将不断重发被NAK的分组直到收到端点的ACK握手分组。21.3.6 控制传输控制传输由3个阶段组成首先是主机发送SETUP分组的SETUP阶段然后是主机发送数据的数据阶段最后是状态阶段由与数据阶段方向相反的数据分组构成。SETUP传输只发生在控制端点它非常类似于OUT分组的传输过程。使能SETUP传输除了需要分别初始化DTOG_TX位为“1”DTOG_RX位为“0”外还需要设置STAT_TX位和STAT_RX位为10NAK由应用程序根据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事件时又收到了SETUP分组USB模块会丢掉收到的SETUP分组并且不回答任何握手分组以此来模拟一个接收错误迫使主机再次发送SETUP分组。这样做是为了避免丢失紧随一次CTR_RX中断之后的又一个SETUP分组传输。21.3.7 双缓冲端点USB标准为不同的传输模式定义了不同的端点类型其中批量端点适用于在主机PC和USB设备之间传输大批量的数据主机可以在一帧内利用尽可能多的带宽批量传输数据使传输效率得到提高。当USB设备处理前一次的数据传输时又收到新的数据分组它将回应NAK分组PC主机会不断重发同样的数据分组直到设备在可以处理数据时回应ACK分组。这样的重传占用了很多带宽影响了批量传输的速率因此引入了批量端点的双缓冲机制提高数据传输率。使用双缓冲机制时单向端点的数据传输将使用到该端点的接收和发送两块数据缓冲区。数据翻转位用来选择当前使用到两块缓冲区中的哪一块使应用程序可以在USB模块访问其中一块缓冲区的同时对另一块缓冲区进行操作。例如对一个双缓冲批量端点进行OUT分组传输时USB模块将来自PC主机的数据保存到一个缓冲区同时应用程序可以对另一个缓冲区中的数据进行处理。因为切换缓冲区的管理机制需要用到所有4个缓冲区描述表的表项分别用来表示每个方向上的两个缓冲区的地址指针和缓冲区大小因此用来实现双缓冲批量端点的USB_EpnR寄存器必须配置为单向。所以只需要设定STAT_RX位作为双缓冲批量接收端点或者STAT_TX位作为双缓冲批量发送端点。如果需要一个双向的双缓冲批量端点就必须使用两个USB_EpnR寄存器。为尽可能利用双缓冲的优势达到较高的传输速率双缓冲批量端点的流量控制流程与其他端点的稍有不同。它只在缓冲区发生访问冲突时才会设置端点为NAK状态而不是在每次传输成功后都将端点设为NAK状态。DTOG位用来标识USB模块当前所使用的储存缓冲区而SW_BUF位用来标识应用程序当前所使用的储存缓冲区。当作为发送端点使用时DTOG_TXUSB_EpnR寄存器的第6位用作DTOGDTOG_RXUSB_EpnR寄存器的第14位用作SW_BUF。双缓冲批量端点缓冲区标识定义详见表21-6具体的标识方式详见表21-7。可以通过首先将USB_EpnR寄存器的EP_TYPE位设为“00”定义端点为批量端点再将EP_KIND位设为“1”定义端点为双缓冲端点即可得到一个双缓冲批量端点。应用程序根据传输开始时用到的缓冲区来初始化DTOG和SW_BUF位。DBL_BUF位EP_KIND位设置之后每完成一次传输后USB模块将根据双缓冲批量端点的流量控制操作并且持续到DBL_BUF变为无效为止。每次传输结束根据端点的传输方向CTR_RX位或CTR_TX位将会置位。与此同时硬件将设置相应的DTOG位完全独立于软件来实现缓冲区交换机制。DBL_BUF位设置后每次传输结束时双缓冲批量端点的STAT位的取值不会像其他类型端点一样受到传输过程的影响而是一直保持为“11”有效。如果在收到新的数据分组传输请求时USB模块和应用程序发生了缓冲区访问冲突即DTOG和SW_BUF为相同的值这时状态位将会被设置为“10”NAK。应用程序在响应CTR中断时首先要清除中断标志然后再处理传输完成的数据。应用程序访问缓冲区之后需要翻转SW_BUF位以通知USB模块该块缓冲区已变为可用状态。由此可见双缓冲批量传输的NAK分组的数目只由应用程序处理一次数据传输的快慢所决定如果数据处理的时间小于USB总线上完成一次数据传输的时间则不会发生重传数据的传输率仅受限于USB主机。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2488773.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!