我正在为 NXP LPC1788 微控制器开发代码,我的部分工作是使基于它的产品与 USB 兼容。大部分工作都已完成,通常通过 USB 进行的通信几乎与通过 CAN 进行的通信一样好。
但是,我遇到的一个问题是,当从微控制器产生持续输出的 USB 消息时,这些消息非常接近发送,其中一些消息偶尔会丢失。
我正在使用基于WinUSB编写的自定义驱动程序来接收PC端的消息,我最初怀疑问题出在事物的接收端。但是,使用 USBLyzer,我现在确信问题出在发送端 - USBLyzer 日志与我从WinUsb_ReadPipe()得到的日志完全匹配。
LPC1788 使用 USB 2.0 全速协议,我已经确认使用探头以大约 12 MHz 的频率发送和接收信息,这是应该的。
该设备配置为使用两个端点:逻辑端点 2 IN 和逻辑端点 2 OUT。这两个都配置为批量传输,最大数据包大小为 64 字节。
我认为消息的发送间隔至少为 500-600 微秒(我在线程中引入了 500 微秒的人为延迟,消息传输所需的时间应该比这少得多)。这是关于我上周得到的;我现在无法检查,因为我的调试工具正在运行。
这是微控制器的 USB 初始化代码:
void USBInit()
{
// Configure USB pins.
PINSEL_ConfigPin(0, 29, 1); // USB_D+1
PINSEL_ConfigPin(0, 30, 1); // USB_D-1
PINSEL_ConfigPin(1, 18, 1); // USB_UP_LED1
PINSEL_ConfigPin(2, 9, 1); // USB_CONNECT1
PINSEL_ConfigPin(1, 30, 2); // USB_VBUS
// Turn on power and clock
CLKPWR_ConfigPPWR(CLKPWR_PCONP_PCUSB, ENABLE);
PINSEL_SetPinMode(1, 30, PINSEL_BASICMODE_PLAINOUT);
// Set DEV_CLK_EN and AHB_CLK_EN.
LPC_USB->USBClkCtrl |= 0x12;
// Wait until change is reflected in clock status register.
while((LPC_USB->USBClkSt & 0x12) != 0x12);
// Enable NVIC USB interrupts.
NVIC_EnableIRQ(USB_IRQn);
// Reset the USB.
USBReset();
// Set device address to 0x0 and enable device & connection.
USBSetAddress(0);
}
这是微控制器用于通过 USB 发送消息的代码:
uint32_t USB_Send(uint32_t endpoint, uint8_t *pData, uint32_t count)
{
// Convert into a form that can be sent successfully using USB.
uint8_t data[USB_MAX_PACKET_SIZE];
for(int i=0; i < count; i++)
{
data[i*2] = hex[(pData[i] >> 4)];
data[(i*2)+1] = hex[(pData[i] & 0xF)];
}
return USBWriteEndpoint(endpoint, data, count*2);
}
uint32_t USBWriteEndpoint(uint32_t endpoint, uint8_t *pData, uint32_t count)
{
uint32_t i;
LPC_USB->Ctrl = ((endpoint & 0xF) << 2) | CTRL_WR_EN;
LPC_USB->TxPLen = count;
for(i=0; i < (count+3)/4; i++)
{
LPC_USB->TxData = *((__packed uint32_t *)pData);
pData += 4;
}
LPC_USB->Ctrl = 0;
USBValidateEndpoint(endpoint);
return count;
}
void USBValidateEndpoint(uint32_t endpoint)
{
writeSIEEndpointCommand(endpoint, CMD_VALID_BUF);
}
void writeSIECommandData(uint32_t cmd, uint32_t data)
{
LPC_USB->DevIntClr = CCEMTY_INT;
LPC_USB->CmdCode = cmd;
while((LPC_USB->DevIntSt & CCEMTY_INT) == 0);
LPC_USB->DevIntClr = CCEMTY_INT;
LPC_USB->CmdCode = data;
while((LPC_USB->DevIntSt & CCEMTY_INT) == 0);
}
编辑
为了了解正在发生的事情,这是一个从我的 USB 驱动程序的接收函数生成的日志文件(来自 USBLyzer 的那个实际上是相同的):
0000030D000D
0000010D002D0004001B0024
0000000D0FFF001600310016
0000010D002D0004001F0028
0000020D00280028001B002D
0000030D0009
0000000D0FFF001600310016
0000010D002D0004001F0028
0000020D00280028001B002D
0000030D0009
0000010D002D0004001F0028
0000020D00280028001B002D
0000030D0009
0000010D002D0004001F0028
0000020D00280028001B002D
0000030D0009
0000010D002D0004001F0028
0000020D00280028001B002D
0000030D0009
0000000D0FFF001600310016
0000010D002D0004001F0028
0000020D00280028001B002D
0000030D0009
0000010D002D0004001F0028
我应该在以下周期收到消息:
0000000D...
0000010D...
0000020D...
0000030D...
您可以从此日志中看到循环中的一些消息被跳过。
编辑 2
以下是 USBLyzer 生成的原始和过滤捕获日志的摘录。原始日志主要包含取消的请求,因为我的驱动程序是轮询驱动的并且使用超时。
原始日志:
USBlyzer Report
Capture List
Type Seq Time Elapsed Duration Request Request Details Raw Data I/O C:I:E Device Object Device Name Driver Name IRP Status
START 0001 11:09:15.413
URB 0002 11:09:18.484 3.071197 s Bulk or Interrupt Transfer 10 bytes data 30 30 30 30 30 30 31 46... out 01:00:02 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA801142FAB0h
00000000 30 30 30 30 30 30 31 46 30 31 0000001F01
URB 0003 11:09:18.484 3.071212 s Bulk or Interrupt Transfer 64 bytes buffer in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h
URB 0004-0002 11:09:18.484 3.071371 s 174 us Bulk or Interrupt Transfer 10 bytes buffer out 01:00:02 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA801142FAB0h Success (Success)
URB 0005-0003 11:09:18.485 3.071586 s 374 us Bulk or Interrupt Transfer in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Cancelled (Canceled)
URB 0006 11:09:18.485 3.071608 s Bulk or Interrupt Transfer 64 bytes buffer in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h
URB 0007-0006 11:09:18.486 3.072582 s 974 us Bulk or Interrupt Transfer in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Cancelled (Canceled)
URB 0008 11:09:18.486 3.072603 s Bulk or Interrupt Transfer 64 bytes buffer in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h
URB 0009-0008 11:09:18.487 3.073598 s 996 us Bulk or Interrupt Transfer in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Cancelled (Canceled)
URB 0010 11:09:18.487 3.073630 s Bulk or Interrupt Transfer 64 bytes buffer in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h
URB 0011-0010 11:09:18.488 3.074601 s 970 us Bulk or Interrupt Transfer in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Cancelled (Canceled)
[...]
URB 2504-2501 11:09:19.734 4.320666 s 161 us Bulk or Interrupt Transfer 14 bytes buffer out 01:00:02 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA800CF662D0h Success (Success)
URB 2505-2503 11:09:19.734 4.320785 s 192 us Bulk or Interrupt Transfer 24 bytes data 30 30 30 30 30 30 30 44... in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Success (Success)
00000000 30 30 30 30 30 30 30 44 30 46 46 46 30 30 31 36 0000000D0FFF0016
00000010 30 30 33 31 30 30 31 42 0031001B
过滤的日志:
USBlyzer Report
Capture List
Type Seq Time Elapsed Duration Request Request Details Raw Data I/O C:I:E Device Object Device Name Driver Name IRP Status
URB 0004-0002 11:09:18.484 3.071371 s 174 us Bulk or Interrupt Transfer 10 bytes buffer out 01:00:02 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA801142FAB0h Success (Success)
URB 2504-2501 11:09:19.734 4.320666 s 161 us Bulk or Interrupt Transfer 14 bytes buffer out 01:00:02 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA800CF662D0h Success (Success)
URB 2505-2503 11:09:19.734 4.320785 s 192 us Bulk or Interrupt Transfer 24 bytes data 30 30 30 30 30 30 30 44... in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Success (Success)
00000000 30 30 30 30 30 30 30 44 30 46 46 46 30 30 31 36 0000000D0FFF0016
00000010 30 30 33 31 30 30 31 42 0031001B
URB 2507-2506 11:09:19.734 4.321309 s 459 us Bulk or Interrupt Transfer 24 bytes data 30 30 30 30 30 31 30 44... in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Success (Success)
00000000 30 30 30 30 30 31 30 44 30 30 32 44 30 30 30 34 0000010D002D0004
00000010 30 30 31 46 30 30 32 44 001F002D
URB 2511-2510 11:09:19.735 4.321931 s 311 us Bulk or Interrupt Transfer 24 bytes data 30 30 30 30 30 32 30 44... in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Success (Success)
00000000 30 30 30 30 30 32 30 44 30 30 32 38 30 30 32 38 0000020D00280028
00000010 30 30 31 42 30 30 33 31 001B0031
URB 2513-2512 11:09:19.735 4.322306 s 332 us Bulk or Interrupt Transfer 12 bytes data 30 30 30 30 30 33 30 44... in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Success (Success)
00000000 30 30 30 30 30 33 30 44 30 30 30 44 0000030D000D
URB 2725-2724 11:09:19.840 4.426662 s 89 us Bulk or Interrupt Transfer 24 bytes data 30 30 30 30 30 30 30 44... in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Success (Success)
00000000 30 30 30 30 30 30 30 44 30 46 46 46 30 30 31 36 0000000D0FFF0016
00000010 30 30 33 31 30 30 31 42 0031001B
URB 2727-2726 11:09:19.840 4.427183 s 471 us Bulk or Interrupt Transfer 24 bytes data 30 30 30 30 30 31 30 44... in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Success (Success)
00000000 30 30 30 30 30 31 30 44 30 30 32 44 30 30 30 34 0000010D002D0004
00000010 30 30 31 46 30 30 32 44 001F002D
URB 2731-2730 11:09:19.841 4.427803 s 209 us Bulk or Interrupt Transfer 24 bytes data 30 30 30 30 30 32 30 44... in 01:00:82 FFFFFA800FC98440h USBPDO-11 usbhub FFFFFA8010E965A0h Success (Success)
00000000 30 30 30 30 30 32 30 44 30 30 32 38 30 30 32 38 0000020D00280028
00000010 30 30 31 42 30 30 33 31 001B0031