MAX3420E系统调试
引言
当您设计了一块电路板,将max3420e与您喜爱的微控制器整合在一起。加电,插入usb,不能正常工作...,怎么办? 本文为您提供了答案。
第一次调试usb外设器件时,会面临很大的挑战。要使max3420e能够正常工作,首先需要按下列步骤进行检查。
检查usb b型连接器的引脚
这是最容易出错的地方—视图是顶视图还是底视图? 引脚1在哪里? 如果您不是机械工程师,这些视图会让人感觉无所适从。图1和图2可帮您解决这一问题。


应采用欧姆表来检查max3420e和usb连接器之间的连线。特别注意d+和d-。二者很容易搞反。请注意,max3420e与连接器d+和d-引脚之间有33电阻。对于这么小的电阻,大部分测试是否接通的仪表都会发出“嘀嘀”声。如果需要检查usb电缆,请参考图3。
usb“完整性”检查
本节阐述设备与usb的连接情况。完整性检查给出了d+和d-线的工作情况,在没有usb总线分析仪的情况下,这种方法非常有效。
复位处理器,将电缆连接至pc usb端口,初始化代码执行完毕后,在设置connect位的语句前停止运行。该语句如下:
wreg(rusbctl,bmconnect); // connect to usb
在执行该语句之前,d+和d-应均为低电平。这是因为电缆的主机侧电路通过15k电阻将这些信号下拉至地。现在,单步执行connect语句后,max3420e在d+和vcc
(3.3v)之间接入一个1.5k内部电阻。此时,d+应变为高电平,其后会出现一些突发脉冲(图4)。

上面的波形是d+,下面的是d-。该突发波形持续约18s,然后消失。d+保持高电平,d-保持低电平,然后弹出下面的windows xp消息框(图5):

怎么回事?
请注意,程序为单步执行。到目前为止所作的只是连接了d+上拉电阻。该上拉提示pc有新的usb设备刚刚插入,因此pc开始向该设备发送信号,确定设备类型。这就是图4中的脉冲信号。由于微控制器代码停止运行,因此不会命令max3420e做出任何响应。pc由于没有收到响应信号,最终决定(18秒后)忽略该设备。d+为高电平和d-为低电平的总线状态称为“usb总线挂起”或者“挂起”。主机停止发送任何信号,max3420e的d+上拉电阻保持d+信号为高电平。

图6所示为利用lecroy instruments (lecroy兼并了catc,catc是该分析仪的最初生产商)的usb总线分析仪测得的总线过程。当pc探测到设备插入后(connect = 1),它发出一个usb总线复位信号(没有画出)。然后,在transfer 0,它发出一个“get_descriptor”请求以获取“device”类型。5.687s之后,pc发出第二个usb总线复位信号,再尝试5.578s,要求得到设备描述符。pc第三次复位总线,再尝试5.580s,然后挂起总线并放弃尝试。由于没有运行固件,设备不会听取或应答(ack) pc的请求。

为清晰起见,图6没有画出max3420e回送的nak (非应答)握手信号。图7将第一次传输过程展开,详细地显示数据包。现在可以看到transfer 0以下面三个封包开始:
主机向刚刚连上的设备 在这种情况下,usb发送地址0)发送一个setup包(63)。
主机发送一个data包(64),包含一个8字节“操作码”。
外设(max3420e)回送一个ack包(65),确认无差错地收到两个主机封包。
如果打开含有max3420e的系统,插入usb,设置connect = 1 (但是不再进行其他操作),max3420e将发出ack握手包(上面第3步的65字节包)。max3420e硬件自动应答control传输的setup阶段,这是由usb规范规定的。
接下来,主机开始发送in请求,并从transaction 1开始。对应每个in请求,max3420e回送nak (非应答)握手信号。这是因为还没有运行程序,因此,与max3420e连接的微控制器不会收到sudav
irq (setup数据就绪中断请求)。
注意:max3420e通过置位sudav irq,提示微控制器收到了setup包。该信息通知微控制器需要对数据包解码,并回送要求的数据作为响应。
这些in-nak过程持续5.687s,此时pc会复位总线,开始第二次尝试。图4中的脉冲信号即是in-nak过程。如果仔细观察示波器,5s后波形将略有变化—这对应总线复位(d+和d-同时置低约30ms),其后是另一个setup包。然后,in-nak再持续5s。
供参考:另一个分析仪

