我的USB设备(微控制器)阻止Windows启动

时间:2014-10-17 10:16:30

标签: usb microcontroller lpc

我一直在为恩智浦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

分别将iManufactureriProductiSerialNumber更改为0x1,0x2和0x3,以便USBLyzer不会获取字符串描述符,这些字符串描述符不是很有希望标志。如果我使用原始索引值,它会。我还没有检查这会如何影响计算机的启动能力。

编辑3

我注意到我的iSerialNumberiInterface参数为2。 0x30+0x14 = 0x44

我会看看是否有任何修复。

编辑4

在纠正上述两个参数后,我的问题似乎已得到解决。 TurboJ引起了我的注意,指数值意味着很小,例如0x1,0x2,0x3 ......

NXP似乎对如何操作有不同的想法,我复制了他们的方式,但我想我可以稍后修改代码,使其像其他USB设备一样工作。

2 个答案:

答案 0 :(得分:2)

 0x04,                              /* iManufacturer */
 0x30,                              /* iProduct */
 0x42,                              /* iSerialNumber */

您的iProductiSerialNumber字节似乎已关闭 - 这些是索引号,通常很小。您的描述符在字符串描述符中需要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;

这意味着他们必须使用荒谬的索引值指定iManufactureriProduct等,例如(在他们的情况下)0x040x20和{{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等指定为iProduct0x01 ......

我已经使用两台计算机对此进行了测试,并且当我的应用程序连接并运行时,两者都能够成功启动。