m0_19974968745 2023-10-29 14:47 采纳率: 44.4%
浏览 104
已结题

求CH32V307 usb虚拟串口的代码解释

1、本问题来自CH32V307VCT6 的出厂示例代码,代码的功能是将CH32V307单片机的USB口虚拟成上位机的一个串口。
2、代码在单片机上运行的基本原理是:实现USB接口数据与USART2数据的交叉转发。如上位机给USB接口发送一段数据,USB接口中断程序收到数据后,通过USART2发送出去; 或者,USART2接收到数据后,通过USB接口上传到上位机。
3、经初步理解和调试,上位机通过串口调试程序可以设置虚拟串口的波特率,而该波特率数值同时下传给单片机的USB接口中断程序,中断程序中有一段代码再将此数值设置给单片机的USART2。
4、本提问的目的是寻求对以下终端服务代码的详细解释,要求逐行逐句进行解释和大体框架解释。


```c
void OTG_FS_IRQHandler( void )
{
    uint8_t  intflag, intst, errflag;
    uint16_t len, i;
    uint32_t baudrate;

    intflag = USBOTG_FS->INT_FG;
    intst   = USBOTG_FS->INT_ST;

    if( intflag & USBFS_UIF_TRANSFER )
    {
        switch (intst & USBFS_UIS_TOKEN_MASK)
        {
            /* data-in stage processing */
            case USBFS_UIS_TOKEN_IN:
                switch ( intst & ( USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK ) )
                {
                    /* end-point 0 data in interrupt */
                    case USBFS_UIS_TOKEN_IN | DEF_UEP0:
                        if( USBFS_SetupReqLen == 0 )
                        {
                            USBOTG_FS->UEP0_RX_CTRL = USBFS_UEP_R_TOG | USBFS_UEP_R_RES_ACK;
                        }
                        if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )
                        {
                            /* Non-standard request endpoint 0 Data upload */
                        }
                        else
                        {
                            /* Standard request endpoint 0 Data upload */
                            switch( USBFS_SetupReqCode )
                            {
                                case USB_GET_DESCRIPTOR:
                                        len = USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
                                        memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len );
                                        USBFS_SetupReqLen -= len;
                                        pUSBFS_Descr += len;
                                        USBOTG_FS->UEP0_TX_LEN   = len;
                                        USBOTG_FS->UEP0_TX_CTRL ^= USBFS_UEP_T_TOG;
                                        break;

                                case USB_SET_ADDRESS:
                                        USBOTG_FS->DEV_ADDR = (USBOTG_FS->DEV_ADDR & USBFS_UDA_GP_BIT) | USBFS_DevAddr;
                                        break;

                                default:
                                        break;
                            }
                        }
                        break;

                    /* end-point 1 data in interrupt */
                    case ( USBFS_UIS_TOKEN_IN | DEF_UEP1 ):
                        USBOTG_FS->UEP1_TX_CTRL ^= USBFS_UEP_T_TOG;
                        USBOTG_FS->UEP1_TX_CTRL = (USBOTG_FS->UEP1_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
                        USBFS_Endp_Busy[ DEF_UEP1 ] = 0;
                        break;

                    /* end-point 3 data in interrupt */
                    case ( USBFS_UIS_TOKEN_IN | DEF_UEP3 ):
                        USBOTG_FS->UEP3_TX_CTRL ^= USBFS_UEP_T_TOG;
                        USBOTG_FS->UEP3_TX_CTRL = (USBOTG_FS->UEP3_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
                        USBFS_Endp_Busy[ DEF_UEP3 ] = 0;
                        Uart.USB_Up_IngFlag = 0x00;
                        break;

                    /* end-point 4 data in interrupt */
                    case ( USBFS_UIS_TOKEN_IN | DEF_UEP4 ):
                        USBOTG_FS->UEP4_TX_CTRL ^= USBFS_UEP_T_TOG;
                        USBOTG_FS->UEP4_TX_CTRL = (USBOTG_FS->UEP4_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
                        USBFS_Endp_Busy[ DEF_UEP4 ] = 0;
                        break;

                    default :
                        break;
                }
                break;

            /* data-out stage processing */
            case USBFS_UIS_TOKEN_OUT:
                switch ( intst & ( USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK ) )
                {
                    /* end-point 0 data out interrupt */
                    case USBFS_UIS_TOKEN_OUT | DEF_UEP0:
                        len = USBOTG_FS->RX_LEN;
                        if ( intst & USBFS_UIS_TOG_OK )
                        {
                            if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )
                            {
                                /* Non-standard request end-point 0 Data download */
                                USBFS_SetupReqLen = 0;
                                /* Non-standard request end-point 0 Data download */
                                if( USBFS_SetupReqCode == CDC_SET_LINE_CODING )
                                {
                                      /* Save relevant parameters such as serial port baud rate */
                                      /* The downlinked data is processed in the endpoint 0 OUT packet, the 7 bytes of the downlink are, in order
                                         4 bytes: baud rate value: lowest baud rate byte, next lowest baud rate byte, next highest baud rate byte, highest baud rate byte.
                                         1 byte: number of stop bits (0: 1 stop bit; 1: 1.5 stop bit; 2: 2 stop bits).
                                         1 byte: number of parity bits (0: None; 1: Odd; 2: Even; 3: Mark; 4: Space).
                                         1 byte: number of data bits (5,6,7,8,16); */
                                      Uart.Com_Cfg[ 0 ] = USBFS_EP0_Buf[ 0 ];
                                      Uart.Com_Cfg[ 1 ] = USBFS_EP0_Buf[ 1 ];
                                      Uart.Com_Cfg[ 2 ] = USBFS_EP0_Buf[ 2 ];
                                      Uart.Com_Cfg[ 3 ] = USBFS_EP0_Buf[ 3 ];
                                      Uart.Com_Cfg[ 4 ] = USBFS_EP0_Buf[ 4 ];
                                      Uart.Com_Cfg[ 5 ] = USBFS_EP0_Buf[ 5 ];
                                      Uart.Com_Cfg[ 6 ] = USBFS_EP0_Buf[ 6 ];
                                      Uart.Com_Cfg[ 7 ] = DEF_UARTx_RX_TIMEOUT;

                                      /* 保存当前串口的波特率 */
                                      baudrate = USBFS_EP0_Buf[ 0 ];
                                      baudrate += ((uint32_t)USBFS_EP0_Buf[ 1 ] << 8 );
                                      baudrate += ((uint32_t)USBFS_EP0_Buf[ 2 ] << 16 );
                                      baudrate += ((uint32_t)USBFS_EP0_Buf[ 3 ] << 24 );
                                      Uart.Com_Cfg[ 7 ] = Uart.Rx_TimeOutMax;

                                      /* 串口初始化操作 */
                                      UART2_USB_Init( );
                                 }
                                 else if( USBFS_SetupReqCode == HID_SET_REPORT )
                                 {
                                     memcpy(&HID_Report_Buffer[Hid_Report_Ptr],USBFS_EP0_Buf,len);
                                     USBFS_SetupReqLen -= len;
                                     Hid_Report_Ptr += len;
                                     USBOTG_FS->UEP0_RX_CTRL ^= USBFS_UEP_R_TOG;
                                     USBOTG_FS->UEP0_RX_CTRL = (USBOTG_FS->UEP0_RX_CTRL & USBFS_UEP_R_RES_MASK) | USBFS_UEP_R_RES_ACK;
                                 }
                            }
                            else
                            {
                                /* Standard request end-point 0 Data download */
                                /* Add your code here */
                            }
                            if( USBFS_SetupReqLen == 0 )
                            {
                                USBOTG_FS->UEP0_TX_LEN  = 0;
                                USBOTG_FS->UEP0_TX_CTRL = USBFS_UEP_T_TOG | USBFS_UEP_T_RES_ACK;
                            }
                        }
                        break;

                    /* end-point 2 data out interrupt */
                    case USBFS_UIS_TOKEN_OUT | DEF_UEP2:
                        USBOTG_FS->UEP2_RX_CTRL ^= USBFS_UEP_R_TOG;

                        Uart.Tx_PackLen[ Uart.Tx_LoadNum ] = USBOTG_FS->RX_LEN;
                        Uart.Tx_LoadNum++;
                        USBOTG_FS->UEP2_DMA = (uint32_t)(uint8_t *)&UART2_Tx_Buf[ ( Uart.Tx_LoadNum * DEF_USB_FS_PACK_LEN ) ];
                        if( Uart.Tx_LoadNum >= DEF_UARTx_TX_BUF_NUM_MAX )
                        {
                            Uart.Tx_LoadNum = 0x00;
                            USBOTG_FS->UEP2_DMA = (uint32_t)(uint8_t *)&UART2_Tx_Buf[ 0 ];
                        }
                        Uart.Tx_RemainNum++;

                        if( Uart.Tx_RemainNum >= ( DEF_UARTx_TX_BUF_NUM_MAX - 2 ) )
                        {
                            USBOTG_FS->UEP2_RX_CTRL &= ~USBFS_UEP_R_RES_MASK;
                            USBOTG_FS->UEP2_RX_CTRL |= USBFS_UEP_R_RES_NAK;
                            Uart.USB_Down_StopFlag = 0x01;
                        }
                        break;

                        /* end-point 4 data out interrupt */
                    case USBFS_UIS_TOKEN_OUT | DEF_UEP4:
                          USBOTG_FS->UEP4_RX_CTRL ^= USBFS_UEP_R_TOG;
                          /* Reverse the data and re-upload */
                          len = USBOTG_FS->RX_LEN;
                          for( i = 0; i < len; i++ )
                          {
                              USBFS_EP4_Buf[ i + 64 ] = ~USBFS_EP4_Buf[ i ];
                          }
                          USBOTG_FS->UEP4_TX_LEN  = len;
                          USBOTG_FS->UEP4_TX_CTRL &= ~USBFS_UEP_R_RES_MASK;
                          USBOTG_FS->UEP4_TX_CTRL |= USBFS_UEP_R_RES_ACK;
                        break;

                    default:
                        break;
                }
                break;

            /* Setup stage processing */
            case USBFS_UIS_TOKEN_SETUP:
                USBOTG_FS->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_NAK;
                USBOTG_FS->UEP0_RX_CTRL = USBFS_UEP_R_TOG|USBFS_UEP_R_RES_NAK;
                /* Store All Setup Values */
                USBFS_SetupReqType  = pUSBFS_SetupReqPak->bRequestType;
                USBFS_SetupReqCode  = pUSBFS_SetupReqPak->bRequest;
                USBFS_SetupReqLen   = pUSBFS_SetupReqPak->wLength;
                USBFS_SetupReqValue = pUSBFS_SetupReqPak->wValue;
                USBFS_SetupReqIndex = pUSBFS_SetupReqPak->wIndex;
                len = 0;
                errflag = 0;
                if ( ( USBFS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )
                {
                    /* usb non-standard request processing */
                    if( USBFS_SetupReqType & USB_REQ_TYP_CLASS )
                    {
                        /* Class requests */
                        switch( USBFS_SetupReqCode )
                        {
                            case CDC_GET_LINE_CODING:
                                pUSBFS_Descr = (uint8_t *)&Uart.Com_Cfg[ 0 ];
                                len = 7;
                                break;

                            case CDC_SET_LINE_CODING:
                                break;

                            case CDC_SET_LINE_CTLSTE:
                                break;

                            case CDC_SEND_BREAK:
                                break;

                            case HID_SET_REPORT:                            /* 0x09: SET_REPORT */
                                 Hid_Report_Ptr = 0;
                                 break;

                            case HID_GET_REPORT:                            /* 0x01: GET_REPORT */
                                if( USBFS_SetupReqIndex == 0x00 )
                                {
                                    Hid_Report_Ptr = 0;
                                    len = (USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
                                    memcpy( USBFS_EP0_Buf, &HID_Report_Buffer[Hid_Report_Ptr], len );
                                    Hid_Report_Ptr += len;
                                }
                                else
                                {
                                    errflag = 0xFF;
                                }
                                break;

                            case HID_SET_IDLE:                              /* 0x0A: SET_IDLE */
                                if( USBFS_SetupReqIndex == 0x00 )
                                {
                                    USBFS_HidIdle = (uint8_t)( USBFS_SetupReqValue >> 8 );
                                }
                                else
                                {
                                    errflag = 0xFF;
                                }
                                break;

                            case HID_SET_PROTOCOL:                          /* 0x0B: SET_PROTOCOL */
                                if( USBFS_SetupReqIndex == 0x00 )
                                {
                                    USBFS_HidProtocol = (uint8_t)USBFS_SetupReqValue;
                                }
                                else
                                {
                                    errflag = 0xFF;
                                }
                                break;

                            case HID_GET_IDLE:                              /* 0x02: GET_IDLE */
                                if( USBFS_SetupReqIndex == 0x00 )
                                {
                                    USBFS_EP0_Buf[ 0 ] = USBFS_HidIdle;
                                    len = 1;
                                }
                                else
                                {
                                    errflag = 0xFF;
                                }
                                break;

                             case HID_GET_PROTOCOL:                          /* 0x03: GET_PROTOCOL */
                                 if( USBFS_SetupReqIndex == 0x00 )
                                 {
                                     USBFS_EP0_Buf[ 0 ] = USBFS_HidProtocol;
                                     len = 1;
                                 }
                                 else
                                 {
                                     errflag = 0xFF;
                                 }
                                 break;

                            default:
                                errflag = 0xff;
                                break;
                        }
                    }
                    else if( USBFS_SetupReqType & USB_REQ_TYP_VENDOR )
                    {
                        /* Manufacturer request */
                    }
                    else
                    {
                        errflag = 0xFF;
                    }

                    /* Copy Descriptors to Endp0 DMA buffer */
                    len = (USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
                    memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len );
                    pUSBFS_Descr += len;
                }
                else
                {
                    /* usb standard request processing */
                    switch( USBFS_SetupReqCode )
                    {
                        /* get device/configuration/string/report/... descriptors */
                        case USB_GET_DESCRIPTOR:
                            switch( (uint8_t)( USBFS_SetupReqValue >> 8 ) )
                            {
                                /* get usb device descriptor */
                                case USB_DESCR_TYP_DEVICE:
                                    pUSBFS_Descr = MyDevDescr;
                                    len = DEF_USBD_DEVICE_DESC_LEN;
                                    break;

                                /* get usb configuration descriptor */
                                case USB_DESCR_TYP_CONFIG:
                                    pUSBFS_Descr = MyCfgDescr;
                                    len = DEF_USBD_CONFIG_DESC_LEN;
                                    break;

                                /* get hid report descriptor */
                                case USB_DESCR_TYP_REPORT:
                                    pUSBFS_Descr = MyHIDReportDesc;
                                    len = DEF_USBD_REPORT_DESC_LEN;
                                    break;

                                /* get hid descriptor */
                                case USB_DESCR_TYP_HID:
                                    if( USBFS_SetupReqIndex == 0x02 )
                                    {
                                        pUSBFS_Descr = &MyCfgDescr[ 84 ];
                                        len = 9;
                                    }
                                    else
                                    {
                                        errflag = 0xFF;
                                    }
                                    break;

                                /* get usb string descriptor */
                                case USB_DESCR_TYP_STRING:
                                    switch( (uint8_t)( USBFS_SetupReqValue & 0xFF ) )
                                    {
                                        /* Descriptor 0, Language descriptor */
                                        case DEF_STRING_DESC_LANG:
                                            pUSBFS_Descr = MyLangDescr;
                                            len = DEF_USBD_LANG_DESC_LEN;
                                            break;

                                        /* Descriptor 1, Manufacturers String descriptor */
                                        case DEF_STRING_DESC_MANU:
                                            pUSBFS_Descr = MyManuInfo;
                                            len = DEF_USBD_MANU_DESC_LEN;
                                            break;

                                        /* Descriptor 2, Product String descriptor */
                                        case DEF_STRING_DESC_PROD:
                                            pUSBFS_Descr = MyProdInfo;
                                            len = DEF_USBD_PROD_DESC_LEN;
                                            break;

                                        /* Descriptor 3, Serial-number String descriptor */
                                        case DEF_STRING_DESC_SERN:
                                            pUSBFS_Descr = MySerNumInfo;
                                            len = DEF_USBD_SN_DESC_LEN;
                                            break;

                                        default:
                                            errflag = 0xFF;
                                            break;
                                    }
                                    break;

                                default :
                                    errflag = 0xFF;
                                    break;
                            }

                            /* Copy Descriptors to Endp0 DMA buffer */
                            if( USBFS_SetupReqLen>len )
                            {
                                USBFS_SetupReqLen = len;
                            }
                            len = (USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
                            memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len );
                            pUSBFS_Descr += len;
                            break;

                        /* Set usb address */
                        case USB_SET_ADDRESS:
                            USBFS_DevAddr = (uint8_t)( USBFS_SetupReqValue & 0xFF );
                            break;

                        /* Get usb configuration now set */
                        case USB_GET_CONFIGURATION:
                            USBFS_EP0_Buf[0] = USBFS_DevConfig;
                            if ( USBFS_SetupReqLen > 1 )
                            {
                                USBFS_SetupReqLen = 1;
                            }
                            break;

                        /* Set usb configuration to use */
                        case USB_SET_CONFIGURATION:
                            USBFS_DevConfig = (uint8_t)( USBFS_SetupReqValue & 0xFF );
                            USBFS_DevEnumStatus = 0x01;
                            break;

                        /* Clear or disable one usb feature */
                        case USB_CLEAR_FEATURE:
                            if ( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
                            {
                                /* clear one device feature */
                                if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP )
                                {
                                    /* clear usb sleep status, device not prepare to sleep */
                                    USBFS_DevSleepStatus &= ~0x01;
                                }
                            }
                            else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
                            {
                                /* Clear End-point Feature */
                                if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT )
                                {
                                    switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) )
                                    {
                                        case ( DEF_UEP_IN | DEF_UEP1 ):
                                            /* Set End-point 1 IN NAK */
                                            USBOTG_FS->UEP1_TX_CTRL = USBFS_UEP_T_RES_NAK;
                                            break;

                                        case ( DEF_UEP_OUT | DEF_UEP2 ):
                                            /* Set End-point 2 OUT ACK */
                                            USBOTG_FS->UEP2_RX_CTRL = USBFS_UEP_R_RES_ACK;
                                            break;

                                        case ( DEF_UEP_IN | DEF_UEP3 ):
                                            /* Set End-point 3 IN NAK */
                                            USBOTG_FS->UEP3_TX_CTRL = USBFS_UEP_T_RES_NAK;
                                            break;

                                        case ( DEF_UEP_IN | DEF_UEP4 ):
                                            /* Set End-point 4 IN NAK */
                                            USBOTG_FS->UEP4_TX_CTRL = USBFS_UEP_T_RES_NAK;
                                            break;

                                        case ( DEF_UEP_OUT | DEF_UEP4 ):
                                            /* Set End-point 4 OUT ACK */
                                            USBOTG_FS->UEP4_RX_CTRL = USBFS_UEP_R_RES_ACK;
                                            break;

                                        default:
                                            errflag = 0xFF;
                                            break;
                                    }
                                }
                                else
                                {
                                    errflag = 0xFF;
                                }
                            }
                            else
                            {
                                errflag = 0xFF;
                            }
                            break;

                        /* set or enable one usb feature */
                        case USB_SET_FEATURE:
                            if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
                            {
                                /* Set Device Feature */
                                if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP )
                                {
                                    if( MyCfgDescr[ 7 ] & 0x20 )
                                    {
                                        /* Set Wake-up flag, device prepare to sleep */
                                        USBFS_DevSleepStatus |= 0x01;
                                    }
                                    else
                                    {
                                        errflag = 0xFF;
                                    }
                                }
                                else
                                {
                                    errflag = 0xFF;
                                }
                            }
                            else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
                            {
                                /* Set End-point Feature */
                                if( (uint8_t)( USBFS_SetupReqValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT )
                                {
                                    /* Set end-points status stall */
                                    switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) )
                                    {
                                        case ( DEF_UEP_IN | DEF_UEP1 ):
                                            /* Set End-point 1 IN STALL */
                                            USBOTG_FS->UEP1_TX_CTRL = ( USBOTG_FS->UEP1_TX_CTRL & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL;
                                            break;

                                        case ( DEF_UEP_OUT | DEF_UEP2 ):
                                            /* Set End-point 2 OUT STALL */
                                            USBOTG_FS->UEP2_RX_CTRL = ( USBOTG_FS->UEP2_RX_CTRL & ~USBFS_UEP_R_RES_MASK ) | USBFS_UEP_R_RES_STALL;
                                            break;

                                        case ( DEF_UEP_IN | DEF_UEP3 ):
                                            /* Set End-point 3 IN STALL */
                                            USBOTG_FS->UEP3_TX_CTRL = ( USBOTG_FS->UEP3_TX_CTRL & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL;
                                            break;

                                        case ( DEF_UEP_IN | DEF_UEP4 ):
                                            /* Set End-point 4 IN STALL */
                                            USBOTG_FS->UEP4_TX_CTRL = ( USBOTG_FS->UEP4_TX_CTRL & ~USBFS_UEP_T_RES_MASK ) | USBFS_UEP_T_RES_STALL;
                                            break;

                                        case ( DEF_UEP_OUT | DEF_UEP4 ):
                                            /* Set End-point 4 OUT STALL */
                                            USBOTG_FS->UEP4_RX_CTRL = ( USBOTG_FS->UEP4_RX_CTRL & ~USBFS_UEP_R_RES_MASK ) | USBFS_UEP_R_RES_STALL;
                                            break;

                                        default:
                                            errflag = 0xFF;
                                            break;
                                    }
                                }
                                else
                                {
                                    errflag = 0xFF;
                                }
                            }
                            else
                            {
                                errflag = 0xFF;
                            }
                            break;

                        /* This request allows the host to select another setting for the specified interface  */
                        case USB_GET_INTERFACE:
                            USBFS_EP0_Buf[0] = 0x00;
                            if ( USBFS_SetupReqLen > 1 )
                            {
                                USBFS_SetupReqLen = 1;
                            }
                            break;

                        case USB_SET_INTERFACE:
                            break;

                        /* host get status of specified device/interface/end-points */
                        case USB_GET_STATUS:
                            USBFS_EP0_Buf[ 0 ] = 0x00;
                            USBFS_EP0_Buf[ 1 ] = 0x00;
                            if ( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
                            {
                                if( USBFS_DevSleepStatus & 0x01 )
                                {
                                    USBFS_EP0_Buf[ 0 ] = 0x02;
                                }
                            }
                            else if( ( USBFS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
                            {
                                switch( (uint8_t)( USBFS_SetupReqIndex & 0xFF ) )
                                {
                                    case ( DEF_UEP_IN | DEF_UEP1 ):
                                        if( ( (USBOTG_FS->UEP1_TX_CTRL) & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL )
                                        {
                                            USBFS_EP0_Buf[ 0 ] = 0x01;
                                        }
                                        break;

                                    case ( DEF_UEP_OUT | DEF_UEP2 ):
                                        if( ( (USBOTG_FS->UEP2_RX_CTRL) & USBFS_UEP_R_RES_MASK ) == USBFS_UEP_R_RES_STALL )
                                        {
                                            USBFS_EP0_Buf[ 0 ] = 0x01;
                                        }
                                        break;

                                    case ( DEF_UEP_IN | DEF_UEP3 ):
                                        if( ( (USBOTG_FS->UEP3_TX_CTRL) & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL )
                                        {
                                            USBFS_EP0_Buf[ 0 ] = 0x01;
                                        }
                                        break;

                                    case ( DEF_UEP_IN | DEF_UEP4 ):
                                        if( ( (USBOTG_FS->UEP4_TX_CTRL) & USBFS_UEP_T_RES_MASK ) == USBFS_UEP_T_RES_STALL )
                                        {
                                            USBFS_EP0_Buf[ 0 ] = 0x01;
                                        }
                                        break;

                                    case ( DEF_UEP_OUT | DEF_UEP4 ):
                                        if( ( (USBOTG_FS->UEP4_RX_CTRL) & USBFS_UEP_R_RES_MASK ) == USBFS_UEP_R_RES_STALL )
                                        {
                                            USBFS_EP0_Buf[ 0 ] = 0x01;
                                        }
                                        break;

                                    default:
                                        errflag = 0xFF;
                                        break;
                                }
                            }
                            else
                            {
                                errflag = 0xFF;
                            }

                            if( USBFS_SetupReqLen > 2 )
                            {
                                USBFS_SetupReqLen = 2;
                            }

                            break;

                        default:
                            errflag = 0xFF;
                            break;
                    }
                }
                /* errflag = 0xFF means a request not support or some errors occurred, else correct */
                if( errflag == 0xff)
                {
                    /* if one request not support, return stall */
                    USBOTG_FS->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_STALL;
                    USBOTG_FS->UEP0_RX_CTRL = USBFS_UEP_R_TOG|USBFS_UEP_R_RES_STALL;
                }
                else
                {
                    /* end-point 0 data Tx/Rx */
                    if( USBFS_SetupReqType & DEF_UEP_IN )
                    {
                        /* tx */
                        len = (USBFS_SetupReqLen>DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
                        USBFS_SetupReqLen -= len;
                        USBOTG_FS->UEP0_TX_LEN  = len;
                        USBOTG_FS->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_ACK;
                    }
                    else
                    {
                        /* rx */
                        if( USBFS_SetupReqLen == 0 )
                        {
                            USBOTG_FS->UEP0_TX_LEN  = 0;
                            USBOTG_FS->UEP0_TX_CTRL = USBFS_UEP_T_TOG|USBFS_UEP_T_RES_ACK;
                        }
                        else
                        {
                            USBOTG_FS->UEP0_RX_CTRL = USBFS_UEP_R_TOG|USBFS_UEP_R_RES_ACK;
                        }
                    }
                }
                break;

            /* Sof pack processing */
            case USBFS_UIS_TOKEN_SOF:
                break;

            default :
                break;
        }
        USBOTG_FS->INT_FG = USBFS_UIF_TRANSFER;
    }
    else if( intflag & USBFS_UIF_BUS_RST )
    {
        /* usb reset interrupt processing */
        USBOTG_FS->DEV_ADDR = 0;
        USBFS_Device_Endp_Init( );
        UART2_ParaInit( 1 );
        USBOTG_FS->INT_FG = USBFS_UIF_BUS_RST;
    }
    else if( intflag & USBFS_UIF_SUSPEND )
    {
        /* usb suspend interrupt processing */
        if ( USBOTG_FS->MIS_ST & USBFS_UMS_SUSPEND )
        {
            USBFS_DevSleepStatus |= 0x02;
            if( USBFS_DevSleepStatus == 0x03 )
            {
                /* Handling usb sleep here */
            }
        }
        else
        {
            USBFS_DevSleepStatus &= ~0x02;
        }
        USBOTG_FS->INT_FG = USBFS_UIF_SUSPEND;
    }
    else
    {
        /* other interrupts */
        USBOTG_FS->INT_FG = intflag;
    }
}

```

  • 写回答