产生图6和图7波形的usb总线分析仪可能超出了您的预算。尽管本应用笔记假设您只有一个示波器和欧姆表,我们还是强烈建议在usb开发过程中使用usb总线分析仪。我们使用的lecroy/catc具有多种优点,包括友好的界面和丰富的软件,最重要的是它享有工业标准usb测量工具的美誉。通过比对catc波形来确定实际情况,解决了许多争论不休的问题(硬件、软件和芯片等)。总线总是如实反映情况。
幸亏现在有低成本usb分析仪。图8所示为beagle-usb的屏幕截图。beagle分析仪能够以比lecroy/catc低很多的价格显示总线的工作情况。如果对比图8中的index 10和图6中的64字节数据包,会发现它们显示了完全相同的setup数据包。
检查进程
如果观察到了图4中的信号,已经可以确定usb连接器的连线是正确的,而且max3420e供电正常。如果还没有观察到该显示,可以尝试以下措施:
测量max3420e的res#引脚,确定其为高电平。
测量晶振,确保其振荡频率为12mhz。必须是12mhz ±0.25%才能满足usb规范。如果超出容限,检查所连接的负载电容是否与并联谐振晶体所规定的电容一致(通常采用18pf)。
检查vcc是否为3.3v。
检查系统接口电压vl。确保不超过3.6v。
如果由vbus通过一个3.3v稳压器对max3420e的vcc引脚供电,确定连接了usb。否则,max3420e的vcc无法供电。
注意:由于固件运行与否和usb电缆连接无关,因此,与总线供电的设计相比,调试自供电设计要简单一些。可以先采用外部电源对样机供电。如果需要,以后可以再转为总线供电。
下一步检查您的控制器是否能够成功地通过spi总线与max3420e寄存器组进行通信。
检查rreg()和wreg()。
编写任何程序,无论是采用maxim的实例代码还是自己从头开始编写代码,都需要使用读写max3420e寄存器的函数。下面的例子使用了这些函数原型:
unsigned char rreg(byte r); // read a max3420e register byte
void wreg(byte r,byte v); // write a max3420e register byte
在调试处理usb传输的代码前,先编写一个简单的子程序来测试这些函数。参见图9的例子:

图9中的测试代码先复位max3420e,然后向usbien寄存器写入每字节移动1位的8个字节。每个字节中有一位置位,从00000001开始,然后是00000010,最终以10000000结束。单步执行该函数,检查“rd”值8次,确定其值为0x01,0x02,0x04,0x08,0x10,0x20,0x40和0x80。如果是这样,则可以确定spi接口寄存器的写和读操作均正常。如果能够写入usbien寄存器,并可靠的读回其内容,那么就可以读写所有的max3420e寄存器。

图10所示为采用crossstudio调试maxq2000微控制器的屏幕截图。将光标指向“rd”变量时,将激活弹出窗口(截图没有显示光标)。单步执行代码时,可采用这种方式来查看任何变量。
测试代码首先设置微处理器spi端口。对应每种微处理器类型和特定io引脚分配,spi_init()函数各不相同。然后,代码向pinctl寄存器写入0x10,设置max3420e spi接口为全双工工作模式。这将置位fdupspi位。代码置位chipres位,然后对其清零,使max3420e处于已知的状态。建议在代码的开始部分包含芯片复位功能,从而在每一个调试周期的开始使max3420e处于已知的状态。
如果图10中的代码没有产生正确的结果,应检查spi信号,确定其工作是否正常。

测试程序test_spi()中的第一次wreg()调用,向max3420e的寄存器17写入数值0x10。spi总线的波形应与图11所示一致。
注意:图11所示的波形使用spi模式(0,0),在sclk的上升沿采样spi数据,sclk的空闲电平为低电平。spi接口不同,显示的波形会有不同的脉冲持续时间,但是对应sclk上升沿的数值应该相同。每次访问spi的第一个字节是命令字节,其字节格式如图12所示。注意图11中对应前一部分slck上升沿的mosi波形,位模式10001010指定寄存器17 (第7位至第3位是10001,数值为17)。同样,第1位为高电平,表明是写操作。第二个字节的位模式是00010000。这是写入寄存器17的数据,即0x10 (只有第4位fdupspi寄存器位置位)。因此,该spi访问将0x10写入寄存器17,置位fdupspi位。

得到这些波形的一种简单方法是设置示波器或者逻辑分析仪在ss#的下降沿触发,单步执行wreg()调用。

test_spi()中的下一条语句是rreg()函数。第一次进入循环体时,将数值0x01写入usbien寄存器,如图13所示。

