2.1 LM3S处理器简介
Luminary Micr公司Stellaris所提供一系列的微控制器是首款基于Cortex-m3的控制器,它们为对成本尤其敏感的嵌入式微控制器应用方案带来了高性能的32位运算能力。 这些具备领先技术的芯片使用户能够以传统的8位和16位器件的价位来享受32位的性能,而且所有型号都是以小占位面积的封装形式提供。
<ignore_js_op>
Stellaris系列芯片能够提供高效的性能、广泛的集成功能以及按照要求定位的选择,适用于各种关注成本并明确要求具有的过程控制以及连接能力的应用方案。LM3S3000、LM3S5000系列, 支持最大主频为50 MHz,128 KByte FLASH,32~64 KByte SRAM,LQFP-64/LQFP-100封装,集成CAN控制器、睡眠模块、正交编码器、ADC、带死区PWM、温度传感器、模拟比较器、UART、SSI、通用定时器,I2C、CCP、DMA控制器等外设,芯片内部固化驱动库,支持USB Host/Device/OTG功能,可运行在全速和低速模式,它符合USB2.0标准,包含挂起和唤醒信号。它包含32个端点,其中包含2个用于控制传输的专用连接端点(一个用于输入,一个用于输出),其他30个端点带有可软件动态定义大小的FIFO并以支持多包队列。FIFO支持µDMA,可有效降低系统资源的占用。USB Device启动方式灵活,可软件控制是否在启动时连接。USB控制器遵从OTG标准的会话请求协议(SRP)和主机协商协议(HNP)。
Stellaris USB模块特性:
a.符合USB-IF认证标准
b.支持USB 2.0 全速模式(12 Mbps) 和低速模式(1.5 Mbps)
c.集成PHY
d.传输类型:控制传输(Control),中断传输(Interrupt),批量传输(Bulk),等时传输(Isochronous)
e.32端点:1个专用的输入控制端点和1个专用输出控制端点;15个可配置的输入端点和15个可配置的输出端点。
f.4 KB专用端点内存空间:可支持双缓存的1023字节最大包长的等时传输。
g.支持VBUS 电压浮动(droop)和有效ID检测,并产生中断信号
h.高效传输µDMA :用于发送和接收的独立通道多达3个输入端点和3个输出端点,当FIFO中包含需要的大量数据时,触发通道请求。
本书主要讲Stellaris USB处理器的相关使用与USB协议,有关LM3S系列处理器其它外设操作与使用请参考《嵌入式系统原理与应用—基于Cortex-m3和uc/os-II》,ISBN:978564709310,电子科技大学出版社。
2.2 Stellaris USB模块
<ignore_js_op>
USB模块框图
一些USB控制器的信号是GPIO的复用功能,这些管脚在复位时默认设置为GPIO信号。当需要使用USB功能时,应将相关GPIO备选功能选择寄存器(GPIOAFSEL)中的AFSEL 位置位,表示启用GPIO的备选功能;同时还应将括号内的数字写入GPIO端口控制寄存器(GPIOCTRL)的PMCn位域,表示将USB信号分配给指定的GPIO管脚。USB0VBUS和USB0ID信号通过清除GPIO数字使能寄存器(GPIODEN)中相应的DEN位来配置。关于配置GPIO的详细信息,请参阅《嵌入式系统原理与应用—基于Cortex-m3和uc/os-II》(ISBN:978564709310,电子科技大学出版社)及相关数据手册。
当用于OTG模式时,由于USB0VBUS和USB0ID是USB专用的管脚,不需要配置,直接连接到USB连接器的VBUS和ID信号。如果USB控制器专用于主机或设备,USB通用控制和状态寄存器(USBGPCS)中的DEVMODOTG和DEVMOD位用于连接USB0VBUS和USB0ID到内部固定电平,释放PB0和PB1管脚用于通用GPIO。当用作自供电的设备时,需要监测VBUS值,来确定主机是否断开VBUS,从而禁止自供电设备D+/D-上的上拉电阻。此功能可通过将一个标准GPIO连接到VBUS实现。
2.2.1 功能描述
在管脚USB0RBIAS和地之间需要接一个1%精度的9.1 kΩ电阻,且该电阻离USB0RBIAS管脚越近越好。由于损耗在该电阻上的功率很小,可以采用贴片电阻。Stellaris USB支持OTG标准的回话请求协议(SRP)和主机协商协议(HNP),提供完整的OTG协商。回话请求协议(SRP)允许连接在USB线缆B端的B类设备向连接在A端的A类设备发出请求,通知A类设备打开VBUS 电源。主机协商协议(HNP)用于在初始会话请求协议提供供电后,决定USB线缆哪端的设备作为USB Host主控制器。当连接到非OTG外设或设备时,OTG控制器可以探测出线缆的另一端接入是USB Host主机还是Device设备,并通过一个寄存器指示OTG运行在Host主机还是Device设备角色,上述过程是USB控制器自动完成的。基于这种自动探测机制,系统使用A类/B类连接器取代AB类连接器,可支持与另外的OTG设备完整的OTG协商。
另外,USB控制器支持接入非OTG外设或Host主控制器。它可以被设置为专用于Host或Device功能,此时USB0VBUS和USB0ID管脚可被设置作为的GPIO口使用。当USB控制器被用作自供电的Device时,必须将VBUS接到GPIO或模拟比较器的输入,在VBUS掉电时产生中断,用于关闭USB0DP的上拉电阻。
注意: 当使用USB模块时,系统必须运行在20MHz频率或以上。
2.2.2 作为设备
USB控制器作为USB设备(Device)操作时,输入事务通过使用端点的发送端点寄存器,由端点的发送接口进行控制。输出事务通过使用端点的接收端点寄存器,由端点的接收接口进行控制。当配置端点的FIFO大小时,需要考虑最大数据包大小。
a.批量传输:批量端点的FIFO可配置为最大包长(最大64字节),如果使用双包缓存,则需要配置为2倍于最大包长大小(后面的章节将详细描述)。
b.中断传输:中断端点的FIFO可配置为最大包长(最大64字节),如果使用双包缓存,则需要配置为2倍于最大包长大小。
c.等时传输:等时端点的FIFO比较灵活,最大支持1023字节。
d.控制传输:USB设备可能指定一个独立的控制端点,但在大多数情况,USB设备使用USB控制器的端点0作为专用的控制端点。
① 端点
USB控制器作为设备运行时,提供两个专用的控制端点(输入和输出)和用于与主机通讯的30个可配置的端点(15输入和15输出) 。端点的端点号和方向与对应的相关寄存器有直接联系。比如,当主机发送到端点1,所有的配置和数据存在于端点1发送寄存器接口中。端点0是专用的控制端点,用于枚举期间的端点0的所有控制传输或其他端点0的控制请求。端点0使用USB控制器FIFO内存(RAM)的前64字节,此内存对于输入事务和输出事务是共享的。其余30个端点可配置为控制端点、批量端点、中断端点或等时端点。他们应被作为15个可配置的输入端点和15个可配置的输出端点来对待。这些成对的端点的输入和输出端点不需要必须配置为相同类型,比如端点对(endpoint pairs)的输出部分可以设置为批量端点,而输入部分可以设置为中断端点。每个端点的FIFO的地址和大小可以根据应用需求来修改。
② 输入事务
输入事务是相对主机而言的,输入事务的数据通过发送端点的FIFO来处理。15个可配置的输入端点的FIFO大小由USB发送FIFO起始地址寄存器(USBTXFIFOADD)决定,传输时发送端点FIFO中的最大数据包大小可编程配置,该大小由写入该端点的USB端点n最大发送数据寄存器 (USBTXMAXPn)中的值决定,USBTXMAXPn值不能大于FIFO的大小。端点的FIFO可配置为双包缓存或单包缓存,当双包缓存使能时, FIFO中可缓冲两个数据包,这需要FIFO至少为两个数据包大小。当不使用双包缓存时,即使数据包的大小小于FIFO大小的一半,也只能缓冲一个数据包。
单包缓冲:如果发送端点FIFO的大小小于该端点最大包长的两倍时(由USB发送动态FIFO大小寄存器USBTXFIFOSZ设定),只能使用单包缓冲,在FIFO中缓冲一个数据包。当数据包已装载到TXFIFO中时,USB端点n发送控制和状态低字节寄存器USBTXCSRLn中的TXRDY位必须被置位,如果USB端点n发送控制和状态高字节寄存器USBTXCSRHn中的AUTOSET位被置1,TXRDY位将在最大包长的包装载到FIFO中时自动置位;如果数据包小于最大包长,位TXRDY必须手动置位。当TXRDY位被手动或自动置1时,表明要发送的数据包已准备好。如果数据包成功发送,TXRDY位和FIFONE位将被清0,同时产生相应的中断信号,此时下一包数据可装载到FIFO中。
双包缓存:如果发送端点FIFO的大小至少两倍于该端点最大包长时,允许使用双包缓存,FIFO中可以缓冲两个数据包。当数据包已装载到TXFIFO中时,USBTXCSRLn中的TXRDY位必须被置位,如果寄存器USBTXCSRHn中的AUTOSET位被置1,TXRDY位将在最大包长的包装载到FIFO中时自动置位;如果数据包小于最大包长,位TXRDY必须手动置位。当TXRDY位被手动或自动置1时,表明要发送的数据包已准备好。在装载完第一个包后,TXRDY位立即清除,同时产生中断信号;此时第二个数据包可装载到TXFIFO中,TXRDY位重新置位(手动或自动),此时,两个要发送的包都已准备好,如果任一数据包成功发送,TXRDY位和FIFONE位将被清0,同时产生相应的发送端点中断信号,此时下一包数据可装载到TXFIFO中。寄存器USBTXCSRLn中的FIFONE位的状态表明此时可以装载几个包,如果FIFONE位置1,表明FIFO中还有一个包未发送,只能装载一个数据包;如果FIFONE位为0,表明FIFO中没有未发送的包,可以装载两个数据包。
如果USB发送双包缓存禁止寄存器USBTXDPKTBUFDIS中的EPn位置位,相应的端点禁止双包缓存。此位缺省为置1,需要使能双包缓存时必须清0该位。
③ 输出事务
输出事务是相对主机而言的,输出事务的数据通过接收端点的FIFO来处理。15个可配置的输出端点的FIFO大小由USB接收FIFO起始地址寄存器(USBRXFIFOADD)决定,传输时接收端点FIFO中的最大数据包大小可编程配置,该大小由写入该端点的USB端点n最大接收数据寄存器 (USBRXMAXPn)中的值决定。端点的FIFO可配置为双包缓存或单包缓存,当双包缓存使能时FIFO中可缓冲两个数据包。当不使用双包缓存时,即使数据包的大小小于FIFO大小的一半,也只能缓冲一个数据包。
单包缓存:如果接收端点FIFO的大小小于该端点最大包长的两倍时,只能使用单包缓冲,在FIFO中缓冲一个数据包。当数据包已接收到RXFIFO中时,USB端点n接收控制和状态低字节寄存器USBRXCSRLn中的RXRDY和FULL位置位,同时发出相应的中断信号,表明接收FIFO中有一个数据包需要读出。当数据包从FIFO中读出时,RXRDY位必须被清0以允许接收后面的数据包,同时向USB主机发送确认信号。如果USB端点n接收控制和状态高字节寄存器USBRXCSRHn中的AUTOCl位被置1,RXRDY和FULL位将在最大包长的包从FIFO中读出时自动清0;如果数据包小于最大包长,位RXRDY必须手动清0。
双包缓存:如果接收端点的FIFO大小不小于该端点的最大包长的2倍时,可以使用双缓冲机制缓存两个数据包。当第一个数据包被接收缓存到RXFIFO,寄存器USBRXCSRLn中的RXRDY位置位,同时产生相应的接收端点中断信号,指示有一个数据包需要从RXFIFO中读出。当第一个数据包被接收时,寄存器USBRXCSRLn的FULL位不置位,该位只有在第二个数据包被接收缓存到FIFO时才置位。当从FIFO从读出一个包时,RXRDY位必须清0以允许接收后面的包。如果USB端点n接收控制和状态高字节寄存器USBRXCSRHn中的AUTOCl位被置1,RXRDY位将在最大包长的包从FIFO中读出时自动清0;如果数据包小于最大包长,RXRDY位必须手动清0。当RXRDY位清0时,FULL位为1,USB控制器先清除FULL位,然后再置位RXRDY位,表明FIFO中的另一个数据包等待被读出。
如果USB接收双包缓存禁止寄存器USBRXDPKTBUFDIS中的EPn位置位,相应的端点禁止双包缓存。此位缺省为置1,需要使能双包缓存时必须清0该位。
④ 调度
传输事务由Host主机控制器调度决定,Device设备无法控制事务调度。设备等待Host主控制器发出请求,随时可建立传输事务。当传输事务完成或由于某些原因被终止时,会产生中断信号。当Host主控制器发起请求,而Device设备还没有准备好,设备会返回一个NAK忙信号。
⑤ 设备挂起(SUSPEND)
USB总线空闲达3ms时,USB控制器自动进入挂起(SUSPEND)模式。如果USB中断使能寄存器USBIE中使能挂起(SUSPEND)中断,此时会发出一个中断信号。当USB控制器进入挂起模式,USB PHY也将进入挂起模式。当检测到唤醒(RESUME)信号时,USB控制器退出挂起模式,同时使USB PHY退出挂起模式,此时如果唤醒中断使能,将产生中断信号。设置USB电源寄存器USBPOWER中的RESUME位同样可以强制USB控制器退出挂起模式。当此位置位,USB控制器退出挂起模式,同时在总线上发出唤醒信号。RESUME位必须在10ms(最大15ms)后清0来结束唤醒信号。为满足电源功耗需求,LM3S USB控制器可进入深睡眠模式。
⑥ 帧起始
当USB控制器运行在设备模式,它每1ms收到一次主机发出的帧起始包(SOF)。当收到SOF包时,包中包含的11位帧号写入USB帧值寄存器USBFRAME中,同时发出SOF中断信号,由应用程序处理。一旦USB控制器开始收到SOF包,它将预期每1ms收到1次。如果超过1.00358ms没有收到SOF包,将假定此包丢失,寄存器USBFRAME也将不更新。当SOF包重新成功接收时,USB控制器继续,并重新同步这些脉冲。
使用SOF中断可以每1ms获得一个基本时钟,可当tick使用,并且使用方便。后面会有重要应用。
⑥ USB复位
当USB控制器处于设备模式,如果检测到USB总线上复位信号,USB控制将自动:清除寄存器USBFADDR,清除USB端点索引寄存器(USBEPIDX),清空所有端点FIFO,清除所有控制/状态寄存器,使能所有端点中断,产生复位中断信号。刚接入到主机的USB设备,USB复位意味着要进行枚举了。
2.2.3 作为主机
当Stellaris USB控制器运行在主机模式时,可与其他USB设备的点对点通讯,也可用于连接到集线器,与多个设备进行通讯。USB控制器支持全速和低速设备。它自动执行必要的事务传输,允许USB 2.0集线器使用低速设备和全速设备。支持控制传输、批量传输、等时传输和中断传输。输入事务由端点的接收接口进行控制;输出事务使用端点的发送端点寄存器。当配置端点的FIFO大小时,需要考虑最大数据包大小。
① 端点
端点寄存器用于控制USB端点接口,通过接口可与设备进行通讯。主机端点由1个专用控制输入端点、1个专用控制输出端点、15个可配置的输出端点和15个可配置的输入端点组成。控制端点只能与设备的端点0进行控制传输,用于设备枚举或其他使用设备端点0的控制功能。控制端点输入输出事务共享一个FIFO存储空间,并在FIFO的前64字节。其余输入和输出端点可配置为:控制传输端点、批量传输端点、中断传输端点或等时传输端点。输入和输出控制有成对的三组寄存器,它们可以与不同类型的端点以及不同设备的不同端点进行通讯。例如,第一对端点可分开控制,输出部分与设备的批量输出端点1通讯,同时输入部分与设备的中断端点2通讯。FIFO的地址和大小可以软件设置,并且可以指定用于某一个端点输入或者输出传输。
无论点对点通信还是集线器通信,在访问设备之前,必须设置端点n的接收功能地址寄存器USBRXFUNCADDRn和端点n的发送功能地址寄存器USBTXFUNCADDRn。LM3S 系列USB控制器支持通过集线器连接设备,一个寄存器就可以实现,该寄存器说明集线器地址和每个传输的端口。在本书中的所有例程都未使用集线器访问设备。
② 输入事务
输入事务,相对主机而言是数据输入,与设备输出事务类似的,但传输数据必须通过设置寄存器USBCSRL0中的REQPKT位开始,向事务调度表明此端点存在一个活动的传输。此时事务调度向目标设备发送一个输入令牌包。当主机RXFIFO中接收到数据包时,寄存器USBCSRL0的RXRDY位置位,同时产生相应的接收端点中断信号,指示RXFIFO中有数据包需要读出。
当数据包被读出时,RXRDY位必须清0。寄存器USBRXCSRHn中的AUTOCL位可用于当最大包长的包从RXFIFO中读出时将RXRDY位自动清0。寄存器USBRXCSRHn中的AUTORQ位用于当RXRDY位清0时将REQPKT位自动置位。AUTOCL和AUTORQ位用于µDMA访问,在主处理器不干预时完成批量传输。
当RXRDY位清0时,控制器向设备发送确认信号。当传输一定数据包时,需要将端点n的USBRQPKTCOUNTn寄存器配置为要传输包数量,每一次传输, USBRQPKTCOUNTn寄存器中的值减1,当减到0时,AUTORQ位清0来阻止后面试图进行的数据传输。如传输数量未知, USBRQPKTCOUNTn寄存器必须清0,AUTORQ位保持置位,直到收到结束包,AUTORQ位才清0 (小于USBRXMAXPn寄存器中的MAXLOAD值) 。
用图表示传输过程序。
③ 输出事务
当数据包装载到TXFIFO中时, USBTXCSRLn寄存器中的TXRDY位必须置位。如果置位了USBTXCSRHn寄存器中的AUTOSET位,当最大包长的数据包装载到TXFIFO中时,TXRDY位自动置位。此外,AUTOSET位与µDMA控制器配合使用,可以在不需要软件干预的情况下完成批量传输。
④ 调度
调度由USB主机控制器自动处理。中断传输可以是每1帧进行一次,也可以每255帧进行一次,可以在1帧到255之间以1帧增量调度。批量端点不允许调度参数,但在设备的端点不响应时,允许NAK超时。等时端点可以在每1帧到每216帧之间调度(2的幂)。
USB控制器维持帧计数,并发送SOF包,SOF包发送后,USB主机控制器检查所有配置好的端点,寻找激活的传输事务。REQPKT位置位的接收端点或TXRDY或FIFONE位置位的发送端点,被视为存在激活的传输事务。
如果传输建立在一帧的第一个调度周期,而且端点的间隔计数器减到0,则等时传输和中断传输开始。所以每个端点的中断传输和等时传输每N帧才发生一次,N是通过USB主机端点n 的USBTXINTERVALn寄存器或USB主机端点n的USBRXINTERVALn寄存器设置的间隔。
如果在帧中下一个SOF包之前有足够的提供足够的时间完成传输,则激活的批量传输立即开始。如果传输需要重发时(例如,收到NAK或设备未响应),需要在调度器先检查完其他所有端点是否有激活的传输之后,传输才能重传。这保证了一个发送大量NAK响应的端点不阻塞总线上的其他传输正常进行。
⑤ USB集线器
以下过程只适用于USB2.0集线器的主机。当低速设备或全速设备通过USB 2.0集线器连接到USB主机时,集线器地址和端口信息必须记录在相应的USB端点n的USBRXHUBADDRn寄存器和USB端点n的USBRXHUBPORTn寄存器或者USB端点n的USBTXHUBADDRn寄存器和USB端点n的USBTXHUBPORTn寄存器。
此外,设备的运行速度(全速或低速)必须记录在USB端点0的USBTYPE0寄存器,和设备访问主机USB端点n的USBTXTYPEn寄存器,或者主机USB端点n的USBRXTYPEn寄存器。
对于集线器通讯,这些寄存器的设置记录了USB设备当前相应端点的配置。为了支持更多数量的设备,USB主机控制器允许通过更新这些寄存器配置来实现。
2.2.4 OTG模式
OTG就是On The Go,正在进行中的意思,可以进行“主机与设备”模式切换。USB OTG允许使用时才给VBUS上电,不使用USB总线时,则关断VBUS 。VBUS由总线上的A设备提供电源。OTG控制器通过PHY采样ID输入信号分辨A设备和B设备。ID信号拉低时,检 测到插入A设备(表示OTG控制器作为A设备角色);ID信号为高时,检测到插入B设备(表示OTG控制器作为B设备角色)。注意当在OTG A和OTG B之间切换时,控制器保留所有的寄存器内容。关于OTG使用不在本书重点介绍。
2.3 寄存器描述
使用USB处理器进行USB主机、设备开发离不开相关寄存器操作,USB本身就相当复杂,寄存器相当多,下面就几个常用的寄存器进行介绍。本节主要讲主机与设备模式下的寄存器使用,关于GTO模式下寄存器使用不具体讲解,因为GTO A设备相当于主机,GTO B设备相当于设备。USB寄存器如下表:
寄存器名称 | 类型 | 复位值 | 寄存器描述 |
USBFADDR | R/W | 0x00 | USB地址 |
USBPOWER | R/W | 0x20 | USB电源 |
USBTXIS | RO | 0x0000 | 发送中断状态 |
USBRXIS | RO | 0x0000 | 接收中断状态 |
USBTXIE | R/W | 0xFFFF | 发送中断使能 |
USBRXIE | R/W | 0xFFFE | 接收中断使能 |
USBIS | RO | 0x00 | USB处理模块中断状态 |
USBIE | R/W | 0x06 | USB处理模块中断使能 |
USBFRAME | RO | 0x0000 | USB帧值 |
USBEPIDX | R/W | 0x00 | 端点索引 |
USBTEST | R/W | 0x00 | 测试模式 |
USBFIFOn | R/W | 0x0000.0000 | 端点n FIFO |
USBDEVCTL | R/W | 0x80 | 设备控制 |
USBTXFIFOSZ | R/W | 0x00 | 动态TXFIFO大小 |
USBRXFIFOSZ | R/W | 0x00 | 动态RXFIFO大小 |
USBTXFIFOADD | R/W | 0x0000 | 动态TXFIFO起始地址 |
USBRXFIFOADD | R/W | 0x0000 | 动态RXFIFO起始地址 |
USBCONTIM | R/W | 0x5C | USB连接时序 |
USBVPLEN | R/W | 0x3C | USB OTG VBUS脉冲时序 |
USBFSEOF | R/W | 0x77 | USB全速模式下最后的传输与帧结束时序 |
USBLSEOF | R/W | 0x72 | USB低速模式下最后的传输与帧结束时序 |
USBTXFUNCADDRn | R/W | 0x00 | 发送端点n功能地址 |
USBTXHUBADDRn | R/W | 0x00 | 发送端点n集线器(Hub)地址 |
USBTXHUBPORTn | R/W | 0x00 | 发送端点n集线器(Hub)端口 |
USBRXFUNCADDRn | R/W | 0x00 | 接收端点n功能地址(n不为0) |
USBRXHUBADDRn | R/W | 0x00 | 接收端点n集线器(Hub)地址(n不为0) |
USBRXHUBPORTn | R/W | 0x00 | 接收端点n集线器(Hub)端口(n不为0) |
USBCSRL0 | W1C | 0x00 | 端点0控制和状态低字节 |
USBCSRH0 | W1C | 0x00 | 端点0控制和状态高字节 |
USBCOUNT0 | RO | 0x00 | 端点0接收字节数量 |
USBTYPE0 | R/W | 0x00 | 端点0类型 |
USBNAKLMT | R/W | 0x00 | USB NAK限制 |
USBTXMAXPn | R/W | 0x0000 | 发送端点n最大传输数据 |
USBTXCSRLn | R/W | 0x00 | 发送端点n控制和状态低字节 |
USBTXCSRHn | R/W | 0x00 | 发送端点n控制和状态高字节 |
USBRXMAXPn | R/W | 0x0000 | 接收端点n最大传输数据 |
USBRXCSRLn | R/W | 0x00 | 接收端点n控制和状态低字节 |
USBRXCSRHn | R/W | 0x00 | 接收端点n控制和状态高字节 |
USBRXCOUNTn | RO | 0x0000 | 端点n接收字节数量 |
USBTXTYPEn | R/W | 0x00 | 端点n主机发送配置类型 |
USBTXINTERVALn | R/W | 0x00 | 端点n主机发送间隔 |
USBRXTYPEn | R/W | 0x00 | 端点n主机配置接收类型 |
USBRXINTERVALn | R/W | 0x00 | 端点n主机接收巡检间隔 |
USBRQPKTCOUNTn | R/W | 0x0000 | 端点n块传输中请求包数量 |
USBRXDPKTBUFDIS | R/W | 0x0000 | 接收双包缓存禁止 |
USBTXDPKTBUFDIS | R/W | 0x0000 | 发送双包缓存禁止 |
USBEPC | R/W | 0x0000.0000 | USB外部电源控制 |
USBEPCRIS | RO | 0x0000.0000 | USB外部电源控制原始中断状态 |
USBEPCIM | R/W | 0x0000.0000 | USB外部电源控制中断屏蔽 |
USBEPCISC | R/W | 0x0000.0000 | USB外部电源控制中断状态和清除 |
USBDRRIS | RO | 0x0000.0000 | USB设备唤醒(RESUME)原始中断状态 |
USBDRIM | R/W | 0x0000.0000 | USB设备唤醒(RESUME)中断屏蔽 |
USBDRISC | W1C | 0x0000.0000 | USB设备唤醒(RESUME)中断状态和清除 |
USBGPCS | R/W | 0x0000.0000 | USB通用控制和状态 |
USBVDC | R/W | 0x0000.0000 | VBUS浮动控制 |
USBVDCRIS | RO | 0x0000.0000 | VBUS浮动控制原始中断状态 |
USBVDCIM | R/W | 0x0000.0000 | VBUS浮动控制中断屏蔽 |
USBVDCISC | R/W | 0x0000.0000 | VBUS浮动控制中断状态\清除 |
USBIDVRIS | RO | 0x0000.0000 | ID有效检测原始中断状态 |
USBIDVIM | R/W | 0x0000.0000 | ID有效检测中断屏蔽 |
USBIDVISC | R/W1C | 0x0000.0000 | ID有效检测中断状态与清除 |
USBDMASEL | R/W | 0x0033.2211 | DMA选择 |
表1. USB寄存器
2.3.1 控制状态寄存器
USBFADDR,设备地址寄存器。包含7位设备地址,将通过SET ADDRESS(USBREQ_SET_ADDRESS)请求收到的地址(pUSBRequest->wValue值)写入该寄存器。USBFADDR寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
8 | 保留 | RO | 0 | 保持不变 |
[7:0] | FUNCADDR | R/W | 0 | 设备地址 |
表2. USBFADDR寄存器
例如,在枚举时会用到设置USB设备地址:
void USBDevAddrSet(unsigned long ulBase, unsigned long ulAddress)
{
HWREGB(ulBase + USB_O_FADDR) = (unsigned char)ulAddress;
}
其中ulBase为设备基地址,LM3S USB处理器一般只有一个USB模块,所以只有USB0_BASE(0x40050000);ulAddress为主机USBREQ_SET_ADDRESS请求命令时tUSBRequest.wValue值。
USBPOWER,USB电源控制寄存器,8位。主机模式下,USBPOWER寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:4] | 保留 | RO | 0x02 | 保持不变 |
3 | RESET | R/W | 0 | 总线复位 |
2 | RESUME | R/W | 0 | 总线唤醒,置位后20mS后软件清除 |
1 | SUSPEND | R/W1S | 0 | 总线挂起 |
0 | PWRDNPHY | R/W | 0 | PHY掉电 |
表2. USBPOWER寄存器
USBPOWER,USB电源控制寄存器,8位。设备模式下,USBPOWER寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[5:4] | 保留 | RO | 0x02 | 保持不变 |
7 | ISOUP | R/W | 0 | ISO传输时,TXRDY置位时,收到输入令牌包,将发送0长度的数据包。 |
6 | SOFTCONN | R/W | 0 | 软件连接/断开USB |
3 | RESET | RO | 0 | 总线复位 |
2 | RESUME | R/W | 0 | 总线唤醒,置位后10mS后软件清除 |
1 | SUSPEND | RO | 0 | 总线挂起 |
0 | PWRDNPHY | R/W | 0 | PHY掉电 |
表3. USBPOWER寄存器
#define USB_POWER_ISOUP 0x00000080 // Isochronous Update
#define USB_POWER_SOFTCONN 0x00000040 // Soft Connect/Disconnect
#define USB_POWER_RESET 0x00000008 // RESET Signaling
#define USB_POWER_RESUME 0x00000004 // RESUME Signaling
#define USB_POWER_SUSPEND 0x00000002 // SUSPEND Mode
#define USB_POWER_PWRDNPHY 0x00000001 // Power Down PHY
例如:在主机模式下,把USB总线挂起。
void USBHostSuspend(unsigned long ulBase)
{
//ulBase为设备基地址
HWREGB(ulBase + USB_O_POWER) |= USB_POWER_SUSPEND;
}
例如:在主机模式下,复位USB总线。
void USBHostReset(unsigned long ulBase, tBoolean bStart)
{
//ulBase为设备基地址,bStart确定复位开始/结束。
if(bStart)
{
HWREGB(ulBase + USB_O_POWER) |= USB_POWER_RESET;
}
else
{
HWREGB(ulBase + USB_O_POWER) &= ~USB_POWER_RESET;
}
}
例如:在主机模式下,唤醒USB总线,唤醒开始20ms后必须手动结束。
void USBHostResume(unsigned long ulBase, tBoolean bStart)
{
//ulBase为设备基地址,bStart确定唤醒开始/结束。
if(bStart)
{
HWREGB(ulBase + USB_O_POWER) |= USB_POWER_RESUME;
}
else
{
HWREGB(ulBase + USB_O_POWER) &= ~USB_POWER_RESUME;
}
}
例如:在设备模式下,设备连接/断开主机。
void USBDevConnect(unsigned long ulBase)
{
//ulBase为设备基地址。
HWREGB(ulBase + USB_O_POWER) |= USB_POWER_SOFTCONN;
}
void USBDevDisconnect(unsigned long ulBase)
{
//ulBase为设备基地址。
HWREGB(ulBase + USB_O_POWER) &= (~USB_POWER_SOFTCONN);
}
USBFRAME,16位只读寄存器,保存最新收到的帧编号。USBFRAME寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[15:11] | 保留 | RO | 0 | 保持不变 |
[10:0] | FRAME | RO | 0 | 帧编号 |
表4. USBFRAME寄存器
例如:获取最新帧编号。
unsigned long USBFrameNumberGet(unsigned long ulBase)
{
//ulBase为设备基地址。
return(HWREGH(ulBase + USB_O_FRAME));
}
USBTEST,测试模式,回应USBREQ_SET_FEATURE的USB_FEATURE_TEST_MODE命令,使USB控制器进入测试模式,任何时候,只能有一位被设置,但不用于正常操作。在主机模式下,USBTEST寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[4:0] | 保留 | RO | 0 | 保持不变 |
7 | FORCEH | R/W | 0 | 强制为主机模式 |
6 | FIFOACC | R/W1S | 0 | 将端点0的TXFIFO数据传送到RXFIFO |
5 | FORCEFS | R/W | 0 | 强制全速模式 |
表5. USBTEST寄存器
在设备模式下,USBTEST寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[4:0]、7 | 保留 | RO | 0 | 保持不变 |
6 | FIFOACC | R/W1S | 0 | 将端点0的TXFIFO数据传送到RXFIFO |
5 | FORCEFS | R/W | 0 | 强制全速模式 |
表6. USBTEST寄存器
USBDEVCTL,USB设备控制器,提供USB控制器当前状态信息,可指示接入设备是全速还是低速。USBDEVCTL寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | DEV | RO | 1 | 设备模式,OTG A端。 |
6 | FSDEV | RO | 0 | 全速设备 |
5 | LSDEV | RO | 0 | 低速设备 |
[4:3] | VBUS | RO | 0 | VBUS 电平 |
2 | HOST | RO | 0 | Host主机模式 |
1 | HOSTREQ | R/W | 0 | 主机请求 |
0 | SESSION | R/W | 0 | 会话开始/结束 |
表7. USBDEVCTL寄存器
#define USB_DEVCTL_DEV 0x00000080 // Device Mode
#define USB_DEVCTL_FSDEV 0x00000040 // Full-Speed Device Detected
#define USB_DEVCTL_LSDEV 0x00000020 // Low-Speed Device Detected
#define USB_DEVCTL_VBUS_M 0x00000018 // VBUS Level
#define USB_DEVCTL_VBUS_NONE 0x00000000 // Below SessionEnd
#define USB_DEVCTL_VBUS_SEND 0x00000008 // Above SessionEnd, below AValid
#define USB_DEVCTL_VBUS_AVALID 0x00000010 // Above AValid, below VBUSValid
#define USB_DEVCTL_VBUS_VALID 0x00000018 // Above VBUSValid
#define USB_DEVCTL_HOST 0x00000004 // Host Mode
#define USB_DEVCTL_HOSTREQ 0x00000002 // Host Request
#define USB_DEVCTL_SESSION 0x00000001 // Session Start/End
例如:获取当前USB工作模式。
unsigned long USBModeGet(unsigned long ulBase)
{
return(HWREGB(ulBase + USB_O_DEVCTL) &
(USB_DEVCTL_DEV | USB_DEVCTL_HOST | USB_DEVCTL_SESSION |
USB_DEVCTL_VBUS_M));
}
返回下面参数:
#define USB_DUAL_MODE_HOST 0x00000001
#define USB_DUAL_MODE_DEVICE 0x00000081
#define USB_DUAL_MODE_NONE 0x00000080
#define USB_OTG_MODE_ASIDE_HOST 0x0000001d
#define USB_OTG_MODE_ASIDE_NPWR 0x00000001
#define USB_OTG_MODE_ASIDE_SESS 0x00000009
#define USB_OTG_MODE_ASIDE_AVAL 0x00000011
#define USB_OTG_MODE_ASIDE_DEV 0x00000019
#define USB_OTG_MODE_BSIDE_HOST 0x0000009d
#define USB_OTG_MODE_BSIDE_DEV 0x00000099
#define USB_OTG_MODE_BSIDE_NPWR 0x00000081
#define USB_OTG_MODE_NONE 0x00000080
USBCONTIM,连接时序控制寄存器,用于控制USB连接。USBCONTIM寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:4] | WTCON | R/W | 0x5 | 连接等待 |
[3:0] | WTID | R/W | 0xC | ID等待 |
表8. USBCONTIM寄存器
WTCON,此位域可按需求配置等待延时,满足连接/断开的滤波需求;单位为533.3ns,复位后为0x5,默认为2.667µs。
WTID,此位域配置ID等待延时,等待ID值有效时才使能OTG的ID检测。单位为4.369 ms,复位后为0xC,默认为52.43 ms。
USBVPLEN,VBUS脉冲时序配置寄存器,控制VBUS脉冲充电的持续时间。USBVPLEN寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:0] | VPLEN | R/W | 0x3c | VBUS脉冲宽度 |
表9. USBVPLEN寄存器
VPLEN,用于配置VBUS脉冲充电的持续时间,单位546.1 µs,默认为32.77 ms。
USBFSEOF,用于配置全速模式下最后传输开始与帧结束(EOF)之间的最小时间间隔。
USBFSEOF寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:0] | FSEOFG | R/W | 0x77 | 全速模式帧间隙 |
表10. USBFSEOF寄存器
FSEOFG,在全速传输中用于配置最后的传输与帧结束之间的最小时间间隙,单位533.3ns,默认为63.46 µs。
USBLSEOF,用于配置低速模式下最后传输开始与帧结束(EOF)之间的最小时间间隔。
USBLSEOF寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:0] | LSEOFG | R/W | 0x72 | 低速模式帧间隙 |
表11. USBLSEOF寄存器
FSEOFG,在低速传输中用于配置最后的传输与帧结束之间的最小时间间隙,单位1.067 µs,默认为121.6 µs。
注意:USBCONTIM、USBVPLEN、USBFSEOF、USBLSEOF一般不用配置,保持默认情况就能满足USB通信。
USBGPCS,USB通用控制状态寄存器,提供内部ID信号的状态。
USBGPCS寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[31:2] | 保留 | RO | 0 | 保持不变 |
1 | DEVMODOTG | R/W | 0 | 使能ID控制模式 |
0 | DEVMOD | R/W | 0 | 模式控制 |
表12. USBGPCS寄存器
#define USB_GPCS_DEVMODOTG 0x00000002 // Enable Device Mode
#define USB_GPCS_DEVMOD 0x00000001 // Device Mode
例如:设置主机模式。
void USBHostMode(unsigned long ulBase)
{
//ulBase为设备基地址。
HWREGB(ulBase + USB_O_GPCS) &= ~(USB_GPCS_DEVMOD);
}
2.3.2 中断控制
USBTXIS,发送中断状态寄存器,16位只读寄存器,读取数据时,清除相应标志位。
USBTXIS寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
15..0 | EPn | RO | 0 | 端点发送中断标志 |
表13. USBTXIS寄存器
USBRXIS,接收中断状态寄存器。USBRXIS寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
15..1 | EPn | R/W | 0 | 端点接收中断标志 |
表14. USBRXIS寄存器
USBTXIE,发送中断使能寄存器,16位只读寄存器,读取数据时,清除相应标志位。
USBTXIE寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
15..0 | EPn | RO | 0 | 端点发送中断标志 |
表15. USBTXIE寄存器
USBRXIE,接收中断使能寄存器。USBRXIE寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
15..1 | EPn | R/W | 0 | 端点接收中断标志 |
表16. USBRXIE寄存器
USBIS,通用中断状态寄存器,8位只读寄存器,读取数据时,清除相应标志位。
USBIS寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | VBUSERR | RO | 0 | VBUS中断(只有主机模式使用) |
6 | SESREQ | RO | 0 | 会话请求中断(只有主机模式使用) |
5 | DISCON | RO | 0 | 连接断开中断 |
4 | CONN | RO | 0 | 连接中断 |
3 | SOF | RO | 0 | 帧起始中断 |
2 | BABBLE | RO | 0 | Babble中断 |
1 | RESUME | RO | 0 | 唤醒中断 |
0 | SUSPEND | RO | 0 | 挂起中断(只有设备模式使用) |
表17. USBIS寄存器
USBIE,通用中断使能寄存器,USBIE寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | VBUSERR | RO | 0 | VBUS中断使能(只有主机模式使用) |
6 | SESREQ | RO | 0 | 会话请求中断使能(只有主机模式使用) |
5 | DISCON | RO | 0 | 连接断开中断使能 |
4 | CONN | RO | 0 | 连接中断使能 |
3 | SOF | RO | 0 | 帧起始中断使能 |
2 | BABBLE | RO | 0 | Babble中断使能 |
1 | RESUME | RO | 0 | 唤醒中断使能 |
0 | SUSPEND | RO | 0 | 挂起中断使能(只有设备模式使用) |
表18. USBIE寄存器
此外还有USBEPC、USBEPCRIS、USBEPC、USBEPCRIS、USBEPCIM、USBEPCISC电源管理中断;USBIDVISC、USBIDVIM、USBIDVRIS等ID检测中断控制;USBDRRIS、USBDRIM、USBDRISC唤醒中断控制;USBVDC、USBVDCRIS、USBVDCIM、USBVDCISC的VBUS Droop控制中断。这些中断使用较少,不在此详细描述。
例如,写一组函数,控制、管理上面中断。
USBIntEnable()、USBIntDisable()的ulFlags参数, USBIntStatus()返回参数:
#define USB_INTCTRL_ALL 0x000003FF // All control interrupt sources
#define USB_INTCTRL_STATUS 0x000000FF // Status Interrupts
#define USB_INTCTRL_VBUS_ERR 0x00000080 // VBUS Error
#define USB_INTCTRL_SESSION 0x00000040 // Session Start Detected
#define USB_INTCTRL_SESSION_END 0x00000040 // Session End Detected
#define USB_INTCTRL_DISCONNECT 0x00000020 // Disconnect Detected
#define USB_INTCTRL_CONNECT 0x00000010 // Device Connect Detected
#define USB_INTCTRL_SOF 0x00000008 // Start of Frame Detected
#define USB_INTCTRL_BABBLE 0x00000004 // Babble signaled
#define USB_INTCTRL_RESET 0x00000004 // Reset signaled
#define USB_INTCTRL_RESUME 0x00000002 // Resume detected
#define USB_INTCTRL_SUSPEND 0x00000001 // Suspend detected
#define USB_INTCTRL_MODE_DETECT 0x00000200 // Mode value valid
#define USB_INTCTRL_POWER_FAULT 0x00000100 // Power Fault detected
//端点中断控制
#define USB_INTEP_ALL 0xFFFFFFFF // Host IN Interrupts
#define USB_INTEP_HOST_IN 0xFFFE0000 // Host IN Interrupts
#define USB_INTEP_HOST_IN_15 0x80000000 // Endpoint 15 Host IN Interrupt
#define USB_INTEP_HOST_IN_14 0x40000000 // Endpoint 14 Host IN Interrupt
#define USB_INTEP_HOST_IN_13 0x20000000 // Endpoint 13 Host IN Interrupt
#define USB_INTEP_HOST_IN_12 0x10000000 // Endpoint 12 Host IN Interrupt
#define USB_INTEP_HOST_IN_11 0x08000000 // Endpoint 11 Host IN Interrupt
#define USB_INTEP_HOST_IN_10 0x04000000 // Endpoint 10 Host IN Interrupt
#define USB_INTEP_HOST_IN_9 0x02000000 // Endpoint 9 Host IN Interrupt
#define USB_INTEP_HOST_IN_8 0x01000000 // Endpoint 8 Host IN Interrupt
#define USB_INTEP_HOST_IN_7 0x00800000 // Endpoint 7 Host IN Interrupt
#define USB_INTEP_HOST_IN_6 0x00400000 // Endpoint 6 Host IN Interrupt
#define USB_INTEP_HOST_IN_5 0x00200000 // Endpoint 5 Host IN Interrupt
#define USB_INTEP_HOST_IN_4 0x00100000 // Endpoint 4 Host IN Interrupt
#define USB_INTEP_HOST_IN_3 0x00080000 // Endpoint 3 Host IN Interrupt
#define USB_INTEP_HOST_IN_2 0x00040000 // Endpoint 2 Host IN Interrupt
#define USB_INTEP_HOST_IN_1 0x00020000 // Endpoint 1 Host IN Interrupt
#define USB_INTEP_DEV_OUT 0xFFFE0000 // Device OUT Interrupts
#define USB_INTEP_DEV_OUT_15 0x80000000 // Endpoint 15 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_14 0x40000000 // Endpoint 14 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_13 0x20000000 // Endpoint 13 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_12 0x10000000 // Endpoint 12 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_11 0x08000000 // Endpoint 11 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_10 0x04000000 // Endpoint 10 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_9 0x02000000 // Endpoint 9 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_8 0x01000000 // Endpoint 8 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_7 0x00800000 // Endpoint 7 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_6 0x00400000 // Endpoint 6 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_5 0x00200000 // Endpoint 5 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_4 0x00100000 // Endpoint 4 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_3 0x00080000 // Endpoint 3 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_2 0x00040000 // Endpoint 2 Device OUT Interrupt
#define USB_INTEP_DEV_OUT_1 0x00020000 // Endpoint 1 Device OUT Interrupt
#define USB_INTEP_HOST_OUT 0x0000FFFE // Host OUT Interrupts
#define USB_INTEP_HOST_OUT_15 0x00008000 // Endpoint 15 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_14 0x00004000 // Endpoint 14 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_13 0x00002000 // Endpoint 13 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_12 0x00001000 // Endpoint 12 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_11 0x00000800 // Endpoint 11 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_10 0x00000400 // Endpoint 10 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_9 0x00000200 // Endpoint 9 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_8 0x00000100 // Endpoint 8 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_7 0x00000080 // Endpoint 7 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_6 0x00000040 // Endpoint 6 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_5 0x00000020 // Endpoint 5 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_4 0x00000010 // Endpoint 4 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_3 0x00000008 // Endpoint 3 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_2 0x00000004 // Endpoint 2 Host OUT Interrupt
#define USB_INTEP_HOST_OUT_1 0x00000002 // Endpoint 1 Host OUT Interrupt
#define USB_INTEP_DEV_IN 0x0000FFFE // Device IN Interrupts
#define USB_INTEP_DEV_IN_15 0x00008000 // Endpoint 15 Device IN Interrupt
#define USB_INTEP_DEV_IN_14 0x00004000 // Endpoint 14 Device IN Interrupt
#define USB_INTEP_DEV_IN_13 0x00002000 // Endpoint 13 Device IN Interrupt
#define USB_INTEP_DEV_IN_12 0x00001000 // Endpoint 12 Device IN Interrupt
#define USB_INTEP_DEV_IN_11 0x00000800 // Endpoint 11 Device IN Interrupt
#define USB_INTEP_DEV_IN_10 0x00000400 // Endpoint 10 Device IN Interrupt
#define USB_INTEP_DEV_IN_9 0x00000200 // Endpoint 9 Device IN Interrupt
#define USB_INTEP_DEV_IN_8 0x00000100 // Endpoint 8 Device IN Interrupt
#define USB_INTEP_DEV_IN_7 0x00000080 // Endpoint 7 Device IN Interrupt
#define USB_INTEP_DEV_IN_6 0x00000040 // Endpoint 6 Device IN Interrupt
#define USB_INTEP_DEV_IN_5 0x00000020 // Endpoint 5 Device IN Interrupt
#define USB_INTEP_DEV_IN_4 0x00000010 // Endpoint 4 Device IN Interrupt
#define USB_INTEP_DEV_IN_3 0x00000008 // Endpoint 3 Device IN Interrupt
#define USB_INTEP_DEV_IN_2 0x00000004 // Endpoint 2 Device IN Interrupt
#define USB_INTEP_DEV_IN_1 0x00000002 // Endpoint 1 Device IN Interrupt
#define USB_INTEP_0 0x00000001 // Endpoint 0 Interrupt
中断使能函数:
void USBIntEnable(unsigned long ulBase, unsigned long ulFlags)
{
//发送中断控制
if(ulFlags & (USB_INT_HOST_OUT | USB_INT_DEV_IN | USB_INT_EP0))
{
HWREGH(ulBase + USB_O_TXIE) |=
ulFlags & (USB_INT_HOST_OUT | USB_INT_DEV_IN | USB_INT_EP0);
}
//接收中断控制
if(ulFlags & (USB_INT_HOST_IN | USB_INT_DEV_OUT))
{
HWREGH(ulBase + USB_O_RXIE) |=
((ulFlags & (USB_INT_HOST_IN | USB_INT_DEV_OUT)) >>
USB_INT_RX_SHIFT);
}
//通用中断控制
if(ulFlags & USB_INT_STATUS)
{
HWREGB(ulBase + USB_O_IE) |=
(ulFlags & USB_INT_STATUS) >> USB_INT_STATUS_SHIFT;
}
//电源中断控制
if(ulFlags & USB_INT_POWER_FAULT)
{
HWREG(ulBase + USB_O_EPCIM) = USB_EPCIM_PF;
}
//ID 中断控制
if(ulFlags & USB_INT_MODE_DETECT)
{
HWREG(USB0_BASE + USB_O_IDVIM) = USB_IDVIM_ID;
}
}
中断禁止函数:
void USBIntDisable(unsigned long ulBase, unsigned long ulFlags)
{
//发送中断控制
if(ulFlags & (USB_INT_HOST_OUT | USB_INT_DEV_IN | USB_INT_EP0))
{
HWREGH(ulBase + USB_O_TXIE) &=
~(ulFlags & (USB_INT_HOST_OUT | USB_INT_DEV_IN | USB_INT_EP0));
}
//接收中断控制
if(ulFlags & (USB_INT_HOST_IN | USB_INT_DEV_OUT))
{
HWREGH(ulBase + USB_O_RXIE) &=
~((ulFlags & (USB_INT_HOST_IN | USB_INT_DEV_OUT)) >>
USB_INT_RX_SHIFT);
}
//通用中断控制
if(ulFlags & USB_INT_STATUS)
{
HWREGB(ulBase + USB_O_IE) &=
~((ulFlags & USB_INT_STATUS) >> USB_INT_STATUS_SHIFT);
}
//电源中断控制
if(ulFlags & USB_INT_POWER_FAULT)
{
HWREG(ulBase + USB_O_EPCIM) = 0;
}
//ID 中断控制
if(ulFlags & USB_INT_MODE_DETECT)
{
HWREG(USB0_BASE + USB_O_IDVIM) = 0;
}
}
获取中断标志并清除函数:
unsigned long USBIntStatus(unsigned long ulBase)
{
unsigned long ulStatus;
ulStatus = (HWREGB(ulBase + USB_O_TXIS));
ulStatus |= (HWREGB(ulBase + USB_O_RXIS) << USB_INT_RX_SHIFT);
ulStatus |= (HWREGB(ulBase + USB_O_IS) << USB_INT_STATUS_SHIFT);
if(HWREG(ulBase + USB_O_EPCISC) & USB_EPCISC_PF)
{
ulStatus |= USB_INT_POWER_FAULT;
HWREGB(ulBase + USB_O_EPCISC) |= USB_EPCISC_PF;
}
if(HWREG(USB0_BASE + USB_O_IDVISC) & USB_IDVRIS_ID)
{
ulStatus |= USB_INT_MODE_DETECT;
HWREG(USB0_BASE + USB_O_IDVISC) |= USB_IDVRIS_ID;
}
return(ulStatus);
}
端点中断使用较为频繁,可单独控制。
void USBIntDisableEndpoint(unsigned long ulBase, unsigned long ulFlags)
{
HWREGH(ulBase + USB_O_TXIE) &=
~(ulFlags & (USB_INTEP_HOST_OUT | USB_INTEP_DEV_IN | USB_INTEP_0));
HWREGH(ulBase + USB_O_RXIE) &=
~((ulFlags & (USB_INTEP_HOST_IN | USB_INTEP_DEV_OUT)) >>
USB_INTEP_RX_SHIFT);
}
void USBIntEnableEndpoint(unsigned long ulBase, unsigned long ulFlags)
{
HWREGH(ulBase + USB_O_TXIE) |=
ulFlags & (USB_INTEP_HOST_OUT | USB_INTEP_DEV_IN | USB_INTEP_0);
HWREGH(ulBase + USB_O_RXIE) |=
((ulFlags & (USB_INTEP_HOST_IN | USB_INTEP_DEV_OUT)) >>
USB_INTEP_RX_SHIFT);
}
unsigned long USBIntStatusEndpoint(unsigned long ulBase)
{
unsigned long ulStatus;
ulStatus = HWREGH(ulBase + USB_O_TXIS);
ulStatus |= (HWREGH(ulBase + USB_O_RXIS) << USB_INTEP_RX_SHIFT);
return(ulStatus);
}
2.3.3 端点寄存器
USBEPIDX,USB端点索引寄存器。设置端点FIFO大小和起始地址要配合USBEPIDX使用。USBEPIDX寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:4] | 保留 | RO | 0 | 保留 |
[3:0] | EPIDX | R/W | 0 | 端点索引 |
表19. USBEPIDX寄存器
USBRXFIFOSZ、USBTXFIFOSZ ,USB接收/发送FIFO大小寄存器。USBRXFIFOSZ、USBTXFIFOSZ寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:5] | 保留 | RO | 0 | 保留 |
4 | DPB | R/W | 0 | 双包缓存 |
[3:0] | SIZE | R/W | 0 | 最大包 8*(2^SIZE) |
表20. USBRXFIFOSZ、USBTXFIFOSZ寄存器
USBRXFIFOADD、USBTXFIFOADD ,USB接收/发送FIFO首地址寄存器。USBRXFIFOADD、USBTXFIFOADD寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[15:9] | 保留 | RO | 0 | 保留 |
[8:0] | ADDR | R/W | 0 | 最大包 8*SIZE |
表21. USBRXFIFOADD、USBTXFIFOADD寄存器
注意:访问要用到索引寄存器的FIFO寄存器只有USBRXFIFOSZ、USBTXFIFOSZ、USBRXFIFOADD、USBTXFIFOADD四个。
例如:写一个函数,控制端点的FIFO。
static void USBIndexWrite(unsigned long ulBase, unsigned long ulEndpoint,
unsigned long ulIndexedReg, unsigned long ulValue,
unsigned long ulSize)
{
unsigned long ulIndex;
// 保存当前索引寄存器值.
ulIndex = HWREGB(ulBase + USB_O_EPIDX);
// 写新值到端点索引寄存器
HWREGB(ulBase + USB_O_EPIDX) = ulEndpoint;
//根据寄存器大小写入新值到FIFO寄存器。
if(ulSize == 1)
{
HWREGB(ulBase + ulIndexedReg) = ulValue;
}
else
{
HWREGH(ulBase + ulIndexedReg) = ulValue;
}
//恢复以前索引寄存器值。
HWREGB(ulBase + USB_O_EPIDX) = ulIndex;
}
USBTXFUNCADDRn,发送端点功能地址寄存器。在主机模式下,用于设置端点n访问的目标地址。USBTXFUNCADDRn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | 保留 | RO | 0 | 保留 |
[6:0] | ADDR | R/W | 0 | 设备总线地址 |
表22 USBTXFUNCADDRn寄存器
USBTXHUBPORTn,发送端点n集线器端口号寄存器。USBTXHUBPORTn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | 保留 | RO | 0 | 保留 |
[6:0] | ADDR | R/W | 0 | 集线器端口 |
表23 USBTXHUBPORTn寄存器
USBTXHUBADDRn,发送端点n集线器地址寄存器,USBTXHUBADDRn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | MULTTRAN | RO | 0 | 多路开关 |
[6:0] | ADDR | R/W | 0 | 集线器地址 |
表24 USBTXHUBADDRn寄存器
USBRXFUNCADDRn,接收端点功能地址寄存器。在主机模式下,用于设置端点n访问的目标地址。USBRXFUNCADDRn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | 保留 | RO | 0 | 保留 |
[6:0] | ADDR | R/W | 0 | 设备总线地址 |
表25 USBRXFUNCADDRn寄存器
USBRXHUBPORTn,接收端点n集线器端口号寄存器。USBRXHUBPORTn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | 保留 | RO | 0 | 保留 |
[6:0] | ADDR | R/W | 0 | 集线器端口 |
表26 USBRXHUBPORTn寄存器
USBRXHUBADDRn,接收端点n集线器地址寄存器,USBRXHUBADDRn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | MULTTRAN | RO | 0 | 多路开关 |
[6:0] | ADDR | R/W | 0 | 集线器地址 |
表27 USBRXHUBADDRn寄存器
注意:USBTXFUNCADDR0、USBTXHUBPORT0 、USBTXHUBADDR0同时用于端点0的接收和发送。
例如:写一个函数,主机端点访问某个设备地址。
USBHostAddrSet() 的ulEndpoint参数:
#define USB_EP_0 0x00000000 // Endpoint 0
#define USB_EP_1 0x00000010 // Endpoint 1
#define USB_EP_2 0x00000020 // Endpoint 2
#define USB_EP_3 0x00000030 // Endpoint 3
#define USB_EP_4 0x00000040 // Endpoint 4
#define USB_EP_5 0x00000050 // Endpoint 5
#define USB_EP_6 0x00000060 // Endpoint 6
#define USB_EP_7 0x00000070 // Endpoint 7
#define USB_EP_8 0x00000080 // Endpoint 8
#define USB_EP_9 0x00000090 // Endpoint 9
#define USB_EP_10 0x000000A0 // Endpoint 10
#define USB_EP_11 0x000000B0 // Endpoint 11
#define USB_EP_12 0x000000C0 // Endpoint 12
#define USB_EP_13 0x000000D0 // Endpoint 13
#define USB_EP_14 0x000000E0 // Endpoint 14
#define USB_EP_15 0x000000F0 // Endpoint 15
#define NUM_USB_EP 16 // Number of supported endpoints
void USBHostAddrSet(unsigned long ulBase, unsigned long ulEndpoint,
unsigned long ulAddr, unsigned long ulFlags)
{
//根据ulFlags设置发送还是接地址
if(ulFlags & USB_EP_HOST_OUT)
{
HWREGB(ulBase + USB_O_TXFUNCADDR0 + (ulEndpoint >> 1)) = ulAddr;
}
else
{
HWREGB(ulBase + USB_O_TXFUNCADDR0 + 4 + (ulEndpoint >> 1)) = ulAddr;
}
}
例如:写一个函数,主机端点通过集线器访问某个设备地址。
void USBHostHubAddrSet(unsigned long ulBase, unsigned long ulEndpoint,
unsigned long ulAddr, unsigned long ulFlags)
{
////根据ulFlags设置发送还是接地址
if(ulFlags & USB_EP_HOST_OUT)
{
HWREGB(ulBase + USB_O_TXHUBADDR0 + (ulEndpoint >> 1)) = ulAddr;
}
else
{
HWREGB(ulBase + USB_O_TXHUBADDR0 + 4 + (ulEndpoint >> 1)) = ulAddr;
}
}
USBTXMAXPn,发送端点n最大传输数据寄存器, 定义发送端点单次可传输的最大数据长度。USBTXMAXPn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[15:11] | 保留 | RO | 0 | 保留 |
[10:0] | MAXLOAD | R/W | 0 | 单次传输数据最大字节数 |
表28 USBTXMAXPn寄存器
USBRXCOUNTn,USB端点n接收字节数寄存器, 从RXFIFO中读出数据的字节数。USBRXCOUNTn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[15:13] | 保留 | RO | 0 | 保留 |
[12:0] | COUNT | R/W | 0 | 接收字节数 |
表29 USBRXCOUNTn寄存器
USBTXTYPEn,主机发送类型寄存器,配置发送端点的目标端点号,传输协议,以及其运行速度。USBTXTYPEn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:6] | SPEED | R/W | 0 | 运行速度 |
[5:4] | PROTO | R/W | 0 | 协议 |
[3:0] | TEP | R/W | 0 | 目标端点号 |
表30 USBTXTYPEn寄存器
USBTXTYPEn,主机发送类型寄存器,配置发送端点的目标端点号,传输协议,以及其运行速度。USBTXTYPEn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:6] | SPEED | R/W | 0 | 运行速度 |
[5:4] | PROTO | R/W | 0 | 协议 |
[3:0] | TEP | R/W | 0 | 目标端点号 |
表31 USBTXTYPEn寄存器
USBTXINTERVALn, 主机发送间隔寄存器。USBTXINTERVALn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:0] | TXPOLL / NAKLMT | R/W | 0 | NAK超时时间间隔 |
表32 USBTXINTERVALn寄存器
USBRXTYPEn,主机接收类型寄存器,配置接收端点的目标端点号,传输协议,以及其运行速度。USBRXTYPEn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:6] | SPEED | R/W | 0 | 运行速度 |
[5:4] | PROTO | R/W | 0 | 协议 |
[3:0] | TEP | R/W | 0 | 目标端点号 |
表33 USBRXTYPEn寄存器
USBRXINTERVALn, 主机接收间隔寄存器。USBRXINTERVALn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:0] | TXPOLL / NAKLMT | R/W | 0 | NAK超时时间间隔 |
表34 USBRXINTERVALn寄存器
USBRQPKTCOUNTn,块传输请求包数量寄存器。USBRQPKTCOUNTn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[15:0] | COUNT | R/W | 0 | 块传输包数量 |
表35 USBRQPKTCOUNTn寄存器
USBRXDPKTBUFDIS,接收双包缓存禁止寄存器,USBRXDPKTBUFDIS寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
15..0 | EPn | R/W | 0 | 接收双包缓存禁止 |
表36 USBRXDPKTBUFDIS寄存器
USBTXDPKTBUFDIS,发送双包缓存禁止寄存器,USBTXDPKTBUFDIS寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
15..0 | EPn | R/W | 0 | 发送双包缓存禁止 |
表37 USBTXDPKTBUFDIS寄存器
USBFIFOn,FIFO端点寄存器,主要进行FIFO访问。写操作,将向TXFIFO中写入数据;读操作,将从RXFIFO中读出数据。USBFIFOn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[31:0] | EPDATA | R/W | 0 | 端点数据 |
表38 USBFIFOn寄存器
USBCSRL0,端点0控制和状态低字节寄存器,为端点0提供控制和状态位。USBCSRL0寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 主机/设备 |
7 | NAKTO/SETENDC | R/W | 0 | NAK超时/SETEND清0 |
6 | STATUS/RXRDYC | R/W | 0 | 状态包/清RXRDY位 |
5 | REQPKT/STALL | R/W | 0 | 请求包/发送STALL握手 |
4 | ERROR/SETEND | R/W | 0 | 错误/Setup End |
3 | SETUP/DATAEND | R/W | 0 | 建立令牌包/数据结束 |
2 | STALLED | R/W | 0 | 端点挂起 |
1 | TXRDY | R/W | 0 | 发送包准备好 |
0 | RXRDY | R/W | 0 | 接收包准备好 |
表39 USBCSRL0寄存器
USBCSRH0,端点0控制和状态高字节寄存器,为端点0提供控制和状态位。USBCSRH0寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
[7:3] | 保留 | RO | 0 | 保留 |
2 | DTWE | R/W | 0 | 数据切换写使能(只有主机模式) |
1 | DT | R/W | 0 | 数据切换(只有主机模式) |
0 | FLUSH | R/W | 0 | 清空FIFO |
表40 USBCSRH0寄存器
USBTXCSRLn,发送端点n(非端点0)控制和状态低字节寄存器,为端点n提供控制和状态位。USBTXCSRLn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 主机/设备 |
7 | NAKTO | R/W | 0 | NAK超时(只有主机) |
6 | CLRDT | R/W | 0 | 清除数据转换 |
5 | STALLED | R/W | 0 | 端点挂起 |
4 | SETUP/STALL | R/W | 0 | 建立令牌包/发送STALL |
3 | FLUSH | R/W | 0 | 清空 FIFO |
2 | ERROR/UNDRN | R/W | 0 | 错误/欠运转 |
1 | FIFONE | R/W | 0 | FIFO不空 |
0 | TXRDY | R/W | 0 | 发送包准备好 |
表41 USBTXCSRLn寄存器
USBTXCSRHn,发送端点n(非端点0)控制和状态高字节寄存器,为端点n提供控制和状态位。USBTXCSRHn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | AUTOSET | R/W | 0 | 自动置位 |
6 | ISO | R/W | 0 | ISO传输(只有设备模式) |
5 | MODE | R/W | 0 | 模式 |
4 | DMAEN | R/W | 0 | DMA请求使能 |
3 | FDT | R/W | 0 | 强制数据切换 |
2 | DMAMOD | R/W | 0 | DMA请求模式 |
1 | DTWE | R/W | 0 | 数据切换写使能(只有主机模式) |
0 | DT | R/W | 0 | 数据切换(只有主机模式) |
表42 USBTXCSRHn寄存器
USBRXCSRLn,接收端点n控制和状态低字节寄存器,USBRXCSRLn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 主机/设备 |
7 | CLRDT | R/W | 0 | 清除数据转换 |
6 | STALLED | R/W | 0 | 端点挂起 |
5 | REQPKT/ STALL | R/W | 0 | 请求包/发送STALL握手 |
4 | FLUSH | R/W | 0 | 清空FIFO |
3 | DATAERR\NAKTO/ DATAERR | R/W | 0 | 数据错误\NAK超时 /数据错误 |
2 | ERROR/OVER | R/W | 0 | 错误/Overrun |
1 | FULL | R/W | 0 | 错误 |
0 | RXRDY | R/W | 0 | 接收包准备好 |
表43 USBRXCSRLn寄存器
USBRXCSRHn,接收端点n控制和状态高字节寄存器,为接收端点提供额外的控制和状态位。USBRXCSRHn寄存器描述如下表:
位 | 名称 | 类型 | 复位 | 描述 |
7 | AUTOCL | R/W | 0 | 自动清除 |
6 | AUTORQ | R/W | 0 | 自动请求 |
5 | DMAEN | R/W | 0 | DMA请求使能 |
4 | PIDERR | R/W | 0 | PID错误 |
3 | DMAMOD | R/W | 0 | DMA请求模式 |
2 | DTWE | R/W | 0 | 数据切换写使能(只有主机模式) |
1 | DT | R/W | 0 | 数据切换(只有主机模式) |
0 | 保留 | RO | 0 | 保留 |
表44 USBRXCSRHn寄存器
例如:写一个函数,配置端点。
USBHostEndpointConfig()和USBDevEndpointConfigSet()的ulFlags参数:
#define USB_EP_AUTO_SET 0x00000001 // Auto set feature enabled
#define USB_EP_AUTO_REQUEST 0x00000002 // Auto request feature enabled
#define USB_EP_AUTO_CLEAR 0x00000004 // Auto clear feature enabled
#define USB_EP_DMA_MODE_0 0x00000008 // Enable DMA access using mode 0
#define USB_EP_DMA_MODE_1 0x00000010 // Enable DMA access using mode 1
#define USB_EP_MODE_ISOC 0x00000000 // Isochronous endpoint
#define USB_EP_MODE_BULK 0x00000100 // Bulk endpoint
#define USB_EP_MODE_INT 0x00000200 // Interrupt endpoint
#define USB_EP_MODE_CTRL 0x00000300 // Control endpoint
#define USB_EP_MODE_MASK 0x00000300 // Mode Mask
#define USB_EP_SPEED_LOW 0x00000000 // Low Speed
#define USB_EP_SPEED_FULL 0x00001000 // Full Speed
#define USB_EP_HOST_IN 0x00000000 // Host IN endpoint
#define USB_EP_HOST_OUT 0x00002000 // Host OUT endpoint
#define USB_EP_DEV_IN 0x00002000 // Device IN endpoint
#define USB_EP_DEV_OUT 0x00000000 // Device OUT endpoint
ulFIFOSize 参数:
#define USB_FIFO_SZ_8 0x00000000 // 8 byte FIFO
#define USB_FIFO_SZ_16 0x00000001 // 16 byte FIFO
#define USB_FIFO_SZ_32 0x00000002 // 32 byte FIFO
#define USB_FIFO_SZ_64 0x00000003 // 64 byte FIFO
#define USB_FIFO_SZ_128 0x00000004 // 128 byte FIFO
#define USB_FIFO_SZ_256 0x00000005 // 256 byte FIFO
#define USB_FIFO_SZ_512 0x00000006 // 512 byte FIFO
#define USB_FIFO_SZ_1024 0x00000007 // 1024 byte FIFO
#define USB_FIFO_SZ_2048 0x00000008 // 2048 byte FIFO
#define USB_FIFO_SZ_4096 0x00000009 // 4096 byte FIFO
#define USB_FIFO_SZ_8_DB 0x00000010 // 8 byte double buffered FIFO
#define USB_FIFO_SZ_16_DB 0x00000011 // 16 byte double buffered FIFO
#define USB_FIFO_SZ_32_DB 0x00000012 // 32 byte double buffered FIFO
#define USB_FIFO_SZ_64_DB 0x00000013 // 64 byte double buffered FIFO
#define USB_FIFO_SZ_128_DB 0x00000014 // 128 byte double buffered FIFO
#define USB_FIFO_SZ_256_DB 0x00000015 // 256 byte double buffered FIFO
#define USB_FIFO_SZ_512_DB 0x00000016 // 512 byte double buffered FIFO
#define USB_FIFO_SZ_1024_DB 0x00000017 // 1024 byte double buffered FIFO
#define USB_FIFO_SZ_2048_DB 0x00000018 // 2048 byte double buffered FIFO
端点转化到其状态控制器寄存器地址:
#define EP_OFFSET(Endpoint) (Endpoint - 0x10)
主机端点配置函数:
void USBHostEndpointConfig(unsigned long ulBase, unsigned long ulEndpoint,
unsigned long ulMaxPayload,
unsigned long ulNAKPollInterval,
unsigned long ulTargetEndpoint, unsigned long ulFlags)
{
unsigned long ulRegister;
//判断是否是端点0,端点0的发送与接收配置使用同一寄存器。
if(ulEndpoint == USB_EP_0)
{
HWREGB(ulBase + USB_O_NAKLMT) = ulNAKPollInterval;
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_TYPE0) =
((ulFlags & USB_EP_SPEED_FULL) ? USB_TYPE0_SPEED_FULL :
USB_TYPE0_SPEED_LOW);
}
//端点1-15配置
else
{
ulRegister = ulTargetEndpoint;
if(ulFlags & USB_EP_SPEED_FULL)
{
ulRegister |= USB_TXTYPE1_SPEED_FULL;
}
else
{
ulRegister |= USB_TXTYPE1_SPEED_LOW;
}
switch(ulFlags & USB_EP_MODE_MASK)
{
case USB_EP_MODE_BULK:
{
ulRegister |= USB_TXTYPE1_PROTO_BULK;
break;
}
case USB_EP_MODE_ISOC:
{
ulRegister |= USB_TXTYPE1_PROTO_ISOC;
break;
}
case USB_EP_MODE_INT:
{
ulRegister |= USB_TXTYPE1_PROTO_INT;
break;
}
case USB_EP_MODE_CTRL:
{
ulRegister |= USB_TXTYPE1_PROTO_CTRL;
break;
}
}
//发送/接收端点配置
if(ulFlags & USB_EP_HOST_OUT)
{
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_TXTYPE1) =
ulRegister;
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_TXINTERVAL1) =
ulNAKPollInterval;
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_TXMAXP1) =
ulMaxPayload;
ulRegister = 0;
if(ulFlags & USB_EP_AUTO_SET)
{
ulRegister |= USB_TXCSRH1_AUTOSET;
}
if(ulFlags & USB_EP_DMA_MODE_1)
{
ulRegister |= USB_TXCSRH1_DMAEN | USB_TXCSRH1_DMAMOD;
}
else if(ulFlags & USB_EP_DMA_MODE_0)
{
ulRegister |= USB_TXCSRH1_DMAEN;
}
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_TXCSRH1) =
(unsigned char)ulRegister;
}
else
{
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_RXTYPE1) =
ulRegister;
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_RXINTERVAL1) =
ulNAKPollInterval;
ulRegister = 0;
if(ulFlags & USB_EP_AUTO_CLEAR)
{
ulRegister |= USB_RXCSRH1_AUTOCL;
}
//DMA控制
if(ulFlags & USB_EP_DMA_MODE_1)
{
ulRegister |= USB_RXCSRH1_DMAEN | USB_RXCSRH1_DMAMOD;
}
else if(ulFlags & USB_EP_DMA_MODE_0)
{
ulRegister |= USB_RXCSRH1_DMAEN;
}
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_RXCSRH1) =
(unsigned char)ulRegister;
}
}
}
设备端点配置函数:
void USBDevEndpointConfigSet(unsigned long ulBase, unsigned long ulEndpoint,
unsigned long ulMaxPacketSize, unsigned long ulFlags)
{
unsigned long ulRegister;
if(ulFlags & USB_EP_DEV_IN)
{
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_TXMAXP1) =
ulMaxPacketSize;
ulRegister = 0;
if(ulFlags & USB_EP_AUTO_SET)
{
ulRegister |= USB_TXCSRH1_AUTOSET;
}
if(ulFlags & USB_EP_DMA_MODE_1)
{
ulRegister |= USB_TXCSRH1_DMAEN | USB_TXCSRH1_DMAMOD;
}
else if(ulFlags & USB_EP_DMA_MODE_0)
{
ulRegister |= USB_TXCSRH1_DMAEN;
}
if((ulFlags & USB_EP_MODE_MASK) == USB_EP_MODE_ISOC)
{
ulRegister |= USB_TXCSRH1_ISO;
}
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_TXCSRH1) =
(unsigned char)ulRegister;
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_TXCSRL1) =
USB_TXCSRL1_CLRDT;
}
else
{
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_RXMAXP1) =
ulMaxPacketSize;
ulRegister = 0;
if(ulFlags & USB_EP_AUTO_CLEAR)
{
ulRegister = USB_RXCSRH1_AUTOCL;
}
if(ulFlags & USB_EP_DMA_MODE_1)
{
ulRegister |= USB_RXCSRH1_DMAEN | USB_RXCSRH1_DMAMOD;
}
else if(ulFlags & USB_EP_DMA_MODE_0)
{
ulRegister |= USB_RXCSRH1_DMAEN;
}
if((ulFlags & USB_EP_MODE_MASK) == USB_EP_MODE_ISOC)
{
ulRegister |= USB_RXCSRH1_ISO;
}
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_RXCSRH1) =
(unsigned char)ulRegister;
HWREGB(ulBase + EP_OFFSET(ulEndpoint) + USB_O_RXCSRL1) =
USB_RXCSRL1_CLRDT;
}
}
从FIFO中读取数据函数:
long USBEndpointDataGet(unsigned long ulBase, unsigned long ulEndpoint,
unsigned char *pucData, unsigned long *pulSize)
{
unsigned long ulRegister, ulByteCount, ulFIFO;
if(ulEndpoint == USB_EP_0)
{
ulRegister = USB_O_CSRL0;
}
else
{
ulRegister = USB_O_RXCSRL1 + EP_OFFSET(ulEndpoint);
}
//判断数据是否准备好。
if((HWREGH(ulBase + ulRegister) & USB_CSRL0_RXRDY) == 0)
{
*pulSize = 0;
return(-1);
}
//获取要读取的数据个数
ulByteCount = HWREGH(ulBase + USB_O_COUNT0 + ulEndpoint);
ulByteCount = (ulByteCount < *pulSize) ? ulByteCount : *pulSize;
*pulSize = ulByteCount;
ulFIFO = ulBase + USB_O_FIFO0 + (ulEndpoint >> 2);
//从FIFO中读取
for(; ulByteCount > 0; ulByteCount--)
{
*pucData++ = HWREGB(ulFIFO);
}
return(0);
}
写数据到FIFO中函数:
long USBEndpointDataPut(unsigned long ulBase, unsigned long ulEndpoint,
unsigned char *pucData, unsigned long ulSize)
{
unsigned long ulFIFO;
unsigned char ucTxPktRdy;
if(ulEndpoint == USB_EP_0)
{
ucTxPktRdy = USB_CSRL0_TXRDY;
}
else
{
ucTxPktRdy = USB_TXCSRL1_TXRDY;
}
//判断是否可以写入数据
if(HWREGB(ulBase + USB_O_CSRL0 + ulEndpoint) & ucTxPktRdy)
{
return(-1);
}
//计算FIFO地址
ulFIFO = ulBase + USB_O_FIFO0 + (ulEndpoint >> 2);
//写入FIFO
for(; ulSize > 0; ulSize--)
{
HWREGB(ulFIFO) = *pucData++;
}
return(0);
}
发送刚写入FIFO的数据函数:
long USBEndpointDataSend(unsigned long ulBase, unsigned long ulEndpoint,
unsigned long ulTransType)
{
unsigned long ulTxPktRdy;
if(ulEndpoint == USB_EP_0)
{
ulTxPktRdy = ulTransType & 0xff;
}
else
{
ulTxPktRdy = (ulTransType >> 8) & 0xff;
}
// 判断发送数据包是否准备好
if(HWREGB(ulBase + USB_O_CSRL0 + ulEndpoint) & USB_CSRL0_TXRDY)
{
return(-1);
}
//发送刚写入的数据
HWREGB(ulBase + USB_O_CSRL0 + ulEndpoint) = ulTxPktRdy;
return(0);
}
以上介绍了常用USB寄存器,不常用寄存器请读者参考相关数据手册。通过以上寄存器操作可以开发USB主机与设备模块,可以完成全部USB2.0支持的全速和低速系统开发。一般情况下,不使用寄存器级编程,为了方便使用,LM3S处理器官方已经制作好了C语言“driverlib.lib”库,并免费为开发人员提供,在LM3S5000系列MCU中已将“driverlib.lib”库预先放入ROM中,节约程序储存空间,并且调用速度更快。第三章将重点介绍Stellaris处理器的USB底层驱动函数。已经编译到driverlib.lib中,只要加入usb.h头文件就可以进行开发。第四章及以后的章节会介绍使用usblib.lib开发USB主机与设备模块。
2.4 USB处理配置使用
与其它处理器一样,在使用其相关外设资源时,要先进行初始化配置。初始化与配置分为四步:
① 内核配置
使用USB处理器前必须配置RCGC2寄存器,使能其外设时钟;使能USB的PLL为PHY提供时钟;使能相应USB中断。
② 管脚配置
配置RCGC2使能相应GPIO模块;配置GPIOPCTL寄存器中的PMCn位,分配USB信号到合适的管脚上(根据具体芯片配置,有的芯片不需要此步);作为设备时,必须禁止向VBUS供电,使用外部主机控制器供电。通常使用USB0EPEN信号用于控制外部稳压器,禁止使能外部稳压器,避免同时驱动电源管脚USB0VBUS。
③ 端点配置
在主机模式,在和设备端点建立连接时配置;在设备模式,设备枚举之前配置。实际使用时端点很少需要设置,但都很重要。
④ 建立通信
硬件配置完成后还需进行协议配置,比如描述符、类协议之类,与USB通信相关的协议部分都需要考虑。
例如:使用USB处理器做鼠标,开始进要进行以下配置(①、②步骤,③、④后面详细讲)。
//配置内核CPU时钟,作设备时不能低于20MHz.
HWREG(SYSCTL_RCC) &= ~(SYSCTL_RCC_MOSCDIS);
SysCtlDelay(524288);
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) &
~(SYSCTL_RCC_PWRDN | SYSCTL_RCC_XTAL_M |
SYSCTL_RCC_OSCSRC_M)) |
SYSCTL_RCC_XTAL_8MHZ | SYSCTL_RCC_OSCSRC_MAIN);
SysCtlDelay(524288);
HWREG(SYSCTL_RCC) = ((HWREG(SYSCTL_RCC) & ~(SYSCTL_RCC_BYPASS |
SYSCTL_RCC_SYSDIV_M)) | SYSCTL_RCC_SYSDIV_4 |
SYSCTL_RCC_USESYSDIV);
//使能USB设备时钟
SysCtlPeripheralEnable(SYSCTL_PERIPH_USB0);
// 打开 USB Phy 时钟.
SysCtlUSBPLLEnable();
//清除中断标志。
USBIntStatusControl(USB0_BASE);
USBIntStatusEndpoint(USB0_BASE);
//使能相关中断
USBIntEnableControl(USB0_BASE, USB_INTCTRL_RESET |
USB_INTCTRL_DISCONNECT |
USB_INTCTRL_RESUME |
USB_INTCTRL_SUSPEND |
USB_INTCTRL_SOF);
USBIntEnableEndpoint(USB0_BASE, USB_INTEP_ALL);
//开总中断
IntEnable(INT_USB0);
//引脚配置
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,0xf0);
GPIOPinWrite(GPIO_PORTF_BASE,0xf0,0);
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE,0x0f);
HWREG(GPIO_PORTF_BASE+GPIO_O_PUR) = 0x0f;