基于STM32的USB枚举过程学习笔记(转)
之前使用ST官方的库以及网络的资料,完成了使用USB HID类进行STM32和PC机的通讯。由于其他原因并没有深入的分析,虽然实现了功能,但是关于USB设备的枚举,以及具体的通讯方式都没有清晰的概念,所以现在回头重新学习USB相关知识。主要参考资料是《圈圈教你玩USB》、USB枚举过程图解,ST官方的USB HID例程。
一,USB数据包
1. USB数据包分类
USB总线上的数据传输以包为基本的单位。USB协议规定了四种包:令牌包、数据包、握手包、特殊包。不同的包通过包中的8位PID域区分。
令牌包
令牌包用于启动 一次USB传输,USB的数据传输必须由主机发起。令牌包有四种:
输出令牌包(OUT):用来通知设备将要输出一个数据包。 数据方向 主机-->设备
输入令牌包(IN):用来通知设备将要返回一个数据包。 数据方向 设备-->主机
建立令牌包(SETUP):通知设备将要输出一个数据包,类似OUT包。不过SETUP包只能往端点0发包,只用在控制传输中。
帧起始包(SOF):用于帧计数,USB全速设备每毫秒产生一帧,USB高速设备每125μS产生一帧。
OUT , IN, SETUP包的结构:同步域+8位PID+7位地址+4位端点号+5位CRC校验+包结束符EOP
数据包
数据包用来传输数据,分成DATA0. DATA1 。数据格式如下
同步域+8位PID+N个字节的数据+CRC16校验+包结束符EOP
握手包
握手包用来表示一个传输是否被对方确认,有ACK,NAK,STALL,NYET。
ACK:表示正确的接收数据并且有足够的空间容纳数据。主机和设备都可以使用ACK来确认,NAK,STALL,NYET只能够用于设备返回,主机不能使用。
NAK:表示没有数据需要返回,或者数据正确接收但是没有空间容纳。当主机收到NAK后,知道设备还未准备好,主机会在合适的时候重新进行数据传输。
STALL:表示设备无法执行该请求,或者端点已经被挂起。
NYET:USB高速设备中用。
握手包的格式:同步域+8位PID+包结束符EOP
2. 数据包的处理
在传输过程中,具体的处理细节由USB接口的芯片处理完成。
当USB接口芯片正确接收到数据时,如果有空间保存,则它将数据保存并返回ACK,同时,设置一个标志表示已经正确接收到数据;如果没有空间保存数据,则自动返回NAK。
收到输入请求时,如果有数据需要发送,则发送数据,并等待接收ACK。只有到数据成功发送出去(即接收到ACK标志后),它才设置标志,表示数据已成功发送;如果无数据需要发送,则它自动返回NAK。
通常只需根据芯片提供的一些标志,准备要发送的数据到端点,或者从端点读取接收到的数据即可。
二 ,USB事务
虽然USB定义了数据在总线上传输的基本单位是包,为了传输数据,必须按照一定的关系把这些不同的包组织成事务才能传输数据。事务通常由两个或者三个包组成:令牌包、数据包和握手包。
令牌包用来启动一个事务,总是由主机发送;数据包用来传送数据,可以从主机到设备,也可以由设备到主机,方向由令牌包来指定;握手包用来指定数据传输结果。
三,USB传输类型
USB规定了4种传输类型:批量传输、等时传输、中断传输、控制传输。其中前三个传输一次数据都是一个事务;控制传输包括三个过程,建立过程和状态过程分别是一个事务,数据过程则可能包含多个事务。
接下来介绍USB设备的枚举,枚举就是从设备读取各种描述符信息,这样主机就可以根据这些信息来加载合适的驱动,从而知道是什么样的设备,如何进行通信。 枚举过程使用的是控制传输。控制传输可以保证数据的正确性。控制传输分三个过程:建立过程,可选数据过程及状态过程。
下面介绍枚举的详细过程。
USB主机检测到USB设备插入后,就会先对设备复位,并通过一个带数据过程的控制传输完成设备描述符的获取。
第一步,USB主机会往地址0的端点0发送获取设备描述符的标准请求,发送请求属于控制传输的建立过程。建立过程是一个事务。首先是令牌包,即主机发送一个SETUP令牌,令牌的格式如上一篇描述的那样,有令牌的PID,地址和端点号等;其次是数据包,SETUP使用DATA0数据包,数据包中包括标准请求的ID;最后是握手包,设备只能使用ACK来应答,除非出错不应答。下面根据网上找的USB协议分析捕捉的图分析该建立过程。
下面通过STM32官方的USB的例子,自己添加打印信息,查看该控制传输的建立工程中USB主机发送的请求。如上一篇介绍,我们只需根据硬件置的标志位来判断USB传输的状态即可。在usb_istr.c的USB_Istr()函数中,根据中断标志,添加打印信息。在正确传输中断的处理函数CTR_LP()中Setup0_Process()函数表示端点0的建立过程,即上面USB主机复位获取设备描述符将执行的函数。增加打印信息的函数如下:
/*******************************************************************************
* Function Name : Setup0_Process
* Description : Get the device request data and dispatch to individual process.
* Input : None.
* Output : None.
* Return : Post0_Process.
*******************************************************************************/
uint8_t Setup0_Process(void)
{
union
{
uint8_t* b;
uint16_t* w;
} pBuf;
#ifdef STM32F10X_CL
USB_OTG_EP *ep;
uint16_t offset = 0;
ep = PCD_GetOutEP(ENDP0);
pBuf.b = ep->xfer_buff;
#else
uint16_t offset = 1;
pBuf.b = PMAAddr + (uint8_t *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */
#endif /* STM32F10X_CL */
#ifdef USB_DEBUG0
printf("\r\nSETUP0中断-->控制传输.建立过程\r\n");
#endif /* #if USB_DEBUG0 */
if (pInformation->ControlState != PAUSE)
{
#ifdef USB_DEBUG0
printf("设备可以接收新的数据\r\n");
#endif /* USB_DEBUG0 */
pInformation->USBbmRequestType = *pBuf.b++; /* bmRequestType */
pInformation->USBbRequest = *pBuf.b++; /* bRequest */
pBuf.w += offset; /* word not accessed because of 32 bits addressing */
pInformation->USBwValue = ByteSwap(*pBuf.w++); /* wValue */
pBuf.w += offset; /* word not accessed because of 32 bits addressing */
pInformation->USBwIndex = ByteSwap(*pBuf.w++); /* wIndex */
pBuf.w += offset; /* word not accessed because of 32 bits addressing */
pInformation->USBwLength = *pBuf.w; /* wLength */
#ifdef USB_DEBUG0
printf("设备接收数据如下:\r\n");
printf("0x%x ",pInformation->USBbmRequestType);//用于指定请求的 数据传输反向 请求类型 请求的接收者
printf("0x%x ",pInformation->USBbRequest);//标准请求及代码
printf("0x%x ",pInformation->USBwValue0);
printf("0x%x ",pInformation->USBwValue1);//具体见圈圈书P77页
printf("0x%x ",pInformation->USBwIndex0);
printf("0x%x ",pInformation->USBwIndex1);
printf("0x%x ",pInformation->USBwLength1);
printf("0x%x ",pInformation->USBwLength0);
printf("\r\n");
#endif /* USB_DEBUG0 */
}
return Post0_Process();
pInformation->ControlState = SETTING_UP;
if (pInformation->USBwLength == 0)
{
/* Setup with no data stage */
NoData_Setup0();
}
else
{
/* Setup with data stage */
Data_Setup0();
}
return Post0_Process();
}
在打印信息之后直接就让函数返回,使主机得不到ACK应答,下面根据打印信息看下测试情况。
根据打印信息,由于从机没有ACK应答给PC机的请求,在PC机尝试发了3次请求后,就放弃了。可以在PC机的设备管理器看到,在请求打印3次以后出现了unknown device。
关于8个字节的请求代码的具体含义请参照USB协议,或者在《圈圈教你玩USB》里面对照。
以上就是枚举过程获取设备描述符的第一步控制传输的建立过程,主机发送获取描述符的请求,下一篇我们将代码中ACK返回,使主机接收到建立过程的应答,从而进入到数据过程,即设备响应主机的请求,将设备描述符发送给主机。
上一篇介绍到了主机上电复位USB设备,在控制传输的建立过程,发送了8个字节的数据给设备,这8个字节为0x80 0x06 0x00 0x01 0x00 0x00 0x40 0x00,该请求为USB标准设备请求中的GET_DESCRIPTOR请求。0x80表示标准设备请求,数据方向是设备到主机。0x60表示请求类型GET_DESCRIPTOR。0x01表示描述符类型是设备描述符。0x40表示描述符长度。
设备在收到该请求以后,首先进行解析,根据请求中的0x40表示该控制传输有数据过程,因此进入到Data_Setup0()函数。该函数根据请求的不同描述符,执行不同的回调函数
CopyRoutine(),并在DataStageIn()函数中把要发送给主机的描述符填入USB缓冲区,等待USB主机发送IN令牌包。
主机在建立过程最后收到ACK以后,发送IN令牌包,从而进入到数据过程。在CTR_LP()函数中判断是IN0中断后,进入In0_Process()函数。在数据过程将之前填在USB缓冲器的设备描述符发给主机,并等待主机的应答。
主机在确认接收到的设备描述符没有出错后,就会返回一个0数据长度的确认包,即控制传输的状态过程。在CTR_LP()函数中判断是OUT0中断,进入Out0_Process()函数,由于在状态过程,所以调用回调函数Process_Status_OUT()。
下面和上篇一样,对照着USB分析仪捕捉的数据分析获取设备描述符这次控制传输的数据过程和状态过程。
下面通过串口打印信息查看获取设备描述符控制传输过程中的数据包的数据。打印信息如下
至此,USB主机成功获取到设备描述符。打印信息最后可以看到,主机再次复位USB,将进入到设置地址的阶段。
---------------------
作者:qq236106303
来源:CSDN
原文:https://blog.csdn.net/qq236106303/article/details/8179005
版权声明:本文为博主原创文章,转载请附上博文链接!
---------------------
作者:qq236106303
来源:CSDN
原文:https://blog.csdn.net/qq236106303/article/details/8177568
版权声明:本文为博主原创文章,转载请附上博文链接!
---------------------
作者:qq236106303
来源:CSDN
原文:https://blog.csdn.net/qq236106303/article/details/8176994
版权声明:本文为博主原创文章,转载请附上博文链接!
基于STM32的USB枚举过程学习笔记(转)的更多相关文章
- 基于STM32的USB枚举过程学习笔记
源:基于STM32的USB枚举过程学习笔记 基于STM32的USB枚举过程学习笔记(一) 基于STM32的USB枚举过程学习笔记(二) 基于STM32的USB枚举过程学习笔记(三) 基于STM32的U ...
- USB枚举过程的详细流程
USB枚举过程的详细流程 用户将一个USB设备插入USB端口,主机为端口供电,设备此时处于上电状态.主机检测设备.1>Hub使用中断通道将事件报告给Host.2>Host发送Get_Por ...
- 基于jquery的插件turn.js学习笔记
基于jquery的插件turn.js学习笔记 简介 turn.js是一个可以实现3d书籍展示效果的jq插件,使用html5和css3来执行效果.可以很好的适应于ios和安卓等触摸设备. How it ...
- USB Mass Storage学习笔记-STM32+FLASH实现U盘
一.内容概述 采用STM32内部自带USB控制器外加大页NAND FLASH K9F1G08U0A实现一个128M的U盘. 1.STM32的USB控制器 STM32F103的MCU自带USB从控制器 ...
- USB枚举过程
1. 枚举是什么? 枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序.调试USB设备,很重要的一点就是USB的枚举过程,只 ...
- USB 枚举过程详解
Windows 对USB设备的枚举过程流程图如图1所示: 图1 WP8的USB功能只支持一个配置,三个接口,也就是分别有如下的字段: 设备描述符的bNumConfigurations=1, 配置描述符 ...
- USB枚举过程【转】
转自:http://blog.csdn.net/myarrow/article/details/8270029 1. 枚举是什么? 枚举就是从设备读取一些信息,知道设备是什么样的设备,如 ...
- 《自制编程语言--基于C语言 郑钢》学习笔记
<自制编程语言>学习笔记 本仓库内容 <自制编程语言>源码 src/sparrow.tgz <自制编程语言>读书笔记 docs/* <自制编程语言>样章 ...
- 20135202闫佳歆--week 8 进程的切换和系统的一般执行过程--学习笔记
此为个人笔记存档 week 8 进程的切换和系统的一般执行过程 一.进程调度与进程切换 1.不同的进程有不同的调度需求 第一种分类: I/O密集型(I/O-bound) 频繁的进行I/O 通常会花费很 ...
随机推荐
- C# Textbox 自动换行
方法1 使用textbox的AppendText方法 方法2 textBox.ScrollToCaret(); this.textBox.Focus();//获取焦点 this.textBox.Sel ...
- Encode and Decode TinyURL
TinyURL is a URL shortening service where you enter a URL such as https://leetcode.com/problems/desi ...
- 在deepin 15.5中安装vs code并配置c/c++环境
原文地址:https://blog.csdn.net/DefetC/article/details/79946100 参考了以下几篇文章: https://www.zhihu.com/question ...
- git提交忽略某些文件或文件夹
记得第一次用 github 提交代码,node_modules 目录死活传不上去,哈哈哈,后来才知道在 .gitignore 文件里设置了忽略 node_modules 目录上传.是的, .gitig ...
- 微信支付的安全漏洞之XXE
1.场景:国外安全社区公布微信支付官方SDK存在严重漏洞,可导致商家服务器被入侵(绕过支付的效果).目前,漏洞详细信息以及攻击方式已被公开,影响范围巨大(已确认陌陌.vivo因使用该SDK而存在该漏洞 ...
- python中的while循环和for循环
1.while循环 Gif 演示 Python while 语句执行过程 while 语句时还有另外两个重要的命令 continue,break 来跳过循环,continue 用于跳过该次循环,bre ...
- Resharper 详细教程
前言 注:本文部分内容转载自:http://www.cnblogs.com/luminji/p/3285505.html 原文中部分快捷键在8.2版本中不适用,我已改正,并用红色标注出来 在线API: ...
- Taro覆盖iview样式
/* CustomComp.js */ export default CustomComp extends Component { static options = { addGlobalClass: ...
- kvm虚拟化2-qemu-kvm
Kvm 只支持x86 64的硬件虚拟化 要求cpu必须支持硬件虚拟化 HVM Kvm两个组件: 1 kvm.ko模块装入后为/dev/kvm 工作为hypervisor ,在用户空间通过系统调 ...
- [Sublime]Sublime安装以及插件使用
安装直接去官网下载安装了 安装Package Control关于安装Package Control,有两种方法. 一.自动安装 自动安装很方便,网上代码很多.我用的是Sublime Text3,通过V ...