基于DWC2的USB驱动开发-USB连接详解
一
.
前言
之前一直在阅读手册,规格书,练习招式,学习心法,从这一篇开始我们就要真刀实枪的干了,当然不是一味蛮干。驱动编写,调试,实践的过程会结合阅读规格书,手册,理论结合实践,招式和心法要同步进行。
二
.USB
连接需要几步
?
进行
USB
连接需要几步?我们参考把大象装进冰箱需要几步:第一步打开冰箱门,第二步把大象装入冰箱,第三步关闭冰箱门,完成。
USB
连接同样的简单,第一步插上开发板
USB
接口到电脑,第二步电脑识别到
USB
设备,第三步恭喜你获得一个黄色告警对话框!完美完成!也许很不幸,你没有获得黄色告警对话框,那么就是失败了,后面我们会详细介绍怎么去分析调试。
三
.USB
连接原理
前面我们已经完成了
USB
连接的操作,实践了师傅教的第一招黑虎掏心,
but what
?我干了什么?前面我们说过需要理论结合实践,招式结合心法,招式已经尝试了,但是到底是什么原理呢?到底是怎么做到的呢?那么就要从心法去探究,
USB
江湖的最基础的心法,就是
USB2.0
的规格书。当然招式也有招式的拳谱剑谱,我们这里就对应的使用的
USB
控制器
IP
的规格书
(
这里是新思的
DDC2)
和
PHY
的规格书
(microChip
的
USB334x)
。
我们打开
USB2.0
规格书,翻到
141
页看到如下图,主机
(
或
HUB)
端
D+
和
D-
均由
Rpd=15K
Ω的电阻下拉
,
未接入设备时此时
D+
和
D-
都是
0V
。设备
(
或者下级
HUB)
端通过
D+
或
D-
上拉
Rpu=1.5K
Ω来区分是全速还是低速设备,全速设备
D+
上拉
,
低速设备
D-
上拉。设备端的上拉电阻和主机端下拉电阻分压得到和未接设备时不一样的电平,主机检测该电平即可知道有设备插入,原理就是这么简单,牛逼的武功也往往是很简单,比如六脉神剑也就那么一弹手指。
为什么是上拉
1.5K
呢,因为上拉电阻要保证分压值不小于
VIH
(
min
),因为只有满足该条件才能被识别为高,为什么这个电压能识别为高呢,那就是硬件电气特性决定的了,我喜欢死缠烂打的追问的伙伴,可以继续深挖到收发器,晶体管,半导体
.... ,
如果能追到这一层的那么肯定是孤独求败级别的高手了,膜拜之。
VIH
在规格书中的要求如下至少要为
2V(
可以规格书中搜索找到
)
除了上述要求,上拉电阻还要保证能够在
2.5µs
的最小复位时间内将
D+
或
D-
从
0V
上拉至
VIH
(
min
)
,
因为在复位结束时要进行总线状态评估。
2.5uS
的要求在如下表格中说明
,
即复位最短时间是
2.5uS.
综上要求,
具有可拆卸电缆的设备使用
1.5 kΩ ±5%
电阻器连接到
3.0 V
和
3.6 V
之间的电压源(
VTERM
),以满足这些要求。带有固定电缆的设备可以使用替代端接方式。但是,任何终端的
Thevenin
(
戴维宁
)
电阻必须不小于
900Ω.
注:终端的
Thevenin
(
戴维宁
)
电阻不包括主机
/
集线器上的
15 k
±
5%
的电阻。
上拉电阻器上的电压源必须来源于
USB
电缆上提供的电源或由
USB
电缆上的电源控制,以便在移除
VBUS
时,上拉电阻器不会在其连接的数据线上提供电流。
即
VBUS
断开时上拉也应该断开。
上述表中描述的是针对低速和高速设备连接检测,高速呢,高速设备的连接检测和全速一样,只是后面速度枚举有不同,这个先按下不表,后面再讲解。
四
.USB
连接驱动
驱动编写我们参考控制器
IP
的手册,找到如下寄存器
手册
P529
的
5.4.48 DCTL
,
Offset: 0x804
,
bit1
可以看到默认值是
1
,即默认是断开上拉电阻的,注意这里的逻辑,这个
bit
表示断开连接。
软件写
0
上拉电阻,这样在
DP
或者
DM
上上拉电阻
(
根据速度而定,如何设置速度枚举速度后面再讲
)
,这样主机就可以检测到了。
注意软件操作这个
bit
时不要过于频繁,一般留个
10mS
以上充足的间隔时间,大于上述手册中的描述时间。
注意该位不受控制器软件复位影响。
我们的驱动代码如下,寄存器的操作封装,参考之前的文章,为什么用宏不用结构体,也有专门的文章讲解,可以去瞅瞅。
static void usb_dev_crtl_sft_discon(uint8_t dis)
{
if (dis) {
REG_OTG_DCTL |= DCTL_SOFT_DISCONN;
} else {
REG_OTG_DCTL &= ~(DCTL_SOFT_DISCONN);
}
}
我们之前一直强调,要了解根本原理,不管学习招式还是学习心法,一定要追其核心根本原理。那么这个
bit
写
0
就能上拉,到底是怎么实现的呢,
我们这里操作的是控制器即
LINK
,但是实际工作是由
PHY
去完成的,所以写了这个
bit
之后,
LINK
会通过
PHY
和
LINK
之间的
UTMI
或者
ULPI
接口告诉
PHY
,最终由
PHY
去完成这个上拉工作。于是乎我们去翻阅
PHY
的手册这里是
USB334x
,看到如下图,正是
PHY
将如下上拉电阻拉高来实现连接,至此我们已经了解了整个过程。
但是有好问者,会问那么
LINK
是怎么告诉
PHY
要去上拉电阻的呢,问得很好,高手总是从刨根问底开始的。这个就要了解
UTMI
和
ULPI
协议了,可以参考本系列文章,讲解了
ULPI
协议,甚至讲解了如何使用逻辑分析仪抓包
ULPI
,那么你就可以抓到
ULPI
接口上具体的数据,来调试分析了,比如最终没能上拉,通过
ULPI
抓包可以确定是没有发送到
PHY
还是
PHY
没有执行,进一步缩小范围。
https://mp.weixin.qq.com/s/e4MCpASUXW4oKzfYOdMRwg
https://mp.weixin.qq.com/s/7oTIgxvrui_ZdjCktFo87g
还有更细致的会问,那么这个上拉电阻是所有芯片都会有吗,答案是否,有些芯片是没有的,比如一些
STM32
的
MCU
,这个时候需要外部提供上拉电路,使用
IO
控制。如下
(
网上随便找的一张图
)
,
USB_E
来控制上拉。
五
.
调试
上面我们如果能看到电脑弹出黄色告警的对话框,恭喜你,你已经练就了第一招黑虎掏心。如果不幸没有弹出呢,那么我们就需要进行调试。那么就要派出示波器出来一展身手了。
我们直接使用示波器监控
DP
和
DM
的电平,查看初始是否都为
0
,然后
connect
后
DP
,
DM
是否对应的拉高,拉高的值是否符合要求达到了
VIH
(
min
)。如果没有拉高则从以下方面去分析
:
1.
硬件检查,使用万用表测量
DP DM
到芯片的相应引脚是否联通,测试
DP
,
DM
是否和地或者
VCC
短路。如果外置
PHY
则检查
PHY
是否工作,通过时钟等关键引脚判断。
2.
将
DP DM
配置为普通
IO
,翻转
IO
使用示波器查看硬件连通性。强调下该方式是嵌入式一种常用的测试方法,用于确认
IO
到硬件上是否正常联通,有时还可以使用
IO
做时序分析测试,即在一定的事件发生时翻转
IO
,用示波器测量,这比使用软件定时器和串口打印更精确。多个通道还可以可视化展现相位关系,简单的一招确是调试的大招。
3.
检查
DP DM
是否按照芯片手册配置为了对应的功能,包括输入输出模式,功能选择等,有些芯片可能需要重映射。
4.
检查
USB
相关的初始化是否正确,包括时钟使能,
IO
模块使能,外设模块使能,时钟配置
(
比如
48M
时钟源等
)
,检查模块复位,模块寄存器保护等。回读寄存器确认相应的寄存器是否确实配置成功,回读总是必要的,可靠性编程中需要考虑,写入不一定成功的,芯片也是有出错概率的。
我这里针对 DWC 的 IP ,测试代码如下, 10mS 进行一次断开和连接使用示波器查看
while(1)
{
usb_dev_crtl_sft_discon(0);
iot_timer_delay_ms(10);
usb_dev_crtl_sft_discon(1);
iot_timer_delay_ms(10);
}
我这里是高速模式,示波器测试
DP
波形
(
黄色
)
如下
:
六.总结
以上可以看出
USB
连接原理很简单,就是一个上拉电阻,就好比将大象装进冰箱一样简单。招式虽简单,但是其背后的心法,原理确很重要,细节也很重要。这就是为什么乔峰使出黑虎掏心如此威力巨大,而一些绿林大汉使出来确平平无奇,这是心法和招式理解是否达到了炉火纯晴的地步的区别。
USB
连接也是如此,只是知道上拉,还是知道
LINK
的寄存器如何配置,还是知道
LINK
和
PHY
如何通讯告诉
PHY
去上拉,甚至知道如何去抓包确认,还是知道上拉电阻为什么是
1.5K
有什么要满足的条件,还是知道芯片不带上拉如何去外置上拉等等,都是对应不同的级别。看来一招
USB
连接,一招黑虎掏心也可以分为
18
级,只有练到最高级炉火纯青才能所向披靡,遇
BUG
解
BUG
,遇
fault
杀
fault
。