本帖最后由 ljxh401 于 2021-1-25 20:58 编辑
因为标准库的 usb demo 是基于状态的 不是基于流程的,分析起来很痛苦
将我劝退了好多年,终于下定决心来学习,
看完资料,将它的枚举流程 移植到 ucos2 里面 看起来就非常清晰
枚举的过程的代码如下,通过操作系统,代码容易学习多了
- void JkData_Setup0(USB_REQ *pReq)
- {
- static INT8U recbuf[128];
- INT16U len;
- INT8U flag=0;
- printf("r:%d\r\n",pReq->USBbRequest&0xff);
- if (pReq->USBbRequest == GET_DESCRIPTOR)
- {
- ONE_DESCRIPTOR *pDescriptor=&Device_Descriptor;
- if ( (pReq->USBbmRequestType& (REQUEST_TYPE | RECIPIENT)) == (STANDARD_REQUEST | DEVICE_RECIPIENT))
- {
- switch(pReq->USBwValues>>8)
- {
- case DEVICE_DESCRIPTOR:
- pDescriptor=&Device_Descriptor;
- break;
- case CONFIG_DESCRIPTOR:
- pDescriptor=&Config_Descriptor;
- break;
- case STRING_DESCRIPTOR:
- pDescriptor=&String_Descriptor[pReq->USBwValues&0xff];
- break;
- }
- if(pReq->USBwLengths>pDescriptor->Descriptor_Size)
- {
- len=pDescriptor->Descriptor_Size;
- flag=((len%UsbMaxSize)==0);
- }else
- {
- len=pReq->USBwLengths;
- flag=0;
- }
- SendEp0Data(pDescriptor->Descriptor,len,flag);
- }
- }
- else if(pReq->USBbRequest == SET_ADDRESS)
- {
- //返回一个空回复,作为事务的状态回复
- if(SendEp0Data(NULL,0,1)==OS_NO_ERR)
- SetDeviceAddress(pReq->USBwValues&0xff);
- }
- else if(pReq->USBbRequest==SET_CONFIGURATION)
- {
- //返回一个空回复,作为事务的状态回复
- SendEp0Data(NULL,0,1);
- }
- else if (pReq->USBbRequest == SET_LINE_CODING)
- {
- RecEp0Data(recbuf,7);
- printf("%02X %02X %02X %02X %02X %02X %02X \r\n",recbuf[0],recbuf[1],recbuf[2],recbuf[3],recbuf[4],recbuf[5],recbuf[6]);
- }
- else if (pReq->USBbRequest == GET_LINE_CODING)
- {
- //返回波特率的设置
- if(pReq->USBwLengths>sizeof(linecoding))
- {
- len=sizeof(linecoding);
- flag=((len%UsbMaxSize)==0);
- }else
- {
- len=pReq->USBwLengths;
- flag=0;
- }
- SendEp0Data((INT8U*)&linecoding,len,flag);
- printf("Q:%02X %02X %04X%04X%04X\r\n",pReq->USBbmRequestType,pReq->USBbRequest,pReq->USBwValues,pReq->USBwIndexs,pReq->USBwLengths);
- }
- else if(pReq->USBbRequest == SET_CONTROL_LINE_STATE)
- {
- //收到这个命令之后 不久usb串口就会自动关闭,求解
- SendEp0Data(NULL,0,1);
- }
- else
- {
- //printf("q:%02X %02X %04X%04X%04X\r\n",pReq->USBbmRequestType,pReq->USBbRequest,pReq->USBwValues,pReq->USBwIndexs,pReq->USBwLengths);
- }
- }
全部的修改代码如下
- #include "includes.h"
- #include "hw_config.h"
- #include "usb_istr.h"
- #include "usb_prop.h"
- #define UsbMaxSize 64
- OS_EVENT *OSQUsbEP0;
- void SetUsbEP0Msg( INT32U msg)
- {
- OSQPost(OSQUsbEP0,(void*)msg);
- }
- #define UsbLinkPin PerpheralBit(GPIOC->ODR,12)
- void InitUsb(void)
- {
- SetPinState(GPIOC,GPIO_Pin_12,GPIO_Mode_Out_PP); // mb n
- UsbLinkPin=0;
- Set_USBClock();
- USB_Interrupts_Config();
- USB_Init();
- UsbLinkPin=1;
- }
- /*---- S E N D E P 0 D A T A ----
- 【功能】:上传各种数据 例如描述符 ...
- 【参数】:****
- 【返回】:****
- 【说明】:****
- --------------作者:卢杰西 2021年1月25日16:35:26--------------------------------*/
- INT8U SendEp0Data(INT8U *pSrc,INT16U len,INT8U flag0)
- {
- INT32U msg;
- INT16U sendcnt;
- INT8U pagesize,err=OS_ERR_NONE;
- for(sendcnt=0;sendcnt<len;sendcnt+=UsbMaxSize)
- {
- pagesize=(len-sendcnt)>UsbMaxSize?UsbMaxSize:(len-sendcnt);
- UserToPMABufferCopy(pSrc+sendcnt, GetEPTxAddr(ENDP0), pagesize);
- SetEPTxCount(ENDP0, pagesize);
- SetEPRxValid(ENDP0);
- SetEPTxValid(ENDP0);
- msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);
- if(err!=OS_ERR_NONE)
- {
- break;
- }
- if((msg & EP_CTR_TX)== 0)
- {
- OSQPostFront(OSQUsbEP0, (void *)msg);
- break;
- }
- }
- if(flag0 && err==OS_ERR_NONE)
- {
- //发送空输入
- SetEPTxCount(ENDP0, 0);
- SetEPTxValid(ENDP0);
- SetEPRxValid(ENDP0);
- msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);
- if((msg & EP_CTR_TX)== 0 && err!=OS_TIMEOUT)
- {
- OSQPostFront(OSQUsbEP0, (void *)msg);
- if(len==0) printf("B");
- }
- else if(len==0) printf("b");
- }
- if(len!=0 && err==OS_ERR_NONE)
- {
- //等待空输出返回
- SetEPRxValid(ENDP0);
- msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);
- }
- SetEPRxValid(ENDP0);
- return err;
- }
- /*---- R E C E P 0 D A T A ----
- 【功能】:接收设置数据
- 【参数】:****
- 【返回】:****
- 【说明】:****
- --------------作者:卢杰西 2021年1月25日16:35:03--------------------------------*/
- INT8U RecEp0Data(INT8U *pDst,INT16U len)
- {
- INT32U msg;
- INT16U pagesize;
- INT8U err;
- do{
- SetEPRxValid(ENDP0);
- SetEPTxValid(ENDP0);
- msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);
- if(err==OS_TIMEOUT) break;
- if((msg & (EP_CTR_RX|EP_SETUP))!= EP_CTR_RX)
- {
- OSQPostFront(OSQUsbEP0, (void *)msg);
- break;
- }
- pagesize=GetEPRxCount(ENDP0);
- if(pagesize>len) pagesize=len;
- PMAToUserBufferCopy(pDst, GetEPRxAddr(ENDP0), pagesize);
- len-=pagesize;
- pDst+=pagesize;
- }while(len>0);
- if(len==0)
- {
- //接收完毕
- SetEPTxCount(ENDP0, 0);
- SetEPTxValid(ENDP0);
- msg=(INT32U)OSQPend(OSQUsbEP0,OS_TICKS_PER_SEC/500,&err);
- if((msg & EP_CTR_TX)== 0 && err!=OS_TIMEOUT)
- {
- OSQPostFront(OSQUsbEP0, (void *)msg);
- }
- }
- SetEPRxValid(ENDP0);
- return len;
- }
- extern ONE_DESCRIPTOR Device_Descriptor;
- extern ONE_DESCRIPTOR Config_Descriptor;
- extern ONE_DESCRIPTOR String_Descriptor[4];
- extern LINE_CODING linecoding;
- void JkData_Setup0(USB_REQ *pReq)
- {
- static INT8U recbuf[128];
- INT16U len;
- INT8U flag=0;
- printf("r:%d\r\n",pReq->USBbRequest&0xff);
- if (pReq->USBbRequest == GET_DESCRIPTOR)
- {
- ONE_DESCRIPTOR *pDescriptor=&Device_Descriptor;
- if ( (pReq->USBbmRequestType& (REQUEST_TYPE | RECIPIENT)) == (STANDARD_REQUEST | DEVICE_RECIPIENT))
- {
- switch(pReq->USBwValues>>8)
- {
- case DEVICE_DESCRIPTOR:
- pDescriptor=&Device_Descriptor;
- break;
- case CONFIG_DESCRIPTOR:
- pDescriptor=&Config_Descriptor;
- break;
- case STRING_DESCRIPTOR:
- pDescriptor=&String_Descriptor[pReq->USBwValues&0xff];
- break;
- }
- if(pReq->USBwLengths>pDescriptor->Descriptor_Size)
- {
- len=pDescriptor->Descriptor_Size;
- flag=((len%UsbMaxSize)==0);
- }else
- {
- len=pReq->USBwLengths;
- flag=0;
- }
- SendEp0Data(pDescriptor->Descriptor,len,flag);
- }
- }
- else if(pReq->USBbRequest == SET_ADDRESS)
- {
- //返回一个空回复,作为事务的状态回复
- if(SendEp0Data(NULL,0,1)==OS_NO_ERR)
- SetDeviceAddress(pReq->USBwValues&0xff);
- }
- else if(pReq->USBbRequest==SET_CONFIGURATION)
- {
- //返回一个空回复,作为事务的状态回复
- SendEp0Data(NULL,0,1);
- }
- else if (pReq->USBbRequest == SET_LINE_CODING)
- {
- RecEp0Data(recbuf,7);
- printf("%02X %02X %02X %02X %02X %02X %02X \r\n",recbuf[0],recbuf[1],recbuf[2],recbuf[3],recbuf[4],recbuf[5],recbuf[6]);
- }
- else if (pReq->USBbRequest == GET_LINE_CODING)
- {
- //返回波特率的设置
- if(pReq->USBwLengths>sizeof(linecoding))
- {
- len=sizeof(linecoding);
- flag=((len%UsbMaxSize)==0);
- }else
- {
- len=pReq->USBwLengths;
- flag=0;
- }
- SendEp0Data((INT8U*)&linecoding,len,flag);
- printf("Q:%02X %02X %04X%04X%04X\r\n",pReq->USBbmRequestType,pReq->USBbRequest,pReq->USBwValues,pReq->USBwIndexs,pReq->USBwLengths);
- }
- else if(pReq->USBbRequest == SET_CONTROL_LINE_STATE)
- {
- //收到这个命令之后 不久usb串口就会自动关闭,求解
- SendEp0Data(NULL,0,1);
- }
- else
- {
- //printf("q:%02X %02X %04X%04X%04X\r\n",pReq->USBbmRequestType,pReq->USBbRequest,pReq->USBwValues,pReq->USBwIndexs,pReq->USBwLengths);
- }
- }
- u8 SetupHandle(void)
- {
- USB_REQ req;
- INT8U *pBuf = PMAAddr + (u8 *)(_GetEPRxAddr(ENDP0) * 2); /* *2 for 32 bits addr */
- req.USBbmRequestType=*pBuf++;
- req.USBbRequest=*pBuf++;
- pBuf+=2;
- req.USBwValues=pBuf[0]+((INT16U)pBuf[1]<<8);
- pBuf+=4;
- req.USBwIndexs=pBuf[0]+((INT16U)pBuf[1]<<8);
- pBuf+=4;
- req.USBwLengths=pBuf[0]+((INT16U)pBuf[1]<<8);
- JkData_Setup0(&req);
- return 1;
- }
- /*---- U S B T A S K ----
- 【功能】:将usb
- 的端点0的控制中断,描述符上移动到这里来,让代码更加清晰,这里是尝试移植stm32的虚拟串口的
- 【参数】:****
- 【返回】:****
- 【说明】:****
- --------------作者:卢杰西 2021年1月23日17:12:35--------------------------------*/
- void UsbTask(void *pt)
- {
- INT8U err;
- INT32U msg;
- CREATE_SMSG(OSQUsbEP0, 10);
- InitUsb();
- while(1)
- {
- msg=(INT32U)OSQPend(OSQUsbEP0,0,&err);
- if ((msg & EP_CTR_TX) != 0)
- {
- printf("B");
- SetEPRxValid(ENDP0);
- }
- else if ((msg &EP_SETUP) != 0)
- {
- SetupHandle();
- }
- else if ((msg & EP_CTR_RX) != 0)
- {
- printf("C");
- SetEPRxValid(ENDP0);
- }
- }
- }
- void CTR_LP(void)
- {
- u32 wEPVal = 0;
- /* stay in loop while pending ints */
- while (((wIstr = _GetISTR()) & ISTR_CTR) != 0)
- {
- _SetISTR((u16)CLR_CTR); /* clear CTR flag */
- /* extract highest priority endpoint number */
- EPindex = (u8)(wIstr & ISTR_EP_ID);
- if (EPindex == 0)
- {
- _SetEPRxStatus(ENDP0, EP_RX_NAK);
- _SetEPTxStatus(ENDP0, EP_TX_NAK);
- wEPVal = _GetENDPOINT(ENDP0);
- if ((wEPVal & EP_CTR_TX) != 0)
- _ClearEP_CTR_TX(ENDP0);
- else if ((wEPVal &EP_SETUP) != 0)
- _ClearEP_CTR_RX(ENDP0); /* SETUP bit kept frozen while CTR_RX = 1 */
- else if ((wEPVal & EP_CTR_RX) != 0)
- _ClearEP_CTR_RX(ENDP0);
- SetUsbEP0Msg(wEPVal);
- }/* if(EPindex == 0) */
- else
- {
- /* Decode and service non control endpoints interrupt */
- /* process related endpoint register */
- wEPVal = _GetENDPOINT(EPindex);
- if ((wEPVal & EP_CTR_RX) != 0)
- {
- /* clear int flag */
- _ClearEP_CTR_RX(EPindex);
- /* call OUT service function */
- (*pEpInt_OUT[EPindex-1])();
- } /* if((wEPVal & EP_CTR_RX) */
- if ((wEPVal & EP_CTR_TX) != 0)
- {
- /* clear int flag */
- _ClearEP_CTR_TX(EPindex);
- /* call IN service function */
- (*pEpInt_IN[EPindex-1])();
- } /* if((wEPVal & EP_CTR_TX) != 0) */
- }/* if(EPindex == 0) else */
- }/* while(...) */
- }
- /*******************************************************************************
- * Function Name : USB_LP_CAN_RX0_IRQHandler
- * Description : This function handles USB Low Priority or CAN RX0 interrupts
- * requests.
- * Input : None
- * Output : None
- * Return : None
- *******************************************************************************/
- void USB_LP_CAN_RX0_IRQHandler(void)
- {
- OSIntEnter();
- USB_Istr();
- OSIntExit();
- }
|
|