打印
[USB驱动]

STM32F4XX USB驱动剖析

[复制链接]
12711|35
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhs2007|  楼主 | 2017-8-24 15:19 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 zhs2007 于 2017-8-24 15:26 编辑

这几年STM32F系列单片机很是流行,本人也用STM32F1XX、STM32F4XX做了几个产品和项目,作为一个从51时代走过来的码农,深感ARM核的强大。
STM32F单片机的成功,我归结为以下几方面:丰富的外设、适中的价格、强大的运算(相比51)、低功耗、良好的生态。
以上这些是本帖的题外话。

下面我就以STM32F4XX做的一个项目为例,说一下我对STM32F4XX USB模块硬件和原厂提供的USB驱动的认识和感受。
1. 先说说STM32F4XX USB硬件,片内有两个USB模块,USB_FS全速模块,USB_HS高速模块,USB_HS模块需要外接ULPI USB PHY,估计是集成的代价较大。这两个模块硬件寄存器相当多,真是个重量级的大家伙,看了都头大。这些寄存器不仅多,而且分布的有点乱,光是名字中含有CFG的就有好几个,相信是有优化的空间的。

2. 原厂提供的USB底层驱动,真的不敢恭维,恕我说的直接一点,就如裹脚布一般又臭又长!
以USB HS DEVICE HID示例来说,相关的C文件有10个,粗略统计这10个C文件中总行数6300行左右(包含注释和空行),头文件懒得去统计了,要想把这些程序完整的梳理一遍,谈何容易啊?我做的项目是用USB_HS模块外接USB3300 PHY芯片做高速HID设备,想在原厂驱动基础上做些修改,真的是太困难了,无从下手。就算改改满足要求了,对于我这样一个略有强迫症的人来说,也很难忍受程序中有那么多不明不白的代码。
原厂USB底层驱动的问题,我总结为以下几点:
(1)文件模块过多。
         并且这些文件功能作用不是很明确,行话叫“内聚不够高”。
(2)结构体嵌套层数过多。
        啥玩意都塞进USB_OTG_CORE_HANDLE结构体中, 啥函数都要传递个USB_OTG_CORE_HANDLE*pdev参数。
(3)函数调用层数过多。
        发送或接收个数据包,最深处应该不下10层函数调用,特别是含有很多函数指针的调用,想调试跟踪一下,简直就像捉迷藏。
(4)函数指针过多。
        我不反对适当的地方用下函数指针作为回调函数,例如有些方案中利用函数指针注册中断或事件处理函数。
        但在STM32F4XX USB驱动中,用了过多的函数指针,并且还将这些函数指针“巧妙地”塞进了一层又一层的结构体中,导致用户很难理解在何时何处调用了这些函数。
(5)基于中断的程序结构。
        基于中断来实现USB底层驱动,这似乎已经成了很多厂商的思维定势。
        这种方式,相当于USB驱动与main()函数主流程是两个并发运行“线程”,那么必然就会带来双线程之间的通信与同步问题,并且造成程序执行流程与状态的复杂。
        从我理解与实践来看,USB DEVICE底层驱动是完全可以不使用中断的,并且也丝毫不会影响通信速度。
        main()函数中每隔几毫秒检查一下,是否有数据包到来,有就处理,没有就该干嘛干嘛,退一步讲,就算有个数据包来了,没有及时处理,也不会引起逻辑错误,最多也就总线上多点NAK罢了,这一点是硬件的基本功能。

