详细内容见《STM32F10xxx中文参考手册》21 USB全速设备接口(USB) 章节、《STM32F10x参考手册(英文)》 23 Universal serial bus full-speed device interface (USB)和《STM32 USB 开发者培训》资料。本章节只概要描述。

一、USB简介

USB外设实现了USB2.0全速总线和APB1总线间的接口。

USB外设支持USB挂起/恢复操作,可以停止设备时钟实现低功耗。
在这里插入图片描述

二、USB主要特征

  • 符合USB2.0全速设备的技术规范;

  • 可配置1到8个USB端点;

  • CRC(循环冗余校验)生成/校验,反向不归零(NRZI)编码/解码和位填充;

  • 支持同步传输;

  • 支持批量/同步端点的双缓冲区机制;

  • 支持USB挂起/恢复操作;

  • 帧锁定时钟脉冲生成;

1、USB寄存器和缓存映射

在这里插入图片描述
特别注意

USB和CAN共用一个专用的512字节的SRAM存储器用于数据的发送和接收,因此不能同时使用 USB和CAN(共享的SRAM被USB和CAN模块互斥地访问)。USB和CAN可以同时用于一个应用 中但不能在同一个时间使用。

2、USB设备框图

在这里插入图片描述

3、USB时钟

在这里插入图片描述
注意:为使USB正常工作,APB1时钟不能低于8MHz !

三、USB功能描述

USB模块PC主机微控制器所实现的功能之间提供了符合USB规范的通信连接。PC主机微控制器之间的数据传输是通过共享一专用的数据缓冲区来完成的,该数据缓冲区能被USB外设直接访问

USB模块同PC主机通信,根据USB规范实现令牌分组的检测,数据发送/接收的处理,和握手分组的处 理。整个传输的格式由硬件完成,其中包括CRC的生成和校验。

USB模块通过一个内部的16位寄存器实现端口与专用缓冲区的数据交换

当USB模块识别出一个有效的功能/端点的令牌分组时,(如果需要传输数据并且端点已配置)随之发生相关的数据传输。在所有的数据传输完成后,如果需要,则根据传输的方向,发送或接收适当的握手分组。

在数据传输结束时,USB模块将触发与端点相关的中断,通过读状态寄存器和/或者利用不同的 中断处理程序,微控制器可以确定:

  • 哪个端点需要得到服务。
  • 产生如位填充、格式、CRC、协议、缺失ACK、缓冲区溢出/缓冲区未满等错误时,正在进 行的是哪种类型的传。

在任何不需要使用USB模块的时候,通过写控制寄存器总可以使USB模块置于低功耗模式 (SUSPEND模式)。通过对USB线上数据传输的检测,可以在低功耗模式下唤醒USB模块。也可以将一特定的中断输入源直接连接到唤醒引脚上,以使系统能立即恢复正常的时钟系统,并支持直接启动或停止时钟系统。
在这里插入图片描述

1、SIE

1、硬件识别同步信号、进行比特填充、产生以及校验CRC、产生以及验证PID、握手。

2、根据外设事件来产生SOF、复位信号等。

2、时钟

1、产生和帧信号同步的时钟脉冲。

2、检测挂起信号(即3ms内USB总线上没有信号)。

3、Packet Buffer interface

1、通过一组收、发 buffer 来管理512字节的本地内存。

2、硬件根据来自SIE的请求来选择合适的 buffer。

4、registers

1、Endpoint 相关寄存器

作用:该EP的传输类型、地址、当前状态。

寄存器:USB_EPnR(n=[0…7])。

2、Contorl 相关寄存器

作用:控制USB模块事件(比如唤醒和休眠)和反应USB模块当前状态。

寄存器:USB控制寄存器(USB_CNTR)、USB帧编号寄存器(USB_FNR)、USB设备地址寄存器(USB_DADDR)、USB分组缓冲区描述表地址寄存器(USB_BTABLE)、发送缓冲区地址寄存器 n(USB_ADDRn_TX)、发送数据字节数寄存器 n(USB_COUNTn_TX)、接收缓冲区地址寄存器 n(USB_ADDRn_RX)、接收数据字节数寄存器 n(USB_COUNTn_RX)。