9条回答 默认 最新

  • bug菌¹ 优质创作者: Java、算法与数据结构技术领域 2023-10-29 17:57
    关注

    该回答引用ChatGPT,望对题主有所帮助/启发;若有帮助,还望采纳。


    该函数是USB中断服务程序,在单片机上运行。函数总体结构是基于USB端点(Endpoint)中断的处理,通过读取端点中断状态寄存器来确定应该执行的操作类型,其主要包括三种类型的操作:数据传输,数据接收,和设置。下面是逐行的代码解释和大体框架解释:

    1. void OTG_FS_IRQHandler( void )
      函数名称为OTG_FS_IRQHandler,是USB中断服务程序的入口函数,void表示没有返回值,括号内的void表示此函数不接收任何参数。函数在单片机运行时会自动调用该函数,当USB接口有数据传输或者数据接收等操作时,此函数会根据中断状态寄存器的值来执行相应的操作。整个函数体的代码如下:
    void OTG_FS_IRQHandler( void )
    {
        uint8_t  intflag, intst, errflag;
        uint16_t len, i;
        uint32_t baudrate;
     
        intflag = USBOTG_FS->INT_FG;
        intst   = USBOTG_FS->INT_ST;
     
        if( intflag & USBFS_UIF_TRANSFER )
        {
          // 对于数据传输中断
        }
        else if ( intflag & USBFS_UIF_SUSPEND )
        {
          //  对于Suspend状态的中断
        }
        else if ( intflag & USBFS_UIF_SOF )
        {
          //  对于SOF帧的中断
        }
        else if ( intflag & USBFS_UIF_RESET )
        {
          //  对于USB总线复位的中断
        }
        else if ( intflag & USBFS_UIF_TOKEN )
        {
          //  对于USB令牌地址匹配的中断
        }
    }
    
    1. uint8_t intflag, intst, errflag;
      这一行代码定义了三个无符号8位整数变量,分别为中断标志、中断状态、和错误标志。

    2. intflag = USBOTG_FS->INT_FG;
      从USB设备寄存器中读取中断标志的值,并将其赋值给intflag变量。

    3. intst = USBOTG_FS->INT_ST;
      从USB设备寄存器中读取中断状态的值,并将其赋值给intst变量。

    4. if( intflag & USBFS_UIF_TRANSFER )
      如果中断标志变量的值与USBFS_UIF_TRANSFER相同,则说明此次中断是数据传输中断。

    5. switch (intst & USBFS_UIS_TOKEN_MASK)
      读取中断状态变量的值并与USBFS_UIS_TOKEN_MASK做按位与运算,得到的结果用于确定中断的类型。

    6. case USBFS_UIS_TOKEN_IN:
      说明本次中断是数据传输的IN口(单向数据传输从外设到主机)。

    7. case USBFS_UIS_TOKEN_OUT:
      说明本次中断是数据传输的OUT口(单向数据传输从主机到外设)。

    8. case USBFS_UIS_TOKEN_SETUP:
      说明本次中断是设置请求。

    9. switch ( intst & ( USBFS_UIS_TOKEN_MASK | USBFS_UIS_ENDP_MASK ) )
      针对不同的中断类型,再次进行细分,确定中断来源。

    10. case USBFS_UIS_TOKEN_IN | DEF_UEP0:
      对于IN口中断,检测是否为端点0(即默认控制端点)的接收中断。

    11. if( USBFS_SetupReqLen == 0 )
      如果收到的数据长度为0,则发送ACK应答信号回复主机。

    12. switch( USBFS_SetupReqCode )
      根据请求的类型(SETUP、OUT、IN)来判断执行哪种操作。

    13. case USB_GET_DESCRIPTOR:
      如果是获取设备描述符,则从全局定义的描述符变量中返回一段数据,将数据长度保存到len变量中。

    14. len = USBFS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : USBFS_SetupReqLen;
      计算实际需要返回的数据长度,取值范围为1~64字节。

    15. memcpy( USBFS_EP0_Buf, pUSBFS_Descr, len );
      将从描述符变量中返回的数据拷贝到端点0缓存中。

    16. USBFS_SetupReqLen -= len;
      更新待返回的数据长度,即减去已经返回的数据长度。

    17. pUSBFS_Descr += len;
      将描述符变量的指针向后移动,指向下一个待返回的数据。

    18. USBOTG_FS->UEP0_TX_LEN = len;
      设置端点0的发送数据长度寄存器的值。

    19. USBOTG_FS->UEP0_TX_CTRL ^= USBFS_UEP_T_TOG;
      翻转端点0的发送数据的数据包序号,用于区分不同的数据包。

    20. case USB_SET_ADDRESS:
      如果是设置设备地址,则从芯片设备寄存器中获取当前设备地址,并将它与新的设备地址进行合并。

    21. USBOTG_FS->DEV_ADDR = (USBOTG_FS->DEV_ADDR & USBFS_UDA_GP_BIT) | USBFS_DevAddr;
      将新的设备地址合并到设备地址寄存器中,并将低两位清零。

    22. USBOTG_FS->UEP1_TX_CTRL ^= USBFS_UEP_T_TOG;
      翻转端点1的发送数据的数据包序号,用于区分不同的数据包。

    23. USBOTG_FS->UEP1_TX_CTRL = (USBOTG_FS->UEP1_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
      设置端点1发送数据的状态为NAK。

    24. USBFS_Endp_Busy[ DEF_UEP1 ] = 0;
      设置端点1的状态为非忙碌状态,用于发送下一个数据包。

    25. case ( USBFS_UIS_TOKEN_IN | DEF_UEP3 ):
      如果是IN口中断,检测是否为端点3(即虚拟串口的发送端口)的数据发送中断。

    26. USBOTG_FS->UEP3_TX_CTRL ^= USBFS_UEP_T_TOG;
      翻转端点3的发送数据的数据包序号,用于区分不同的数据包。

    27. USBOTG_FS->UEP3_TX_CTRL = (USBOTG_FS->UEP3_TX_CTRL & ~USBFS_UEP_T_RES_MASK) | USBFS_UEP_T_RES_NAK;
      设置端点3发送数据的状态为NAK。

    28. USBFS_Endp_Busy[ DEF_UEP3 ] = 0;
      设置端点3的状态为非忙碌状态,用于发送下一个数据包。

    29. Uart.USB_Up_IngFlag = 0x00;
      设置USB上传标志变量为0,用于表示当前没有上传操作。

    30. case USBFS_UIS_TOKEN_OUT | DEF_UEP0:
      检测是否为端点0的数据接收中断。

    31. len = USBOTG_FS->RX_LEN;
      获取数据接收的长度值。

    32. if ( intst & USBFS_UIS_TOG_OK )
      判断是否数据包序号正确。

    33. USBFS_SetupReqLen = 0;
      清空USB请求接收数据长度寄存器。

    34. if( USBFS_SetupReqCode == CDC_SET_LINE_CODING )
      如果是设置串口参数的请求。

    35. Uart.Com_Cfg[ 0 ] = USBFS_EP0_Buf[ 0 ];
      从接收缓存中获取并保存串口波特率参数。

    36. Uart.Com_Cfg[ 1 ] = USBFS_EP0_Buf[ 1 ];
      从接收缓存中获取并保存串口数据位长度参数。

    37. Uart.Com_Cfg[ 2 ] = USBFS_EP0_Buf[ 2 ];
      从接收缓存中获取并保存串口停止位长度参数。

    38. Uart.Com_Cfg[ 3 ] = USBFS_EP0_Buf[ 3 ];
      从接收缓存中获取并保存串口校验位类型参数。

    39. Uart.Com_Cfg[ 4 ] = USBFS_EP0_Buf[ 4 ];
      从接收缓存中获取并保存串口流控制类型参数。

    40. Uart.Com_Cfg[ 5 ] = USBFS_EP0_Buf[ 5 ];
      从接收缓存中获取并保存串

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(8条)

报告相同问题?

问题事件

  • 系统已结题 11月9日
  • 已采纳回答 11月1日
  • 修改了问题 10月29日
  • 创建了问题 10月29日