3. 我最终还是做了一个艰难的决定,基于硬件寄存器,重写一套USB底层驱动,目标是要简洁、稳定、便于调试。
    重写驱动的过程比较曲折,也发现了一个疑似USB硬件BUG,发邮件给原厂确认,至今杳无音信,NND差评!
    经过将近一个月的奋战,最终还是重写出了一个还算满意的驱动,原厂6000多行的代码,被我变成了600多行,虽说过程痛苦,但后面的项目还都可以用。
    重写的高速USB HID驱动,共包含两个C文件:
    usb_dcd.c (300行左右),负责将硬件寄存器抽象为几个基本函数,主要包含初始化函数、SETUP接收函数、控制接收函数、控制发送函数、INT端点发送函数等。这个模块提供的接口函数中有的是非阻塞的,有的是阻塞的。
    usb_hid.c (300行左右),负责枚举与HID协议相关命令处理,调用SETUP接收函数,根据8字节SETUP包,再调用控制接收函数,或调用控制发送函数。该文件中代码其实只有100行左右,其他为描述符的定义。
    在这个驱动基础上,只需稍加改动,就可以实现键盘、鼠标、MSC等其他协议。

写的比较乱,纯属一家之言,不指望原厂能看到改进,只希望给大家提供一个前车之鉴!



usb.png (13.77 KB )

usb.png
评论
awsdrf 2019-11-6 15:18 回复TA
楼主厉害了 

相关帖子

沙发
毛哥临死前| | 2017-8-26 14:35 | 只看该作者
佩服楼主。。。一直想从底层把USB撸出来,但总感觉太复杂,不敢下手

使用特权

评论回复
板凳
ningling_21| | 2017-8-31 08:44 | 只看该作者
这个必须顶

使用特权

评论回复
地板
insignal| | 2017-9-1 08:39 | 只看该作者
本帖最后由 insignal 于 2017-9-1 08:43 编辑

楼主真牛。
我觉得st提供的lib还算不错,结构、层次很清晰(一定要用source insight去看源码,才能更快的看明白)。我用usb3300+F4**做了一个高速hid+mass storage的composite device,就是在lib基础上修改,感觉还行啊,不是那么麻烦。
虽然我也想过要重写,但是想想这个工作量和时间,还是放弃了。
楼主加油,说不定还能卖给st,让st放到官方的例程里,专治像楼主这样有强迫症的高手,哈哈。

使用特权