然后,test_spi()函数读回usbien寄存器的数值,第一次通过循环体时,应等于1 (图14)。每次通过循环体时,写入和读回的位应向左移动一个sclk边沿。
max3420e寄存器写和读操作验证完毕后,可以进一步调试程序。到目前为止所有的检查步骤均属于“完整性检查”。现在,我们开始实际处理usb通信功能的第一步:需要处理器响应不同的max3420e中断请求位。
irq位设置
似乎应该usb总线通信开始后max3420e才会置位中断请求位。实际上,当max3420e上电时,就会有irq位置位,当插入usb电缆和设置connect
= 1时,又有其他irq位置位。下面介绍该启动过程的中断请求情况。
完成复位
当max3420e完成复位后,即使还没有插入usb,某些中断请求位就会置位。这些位是:
epirq寄存器:
in3bavirq
in2bavirq
in0bavirq
epirq寄存器的初始值应为0x19。max3420e置位这三个irq位,指示三个in端点fifo已经准备就绪,可以装入数据。bav表示“buffer
available”。
usbirq寄存器:
oscokirq
usbirq寄存器的初始值应为0x01。上电时,max3420e启动其片内振荡器。振荡器稳定后,max3420e置位oscokirq位,指示已经准备就绪,可以进行工作。如果程序没有通过oscokirq位检查,请确定vcc引脚电压为3.3v。vcc为振荡器供电。
注意:max3420e irq寄存器位不论其对应的使能位(在epien和usbien寄存器中)是否置位,均可有效置位。使能位决定是否将请求位传送到驱动int引脚的逻辑电路。参见应用笔记3661,max3420e中断系统,了解更详细的信息。
usb插入后
插入usb (connect = 0)后,即使usb没有通信,仍有一些usbirq位会置位。epirq位与上面的情况一致,但是更多的usbirq位将置位:
usbirq寄存器:
oscokirq
vbusirq (可能)
vbusirq位指示max3420e通过检测vbcomp引脚上的5v信号,探测到插入了usb电缆。这假定您已经将usb连接器的vbus引脚连接至max3420e微控制器(vbus比较器)的输入引脚。
设置connect = 1之后
连接usb使主机发出一个总线复位信号,产生get_descriptor-device请求,最终挂起总线。这些操作会置位usbirq寄存器中的更多irq位。注意,usb总线复位将清除vbusirq位。
epirq寄存器:
in3bavirq
in2bavirq
in0bavirq
sudavirq (通信开始后)
usbirq寄存器:
oscokirq
uresirq
uresdnirq
suspirq (最后)
如果将vbus接vbcomp引脚,usbirq寄存器读数为0x8d,并持续约20s,然后由于主机挂起总线,读数变为0x9d。
接下来的情况会取决于您的代码。如果您观察到的情况和前面吻合,则表明系统一切正常,可以继续往下检查您的代码。
调试方法:通过3个步骤触发中断
剩下的检查是确保固件能够正确响应pc发出的不同usb请求命令,并由max3420e给出相应信号。如果启动程序,插入usb后,什么也没有发生(可能会出现windows
usb错误消息),那么可能是您的程序没有处理中断。下面的调试方法可以帮助解决这些中断问题。
第1步: 轮询irq位
首先,编写代码直接轮询irq位,当关心的irq位置位后,使处理器进行相应操作。即使主程序循环进行直接轮询,也最好使能中断(各ien位
= 1和ie = 1)。这样可以通过观察max3420e int引脚来了解其工作情况。这一步有效地取消了微控制器中断系统(和代码)检查,使您能够集中精力实现正确的usb功能。当连续读取epirq和usbirq寄存器时,不必担心浪费的spi周期—这一步的目的是使usb正常工作。
第2步: 轮询int引脚状态
一旦usb工作正常后,进行第二步,修改程序来轮询max3420e int引脚状态,检查悬挂的中断。如果第1步已经验证了程序,那么在程序主循环中有部分代码一直读取epirq和usbirq寄存器,检查悬挂的中断。插入轮询微控制器中断引脚状态(连接在max3420e
int引脚上)的语句,修改第1步的连续检查。如果max3420e int引脚未产生中断,可以跳过读取epirq和usbirq寄存器的语句。这种简单的检查方式极大地减少了微控制器和max3420e之间的spi数据流量,这是因为只有irq位置位时,才对其进行测试。
第3步: 检查微控制器中断程序
第3步也是最后一步,将max3420e整合到微处理器的中断系统中。这通常要写一个中断向量,以自动将程序执行位置指向max3420e处理程序。
评论