STM32的usb串口demo移植到ucos,看枚举的过程就清晰多了

[复制链接]
 楼主| ljxh401 发表于 2021-1-25 18:16 | 显示全部楼层 |阅读模式
本帖最后由 ljxh401 于 2021-1-25 20:58 编辑

因为标准库的 usb demo 是基于状态的 不是基于流程的,分析起来很痛苦
将我劝退了好多年,终于下定决心来学习,
看完资料,将它的枚举流程 移植到 ucos2 里面 看起来就非常清晰

枚举的过程的代码如下,通过操作系统,代码容易学习多了
  1. void JkData_Setup0(USB_REQ *pReq)
  2. {
  3.         static INT8U recbuf[128];
  4.         INT16U len;
  5.         INT8U flag=0;
  6.         printf("r:%d\r\n",pReq->USBbRequest&0xff);
  7.         if (pReq->USBbRequest == GET_DESCRIPTOR)
  8.         {
  9.           ONE_DESCRIPTOR *pDescriptor=&Device_Descriptor;
  10.           if ( (pReq->USBbmRequestType& (REQUEST_TYPE | RECIPIENT)) == (STANDARD_REQUEST | DEVICE_RECIPIENT))
  11.           {
  12.                 switch(pReq->USBwValues>>8)
  13.                 {
  14.                         case DEVICE_DESCRIPTOR:
  15.                                 pDescriptor=&Device_Descriptor;
  16.                                 break;
  17.                         case CONFIG_DESCRIPTOR:
  18.                                 pDescriptor=&Config_Descriptor;
  19.                                 break;
  20.                         case STRING_DESCRIPTOR:
  21.                                 pDescriptor=&String_Descriptor[pReq->USBwValues&0xff];
  22.                                 break;
  23.                 }
  24.                 if(pReq->USBwLengths>pDescriptor->Descriptor_Size)
  25.                 {
  26.                         len=pDescriptor->Descriptor_Size;
  27.                         flag=((len%UsbMaxSize)==0);
  28.                 }else
  29.                 {
  30.                         len=pReq->USBwLengths;
  31.                         flag=0;
  32.                 }
  33.                 SendEp0Data(pDescriptor->Descriptor,len,flag);
  34.           }
  35.         }
  36.         else if(pReq->USBbRequest == SET_ADDRESS)
  37.         {
  38.                 //返回一个空回复,作为事务的状态回复
  39.                 if(SendEp0Data(NULL,0,1)==OS_NO_ERR)
  40.                         SetDeviceAddress(pReq->USBwValues&0xff);
  41.         }
  42.         else if(pReq->USBbRequest==SET_CONFIGURATION)
  43.         {
  44.                 //返回一个空回复,作为事务的状态回复
  45.                 SendEp0Data(NULL,0,1);
  46.         }
  47.         else if (pReq->USBbRequest == SET_LINE_CODING)
  48.         {
  49.                 RecEp0Data(recbuf,7);
  50.                 printf("%02X %02X %02X %02X %02X %02X %02X \r\n",recbuf[0],recbuf[1],recbuf[2],recbuf[3],recbuf[4],recbuf[5],recbuf[6]);
  51.         }        
  52.         else if (pReq->USBbRequest == GET_LINE_CODING)
  53.         {
  54.                 //返回波特率的设置
  55.                 if(pReq->USBwLengths>sizeof(linecoding))
  56.                 {
  57.                         len=sizeof(linecoding);
  58.                         flag=((len%UsbMaxSize)==0);
  59.                 }else
  60.                 {
  61.                         len=pReq->USBwLengths;
  62.                         flag=0;
  63.                 }
  64.                 SendEp0Data((INT8U*)&linecoding,len,flag);               
  65.                 printf("Q:%02X %02X %04X%04X%04X\r\n",pReq->USBbmRequestType,pReq->USBbRequest,pReq->USBwValues,pReq->USBwIndexs,pReq->USBwLengths);        
  66.         }
  67.         else if(pReq->USBbRequest == SET_CONTROL_LINE_STATE)
  68.         {
  69.                 //收到这个命令之后 不久usb串口就会自动关闭,求解
  70.                 SendEp0Data(NULL,0,1);               
  71.         }
  72.         else
  73.         {
  74.                 //printf("q:%02X %02X %04X%04X%04X\r\n",pReq->USBbmRequestType,pReq->USBbRequest,pReq->USBwValues,pReq->USBwIndexs,pReq->USBwLengths);        
  75.         }
  76. }