评论回复
5
zhs2007|  楼主 | 2017-9-4 13:06 | 只看该作者
insignal 发表于 2017-9-1 08:39
楼主真牛。
我觉得st提供的lib还算不错,结构、层次很清晰(一定要用source insight去看源码,才能更快的看 ...

高手实在不敢当!
我因为有多个项目都需要用到F4+USB3300高速通信,所以就狠狠心重写了一版驱动。
重写后的最大好处是代码量大幅减少,可读性增强,逻辑和层次调用关系更简单,便于定位问题,优化速度。
其中有一个项目是HOST模式外接HUB芯片,原厂驱动中没找到HUB驱动,重写也是无奈之举。

使用特权

评论回复
评论
egfsdgdgd 2018-6-1 14:30 回复TA
楼主,你贴个图片。。。我还以为你会贴源代码。。。还是佩服。 
6
ningzhenhai| | 2017-9-16 23:37 | 只看该作者
楼主好,请教一个问题,楼主有没有研究过,STM32F4的高速主机(MSC类,能够识别U盘的),有没有遇到PING的问题?

使用特权

评论回复
7
zhs2007|  楼主 | 2017-9-19 13:55 | 只看该作者
做过HS MSC,但我没有用PING,直接简单粗暴地OUT重传

使用特权

评论回复
8
wenunit| | 2017-11-14 19:13 | 只看该作者
高手,我用STM32F407的HID,只改了下描述符,改了下数据长度,再把应用代码加到接收和发送函数.其它的基本不动...怕出事都不知道哪的事.

使用特权

评论回复
9
wyz6| | 2017-11-15 12:06 | 只看该作者
高人,希望多多指教

使用特权

评论回复
10
zhs2007|  楼主 | 2017-11-18 15:35 | 只看该作者
如果长期用这芯片做项目,花点时间整理一下驱动还是值得的

使用特权

评论回复
11
584025981| | 2017-11-23 12:29 | 只看该作者
大神!

使用特权

评论回复
12
yxf294832618| | 2018-1-17 13:11 | 只看该作者
真大神

使用特权

评论回复
13
sblpp| | 2018-2-21 09:46 | 只看该作者
必须顶起!

使用特权

评论回复
14
新益昌| | 2018-2-28 17:31 | 只看该作者
大神在哪里工作,大神有换工作的想法么?大神帖子下面的大神们有在深圳做USB驱动开发的么?我们公司急需这方面的人。如果有可以加我QQ,3058528247.

使用特权

评论回复
15
zhs2007|  楼主 | 2018-3-1 20:46 | 只看该作者
新益昌 发表于 2018-2-28 17:31
大神在哪里工作,大神有换工作的想法么?大神帖子下面的大神们有在深圳做USB驱动开发的么?我们公司急需这 ...


感谢各位捧场和鼓励。
如果你有USB方面的项目需求,可以联系我。QQ:3042148716

使用特权

评论回复
16
diaozhe| | 2018-4-24 08:56 | 只看该作者
大神,我目前也在重写F4的USB驱动,但是,目前遇到2个问题,想向你请教一下,还望得到你的回复。
1.OTG_FS_DOEPTSIZx寄存器:
手册描述:要接收 SETUP 数据包,必须将控制 OUT 端点中的 STUPCNT 字段 (OTG_FS_DOEPTSIZx) 编程为非零值。但是又接着说:如果在接 收 SETUP 数据包之前,未将 STUPCNT 字段编程为适当值,模块仍能接收 SETUP 数 据包并使 STUPCNT 字段递减。
好像是也不会因为该寄存器的值影响中断,因为没搞清楚,所以直接忽略了该寄存器的设置,仍然可以顺利枚举
2.OTG_FS_DIEPCTL0 和OTG_FS_DOEPCTL0寄存器:
在USB复位中断中,例程注释了:If the EP is already active don't change the EP Control register.      而IN EP0和OUT EP0默认情况下USBAEP=1,所以,按照注释来讲,并不会设置这2个寄存器。
但是,在枚举完成中断中,USB_OTG_EP0Activate函数又根据枚举速度来设置了DIEPCTL0.MPSIZ。
这2个设置不是相互矛盾的吗?

使用特权

评论回复
17
zhs2007|  楼主 | 2018-4-25 10:41 | 只看该作者
diaozhe 发表于 2018-4-24 08:56
大神,我目前也在重写F4的USB驱动,但是,目前遇到2个问题,想向你请教一下,还望得到你的回复。
1.OTG_FS_ ...

1. 我的程序中将STUPCNT固定设置为3,区别应该不大,可能只有当通信异常情况下,主机连续发多次SETUP包才会有差别,没遇到过。
2. 该改的时候,肯定还是要改的。只要不是只读属性,都可以按照需要修改的。
原厂例程中USB驱动都被写成那样了,又何必在意他这一句注释。

这个OTG CORE中,有用没用的寄存器一大堆,很难将每个寄存器都理解透。

使用特权

评论回复
18
diaozhe| | 2018-4-26 13:00 | 只看该作者
zhs2007 发表于 2018-4-25 10:41
1. 我的程序中将STUPCNT固定设置为3,区别应该不大,可能只有当通信异常情况下,主机连续发多次SETUP包才 ...

精辟

使用特权

评论回复
19
darling心弦| | 2018-4-28 11:08 | 只看该作者
有机会请教大神~~~

使用特权

评论回复
20
xdzys2008| | 2018-6-1 15:00 | 只看该作者
如果需要以太网功能,可以RMII/MII接口PHY 如SR8201F  和USB接口以太网芯片可用SR9x00系列

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:工欲善其事,必先利其器! USB总线协议分析 仪 USB技术服务、技术咨询 QQ:3042148716

3

主题

171

帖子

7

粉丝