3、Interrupt 相关寄存器

作用:中断掩码,记录事件。

寄存器:USB控制寄存器(USB_CNTR)、USB中断状态寄存器(USB_ISTR)。

5、Packet buffer memory

1、实际包含packet buffer的地方。

2、最大容量=512字节=256个半字*16比特。

6、Arbiter

接收来自APB1总线和来自USB接口的内存请求,前者优先级更高。

7、Register mapper

把USB外设的字节宽度和位宽度的寄存器,组合成能被APB1访问的16位宽度字。

8、APB1 wrapper

1、为packet buffer memory和寄存器提供了APB1接口。

2、把所有USB外设映射到APB1的地址空间。

9、Interrupt wrapper

1、NVIC.向量20:所有USB事件(正确传输结束、USB复位等)都可触发。

2、NVIC.向量19:只能被同步和double buffer bulk传输的正确传输结束事件触发。

3、NVIC.向量42:只能被(唤醒USB挂起模式)的事件触发 @EXTI_18(只有host唤醒device,才会触发device的这个中断)。

四、USB设备编程

1、系统复位和上电复位

1、应用程序配置USB模块所需要的时钟信号。

2、清除复位信号,使程序可以访问USB模块的寄存器。

3、打开和USB收发器相连的模拟部分(打开内部参考电压给端口收发器供电)。

  • 复位PDWN@CNTR;

  • 等待内部参考电压稳定时间tSTARTUP;

  • 移除施加在该USB模块上的复位条件:软件清零FRES@CNTR;

  • 清除ISTR寄存器,以移除虚假的等待中断(USB未准备好时候触发的中断),然后再使能其他单元;

2、USB复位信号及其对应中断

1、该事件发生时,USB外设的状态和系统复位后状态一样。

2、软件应该在10ms之内使能USB功能:EF@DADDR。

3、初始化EP0R寄存器和ep0对应的包缓存。

4、如果置位了RESETM@CNTR,还会产生中断;直到RESET标志被清零之前,数据 收发都被关闭的。

3、分组缓存区的使用

1、软件通过packet buffer interface来访问它们。

2、这些packet buffer的位置和大小都可配置,由缓冲区描述表指定。

3、缓冲区描述表本身也在这块memory里,它自己 的地址是由USB_BTABLE寄存器指定的。

  • Table里每个端点由4个半字组成(分别表示双向 EP的接收packet和发送packet的位置和大小);
  • 因此该table的位置本身必须以8字节对齐,即 USB_BTABLE的低三位全部为0;

4、USB外设硬件不会把本EP的数据溢出到与其相邻的其他packet。

  • 如果收到的数据多于buffer的长度,则只把前 length个数据放到该EP对应的Packet buffer中;
    在这里插入图片描述
    在这里插入图片描述

1、硬件发送缓冲区

  • 初始化时设定各个EP硬件发送缓冲区的起始地址 @ADDRn_TX@硬件缓冲描述表;
  • 准备好要发送的数据后,设置发送长度@COUNTn_TX@硬件缓冲描述表;

2、硬件接收缓冲区

  • 初始化时设定各个EP硬件接收缓冲区的起始地址 @ADDRn_RX@硬件缓冲描述表;

  • 在初始化时设定各个EP硬件接收缓冲区的长度 @COUNTn_RX的高位@硬件缓冲描述表,以允许接收缓冲区的溢出检测;一般都是接收EP的最大包长;

  • 收到数据并产生ISR中,从硬件接收缓存读取数据之前先要看收到了多少数据(实际收到的数据不一定填满接收缓存的);

4、端点(EP)配置

1、把适当的值写到ADDRn_TX或ADDRn_RX寄存器中,以便USB模块能找到要传输的数据或准备好接收数据的缓冲区。

2、配置EPnR寄存器的EP_TYPE位确定端点的基本类型。

