adongliu 发表于 2013-5-12 21:00:28

求助:lpc17xx USB 通信数据包丢失的原因?

使用keil例子中的CDC改写

中断程序
void USB_IRQHandler (void) {
U32 disr, val, n, m;
U32 episr, episrCur;

disr = LPC_USB->USBDevIntSt;                  /* Device Interrupt Status */

/* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
if (disr & DEV_STAT_INT) {
    LPC_USB->USBDevIntClr = DEV_STAT_INT;
    WrCmd(CMD_GET_DEV_STAT);
    val = RdCmdDat(DAT_GET_DEV_STAT);       /* Device Status */
    if (val & DEV_RST) {                  /* Reset */
      USB_Reset();
#if   USB_RESET_EVENT
      USB_Reset_Event();
#endif
    }
    if (val & DEV_CON_CH) {               /* Connect change */
#if   USB_POWER_EVENT
      USB_Power_Event(val & DEV_CON);
#endif
    }
    if (val & DEV_SUS_CH) {               /* Suspend/Resume */
      if (val & DEV_SUS) {                  /* Suspend */
      USB_Suspend();
#if   USB_SUSPEND_EVENT
      USB_Suspend_Event();
#endif
      } else {                              /* Resume */
      USB_Resume();
#if   USB_RESUME_EVENT
      USB_Resume_Event();
#endif
      }
    }
    goto isr_end;
}

#if USB_SOF_EVENT
/* Start of Frame Interrupt */
if (disr & FRAME_INT) {
    DEV_INT_CLR = FRAME_INT;
    USB_SOF_Event();
}
#endif

#if USB_ERROR_EVENT
/* Error Interrupt */
if (disr & ERR_INT) {
    DEV_INT_CLR = ERR_INT;
    WrCmd(CMD_RD_ERR_STAT);
    val = RdCmdDat(DAT_RD_ERR_STAT);
    USB_Error_Event(val);
}
#endif

/* Endpoint's Slow Interrupt */
if (disr & EP_SLOW_INT) {
    episrCur = 0;
    episr    = LPC_USB->USBEpIntSt;
    for (n = 0; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
      if (episr == episrCur) break;         /* break if all EP interrupts handled */
      if (episr & (1 << n)) {
      episrCur |= (1 << n);
      m = n >> 1;

      LPC_USB->USBEpIntClr = (1 << n);
      while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0);
      val = LPC_USB->USBCmdData;

      if ((n & 1) == 0) {               /* OUT Endpoint */
          if (n == 0) {                     /* Control OUT Endpoint */
            if (val & EP_SEL_STP) {         /* Setup Packet */
            if (USB_P_EP) {
                USB_P_EP(USB_EVT_SETUP);
                continue;
            }
            }
          }
          if (USB_P_EP) {
            USB_P_EP(USB_EVT_OUT);
          }
      } else {                            /* IN Endpoint */
          if (USB_P_EP) {
            USB_P_EP(USB_EVT_IN);
          }
      }
      }
    }
    LPC_USB->USBDevIntClr = EP_SLOW_INT;
}

#if USB_DMA
/* USB_DMA not yet supported */
#endif /* USB_DMA */

isr_end:
;
}端点读写/*
*Read USB Endpoint Data
*    Parameters:      EPNum: Endpoint Number
*                     EPNum.0..3: Address
*                     EPNum.7:    Dir
*                     pData: Pointer to Data Buffer
*    Return Value:    Number of bytes read
*/

U32 USB_ReadEP (U32 EPNum, U8 *pData) {
U32 cnt, n;

LPC_USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_RD_EN;

do {
    cnt = LPC_USB->USBRxPLen;
} while ((cnt & PKT_RDY) == 0);
cnt &= PKT_LNGTH_MASK;

for (n = 0; n < (cnt + 3) / 4; n++) {
    *((__packed U32 *)pData) = LPC_USB->USBRxData;
    pData += 4;
}

LPC_USB->USBCtrl = 0;

if (((EP_MSK_ISO >> (EPNum & 0x0F)) & 1) == 0) {   /* Non-Isochronous Endpoint */
    WrCmdEP(EPNum, CMD_CLR_BUF);
}

return (cnt);
}


/*
*Write USB Endpoint Data
*    Parameters:      EPNum: Endpoint Number
*                     EPNum.0..3: Address
*                     EPNum.7:    Dir
*                     pData: Pointer to Data Buffer
*                     cnt:   Number of bytes to write
*    Return Value:    Number of bytes written
*/

