搜索
bottom↓
回复: 14

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

[复制链接]

出0入0汤圆

发表于 2013-5-12 21:00:28 | 显示全部楼层 |阅读模式
使用keil例子中的CDC改写

中断程序

  1. void USB_IRQHandler (void) {
  2.   U32 disr, val, n, m;
  3.   U32 episr, episrCur;

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

  5.   /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
  6.   if (disr & DEV_STAT_INT) {
  7.     LPC_USB->USBDevIntClr = DEV_STAT_INT;
  8.     WrCmd(CMD_GET_DEV_STAT);
  9.     val = RdCmdDat(DAT_GET_DEV_STAT);       /* Device Status */
  10.     if (val & DEV_RST) {                    /* Reset */
  11.       USB_Reset();
  12. #if   USB_RESET_EVENT
  13.       USB_Reset_Event();
  14. #endif
  15.     }
  16.     if (val & DEV_CON_CH) {                 /* Connect change */
  17. #if   USB_POWER_EVENT
  18.       USB_Power_Event(val & DEV_CON);
  19. #endif
  20.     }
  21.     if (val & DEV_SUS_CH) {                 /* Suspend/Resume */
  22.       if (val & DEV_SUS) {                  /* Suspend */
  23.         USB_Suspend();
  24. #if     USB_SUSPEND_EVENT
  25.         USB_Suspend_Event();
  26. #endif
  27.       } else {                              /* Resume */
  28.         USB_Resume();
  29. #if     USB_RESUME_EVENT
  30.         USB_Resume_Event();
  31. #endif
  32.       }
  33.     }
  34.     goto isr_end;
  35.   }

  36. #if USB_SOF_EVENT
  37.   /* Start of Frame Interrupt */
  38.   if (disr & FRAME_INT) {
  39.     DEV_INT_CLR = FRAME_INT;
  40.     USB_SOF_Event();
  41.   }
  42. #endif

  43. #if USB_ERROR_EVENT
  44.   /* Error Interrupt */
  45.   if (disr & ERR_INT) {
  46.     DEV_INT_CLR = ERR_INT;
  47.     WrCmd(CMD_RD_ERR_STAT);
  48.     val = RdCmdDat(DAT_RD_ERR_STAT);
  49.     USB_Error_Event(val);
  50.   }
  51. #endif

  52.   /* Endpoint's Slow Interrupt */
  53.   if (disr & EP_SLOW_INT) {
  54.     episrCur = 0;
  55.     episr    = LPC_USB->USBEpIntSt;
  56.     for (n = 0; n < USB_EP_NUM; n++) {      /* Check All Endpoints */
  57.       if (episr == episrCur) break;         /* break if all EP interrupts handled */
  58.       if (episr & (1 << n)) {
  59.         episrCur |= (1 << n);
  60.         m = n >> 1;
  61.   
  62.         LPC_USB->USBEpIntClr = (1 << n);
  63.         while ((LPC_USB->USBDevIntSt & CDFULL_INT) == 0);
  64.         val = LPC_USB->USBCmdData;
  65.   
  66.         if ((n & 1) == 0) {                 /* OUT Endpoint */
  67.           if (n == 0) {                     /* Control OUT Endpoint */
  68.             if (val & EP_SEL_STP) {         /* Setup Packet */
  69.               if (USB_P_EP[0]) {
  70.                 USB_P_EP[0](USB_EVT_SETUP);
  71.                 continue;
  72.               }
  73.             }
  74.           }
  75.           if (USB_P_EP[m]) {
  76.             USB_P_EP[m](USB_EVT_OUT);
  77.           }
  78.         } else {                            /* IN Endpoint */
  79.           if (USB_P_EP[m]) {
  80.             USB_P_EP[m](USB_EVT_IN);
  81.           }
  82.         }
  83.       }
  84.     }
  85.     LPC_USB->USBDevIntClr = EP_SLOW_INT;
  86.   }

  87. #if USB_DMA
  88. /* USB_DMA not yet supported */
  89. #endif /* USB_DMA */

  90. isr_end:
  91.   ;
  92. }