3、配置EPnR寄存器的EP_KIND位确定端点的特殊特性。

4、如果是发送方,通过STAT_TX@USB_EPnR使能EP的发送功能,配置COUNTn_TX。

5、如果是接收方,通过STAT_RX@USB_EPnR使能EP的接收功能,配置BL_SIZE、NUM_BLOCK。

特别说明

  • 双向EP0是必备的。
  • 其他EPi,应用可同时使用收、发两个方向或只使用一个方向。

5、IN packet的处理

1、USB外设收到主机发送的PID为IN的令牌包后

1、如果这个packet中的设备地址信息和端点号信息有效,并且端点为Valid状态:

  • USB硬件发送DATA0或DATA1的PID(根据DTOG_TX@USB_EPnR);

  • USB硬件发送待发送的数据;

  • USB硬件发送计算好的CRC;

2、如果该端点状态不是valid:

  • USB硬件不发送data packet,而是根据STAT_TX@USB_EPnR发送NAK或STALL的握手包;

2、USB外设收到主机返回的应答( PID为ACK的握手包)后

1、硬件:

  • 触发 DTOG_TX@USB_EPnR;

  • 硬件把该端点设置为invalid状态(STAT_TX=NAK);

  • 硬件置位CTR_TX,产生中断;

2、软件:

  • 通过检查EP_ID和DIR@USB_ISTR来识别是哪个端点上的通信;

  • 响应CTR_TX中断:

    • 标志清零;
    • 软件准备下次要发送的数据;
    • 更新COUNTn_TX如有必要;
    • 软件重新设置STAT_TX=VALID来重新把该EP设置到发送valid状态;

6、OUT/SETUP packet的处理

1、USB外设收到主机发送的PID为OUT/SETUP的令牌包后

1、如果这个packet中的设备地址信息和端点号信息有效,并且端点为Valid状态:

  • USB硬件从硬件buf中把数据搬移到用户可访问的packet buffer中;
  • USB硬件核对收到的CRC无误,就发出ACK握手包;
  • 如果CRC有误,就不会发出ACK握手包,并置位ERR@USB_ISTR;一般USB模块会自动 恢复来准备接收下一次传输;
  • 如果收到的数据长度超过了分配的空间,硬件回复STALL,置位溢出错误,但不产生中断

2、如果该端点状态不是valid:

  • USB硬件根据STAT_RX@USB_EPnR发送NAK或STALL的握手包;

2、USB外设收到主机返回的应答( PID为ACK的握手包)后

1、硬件

  • 触发 DTOG_RX@USB_EPnR;

  • 硬件把该端点设置为invalid状态(STAT_RX=NAK);

  • 硬件置位CTR_RX,产生中断;

2、软件

  • 通过检查EP_ID和DIR@USB_ISTR来识别是哪个端点上的通信;

  • 响应CTR_RX中断:

    • 标志清零;

    • 软件对收下来的数据进行处理;

    • 软件重新设置STAT_RX=VALID来重新把该EP设置到接收valid状态;

7、Control transfer的处理

1、控制传输组成

1、一个Setup transaction + 0个或多个同方向的data stage + 一个status stage。

2、Setup transaction只能由控制端点完成。

3、初始化:DTOG_TX=1, DTOG_RX=0。

4、触发CTR_RX中断在此ISR中查看SETUP位来确定这是个SETUP/OUT transaction。

  • 硬件把TX和RX的状态都设置成NAK;

5、在除最后一个的每个数据stage时,对未用方向都设置成STALL。

  • 以免主机过早结束传输,device可在status阶段返回STALL应答;

6、使能最后一次数据stage时,把未用方向设置成NAK。

  • 以免主机在最后一次data stage后立马开始status stage时,device可在处理完所有数据前NAK掉;
    在这里插入图片描述

8、双缓冲端点

在这里插入图片描述

1、使能控制

1、只能针对某个BULK类型的EP进行使能。

  • EP_TYPE = “BULK”@ USB_EPnR;
  • EP_KIND = “DBL_BUF” @ USB_EPnR;

