没有合适的资源?快使用搜索试试~ 我知道了~
首页AT91RM9200 OHCI USB主机控制器详解:高效稳定实现与接口设计
AT91RM9200 OHCI USB主机控制器详解:高效稳定实现与接口设计
需积分: 1 1 下载量 114 浏览量
更新于2024-07-20
收藏 514KB PDF 举报
本文档详细介绍了如何基于AT91RM9200这颗微处理器实现一个高效的、稳定的USB主机控制器。AT91RM9200是一款集成了USB Host Controller Interface (OHCI) 功能的单片机,它允许系统直接与USB设备进行通信,而无需额外的专用USB控制器。文章的重点在于讲解如何利用AT91RM9200的内部OHCI引擎来管理USB设备,包括寄存器操作、软件接口设计以及USB设备管理。 首先,作者从概述部分介绍了项目背景,强调了对稳定性和效率的需求,同时确保不会影响CPU上的其他程序运行。接着,文章深入探讨了寄存器层面的操作,如启动控制和批量传输、复位、设备连接设置等,这些是USB通信的基础,涉及到数据传输的控制和管理。 OHCI软件接口部分是核心内容,涵盖了OHCI端点、传输描述符、HCCA(硬件控制缓存区)、基本流程以及各种数据结构的设计和操作。作者详细描述了如何使用这些数据结构来组织和执行USB传输,包括控制和批量端口的数据读写,以及中断寄存器的初始化和中断处理机制。 对于USB设备管理,文档涉及了USB设备的命令和请求、标准请求格式、描述符类型及其作用,以及设备枚举过程中的关键步骤。通过设备描述符(如设备、配置、接口和端点),作者解释了如何解析和响应USB设备的请求,从而实现数据的接收和发送。 最后,文档还提供了USB设备相关的数据结构,如设备信息、Setup包结构和常量定义,这些都是实现USB主机控制器功能必不可少的部分。本文旨在帮助读者理解如何充分利用AT91RM9200的硬件特性,构建出一个高效且可靠的USB主机解决方案。整个文档技术性强,适合有经验的开发人员参考或作为教学材料。
资源详情
资源推荐
* USB 端口复位是否结束
* @return 0 – 没有结束,>0 – 结束
*/
short udpIsBusResetOver(void)
{
return pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES;
}
这个地方的代码有点奇怪,明明是对 pUhp 指针操作进行的复位,结果使用 pUdp 指针
判断复位是否成功,时间太久,我也忘了这是怎么回事,估计是当年从例程里面抄过来的。
不过我的上层代码中,调用复位函数后有延时,已经能够确保复位操作是成功的了,因此这
个函数就这样不管了。
2.5 寄存器(设备连接)
读取 USB 设备连接状态
读取 HcRhPortStatus 寄存器可以得到相应 USB 端口是否有设备连接,但是在嵌入式系统
中,为了增强系统的稳定性,要有适当的算法保证在一段时间内,连续读到设备连接或断开,则
才能确定设备的连接状态,下面的函数在定时中断中被调用,用来检测 USB 设备的连接状况:
/**
* 读取 USB 设备连接情况
*/
void ohciReadConState(unsigned short port)
{
ohciConnectState <<= 1;
//读取寄存器,得到当前状态
if (pUhp->UHP_HcRhPortStatus[port] & 0x01)
{
ohciConnectState |= 1;
}
if (ohciConnectState == 0xFF)
{
//设备连接
ohciConnectFlag = 0x55;
}
else if (ohciConnectState == 0x00)
{
//设备断开
ohciConnectFlag = 0x00;
}
}
定时中断为 10ms,上述代码的意思就是连续 80ms 检测到设备连接或者断开,才能修
改设备的连接状态。
2.6 寄存器(其它)
USB 端口关电
对 USB 端口进行关电处理的目的主要有两个,一是安全拔下 U 盘,防止带电插拔造成
数据丢失或错误,另一个是为了再次开电,对 U 盘内部程序进行复位。
/**
* 断开 USB 端口的供电
*/
short ohciHardDisable(void)
{
// Disable port power
pUhp->UHP_HcRhPortStatus[0] = 0x00000001;
pUhp->UHP_HcRhPortStatus[1] = 0x00000001;
// Disable global power
pUhp->UHP_HcRhStatus = 0x00000001;
return 0;
}
清除中断状态
该程序在中断程序中被调用,在 OHCI 规范中,设置中断是通过 HcInterruptEnable 寄
存器来完成的,而产生中断以后,中断状态寄存器(HcInterruptStatus)的对应位就会被设
置为 1,通过查询该寄存器的内容可以得知当前中断产生的原因。
但是如果中断状态寄存器的数据不清除的话,AM9200 就不会产生新的中断,因此在中
断处理程序中需要调用本函数清除中断状态:
/**
* 清除中断状态寄存器的内容,以便能够产生新的中断
*/
short ohciClearIntrStatus(void)
{
pUhp->UHP_HcInterruptStatus = 0xFFFFFFFF;
return 0;
}
说明:按照 OHCI 规范,在中断状态寄存器的相应位写 1,就可以清除对应的中断状态。
3 第三部分 OHCI 软件接口
基于 OHCI 规范的底层控制端口和批量端口读写接口。
3.1 OHCI(端点)
OHCI (Open Host Controller Interface),是康柏、微软、国家半导体等公司共同制定的一
个 USB 主机接口规范,它提供一个更抽象的接口来完成 USB 数据传输工作。
在 OHCI 规范中,最重要的几个概念是端点(EndPoint - ED)、传输描述符(Transport
Descriptor - TD)、主机控制器通信区(HCCA)。其中 ED 负责确定传输类型(控制传输、
批量传输、同步传输和中断传输)。TD 确定传输参数。HCCA 用于确定数据传输是否完毕。
下面对上面的概念进行说明,主要是翻译了 OHCI 规范的相关内容,更详细的内容请参考
《Open Host Controller Interface Specification for USB》 。
端点
ED(Endpoint Descriptor 端点描述符)包含了 HC 所使用的端点的信息,包括端点地址、
传输速度和最大数据包尺寸等内容。另外 ED 还是 TD(传输描述符)链表的锚点。在 ED
里保存该 ED 收发数据所使用的 TD 链表头指针。当 HC 处理 ED 并且发现一个合法的 TD
地址时,HC 根据 ED 内标明的端点以及 TD 的地址完成数据传输。
在 USB 的规范中规定了 4 种数据传输类型:控制传输、批量传输、同步传输和中断传
输。在 OHCI 中对应这 4 种传输类型有 4 个传输 ED 列表,主要使用控制寄存器(HcControl)
和命令状态寄存器(HcCommandStatus)进行控制。
控制和批量传输的 ED 组成列表,每个 ED 下面带着需要进行处理的 TD,ED 包含端点
所允许的最大的包大小,控制器硬件完成包的分割。每次传输后都会更新指向数据缓冲区的
指针,当起始和终止指针相等时,TD 就释放到完成队列(done-queue)。下图是一个典型的链
表结构图。
在 OHCI 中,每一帧的时间被分为 3 块,首先处理批量和端点列表,这段时间由
HcPeriodicStart 寄存器的设置来控制,然后处理周期性列表(中断和同步列表),处理完毕
如果还有时间,则继续处理批量和端点列表,如下图:
对于控制和批量传输来说,控制端点比批量端点有更多的总线处理机会。每处理 1 个批
量端点就需要处理 N 个控制端点,这个 N:1 的比例叫做控制批量服务比例。HCD 通过
HcControl 寄存器的 ControlBulkServiceRatio 字段来设置比例,比例的范围从 1:1 到 4:1。
HC 强制按照控制批量服务比例进行处理,而不考虑相应列表中的控制和批量 ED 的数
量。如果只有 1 个控制 ED 在控制列表中,而控制批量服务比例为 4:1,则在批量 ED 被服
务之前,该控制 ED 被服务 4 次。如果控制或批量列表中没有 ED,HC 就会跳过对应的列
表,而立刻处理其它的列表并且完成需要的 ED 数量。HC 会根据控制批量服务比例继续检
查空列表,如果有新的 ED,就按照该比例进行处理。
3.2 OHCI(传输描述符)
传输描述符(TD)
传输描述符(TD)是系统内存的数据结构,被 HC 用于定义从端点收发数据的缓冲区。
TD 分为 2 个类型:通用 TD 和同步 TD。通用 TD 用于中断、控制和批量端点,同步 TD
用于同步传输。使用两种不同的 TD 类型是因为缓冲区类型的不同。对于 U 盘主机控制器
来说,不使用同步传输。
若干个传输描述符组成队列链接到 ED 上。ED 提供传输 TD 数据所需要的端点地址。
HCD 把 TD 增加到队列中,而 HC 把 TD 从队列中删除。HC
把 TD 从队列删除后,将其链
接到已完成队列,这个过程叫做“释放”。TD 的释放原因包括正常释放和错误释放。当 TD
释放后,释放情况代码被写到 TD 中,以便 HCD 确定释放原因。
TD 是按照顺序进行处理的。它们被链接到 ED 上。TD 队列的第一个 TD 指针放在 ED
的 NextTransferDescriptor 字段,HC 从该 TD 开始处理队列。当 TD 被释放,就会从队
列中删除,该 TD 的 NextTransferDescriptor 字段所指向的下一个 TD 被转移到队列头。
当 HC 处理 ED 的时候,只会产生一个事务。HC 只有在当前 ED 的所有 TD 都处理完毕后
才会产生下一个事务。
在每一个事务完成以后就会更新通用 TD。有 4 个字段会被更新:CompletionCode、
DataToggleControl、CurrentBufferPointer、ErrorCount。
剩余76页未读,继续阅读
阿拉灯神ding
- 粉丝: 47
- 资源: 22
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- C语言快速排序算法的实现与应用
- KityFormula 编辑器压缩包功能解析
- 离线搭建Kubernetes 1.17.0集群教程与资源包分享
- Java毕业设计教学平台完整教程与源码
- 综合数据集汇总:浏览记录与市场研究分析
- STM32智能家居控制系统:创新设计与无线通讯
- 深入浅出C++20标准:四大新特性解析
- Real-ESRGAN: 开源项目提升图像超分辨率技术
- 植物大战僵尸杂交版v2.0.88:新元素新挑战
- 掌握数据分析核心模型,预测未来不是梦
- Android平台蓝牙HC-06/08模块数据交互技巧
- Python源码分享:计算100至200之间的所有素数
- 免费视频修复利器:Digital Video Repair
- Chrome浏览器新版本Adblock Plus插件发布
- GifSplitter:Linux下GIF转BMP的核心工具
- Vue.js开发教程:全面学习资源指南
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功