复制代码
端点读写
  1. /*
  2. *  Read USB Endpoint Data
  3. *    Parameters:      EPNum: Endpoint Number
  4. *                       EPNum.0..3: Address
  5. *                       EPNum.7:    Dir
  6. *                     pData: Pointer to Data Buffer
  7. *    Return Value:    Number of bytes read
  8. */

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

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

  12.   do {
  13.     cnt = LPC_USB->USBRxPLen;
  14.   } while ((cnt & PKT_RDY) == 0);
  15.   cnt &= PKT_LNGTH_MASK;

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

  20.   LPC_USB->USBCtrl = 0;

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

  24.   return (cnt);
  25. }


  26. /*
  27. *  Write USB Endpoint Data
  28. *    Parameters:      EPNum: Endpoint Number
  29. *                       EPNum.0..3: Address
  30. *                       EPNum.7:    Dir
  31. *                     pData: Pointer to Data Buffer
  32. *                     cnt:   Number of bytes to write
  33. *    Return Value:    Number of bytes written
  34. */

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

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

  38.   LPC_USB->USBTxPLen = cnt;

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

  43.   LPC_USB->USBCtrl = 0;

  44.   WrCmdEP(EPNum, CMD_VALID_BUF);

  45.   return (cnt);
  46. }
复制代码
端点中断程序
  1. void USB_EndPoint2 (U32 event)
  2. {
  3.         LED2_ON;  
  4.                  
  5.   switch (event)
  6.   {
  7.     case USB_EVT_IN:
  8.            USBSndRdy=1;
  9.       break;
  10.     case USB_EVT_OUT:
  11.            USBRecRdy=1;
  12.       break;
  13.   }
  14. }
复制代码
接收数据:
主机向端点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?



请大家帮忙分析一下!

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2013-5-12 21:01:56 | 显示全部楼层
实在是搞不定了,上位机用libusb开双线程读写,读写都会丢失数据。

出0入0汤圆

 楼主| 发表于 2013-5-12 21:06:40 | 显示全部楼层
想用dma,zlg的例子实在是看不明白,我觉得kei的代码风格比较易读。

出0入0汤圆

 楼主| 发表于 2013-5-13 08:27:19 | 显示全部楼层
用户手册上是这样写的;




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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
头像被屏蔽

出0入0汤圆

发表于 2013-5-13 09:16:27 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

出0入0汤圆

 楼主| 发表于 2013-5-13 13:34:12 | 显示全部楼层
批量模式可以1ms发送多个包!

出0入0汤圆

 楼主| 发表于 2013-5-13 13:46:28 | 显示全部楼层
如果不发送0字节数据,则发送接收不会丢失数据,应用上每次读取1024,下位机有时候只有64字节数据,发送完64字节后,必须发送0字节包,否则,上位机读取函数不返回。

出0入0汤圆

 楼主| 发表于 2013-5-14 19:01:42 | 显示全部楼层
今天测试一天,依然没有找到问题,不知道这个是不是lpc17的bug,明天到stm32上面试一下,希望没有这个问题。

出0入0汤圆

 楼主| 发表于 2013-5-15 08:54:54 | 显示全部楼层
测试stm32可以发送0字节数据包,bus hound 不会抓取到0字节数据包,使用正常。使用lpc17发送0字节数据包,bus hound 能抓取到0字节数据包。

出0入0汤圆

 楼主| 发表于 2013-5-30 11:03:16 | 显示全部楼层
为什么中断会覆盖呢? 本来中断是IN中断,结果执行OUT中断。

出0入0汤圆

 楼主| 发表于 2013-5-30 19:02:38 | 显示全部楼层
进入中断后,关闭usb中断,函数结束时,打开中断,问题依旧!

出0入0汤圆

 楼主| 发表于 2013-5-31 21:36:20 | 显示全部楼层
还是keil的例子有问题,stm32有时候也不稳定,最终使用st的库,目前测试正常!

出0入0汤圆

发表于 2013-11-23 11:19:51 | 显示全部楼层
adongliu 发表于 2013-5-13 08:27
用户手册上是这样写的;

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

出0入0汤圆

 楼主| 发表于 2013-11-23 11:27:19 | 显示全部楼层
去zlg下载 吧,上传太慢了!

出0入0汤圆

发表于 2013-11-29 14:34:41 | 显示全部楼层
最近在看USB,还不知道怎么弄,先MARK下吧
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-24 01:39

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表