嵌入式系统usb开发学习概述

本文阐述了嵌入式系统中USB开发的基本思路,强调了理解USB从机开发模型的重要性,介绍了USB协议栈的实现机制及如何在特定硬件平台上移植。文章还对比了USB与fatfs、lwip的开发难度,解析了USB枚举过程,并给出了学习USB开发的建议步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

嵌入式系统usb开发学习概述

如未特别说明, 现阶段学习的usb主要是指usb从机/设备.

简单阅读过一些介绍USB应用基础和协议栈的文档之后, 发现协议栈的内容主要是约定要怎样怎样, 数据包格式啊, 通信机制啊. 但是, 真正落实到MCU上的程序设计时, 首要要搞清楚的是, 哪些工作是由硬件完成的, 那些工作是由软件完成的. 需要软件完成的部分, 可以参考已有的很多优秀且开源的usb协议栈程序, 作为用户来讲, 这部分代码就不需要从头设计编写了, 直接复用就好. 而硬件部分在各个芯片上各有不同, 而当我们需要某个特定的芯片平台上使用usb功能时, 就需要使用具体的usb控制器想方设法满足上层协议栈软件对数据和事件响应的需求, 完成usb协议最终栈的移植.

这里以复杂度相当的文件系统fatfs和以太网协议栈lwip作为类比, 用户在移植时, 只要实现底层简单的读写操作, 并嵌入到协议栈的底层函数中, 中间关于协议栈的复杂机制对于大多数用户来讲都是黑盒子, 用户直接调用协议栈的应用层API就能使用. usb相对于这些协议栈来说, 在底层也比较简单, 但需要明确搞清楚对硬件的需求. 作为一个通信类的协议栈, usb协议栈的基本操作就是传数, 全部数据都是通过"端点"传输的, 而端点在硬件上就是一段内存的缓冲区, 可以向其中写数据(发数), 也可以从中读数据(收数). 另外, usb通信过程中还有一些事件告诉usb协议栈需要分情况处理, 这些事件在硬件上反应在usb的通信包, 有些集成度比较高的usb控制器模块简化了软件判断的工作, 能够使用硬件电路自动检测到这些特殊的通信包, 然后在寄存器上通过一个状态标志位告诉软件, 这样usb的软件部分只要安心处理有效数据的收发就好.

但usb相对于fatfs和lwip相对难学一点的主要原因在于:

  • usb从机开发使用典型的从机开发模型. 基本的usb应用是从机部分, 整个通信过程都是受主机控制, 用户需要编程的从机是需要配合主机进行通信, 主动权不在用户手里, 说白了, 不是平时调程序那样, 想走就走, 想停就停. 这里的应对思路是, 就是要用通信系统的从机开发模型考虑usb的开发过程. 在通信系统的从机开发模型中, 从机不会主动启动通信, 都是被动地在任何可能的时间点接受主机的触发. 这就意味着, 所有的程序执行过程都需要从中断开始. 这样看, 就限定了usb从机编程的基本框架, 对于初学者来说, 至少在阅读现有的usb工程时, 可以找到处理usb实践的入口了. 相似的编程模型可以参考I2C从机.

  • 从机模型通常只能等待主机读或者主机写, 比如u盘设备. 但例如usb键盘这样需要上传给主机数据的设备, 怎样主动向主机发送数据呢? 在usb通信机制中, 至少有两种方法可以处理类似的情况: usb主机会每隔1ms向总线上发一次问询, 问问有没有从机要上报数据, 没错, 这就是轮询; 另一种是远程唤醒, 这是用在低功耗场景中的, 可以以后再看. 所以说, 大体上看, 整个usb系统还是使用轮询机制从从机读数或者写数的, 但具体再usb从机的设计上, 考虑到同时还要执行除usb之外其他的工作, 因此还是将相应主机操作的程序全部放在中断中. 更进一步, 在有些优化的usb协议栈中, 还将usb中断服务程序和多线程结合起来, 紧要的回复先在中断服务程序中进行, 不紧要的处理通过标志位传递给任务中, 让任务慢慢去处理.

  • usb协议栈可以支持多种设备的灵活性. usb的功能不向文件系统那么单一, 它需要支持多种多样的设备, 可以是输入设备的键盘或鼠标, 还可以是输出设备的U盘. usb是通过各种各样的"描述符"让PC识别成不同设备的, 这就是usb的"枚举过程". 其实这个"枚举过程"并没有那么神秘, 在本质上还是传数而已. 我们很多人有使用过LCD屏的经验, 当使用LCD屏之前需要配置一些参数到LCD屏的控制器中, 才能让LCD屏正常工作. usb的"枚举过程"就是向主机初始化的过程, 从机在初始化过程中向主机发送一些信息(或者按照格式填写登记表格), 让主机识别自己, 对应地以特定的模式与本机协同工作. 在初始化到不同的工作模式后, 对应的数据包格式也各自不同. 这些"表格"的格式都有模板, 拿现有的样例程序结合usb协议栈的各种选项表改改, 就能定制自己需要的功能了.

这些就是嵌入式开发者学习usb的基本思路.

建议的学习方式是:

  1. 不要一开始就啃usb协议栈, 可以先了解一些usb的基本概念, 科普一下.
  2. 然后仔细看看自己选用硬件平台上的usb控制器有什么功能, 能够实现哪些基本操作.
  3. 找一款自己倾向的usb协议栈实现代码, 作为usb纯软件部分的框架(这部分代码没必要自己再敲一遍), 最好应用例程比较丰富, 便于自己后期修改.
  4. 想方设法将自己的硬件平台同软件组件对接上.
  5. usb应用层的部分与硬件完全无关, 可以用选用的usb协议栈自带的程序验证一下. 大多数情况下, 到这一步就能够满足绝大多数初学者的应用需求了, 例如hid鼠标键盘, cdc串口, msd大容量存储设备等, 再复杂一点就是复合类, 也有不少usb协议栈的实现提供了样例程序.
  6. 阅读自己移植好的代码, 再看usb协议栈的文档, 尝试定制自己的功能. 例如, 改改设备设备的字符串, 或者定制更复杂的设备等等.

End

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值