U32 USB_WriteEP (U32 EPNum, U8 *pData, U32 cnt) {
U32 n;

LPC_USB->USBCtrl = ((EPNum & 0x0F) << 2) | CTRL_WR_EN;

LPC_USB->USBTxPLen = cnt;

for (n = 0; n < (cnt + 3) / 4; n++) {
    LPC_USB->USBTxData = *((__packed U32 *)pData);
    pData += 4;
}

LPC_USB->USBCtrl = 0;

WrCmdEP(EPNum, CMD_VALID_BUF);

return (cnt);
}
端点中断程序void USB_EndPoint2 (U32 event)
{
        LED2_ON;
               
switch (event)
{
    case USB_EVT_IN:
           USBSndRdy=1;
      break;
    case USB_EVT_OUT:
           USBRecRdy=1;
      break;
}
}接收数据:
主机向端点2发送OUT包-》lpc产生USB中断(在此清除中断)-》调USB_EndPoint2 函数-》在主循环中检查 USBRecRdy状态,如果状态为1,调USB_ReadEP ,在USB_ReadEP 中读取数据
-》 调 WrCmdEP(EPNum, CMD_CLR_BUF); 释放缓存-》准备再次接受数据。
在此过程中如果不释放缓存,还会接收主机的数据吗?如果会,是否就覆盖当前缓存?

发送数据:

检查USBSndRdy状态,如果为1-》调USB_WriteEP 写数据到usb缓存,确认缓存后-》主机下一个in后数据发送到主机,产生USB_EndPoint2 IN中断, 设置 USBSndRdy=1;如果以后无数据直接写0字节数据。
此过程是否是只要确认缓存就产生in中断?确认缓存后如果主机没有in数据,接着再次写数据是否会覆盖原先的数据?


发送和接收是否不能小于1ms?



请大家帮忙分析一下!

adongliu 发表于 2013-5-12 21:01:56

实在是搞不定了,上位机用libusb开双线程读写,读写都会丢失数据。

adongliu 发表于 2013-5-12 21:06:40

想用dma,zlg的例子实在是看不明白,我觉得kei的代码风格比较易读。

adongliu 发表于 2013-5-13 08:27:19

用户手册上是这样写的;




按手册上说的,只要不读取端点,以后的OUT包全部会拒绝,直到清除缓存后。在主循环中检查接收状态,如果为1,再读取端点数据是没有问题的,有时候会检查不到接收状态。

bbs2009 发表于 2013-5-13 09:16:27

adongliu 发表于 2013-5-13 13:34:12

批量模式可以1ms发送多个包!

adongliu 发表于 2013-5-13 13:46:28

如果不发送0字节数据,则发送接收不会丢失数据,应用上每次读取1024,下位机有时候只有64字节数据,发送完64字节后,必须发送0字节包,否则,上位机读取函数不返回。

adongliu 发表于 2013-5-14 19:01:42

今天测试一天,依然没有找到问题,不知道这个是不是lpc17的bug,明天到stm32上面试一下,希望没有这个问题。

adongliu 发表于 2013-5-15 08:54:54

测试stm32可以发送0字节数据包,bus hound 不会抓取到0字节数据包,使用正常。使用lpc17发送0字节数据包,bus hound 能抓取到0字节数据包。

adongliu 发表于 2013-5-30 11:03:16

为什么中断会覆盖呢? 本来中断是IN中断,结果执行OUT中断。

adongliu 发表于 2013-5-30 19:02:38

进入中断后,关闭usb中断,函数结束时,打开中断,问题依旧!

adongliu 发表于 2013-5-31 21:36:20

还是keil的例子有问题,stm32有时候也不稳定,最终使用st的库,目前测试正常!

LingYi 发表于 2013-11-23 11:19:51

adongliu 发表于 2013-5-13 08:27 static/image/common/back.gif
用户手册上是这样写的;




楼主可以把你 使用的手册 共享1下吗 谢谢

adongliu 发表于 2013-11-23 11:27:19

去zlg下载 吧,上传太慢了!

wangyu_hust 发表于 2013-11-29 14:34:41

最近在看USB,还不知道怎么弄,先MARK下吧{:biggrin:}
页: [1]
查看完整版本: 求助:lpc17xx USB 通信数据包丢失的原因?