本帖最后由 宫影空明人不往 于 2024-4-11 10:01 编辑
前言
最近使用APM32F4MCU的USB设备制作了一个小工具,需要对其USB进行眼图测试。在进行眼图测试的时候发现没有任何波形产生,但是USB插上主机时能够正常被识别。
USB信号测试
USB信号质量测试主要包含:Test_J,Test_K,Test_SE0_NAK,Test_Packet,Test_Force_Enable。其测试原理为设备USB控制器的测试控制寄存器,是USB控制器能够进入测试模式,从而使USB控制器能够持续产生测试信号。这时候,在将USB控制器产生测信号接到示波器来进行波形分析进而完成USB的信号质量测试。
通过查看APM32F4xx的应用手册,其控制USB设备进入测试模式的寄存器为OTG_HS1_DCTRL中的TESTSEL位。
其中,选择Test_Packet则能够让USB进入眼图测试。
USB测试模式
通过上面,可以知道进行USB信号测试需要先让USB控制器进入测试模式,并且也知道了如何操作寄存器是USB能够进入相应的测试模式。但是USB设备如何得知自己需要选择并进入相应的测试模式呢。这时我们可以通过判断一个正常的USB设备和我写的USB设备在眼图测试时的USB信号流的差异。当我使用一个正常的U盘设备去进行眼图测试时,发现在开启眼图测试的时候主机会发送一段Set_feature命令给设备,然后设备就会应答并进入测试模式并发送相应的测试信号。具体情况如下:
而当对我自己编写程序的USB设备进行测试时,发现只有主机发送一段Set_feature命令后,设备只作了应答,后续没有相应的测试信号,具体情况如下:
那么可以断定,程序中是没有对Set_feature命令应答后续进行处理的。
USB程序修改
这里使用的USB代码为APM32_USB_SDK_V1.1版本的代码。通过查找Set_Feature相关函数发现,USB代码有对Set_feature命令做处理,具体代码如下:
static USBD_STA_T USBD_REQ_SetFeature(USBD_INFO_T* usbInfo, USBD_REQ_SETUP_T* req)
{
USBD_STA_T usbStatus = USBD_OK;
uint16_t wValue = req->DATA_FIELD.wValue[0] | req->DATA_FIELD.wValue[1] << 8;
switch (wValue)
{
case USBD_FEATURE_REMOTE_WAKEUP:
usbInfo->devRemoteWakeUpStatus = ENABLE;
USBD_CtrlSendStatus(usbInfo);
break;
case USBD_FEATURE_TEST_MODE:
usbInfo->devTestModeStatus = req->DATA_FIELD.wIndex[1];
USBD_CtrlSendStatus(usbInfo);
break;
default:
USBD_REQ_CtrlError(usbInfo, req);
break;
}
return usbStatus;
}
该代码中,会对测试模式的选择的值存储起来。接下来对该变量进行全局搜索,找到该变量使用到的地方。
具体为:
<blockquote> if (usbInfo->devTestModeStatus == ENABLE)
然后发现这里的判断有点问题,因为devTestModeStatus存储的是一个非零的数值,而代码中ENABLE特指的是数值1,因此需要将其判断语句修改成不等于DISABLE。
然后在进入USBD_TestModeHandler(usbInfo);函数中,发现里面没有做相关处理。那么,关于无法测试的原因就找到了。只需要在该函数里面添加上操OTG_HS1_DCTRL寄存器中的TESTSEL位的代码即可,具体为: switch (usbInfo->devTestModeStatus)
{
case TEST_J:
case TEST_K:
case TEST_SE0_NAK:
case TEST_PACKET:
case TEST_FORCE_EN:
USB_OTG_HS_D->DCTRL |= (uint32_t)testMode << 4;
break;
default:
break;
}
最后,在进行USB测试时,能够在示波器上成功显示出相应的波形。
|