本文转自公众号,欢迎关注
基于DWC2的USB驱动开发-设备类驱动框架 (qq.com)
一.前言
从软件顶层,从数据流的角度来看USB的通讯,我们可以看到主要有两类通讯,一类是”控制”相关,一类是”数据流”相关,前者一般通过控制端点0进行,而后者通过接口绑定的其他端点进行。其实这是一种常用的通讯设计范式,不是USB独有,我们在其他自定义应用协议设计时也可以参考。比如ftp协议,服务器即使用21命令端口建立连接,其他端口传输数据,所以可以看到一些设计哲学都是相通的。
至于控制和数据流其实都是一个逻辑上的通道,管道的概念,不一定要物理区分。比如我们只有一个串口,可以定义串口帧,通过帧头的标志区分,就可以虚拟任意个逻辑管道。类似的USB设备的端点和主机的管道也是同样的概念。
所以我们一定要有顶层思维模式,抽象思维模式,尤其对于USB复杂的应用层协议,一定要理清楚其上层逻辑。在驱动编写时只有摸清其框架,才能进行抽象,才能进行驱动程序的编写。否则一上来就陷入到具体的设备的具体的协议内容中很快就会迷失,驱动也会写的不具备移植性。毕竟每一个设备类的规格书都有100页以上,这么多设备,协议文档就多如牛毛,更不用说里面涉及的各种细节,所以有顶层框架性的理解很重要。比如对于UAC设备我们不需要一上来就去关注音量如何设置,而是先要了解其所有的属性的操作是否有一定的框架即共性,是否可以抽象为编程的数据结构模型,操作模型。否则虽然能直接根据手册,一个字节一个字节解析,但是结果是对于每一个属性都要这样单独解析,代码将不具备通用性,且变得很冗余,不可维护,增加一个属性就需要改代码,这不是驱动的设计方式,当然一些小型的嵌入式系统没有驱动层的考虑有可能也会这么直接做,但是那毕竟是特定应用场景上的。
这一篇我们就从框架上,对我们后面要实现的设备协议栈进行整体设计,主要是考虑好数据结构,和操作模型,至于细节后面边写驱动,边调试设备,边修改优化。
二.框架设计
USB的设计初衷就是功能对应接口,即一个功能对应一个接口,接口里绑定端点,注意这里的端点是抽象概念比如终端和单元这些概念,逻辑上是一样的。
但是随着应用的复杂化和功能需求的多元化,后面出现了多功能设备,比如一个摄像头有视频也有音频既是摄像头也是喇叭也可能是麦克风,那么就需要多个接口来对应多个功能,于是UBS规范添加了IAD接口关联描述符来聚合某个功能的接口。一个功能也不限制于一个接口了,也可能有多个接口,然后一个设备也可以有多个功能。
即由以下简单的拓扑结构
变为了以下更复杂的拓扑结构,多了一层IAD做功能聚合对应一个功能,而IAD下面也可以有多个接口,接口下面有多个端点,注意这里的端点是抽象的概念,也可能是比如UVC里的终端和单元等。
那么看到上述图形第一个想到的概念是什么呢,上述图形就是一个链表结构,一层链接一层。
我们设备类驱动位于哪一层呢,从上可以看到设备类即对应功能那么就是IAD这一层。
那么我们的设备类驱动框架就应该是上图改为如下
我们需要
定义驱动层实例,并提供接口可以绑定类实例
定义类层实例,并提供接口可以绑定接口实例
定义接口层实例,并提供接口可以绑定端口实例
定义端口实例,并提供接口可以绑定属性实例
定义属性实例,比如音量设置对应的CS,数据长度,操作类似是GET还是SET,SET GET回调等
至此恭喜你已经完成设备驱动框架的设计,看起来是多么的简单简洁,这就是抽象的威力,了解USB协议顶层逻辑很容易就抽象出该框架,并没有复杂的思想和逻辑,也不需要使用复杂的技术,要说到技术那么上面使用一个单向链表足矣。
三.数据结构设计
上面我们对框架进行了设计,也就是房屋的框架设计阶段完成了,现在去构建各个构建了,比如类模型就可以对应各个功能区怎么设计,比如地下室,停车场怎么设计,
接口模型则对应具体的功能区内的各个模块的设计,比如停车场如何设计自动闸门,如何设计车位布局,端点模型就对应具体车位的设计了,比如车位大小,标志,附属充电桩,编号等。
每个模型对应的数据结构的属性和行为可能不同,但是有一点相同即都是通过单向链表连接同层实例,并且指向下一层链表。
比如对应接口的设计
具体设计这里就不再讲了,每个人自行设计时考虑,可以后面边写驱动边完善,但是可以肯定的是一定包括以下几个元素:
属性部分
行为部分
指向下一个同层实例的指针
指向下一层实例的链表头指针
比如如下对于设备类数据结构的设计,即包含了上述4部分
/**
* struct usbd_dev_class
* 设备类节点
*/
typedef struct usbd_dev_class {
/* 属性部分 */
uint8_t id;
char* name;
/* 行为部分 */
void (*init)(void *dwc);
void (*deinit)(void *dwc);
void (*setup)(void *dwc, ureq_t setup);
void (*setitf)(void *dwc, ureq_t setup);
/* 同级链接 */
struct usbd_dev_class* next;
/* 下一层链接 */
itf_t *itf_list;
} usbd_dev_class;
四.总结
以上进行了设备类驱动框架性的设计,我们遵循自顶向下的设计思路,先设计框架,=然后再填充框架,当然框架不可能一开始设计的就合理,我们后续实际调试具体的设备时可能发现需要修改,我们迭代即可,但是现在开始就需要考虑可扩展性,以便将来迭代扩展。
审核编辑 黄宇
-
usb
+关注
关注
60文章
7907浏览量
264125 -
驱动开发
+关注
关注
0文章
130浏览量
12067 -
驱动框架
+关注
关注
0文章
14浏览量
4032 -
DWC2
+关注
关注
0文章
35浏览量
120
发布评论请先 登录
相关推荐
评论