2、当某个BULK类型的EP被使能“双缓冲”后

1、这个EP只能作为单向端点使用。

  • 作为接收方向:STAT_TX被设置成disable;

  • 作为发送方向:STAT_RX被设置成disable;

2、它的“发送packet memory”和“接收packet memory”都被使用。

  • 一个被USB硬件使用时;
  • 另一个就可被软件使用;

3、由data toggle序列来选择当前哪个packet memory 正在被USB硬件使用。

  • 接收:由DTOG_RX,DTOG_TX作为SW_BUF标志 当前哪个memory正在被application s/w使用;
  • 发送:DTOG_TX;

3、双缓冲下的流控机制

核心思想:一个方向传输使用 2 个缓存区,USB模块和应用程序同时交替使用不同缓存区。

1、由应用程序负责对DTOG和SW_BUF进行初始化。

2、USB通过SW_BUF(DTOG_X)来知道应用软件当前在用哪个packet memory。

3、只有在USB外设访问的buf和软件访问的buf冲突时才NAK数据流;而不是像通常情况 下的一次transaction接收后就把当前EP当前方向状态更改成NAK。

4、每次transaction结束后,CTR_Rx或Tx会被硬件置位;该EP所在方向对应的DTOG 被硬件翻转;STAT仍然保持Valid,只有当新的transaction的令牌包已经收到了,而 此时DTOG和SW_BUF值还相同,则该EP的STAT被置成NAK。

5、CTR_Rx或Tx置位后产生中断:sw需要对中断标志清零,并且在根据SW_BUF访问 完相应buf后,软件触发 SW_BUF来告知USB外设它新触发后对应的buf可以被使 用了。如果在新的transaction来之前,sw没有及时更新SW_BUF,使得此时的 SW_BUF还和刚才USB完成上次transaction后硬件自动触发的DTOG一样的值,则 EP被自动回NAK。

6、只要DBL_BUF被软件设置后,第一次transaction的结束就触发这个特殊的EP流控机 制,直到DBL_BUF被软件复位后这种特殊的流控才不再apply。

9、同步传输

1、需要固定和精确数据率的传输被定义成“同步传输”

1、在枚举时主机知道这是个同步类型的EP,就会在后期每个frame中给它分配所要求的带宽。

2、为节约带宽,同步传输没有重传机制,即没有握手阶段(数据包后没有握手包);因此也 就不需要数据toggle机制,它总是以DATA0作为PID发送数据。

2、同步EP的定义

1、EP_TYPE = 10 (同步);EP状态STAT_RX/TX只有Disable(00)和Valid(11)两种可能。

2、同步EP总是使用双缓冲结构,来缓解SW响应的压力。

10、挂起和唤醒

1、USB规范中定义的外设状态之一:【挂起】

1、从USB总线获得电流不能超过2.5mA。

2、对总线供电设备的要求,自供电设备可不受此限制。

2、设备检测到连续3个SOF包都没有收到,就认为主机要求它挂起

1、硬件置位SUSP@USB_ISTR,产生中断;软件通常做以下操作。

  • 置位FSUSP@USB_CNTR:激活USB外设的挂起模式(但是时钟和模拟收发模块的静态功 耗还在);
  • 关闭或降低除USB之外的其他外设的静态功耗;
  • 置位LP_MODE@USB_CNTR:关闭模拟收发模块的静态功耗;但收发模块仍能检测到 resume序列,USB模块也要继续给上拉电阻供电;

2、在挂起状态时,设备也要能够检测Reset序列。

3、设备的唤醒

1、可以由主机来发起Resume或Reset序列。

2、也可直接由设备自己来发起,但resume序列总是由主机来终结。

  • SW置位RESUME@USB_CNTR,持续1ms~15ms后,SW再复位之;

3、一旦被唤醒后,设备的软件需要如下处理。

  • 复位FSUSP@USB_CNTR;
  • 还可通过RXDP和RXDM位来识别resume triggering event;

五、寄存器

在这里插入图片描述

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