全部的修改代码如下
  1. #include "includes.h"
  2. #include "hw_config.h"
  3. #include "usb_istr.h"
  4. #include "usb_prop.h"

  5. #define UsbMaxSize        64

  6. OS_EVENT *OSQUsbEP0;
  7. void SetUsbEP0Msg( INT32U msg)
  8. {
  9.         OSQPost(OSQUsbEP0,(void*)msg);
  10. }


  11. #define UsbLinkPin                PerpheralBit(GPIOC->ODR,12)
  12. void InitUsb(void)
  13. {
  14.         SetPinState(GPIOC,GPIO_Pin_12,GPIO_Mode_Out_PP);                // mb n
  15.         UsbLinkPin=0;
  16.         Set_USBClock();
  17.         USB_Interrupts_Config();
  18.         USB_Init();
  19.         UsbLinkPin=1;
  20. }

  21. /*---- S E N D   E P 0   D A T A ----
  22. 【功能】:上传各种数据 例如描述符 ...
  23. 【参数】:****
  24. 【返回】:****
  25. 【说明】:****
  26. --------------作者:卢杰西   2021年1月25日16:35:26--------------------------------*/
  27. INT8U SendEp0Data(INT8U *pSrc,INT16U len,INT8U flag0)
  28. {
  29.         INT32U msg;
  30.         INT16U sendcnt;
  31.         INT8U pagesize,err=OS_ERR_NONE;
  32.         for(sendcnt=0;sendcnt<len;sendcnt+=UsbMaxSize)                                
  33.         {
  34.                 pagesize=(len-sendcnt)>UsbMaxSize?UsbMaxSize:(len-sendcnt);
  35.                 UserToPMABufferCopy(pSrc+sendcnt, GetEPTxAddr(ENDP0), pagesize);
  36.                 SetEPTxCount(ENDP0, pagesize);
  37.                 SetEPRxValid(ENDP0);
  38.                 SetEPTxValid(ENDP0);
  39.                 msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);
  40.                 if(err!=OS_ERR_NONE)        
  41.                 {
  42.                         break;
  43.                 }
  44.                 if((msg & EP_CTR_TX)== 0)
  45.                 {
  46.                         OSQPostFront(OSQUsbEP0, (void *)msg);
  47.                         break;
  48.                 }
  49.         }
  50.         if(flag0 && err==OS_ERR_NONE)
  51.         {
  52.                 //发送空输入
  53.                 SetEPTxCount(ENDP0, 0);
  54.                 SetEPTxValid(ENDP0);
  55.                 SetEPRxValid(ENDP0);
  56.                 msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);        
  57.                 if((msg & EP_CTR_TX)== 0 && err!=OS_TIMEOUT)
  58.                 {
  59.                         OSQPostFront(OSQUsbEP0, (void *)msg);
  60.                         if(len==0)        printf("B");
  61.                 }
  62.                 else if(len==0)        printf("b");
  63.         }
  64.         if(len!=0 && err==OS_ERR_NONE)
  65.         {
  66.                 //等待空输出返回
  67.                 SetEPRxValid(ENDP0);
  68.                 msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);        
  69.         }
  70.         SetEPRxValid(ENDP0);
  71.         return err;
  72. }



  73. /*---- R E C   E P 0   D A T A ----
  74. 【功能】:接收设置数据
  75. 【参数】:****
  76. 【返回】:****
  77. 【说明】:****
  78. --------------作者:卢杰西   2021年1月25日16:35:03--------------------------------*/
  79. INT8U RecEp0Data(INT8U *pDst,INT16U len)
  80. {
  81.         INT32U msg;
  82.         INT16U pagesize;
  83.         INT8U err;
  84.         do{
  85.                 SetEPRxValid(ENDP0);
  86.                 SetEPTxValid(ENDP0);
  87.                 msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);        
  88.                 if(err==OS_TIMEOUT)        break;
  89.                 if((msg & (EP_CTR_RX|EP_SETUP))!= EP_CTR_RX)
  90.                 {
  91.                         OSQPostFront(OSQUsbEP0, (void *)msg);
  92.                         break;
  93.                 }
  94.                 pagesize=GetEPRxCount(ENDP0);
  95.                 if(pagesize>len)        pagesize=len;
  96.                 PMAToUserBufferCopy(pDst, GetEPRxAddr(ENDP0), pagesize);
  97.                 len-=pagesize;
  98.                 pDst+=pagesize;
  99.         }while(len>0);
  100.         if(len==0)
  101.         {
  102.                 //接收完毕
  103.                 SetEPTxCount(ENDP0, 0);
  104.                 SetEPTxValid(ENDP0);
  105.                 msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);        
  106.                 if((msg & EP_CTR_TX)== 0 && err!=OS_TIMEOUT)
  107.                 {
  108.                         OSQPostFront(OSQUsbEP0, (void *)msg);
  109.                 }
  110.         }
  111.         SetEPRxValid(ENDP0);        
  112.         return len;
  113. }


  114. extern ONE_DESCRIPTOR Device_Descriptor;
  115. extern ONE_DESCRIPTOR Config_Descriptor;
  116. extern ONE_DESCRIPTOR String_Descriptor[4];
  117. extern LINE_CODING linecoding;
  118. void JkData_Setup0(USB_REQ *pReq)
  119. {
  120.         static INT8U recbuf[128];
  121.         INT16U len;
  122.         INT8U flag=0;
  123.         printf("r:%d\r\n",pReq->USBbRequest&0xff);
  124.         if (pReq->USBbRequest == GET_DESCRIPTOR)
  125.         {
  126.           ONE_DESCRIPTOR *pDescriptor=&Device_Descriptor;
  127.           if ( (pReq->USBbmRequestType& (REQUEST_TYPE | RECIPIENT)) == (STANDARD_REQUEST | DEVICE_RECIPIENT))
  128.           {
  129.                 switch(pReq->USBwValues>>8)
  130.                 {
  131.                         case DEVICE_DESCRIPTOR:
  132.                                 pDescriptor=&Device_Descriptor;
  133.                                 break;
  134.                         case CONFIG_DESCRIPTOR:
  135.                                 pDescriptor=&Config_Descriptor;
  136.                                 break;
  137.                         case STRING_DESCRIPTOR:
  138.                                 pDescriptor=&String_Descriptor[pReq->USBwValues&0xff];
  139.                                 break;
  140.                 }
  141.                 if(pReq->USBwLengths>pDescriptor->Descriptor_Size)
  142.                 {
  143.                         len=pDescriptor->Descriptor_Size;
  144.                         flag=((len%UsbMaxSize)==0);
  145.                 }else
  146.                 {
  147.                         len=pReq->USBwLengths;
  148.                         flag=0;
  149.                 }
  150.                 SendEp0Data(pDescriptor->Descriptor,len,flag);
  151.           }
  152.         }
  153.         else if(pReq->USBbRequest == SET_ADDRESS)
  154.         {
  155.                 //返回一个空回复,作为事务的状态回复
  156.                 if(SendEp0Data(NULL,0,1)==OS_NO_ERR)
  157.                         SetDeviceAddress(pReq->USBwValues&0xff);
  158.         }
  159.         else if(pReq->USBbRequest==SET_CONFIGURATION)
  160.         {
  161.                 //返回一个空回复,作为事务的状态回复
  162.                 SendEp0Data(NULL,0,1);
  163.         }
  164.         else if (pReq->USBbRequest == SET_LINE_CODING)
  165.         {
  166.                 RecEp0Data(recbuf,7);
  167.                 printf("%02X %02X %02X %02X %02X %02X %02X \r\n",recbuf[0],recbuf[1],recbuf[2],recbuf[3],recbuf[4],recbuf[5],recbuf[6]);
  168.         }        
  169.         else if (pReq->USBbRequest == GET_LINE_CODING)
  170.         {
  171.                 //返回波特率的设置
  172.                 if(pReq->USBwLengths>sizeof(linecoding))
  173.                 {
  174.                         len=sizeof(linecoding);
  175.                         flag=((len%UsbMaxSize)==0);
  176.                 }else
  177.                 {
  178.                         len=pReq->USBwLengths;
  179.                         flag=0;
  180.                 }
  181.                 SendEp0Data((INT8U*)&linecoding,len,flag);               
  182.                 printf("Q:%02X %02X %04X%04X%04X\r\n",pReq->USBbmRequestType,pReq->USBbRequest,pReq->USBwValues,pReq->USBwIndexs,pReq->USBwLengths);        
  183.         }
  184.         else if(pReq->USBbRequest == SET_CONTROL_LINE_STATE)
  185.         {
  186.                 //收到这个命令之后 不久usb串口就会自动关闭,求解
  187.                 SendEp0Data(NULL,0,1);               
  188.         }
  189.         else
  190.         {
  191.                 //printf("q:%02X %02X %04X%04X%04X\r\n",pReq->USBbmRequestType,pReq->USBbRequest,pReq->USBwValues,pReq->USBwIndexs,pReq->USBwLengths);        
  192.         }
  193. }

  194. u8 SetupHandle(void)
  195. {
  196.         USB_REQ req;        
  197.         INT8U *pBuf = PMAAddr + (u8 *)(_GetEPRxAddr(ENDP0) * 2);         /* *2 for 32 bits addr */
  198.         req.USBbmRequestType=*pBuf++;
  199.         req.USBbRequest=*pBuf++;
  200.         pBuf+=2;
  201.         req.USBwValues=pBuf[0]+((INT16U)pBuf[1]<<8);
  202.         pBuf+=4;
  203.         req.USBwIndexs=pBuf[0]+((INT16U)pBuf[1]<<8);
  204.         pBuf+=4;
  205.         req.USBwLengths=pBuf[0]+((INT16U)pBuf[1]<<8);
  206.         JkData_Setup0(&req);
  207.         return 1;
  208. }


  209. /*---- U S B   T A S K ----
  210. 【功能】:将usb
  211. 的端点0的控制中断,描述符上移动到这里来,让代码更加清晰,这里是尝试移植stm32的虚拟串口的
  212. 【参数】:****
  213. 【返回】:****
  214. 【说明】:****
  215. --------------作者:卢杰西   2021年1月23日17:12:35--------------------------------*/
  216. void UsbTask(void *pt)
  217. {
  218.         INT8U err;
  219.         INT32U msg;
  220.         CREATE_SMSG(OSQUsbEP0, 10);
  221.         InitUsb();
  222.         while(1)
  223.         {
  224.                 msg=(INT32U)OSQPend(OSQUsbEP0,0,&err);
  225.                 if ((msg & EP_CTR_TX) != 0)
  226.                 {
  227.                         printf("B");
  228.                         SetEPRxValid(ENDP0);
  229.                 }
  230.                 else if ((msg &EP_SETUP) != 0)
  231.                 {
  232.                         SetupHandle();
  233.                 }
  234.                 else if ((msg & EP_CTR_RX) != 0)
  235.                 {
  236.                         printf("C");
  237.                         SetEPRxValid(ENDP0);
  238.                 }
  239.         }
  240. }

  241. void CTR_LP(void)
  242. {
  243.   u32 wEPVal = 0;
  244.   /* stay in loop while pending ints */
  245.   while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
  246.   {
  247.     _SetISTR((u16)CLR_CTR); /* clear CTR flag */
  248.     /* extract highest priority endpoint number */
  249.     EPindex = (u8)(wIstr & ISTR_EP_ID);
  250.     if (EPindex == 0)
  251.     {
  252.                 _SetEPRxStatus(ENDP0, EP_RX_NAK);
  253.                 _SetEPTxStatus(ENDP0, EP_TX_NAK);
  254.                 wEPVal = _GetENDPOINT(ENDP0);
  255.         if ((wEPVal & EP_CTR_TX) != 0)
  256.           _ClearEP_CTR_TX(ENDP0);
  257.         else if ((wEPVal &EP_SETUP) != 0)
  258.           _ClearEP_CTR_RX(ENDP0);                 /* SETUP bit kept frozen while CTR_RX = 1 */
  259.         else if ((wEPVal & EP_CTR_RX) != 0)
  260.           _ClearEP_CTR_RX(ENDP0);
  261.                 SetUsbEP0Msg(wEPVal);
  262.     }/* if(EPindex == 0) */
  263.     else
  264.     {
  265.       /* Decode and service non control endpoints interrupt  */
  266.       /* process related endpoint register */
  267.       wEPVal = _GetENDPOINT(EPindex);
  268.       if ((wEPVal & EP_CTR_RX) != 0)
  269.       {
  270.         /* clear int flag */
  271.         _ClearEP_CTR_RX(EPindex);

  272.         /* call OUT service function */
  273.         (*pEpInt_OUT[EPindex-1])();

  274.       } /* if((wEPVal & EP_CTR_RX) */

  275.       if ((wEPVal & EP_CTR_TX) != 0)
  276.       {
  277.         /* clear int flag */
  278.         _ClearEP_CTR_TX(EPindex);

  279.         /* call IN service function */
  280.         (*pEpInt_IN[EPindex-1])();
  281.       } /* if((wEPVal & EP_CTR_TX) != 0) */
  282.     }/* if(EPindex == 0) else */
  283.   }/* while(...) */
  284. }


  285. /*******************************************************************************
  286. * Function Name  : USB_LP_CAN_RX0_IRQHandler
  287. * Description    : This function handles USB Low Priority or CAN RX0 interrupts
  288. *                  requests.
  289. * Input          : None
  290. * Output         : None
  291. * Return         : None
  292. *******************************************************************************/
  293. void USB_LP_CAN_RX0_IRQHandler(void)
  294. {
  295.         OSIntEnter();
  296.         USB_Istr();
  297.         OSIntExit();
  298. }


Tanxjxj120a 发表于 2021-1-25 18:32 | 显示全部楼层
谢谢分享 收藏学习
xyz549040622 发表于 2021-1-25 23:38 来自手机 | 显示全部楼层
支持一下,谢谢分享。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

52

主题

230

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部

52

主题

230

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部