我一直在为恩智浦LPC1788微控制器开发一个应用程序,该应用程序涉及使用USB与主机PC通信。
一般来说,应用程序运行正常。但是,我在多台不同的计算机上注意到的事情是,如果微控制器已上电并连接到已断电的计算机,然后计算机开启,则计算机将无法启动。拔下微控制器并尝试再次启动计算机将解决问题。
为什么微控制器会阻止计算机启动?我已经用Google搜索了问题,当Windows尝试将USB设备视为无法启动时,似乎会出现此问题。
有没有办法可以阻止我的应用程序发生这种情况?我应该提供哪些信息来帮助其他人诊断问题?
如果它有用,下面是micro的设备描述符:
/* USB Standard Device Descriptor */
const uint8_t USB_DeviceDescriptor[] = {
USB_DEVICE_DESC_SIZE, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL(0x0200), /* 2.00 */ /* bcdUSB */
0xFF, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
USB_MAX_PACKET_SIZE, /* bMaxPacketSize0 */
WBVAL(<...>), /* idVendor */
WBVAL(<...>), /* idProduct */
WBVAL(0x0100), /* 1.00 */ /* bcdDevice */
0x04, /* iManufacturer */
0x30, /* iProduct */
0x42, /* iSerialNumber */
0x01 /* bNumConfigurations */
};
这是配置描述符:
const uint8_t USB_ConfigDescriptor[] = {
/* Configuration 1 */
USB_CONFIGURATION_DESC_SIZE, /* bDescriptorType */
USB_CONFIGURATION_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL( /* wTotalLength */
1*USB_CONFIGURATION_DESC_SIZE +
1*USB_INTERFACE_DESC_SIZE +
2*USB_ENDPOINT_DESC_SIZE
),
0x01, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
USB_CONFIG_SELF_POWERED /*|*/ /* bmAttributes */
/*USB_CONFIG_REMOTE_WAKEUP*/,
USB_CONFIG_POWER_MA(100), /* bMaxPower */
/* Interface 0, Alternate Setting 0, MSC Class */
USB_INTERFACE_DESC_SIZE, /* bLength */
USB_INTERFACE_DESCRIPTOR_TYPE, /* bDescriptorType */
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x02, /* bNumEndpoints */
0xFF, /* bInterfaceClass */
0x0, /* bInterfaceSubClass */
0x0, /* bInterfaceProtocol */
0x5C, /* iInterface */
/* Bulk In Endpoint (data) */
USB_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_ENDPOINT_IN(2), /* bEndpointAddress */
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
WBVAL(0x0040), /* wMaxPacketSize */
0x0, /* bInterval */
/* Bulk Out Endpoint (data) */
USB_ENDPOINT_DESC_SIZE, /* bLength */
USB_ENDPOINT_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_ENDPOINT_OUT(2), /* bEndpointAddress */
USB_ENDPOINT_TYPE_BULK, /* bmAttributes */
WBVAL(0x0040), /* wMaxPacketSize */
0x0, /* bInterval */
/* Terminator */
0 /* bLength */
};
修改
字符串描述符(替换为带下划线的字母):
const uint8_t USB_StringDescriptor[] = {
/* Index 0x00: LANGID Codes */
0x04, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL(0x0409), /* US English */ /* wLANGID */
/* Index 0x04: Manufacturer */
0x2C, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'_',0,
'_',0,
'_',0,
' ',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
' ',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
' ',0,
/* Index 0x30: Product */
0x14, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
'_',0,
' ',0,
/* Index 0x42: Serial Number */
0x1A, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
/* Index 0x5C: Interface 0, Alternate Setting 0 */
0x0E, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
'0',0,
};
编辑2
分别将iManufacturer
,iProduct
和iSerialNumber
更改为0x1,0x2和0x3,以便USBLyzer不会获取字符串描述符,这些字符串描述符不是很有希望标志。如果我使用原始索引值,它会。我还没有检查这会如何影响计算机的启动能力。
编辑3
我注意到我的iSerialNumber
和iInterface
参数为2。 0x30+0x14 = 0x44
。
我会看看是否有任何修复。
编辑4
在纠正上述两个参数后,我的问题似乎已得到解决。 TurboJ引起了我的注意,指数值意味着很小,例如0x1,0x2,0x3 ......
NXP似乎对如何操作有不同的想法,我复制了他们的方式,但我想我可以稍后修改代码,使其像其他USB设备一样工作。
答案 0 :(得分:2)
0x04, /* iManufacturer */
0x30, /* iProduct */
0x42, /* iSerialNumber */
您的iProduct
和iSerialNumber
字节似乎已关闭 - 这些是索引号,通常很小。您的描述符在字符串描述符中需要66个字符串。这些不寻常的高数字可能会导致BIOS USB实现溢出。
答案 1 :(得分:0)
我纠正了我的问题并改进了恩智浦的方法。
NXP的示例USB项目将所有字符串描述符保存在单个数组中。然后他们实现了&#34; USB Get Descriptor&#34;功能如下:
case USB_STRING_DESCRIPTOR_TYPE:
EP0Data.pData = (uint8_t *)USB_StringDescriptor + SetupPacket.wValue.WB.L;
len = ((USB_STRING_DESCRIPTOR *)EP0Data.pData)->bLength;
break;
这意味着他们必须使用荒谬的索引值指定iManufacturer
,iProduct
等,例如(在他们的情况下)0x04
,0x20
和{{1 }}
在我自己的代码中,我修改了他们的方法。我将字符串描述符维护为数组数组:
0x48
然后我改变了处理字符串描述符请求的方式:
const uint8_t USB_StringDescriptor[][100] = {
{
/* Index 0x00: LANGID Codes */
0x04, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL(0x0409), /* US English */ /* wLANGID */
},
{
/* Index 0x01: Manufacturer */
0x2A, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
// ...
},
{
/* Index 0x02: Product */
0x12, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
// ...
},
{
/* Index 0x03: Serial Number */
0x1A, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
// ...
},
{
/* Index 0x04: Interface 0, Alternate Setting 0 */
0x0E, /* bLength */
USB_STRING_DESCRIPTOR_TYPE, /* bDescriptorType */
// ...
}
};
这样,在我的设备描述符中,我可以将case USB_STRING_DESCRIPTOR_TYPE:
EP0Data.pData = (uint8_t *)USB_StringDescriptor[SetupPacket.wValue.WB.L];
len = ((USB_STRING_DESCRIPTOR *)EP0Data.pData)->bLength;
break;
,iManufacturer
等指定为iProduct
,0x01
......
我已经使用两台计算机对此进行了测试,并且当我的应用程序连接并运行时,两者都能够成功启动。