CH32V307 多CDC 串口 程序

 一、简介

首先感谢沁恒送的开发板,提供测试平台用于开发。

在官方例程中USB的例程比其他的开发板要多,这也是沁恒的优势。

在CH32V307/EVT的例程中有simulateCDC,是一个模拟单USB转串口的程序。在这上面修改的4CDC的USB转串口。理论上可以转所有的串口,还是高速2.0的协议。

二、开发

1、修改usb_desc.c

这里主要修改的几个地方,DEV descr 和 cfg descr 。主要是改为复合设备,在CFG 描述中增加其他interface 描述。注意需要添加IAD,同时修改cfg描述长度。

/* Device Descriptor */
const uint8_t  MyDevDescr[ ] =
{
    0x12,       // bLength
    0x01,       // bDescriptorType (Device)
    0x00, 0x02, // bcdUSB 2.00
    0xEF,       // bDeviceClass Communications and CDC Control
    0x02,       // bDeviceSubClass  4
    0x01,       // bDeviceProtocol  0x1
    DEF_USBD_UEP0_SIZE,   // bMaxPacketSize0 64
    (uint8_t)DEF_USB_VID, (uint8_t)(DEF_USB_VID >> 8),  // idVendor 0x1A86
    (uint8_t)DEF_USB_PID, (uint8_t)(DEF_USB_PID >> 8),  // idProduct 0xFE0C
    DEF_IC_PRG_VER, 0x00, // bcdDevice 0.01
    0x01,       // iManufacturer (String Index)
    0x02,       // iProduct (String Index)
    0x03,       // iSerialNumber (String Index)
    0x01,       // bNumConfigurations 1
};
const uint8_t  MyCfgDescr_HS[ ] =
{
    /* Configure descriptor */ //增加bNumInterfaces 增加到8  第三位为总体的长度。当前0X43 需要修改为0XF1
    0x09, 0x02, 0x11, 0x01, 0x08, 0x01, 0x00, 0x80, 0x32,


    /******************** IAD ********************/
   0x08,        // bLength: Interface Descriptor size
   0x0B,        // bDescriptorType: IAD
   0x00,        // bFirstInterface
   0x02,        // bInterfaceCount
   0x02,        // bFunctionClass: CDC
   0x02,        // bFunctionSubClass
   0x01,        // bFunctionProtocol
   0x00,        //!! string descriptor for this interface
    /* Interface 0 (CDC) descriptor */
    0x09, 0x04, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,

    /* CDC Functional Descriptors */
    0x05, 0x24, 0x00, 0x10, 0x01,

    /* Length/management descriptor (data class interface 1) */
    0x05, 0x24, 0x01, 0x00, 0x01,
    0x04, 0x24, 0x02, 0x02,
    0x05, 0x24, 0x06, 0x00, 0x01,

    /* Interrupt upload endpoint descriptor */
    0x07, 0x05, 0x83, 0x03, (uint8_t)DEF_USB_EP3_FS_SIZE, (uint8_t)( DEF_USB_EP3_FS_SIZE >> 8 ), 0x01,

    /* Interface 1 (data interface) descriptor */
    0x09, 0x04, 0x01, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00,

    /* Endpoint descriptor */
    0x07, 0x05, 0x02, 0x02, (uint8_t)DEF_USB_EP2_HS_SIZE, (uint8_t)( DEF_USB_EP2_HS_SIZE >> 8 ), 0x00,

    /* Endpoint descriptor */
    0x07, 0x05, 0x82, 0x02, (uint8_t)DEF_USB_EP2_HS_SIZE, (uint8_t)( DEF_USB_EP2_HS_SIZE >> 8 ), 0x00,


    /******************** IAD ********************/
   0x08,        // bLength: Interface Descriptor size
   0x0B,        // bDescriptorType: IAD
   0x02,        // bFirstInterface
   0x02,        // bInterfaceCount
   0x02,        // bFunctionClass: CDC
   0x02,        // bFunctionSubClass
   0x01,        // bFunctionProtocol
   0x01,        //!! string descriptor for this interface
    /* Interface 2 (CDC) descriptor */
    0x09, 0x04, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,

    /* CDC Functional Descriptors */
    0x05, 0x24, 0x00, 0x10, 0x01,

    /* Length/management descriptor (data class interface 2) */
    0x05, 0x24, 0x01, 0x00, 0x01,
    0x04, 0x24, 0x02, 0x02,
    0x05, 0x24, 0x06, 0x02, 0x03,

    /* Interrupt upload endpoint descriptor */
    0x07, 0x05, 0x85, 0x03, (uint8_t)DEF_USB_EP5_FS_SIZE, (uint8_t)( DEF_USB_EP5_FS_SIZE >> 8 ), 0x01,

    /* Interface 3 (data interface) descriptor */
    0x09, 0x04, 0x03, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00,

    /* Endpoint descriptor */
    0x07, 0x05, 0x04, 0x02, (uint8_t)DEF_USB_EP4_HS_SIZE, (uint8_t)( DEF_USB_EP4_HS_SIZE >> 8 ), 0x00,

    /* Endpoint descriptor */
    0x07, 0x05, 0x84, 0x02, (uint8_t)DEF_USB_EP4_HS_SIZE, (uint8_t)( DEF_USB_EP4_HS_SIZE >> 8 ), 0x00,

    /******************** IAD ********************/
   0x08,        // bLength: Interface Descriptor size
   0x0B,        // bDescriptorType: IAD
   0x04,        // bFirstInterface
   0x02,        // bInterfaceCount
   0x02,        // bFunctionClass: CDC
   0x02,        // bFunctionSubClass
   0x01,        // bFunctionProtocol
   0x00,        //!! string descriptor for this interface
    /* Interface 4 (CDC) descriptor */
    0x09, 0x04, 0x04, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,

    /* CDC Functional Descriptors */
    0x05, 0x24, 0x00, 0x10, 0x01,

    /* Length/management descriptor (data class interface 3) */
    0x05, 0x24, 0x01, 0x00, 0x01,
    0x04, 0x24, 0x02, 0x02,
    0x05, 0x24, 0x06, 0x04, 0x05,

    /* Interrupt upload endpoint descriptor */
    0x07, 0x05, 0x87, 0x03, (uint8_t)DEF_USB_EP7_FS_SIZE, (uint8_t)( DEF_USB_EP7_FS_SIZE >> 8 ), 0x01,

    /* Interface 5 (data interface) descriptor */
    0x09, 0x04, 0x05, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00,

    /* Endpoint descriptor */
    0x07, 0x05, 0x06, 0x02, (uint8_t)DEF_USB_EP6_HS_SIZE, (uint8_t)( DEF_USB_EP6_HS_SIZE >> 8 ), 0x00,

    /* Endpoint descriptor */
    0x07, 0x05, 0x86, 0x02, (uint8_t)DEF_USB_EP6_HS_SIZE, (uint8_t)( DEF_USB_EP6_HS_SIZE >> 8 ), 0x00,

    /******************** IAD ********************/
   0x08,        // bLength: Interface Descriptor size
   0x0B,        // bDescriptorType: IAD
   0x06,        // bFirstInterface
   0x02,        // bInterfaceCount
   0x02,        // bFunctionClass: CDC
   0x02,        // bFunctionSubClass
   0x01,        // bFunctionProtocol
   0x00,        //!! string descriptor for this interface
    /* Interface 6 (CDC) descriptor */
    0x09, 0x04, 0x06, 0x00, 0x01, 0x02, 0x02, 0x01, 0x00,

    /* CDC Functional Descriptors */
    0x05, 0x24, 0x00, 0x10, 0x01,

    /* Length/management descriptor (data class interface 4) */
    0x05, 0x24, 0x01, 0x00, 0x01,
    0x04, 0x24, 0x02, 0x02,
    0x05, 0x24, 0x06, 0x06, 0x07,

    /* Interrupt upload endpoint descriptor */
    0x07, 0x05, 0x89, 0x03, (uint8_t)DEF_USB_EP9_FS_SIZE, (uint8_t)( DEF_USB_EP9_FS_SIZE >> 8 ), 0x01,

    /* Interface 7 (data interface) descriptor */
    0x09, 0x04, 0x07, 0x00, 0x02, 0x0a, 0x00, 0x00, 0x00,

    /* Endpoint descriptor */
    0x07, 0x05, 0x08, 0x02, (uint8_t)DEF_USB_EP8_HS_SIZE, (uint8_t)( DEF_USB_EP8_HS_SIZE >> 8 ), 0x00,

    /* Endpoint descriptor */
    0x07, 0x05, 0x88, 0x02, (uint8_t)DEF_USB_EP8_HS_SIZE, (uint8_t)( DEF_USB_EP8_HS_SIZE >> 8 ), 0x00,
};

 2、修改ch32v30x_usbhs_device.c

这里面主要是修改usb 端点初始化,增加端点。  修改USBHS_IRQHandler 中断处理函数。

/*********************************************************************
 * @fn      USBHS_Device_Endp_Init
 *
 * @brief   Initializes USB device endpoints.
 *
 * @return  none
 */
void USBHS_Device_Endp_Init ( void )
{
    uint8_t i;

    USBHSD->ENDP_CONFIG = USBHS_UEP3_T_EN | USBHS_UEP3_R_EN |
                          USBHS_UEP4_T_EN | USBHS_UEP4_R_EN |
                          USBHS_UEP5_T_EN | USBHS_UEP5_R_EN |
                          USBHS_UEP6_T_EN | USBHS_UEP6_R_EN |
                          USBHS_UEP7_T_EN | USBHS_UEP7_R_EN |
                          USBHS_UEP8_T_EN | USBHS_UEP8_R_EN |
                          USBHS_UEP9_T_EN | USBHS_UEP9_R_EN |
                          USBHS_UEP2_T_EN | USBHS_UEP2_R_EN;

    USBHSD->UEP0_MAX_LEN  = DEF_USBD_UEP0_SIZE;
    USBHSD->UEP2_MAX_LEN  = DEF_USB_EP3_HS_SIZE;
    USBHSD->UEP3_MAX_LEN  = DEF_USB_EP3_HS_SIZE;

    USBHSD->UEP4_MAX_LEN  = DEF_USB_EP4_HS_SIZE;
    USBHSD->UEP5_MAX_LEN  = DEF_USB_EP5_HS_SIZE;

    USBHSD->UEP6_MAX_LEN  = DEF_USB_EP6_HS_SIZE;
    USBHSD->UEP7_MAX_LEN  = DEF_USB_EP7_HS_SIZE;

    USBHSD->UEP8_MAX_LEN  = DEF_USB_EP8_HS_SIZE;
    USBHSD->UEP9_MAX_LEN  = DEF_USB_EP9_HS_SIZE;

    USBHSD->UEP0_DMA    = (uint32_t)(uint8_t *)USBHS_EP0_Buf;

    USBHSD->UEP3_RX_DMA = (uint32_t)(uint8_t *)USBHS_EP3_Tx_Buf;
    USBHSD->UEP2_RX_DMA = (uint32_t)(uint8_t *)&UART2_Tx_Buf[ 0 ];
    USBHSD->UEP2_TX_DMA = (uint32_t)(uint8_t *)USBHS_EP2_Tx_Buf;

    USBHSD->UEP0_TX_LEN  = 0;
    USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_RES_NAK;
    USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_RES_ACK;

    USBHSD->UEP2_TX_LEN  = 0;
    USBHSD->UEP2_TX_CTRL = USBHS_UEP_T_RES_NAK;
    USBHSD->UEP2_RX_CTRL = USBHS_UEP_R_RES_ACK;

    USBHSD->UEP3_TX_LEN  = 0;
    USBHSD->UEP3_TX_CTRL = USBHS_UEP_T_RES_NAK;
    USBHSD->UEP3_RX_CTRL = USBHS_UEP_R_RES_ACK;

    USBHSD->UEP4_TX_LEN  = 0;
    USBHSD->UEP4_TX_CTRL = USBHS_UEP_T_RES_NAK;
    USBHSD->UEP4_RX_CTRL = USBHS_UEP_R_RES_ACK;

    USBHSD->UEP5_TX_LEN  = 0;
    USBHSD->UEP5_TX_CTRL = USBHS_UEP_T_RES_NAK;
    USBHSD->UEP5_RX_CTRL = USBHS_UEP_R_RES_ACK;

    USBHSD->UEP6_TX_LEN  = 0;
    USBHSD->UEP6_TX_CTRL = USBHS_UEP_T_RES_NAK;
    USBHSD->UEP6_RX_CTRL = USBHS_UEP_R_RES_ACK;

    USBHSD->UEP7_TX_LEN  = 0;
    USBHSD->UEP7_TX_CTRL = USBHS_UEP_T_RES_NAK;
    USBHSD->UEP7_RX_CTRL = USBHS_UEP_R_RES_ACK;

    USBHSD->UEP8_TX_LEN  = 0;
    USBHSD->UEP8_TX_CTRL = USBHS_UEP_T_RES_NAK;
    USBHSD->UEP8_RX_CTRL = USBHS_UEP_R_RES_ACK;

    USBHSD->UEP9_TX_LEN  = 0;
    USBHSD->UEP9_TX_CTRL = USBHS_UEP_T_RES_NAK;
    USBHSD->UEP9_RX_CTRL = USBHS_UEP_R_RES_ACK;
    /* Clear End-points Busy Status */
    for( i=0; i<DEF_UEP_NUM; i++ )
    {
        USBHS_Endp_Busy[ i ] = 0;
    }
}

                        default :
                            errflag = 0xFF;
                            break;
                    }

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

                /* Set usb address */
                case USB_SET_ADDRESS:
                    USBHS_DevAddr = (uint16_t)(USBHS_SetupReqValue&0xFF);
                    break;

                /* Get usb configuration now set */
                case USB_GET_CONFIGURATION:
                    USBHS_EP0_Buf[0] = USBHS_DevConfig;
                    if ( USBHS_SetupReqLen > 1 )
                    {
                        USBHS_SetupReqLen = 1;
                    }
                    break;

                /* Set usb configuration to use */
                case USB_SET_CONFIGURATION:
                    USBHS_DevConfig = (uint8_t)(USBHS_SetupReqValue&0xFF);
                    USBHS_DevEnumStatus = 0x01;
                    break;

                /* Clear or disable one usb feature */
                case USB_CLEAR_FEATURE:
                    if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
                    {
                        /* clear one device feature */
                        if((uint8_t)(USBHS_SetupReqValue&0xFF) == 0x01)
                        {
                            /* clear usb sleep status, device not prepare to sleep */
                            USBHS_DevSleepStatus &= ~0x01;
                        }
                        else
                        {
                            errflag = 0xFF;
                        }
                    }
                    else if ( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
                    {
                        /* Set End-point Feature */
                        if( (uint8_t)(USBHS_SetupReqValue&0xFF) == USB_REQ_FEAT_ENDP_HALT )
                        {
                            /* Clear End-point Feature */
                            switch( (uint8_t)(USBHS_SetupReqIndex&0xFF) )
                            {
                                case (DEF_UEP2 | DEF_UEP_IN):
                                    /* Set End-point 2 IN NAK */
                                    USBHSD->UEP2_TX_CTRL = USBHS_UEP_T_RES_NAK;
                                    break;

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

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

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

                    }
                    else
                    {
                        errflag = 0xFF;
                    }
                    break;

                /* set or enable one usb feature */
                case USB_SET_FEATURE:
                    if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
                    {
                        /* Set Device Feature */
                        if( (uint8_t)(USBHS_SetupReqValue&0xFF) == USB_REQ_FEAT_REMOTE_WAKEUP )
                        {
                            if( MyCfgDescr_FS[ 7 ] & 0x20 )
                            {
                                /* Set Wake-up flag, device prepare to sleep */
                                USBHS_DevSleepStatus |= 0x01;
                            }
                            else
                            {
                                errflag = 0xFF;
                            }
                        }
                        else
                        {
                            errflag = 0xFF;
                        }
                    }
                    else if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
                    {
                        /* Set End-point Feature */
                        if( (uint8_t)(USBHS_SetupReqValue&0xFF) == USB_REQ_FEAT_ENDP_HALT )
                        {
                            /* Set end-points status stall */
                            switch((uint8_t)(USBHS_SetupReqIndex&0xFF) )
                            {
                                case (DEF_UEP2 | DEF_UEP_IN):
                                    /* Set End-point 2 IN STALL */
                                    USBHSD->UEP2_TX_CTRL = ( USBHSD->UEP2_TX_CTRL & ~USBHS_UEP_T_RES_MASK ) | USBHS_UEP_T_RES_STALL;
                                    break;

                                case (DEF_UEP2 | DEF_UEP_OUT):
                                    /* Set End-point 2 OUT STALL */
                                    USBHSD->UEP2_RX_CTRL = ( USBHSD->UEP2_RX_CTRL & ~USBHS_UEP_R_RES_MASK ) | USBHS_UEP_R_RES_STALL;
                                    break;

                                case (DEF_UEP3 | DEF_UEP_IN):
                                    /* Set End-point 3 IN STALL */
                                    USBHSD->UEP3_TX_CTRL = ( USBHSD->UEP3_TX_CTRL & ~USBHS_UEP_T_RES_MASK ) | USBHS_UEP_T_RES_STALL;
                                    break;

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

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

                case USB_SET_INTERFACE:
                    break;

                /* host get status of specified device/interface/end-points */
                case USB_GET_STATUS:
                    USBHS_EP0_Buf[0] = 0x00;
                    USBHS_EP0_Buf[1] = 0x00;
                    if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
                    {
                        switch( (uint8_t)( USBHS_SetupReqIndex & 0xFF ) )
                        {
                            case (DEF_UEP2 | DEF_UEP_IN):
                                if( ( (USBHSD->UEP2_TX_CTRL) & USBHS_UEP_T_RES_MASK ) == USBHS_UEP_T_RES_STALL )
                                {
                                    USBHS_EP0_Buf[ 0 ] = 0x01;
                                }
                                break;

                            case (DEF_UEP2 | DEF_UEP_OUT):
                                if( ( (USBHSD->UEP2_RX_CTRL) & USBHS_UEP_R_RES_MASK ) == USBHS_UEP_R_RES_STALL )
                                {
                                    USBHS_EP0_Buf[ 0 ] = 0x01;
                                }
                                break;

                            case (DEF_UEP3 | DEF_UEP_IN):
                                if( ( (USBHSD->UEP3_TX_CTRL) & USBHS_UEP_T_RES_MASK ) == USBHS_UEP_T_RES_STALL )
                                {
                                    USBHS_EP0_Buf[ 0 ] = 0x01;
                                }
                                break;

                            default:
                                 errflag = 0xFF;
                                 break;
                        }
                    }
                    else if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
                    {
                          if( USBHS_DevSleepStatus & 0x01 )
                          {
                              USBHS_EP0_Buf[ 0 ] = 0x02;
                          }
                    }

                    if ( USBHS_SetupReqLen > 2 )
                    {
                        USBHS_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 */
            USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_STALL;
            USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_STALL;
        }
        else
        {
            /* end-point 0 data Tx/Rx */
            if( USBHS_SetupReqType & DEF_UEP_IN )
            {
                /* tx */
                len = (USBHS_SetupReqLen>DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBHS_SetupReqLen;
                USBHS_SetupReqLen -= len;
                USBHSD->UEP0_TX_LEN = len;
                USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_ACK;
            }
            else
            {
                /* rx */
                if( USBHS_SetupReqLen == 0 )
                {
                    USBHSD->UEP0_TX_LEN = 0;
                    USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_ACK;
                }
                else
                {
                    USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_ACK;
                }
            }
        }
        USBHSD->INT_FG = USBHS_UIF_SETUP_ACT;
    }
    else if( intflag & USBHS_UIF_BUS_RST )//USB 设备模式下 USB 总线复位事件中断标志位
    {
        printf("intflag =USBHS_UIF_BUS_RST\n");

        /* usb reset interrupt processing */
        USBHS_DevConfig = 0;
        USBHS_DevAddr = 0;
        USBHS_DevSleepStatus = 0;
        USBHS_DevEnumStatus = 0;

        USBHSD->DEV_AD = 0;
        USBHS_Device_Endp_Init( );
        UART_ParaInit( 0,1 );
        UART_ParaInit( 1,1 );
        UART_ParaInit( 2,1 );
        UART_ParaInit( 3,1 );
        USBHSD->INT_FG = USBHS_UIF_BUS_RST;
    }
    else if( intflag & USBHS_UIF_SUSPEND )//USB 总线挂起或唤醒事件中断标志位
    {
//        printf("intflag =USBHS_UIF_SUSPEND\n");

        USBHSD->INT_FG = USBHS_UIF_SUSPEND;
        /* usb suspend interrupt processing */
        if ( USBHSD->MIS_ST & USBHS_UMS_SUSPEND  )
        {
            USBHS_DevSleepStatus |= 0x02;
            if( USBHS_DevSleepStatus == 0x03 )
            {
                /* Handling usb sleep here */
            }
        }
        else
        {
            USBHS_DevSleepStatus &= ~0x02;
        }
    }
    else
    {
        /* other interrupts */
        USBHSD->INT_FG = intflag;
    }
}

3、修改USART 相关

增加对应的串口配置。 例如RCC供电配置,增加相应的串口BUFF,配置相应的DMA配置,和接收处理函数。

这里我将所有的文件PUSH出来。

/********************************** (C) COPYRIGHT *******************************
* File Name          : Uart.C
* Author             : WCH
* Version            : V1.01
* Date               : 2022/12/13
* Description        : uart serial port related initialization and processing
*******************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* Attention: This software (modified or not) and binary are used for 
* microcontroller manufactured by Nanjing Qinheng Microelectronics.
*******************************************************************************/

#include "Uart.h"

/*******************************************************************************/
/* Variable Definition */
/* Global */

/* The following are serial port transmit and receive related variables and buffers */
volatile UART_CTL Uart[4];

__attribute__ ((aligned(4))) uint8_t  UART2_Tx_Buf[ DEF_UARTx_TX_BUF_LEN ];  /* Serial port 2 transmit data buffer */
__attribute__ ((aligned(4))) uint8_t  UART2_Rx_Buf[ DEF_UARTx_RX_BUF_LEN ];  /* Serial port 2 receive data buffer */
__attribute__ ((aligned(4))) uint8_t  UART3_Tx_Buf[ DEF_UARTx_TX_BUF_LEN ];  /* Serial port 2 transmit data buffer */
__attribute__ ((aligned(4))) uint8_t  UART3_Rx_Buf[ DEF_UARTx_RX_BUF_LEN ];  /* Serial port 2 receive data buffer */
__attribute__ ((aligned(4))) uint8_t  UART4_Tx_Buf[ DEF_UARTx_TX_BUF_LEN ];  /* Serial port 2 transmit data buffer */
__attribute__ ((aligned(4))) uint8_t  UART4_Rx_Buf[ DEF_UARTx_RX_BUF_LEN ];  /* Serial port 2 receive data buffer */
__attribute__ ((aligned(4))) uint8_t  UART6_Tx_Buf[ DEF_UARTx_TX_BUF_LEN ];  /* Serial port 2 transmit data buffer */
__attribute__ ((aligned(4))) uint8_t  UART6_Rx_Buf[ DEF_UARTx_RX_BUF_LEN ];  /* Serial port 2 receive data buffer */
volatile uint32_t UARTx_Rx_DMACurCount[4];                       /* Serial port X receive dma current counter */
volatile uint32_t UARTx_Rx_DMALastCount[4];                      /* Serial port X receive dma last value counter  */

/*********************************************************************
 * @fn      RCC_Configuration
 *
 * @brief   Configures the different system clocks.
 *
 * @return  none
 */
uint8_t RCC_Configuration( void )
{
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE );

    RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART3, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_UART4, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_UART6, ENABLE );
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM2, ENABLE );
    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA2, ENABLE );

    return 0;
}

/*********************************************************************
 * @fn      TIM2_Init
 *
 * @brief   100us Timer
 *          144 * 100 * 13.8888 -----> 100uS
 *
 * @return  none
 */
void TIM2_Init( void )
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure = {0};

    TIM_DeInit( TIM2 );

    /* Time base configuration */
    TIM_TimeBaseStructure.TIM_Period = 100 - 1;
    TIM_TimeBaseStructure.TIM_Prescaler = SystemCoreClock / 1000000 - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit( TIM2, &TIM_TimeBaseStructure );

    /* Clear TIM2 update pending flag */
    TIM_ClearFlag( TIM2, TIM_FLAG_Update );

    /* TIM IT enable */
    TIM_ITConfig( TIM2, TIM_IT_Update, ENABLE );

    /* Enable Interrupt */
    NVIC_EnableIRQ( TIM2_IRQn );

    /* TIM2 enable counter */
    TIM_Cmd( TIM2, ENABLE );
}

/*********************************************************************
 * @fn      UART2_CfgInit
 *
 * @brief   Uart2 configuration initialization
 *
 * @return  none
 */
void UART2_CfgInit( uint32_t baudrate, uint8_t stopbits, uint8_t parity )
{
    USART_InitTypeDef USART_InitStructure = {0};
    GPIO_InitTypeDef  GPIO_InitStructure = {0};
    uint16_t dat = dat;

    /* delete contains in ( ... )  */
    /* First set the serial port introduction to output high then close the TE and RE of CTLR1 register (note that USARTx->CTLR1 register setting 9 bits has a limit) */
    /* Note: This operation must be performed, the TX pin otherwise the level will be pulled low */
    GPIO_SetBits( GPIOA, GPIO_Pin_2 );
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    /* clear te/re */
    USART2->CTLR1 &= ~( USART_CTLR1_TE | USART_CTLR1_RE );

    /* USART2 Hard configured: */
    /* Configure USART1 Rx (PA3) as input floating */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    /* Configure USART2 Tx (PA2) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    /* Test IO */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init( GPIOA, &GPIO_InitStructure );

    /* USART2 configured as follow:
        - BaudRate = 115200 baud  
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
        - USART Clock disabled
        - USART CPOL: Clock is active low
        - USART CPHA: Data is captured on the middle 
        - USART LastBit: The clock pulse of the last data bit is not output to 
                         the SCLK pin
    */
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    /* Number of stop bits (0: 1 stop bit; 1: 1.5 stop bits; 2: 2 stop bits). */
    if( stopbits == 1 )
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
    }
    else if( stopbits == 2 )
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_2;
    }
    else
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
    }

    /* Check digit (0: None; 1: Odd; 2: Even; 3: Mark; 4: Space); */
    if( parity == 1 )
    {
        USART_InitStructure.USART_Parity = USART_Parity_Odd;
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;
    }
    else if( parity == 2 )
    {
        USART_InitStructure.USART_Parity = USART_Parity_Even;
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;
    }
    else
    {
        USART_InitStructure.USART_Parity = USART_Parity_No;
    }
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init( USART2, &USART_InitStructure );
    USART_ClearFlag( USART2, USART_FLAG_TC );

    /* Enable USART2 */
    USART_Cmd( USART2, ENABLE );
}

/*********************************************************************
 * @fn      UART3_CfgInit
 *
 * @brief   Uart3 configuration initialization
 *
 * @return  none
 */
void UART3_CfgInit( uint32_t baudrate, uint8_t stopbits, uint8_t parity )
{
    USART_InitTypeDef USART_InitStructure = {0};
    GPIO_InitTypeDef  GPIO_InitStructure = {0};
    uint16_t dat = dat;

    /* delete contains in ( ... )  */
    /* First set the serial port introduction to output high then close the TE and RE of CTLR1 register (note that USARTx->CTLR1 register setting 9 bits has a limit) */
    /* Note: This operation must be performed, the TX pin otherwise the level will be pulled low */
    GPIO_SetBits( GPIOB, GPIO_Pin_10 );
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    /* clear te/re */
    USART3->CTLR1 &= ~( USART_CTLR1_TE | USART_CTLR1_RE );

    /* USART2 Hard configured: */
    /* Configure USART3 Rx (PB11) as input floating */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    /* Configure USART3 Tx (PB10) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    /* Test IO */

    /* USART2 configured as follow:
        - BaudRate = 115200 baud
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
        - USART Clock disabled
        - USART CPOL: Clock is active low
        - USART CPHA: Data is captured on the middle
        - USART LastBit: The clock pulse of the last data bit is not output to
                         the SCLK pin
    */
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    /* Number of stop bits (0: 1 stop bit; 1: 1.5 stop bits; 2: 2 stop bits). */
    if( stopbits == 1 )
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
    }
    else if( stopbits == 2 )
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_2;
    }
    else
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
    }

    /* Check digit (0: None; 1: Odd; 2: Even; 3: Mark; 4: Space); */
    if( parity == 1 )
    {
        USART_InitStructure.USART_Parity = USART_Parity_Odd;
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;
    }
    else if( parity == 2 )
    {
        USART_InitStructure.USART_Parity = USART_Parity_Even;
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;
    }
    else
    {
        USART_InitStructure.USART_Parity = USART_Parity_No;
    }
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init( USART3, &USART_InitStructure );
    USART_ClearFlag( USART3, USART_FLAG_TC );

    /* Enable USART3 */
    USART_Cmd( USART3, ENABLE );
}

/*********************************************************************
 * @fn      UART4_CfgInit
 *
 * @brief   Uart4 configuration initialization
 *
 * @return  none
 */
void UART4_CfgInit( uint32_t baudrate, uint8_t stopbits, uint8_t parity )
{
    USART_InitTypeDef USART_InitStructure = {0};
    GPIO_InitTypeDef  GPIO_InitStructure = {0};
    uint16_t dat = dat;

    /* delete contains in ( ... )  */
    /* First set the serial port introduction to output high then close the TE and RE of CTLR1 register (note that USARTx->CTLR1 register setting 9 bits has a limit) */
    /* Note: This operation must be performed, the TX pin otherwise the level will be pulled low */
    GPIO_SetBits( GPIOB, GPIO_Pin_0 );
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    /* clear te/re */
    UART4->CTLR1 &= ~( USART_CTLR1_TE | USART_CTLR1_RE );

    /* USART2 Hard configured: */
    /* Configure USART1 Rx (PA3) as input floating */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    /* Configure USART2 Tx (PA2) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    GPIO_PinRemapConfig(GPIO_PartialRemap_USART4,ENABLE);
    USART_DeInit(UART4);
    /* USART2 configured as follow:
        - BaudRate = 115200 baud
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
        - USART Clock disabled
        - USART CPOL: Clock is active low
        - USART CPHA: Data is captured on the middle
        - USART LastBit: The clock pulse of the last data bit is not output to
                         the SCLK pin
    */
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    /* Number of stop bits (0: 1 stop bit; 1: 1.5 stop bits; 2: 2 stop bits). */
    if( stopbits == 1 )
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
    }
    else if( stopbits == 2 )
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_2;
    }
    else
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
    }

    /* Check digit (0: None; 1: Odd; 2: Even; 3: Mark; 4: Space); */
    if( parity == 1 )
    {
        USART_InitStructure.USART_Parity = USART_Parity_Odd;
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;
    }
    else if( parity == 2 )
    {
        USART_InitStructure.USART_Parity = USART_Parity_Even;
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;
    }
    else
    {
        USART_InitStructure.USART_Parity = USART_Parity_No;
    }
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init( UART4, &USART_InitStructure );
    USART_ClearFlag( UART4, USART_FLAG_TC );

    /* Enable USART4 */
    USART_Cmd( UART4, ENABLE );
}

/*********************************************************************
 * @fn      UART6_CfgInit
 *
 * @brief   Uart6 configuration initialization
 *
 * @return  none
 */
void UART6_CfgInit( uint32_t baudrate, uint8_t stopbits, uint8_t parity )
{
    USART_InitTypeDef USART_InitStructure = {0};
    GPIO_InitTypeDef  GPIO_InitStructure = {0};
    uint16_t dat = dat;

    /* delete contains in ( ... )  */
    /* First set the serial port introduction to output high then close the TE and RE of CTLR1 register (note that USARTx->CTLR1 register setting 9 bits has a limit) */
    /* Note: This operation must be performed, the TX pin otherwise the level will be pulled low */
    GPIO_SetBits( GPIOC, GPIO_Pin_0 );
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;
    GPIO_Init( GPIOC, &GPIO_InitStructure );

    /* clear te/re */
    UART6->CTLR1 &= ~( USART_CTLR1_TE | USART_CTLR1_RE );

    /* USART2 Hard configured: */
    /* Configure USART6 Rx (PC1) as input floating */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;
    GPIO_Init( GPIOC, &GPIO_InitStructure );

    /* Configure USART6 Tx (PC0) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init( GPIOC, &GPIO_InitStructure );


    /* USART2 configured as follow:
        - BaudRate = 115200 baud
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
        - USART Clock disabled
        - USART CPOL: Clock is active low
        - USART CPHA: Data is captured on the middle
        - USART LastBit: The clock pulse of the last data bit is not output to
                         the SCLK pin
    */
    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;

    /* Number of stop bits (0: 1 stop bit; 1: 1.5 stop bits; 2: 2 stop bits). */
    if( stopbits == 1 )
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_1_5;
    }
    else if( stopbits == 2 )
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_2;
    }
    else
    {
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
    }

    /* Check digit (0: None; 1: Odd; 2: Even; 3: Mark; 4: Space); */
    if( parity == 1 )
    {
        USART_InitStructure.USART_Parity = USART_Parity_Odd;
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;
    }
    else if( parity == 2 )
    {
        USART_InitStructure.USART_Parity = USART_Parity_Even;
        USART_InitStructure.USART_WordLength = USART_WordLength_9b;
    }
    else
    {
        USART_InitStructure.USART_Parity = USART_Parity_No;
    }
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init( UART6, &USART_InitStructure );
    USART_ClearFlag( UART6, USART_FLAG_TC );

    /* Enable USART6 */
    USART_Cmd( UART6, ENABLE );
}
/*********************************************************************
 * @fn      UART_ParaInit
 *
 * @brief   Uart parameters initialization
 *          mode = 0 : Used in usb modify initialization
 *          mode = 1 : Used in default initializations
 * @return  none
 */
void UART_ParaInit( uint8_t ch, uint8_t mode )
{
    uint8_t i;

    Uart[ch].Rx_LoadPtr = 0x00;
    Uart[ch].Rx_DealPtr = 0x00;
    Uart[ch].Rx_RemainLen = 0x00;
    Uart[ch].Rx_TimeOut = 0x00;
    Uart[ch].Rx_TimeOutMax = 30;

    Uart[ch].Tx_LoadNum = 0x00;
    Uart[ch].Tx_DealNum = 0x00;
    Uart[ch].Tx_RemainNum = 0x00;
    for( i = 0; i < DEF_UARTx_TX_BUF_NUM_MAX; i++ )
    {
        Uart[ch].Tx_PackLen[ i ] = 0x00;
    }
    Uart[ch].Tx_Flag = 0x00;
    Uart[ch].Tx_CurPackLen = 0x00;
    Uart[ch].Tx_CurPackPtr = 0x00;

    Uart[ch].USB_Up_IngFlag = 0x00;
    Uart[ch].USB_Up_TimeOut = 0x00;
    Uart[ch].USB_Up_Pack0_Flag = 0x00;
    Uart[ch].USB_Down_StopFlag = 0x00;
    UARTx_Rx_DMACurCount[ch] = 0x00;
    UARTx_Rx_DMALastCount[ch] = 0x00;

    if( mode )
    {
        Uart[ch].Com_Cfg[ 0 ] = (uint8_t)( DEF_UARTx_BAUDRATE );
        Uart[ch].Com_Cfg[ 1 ] = (uint8_t)( DEF_UARTx_BAUDRATE >> 8 );
        Uart[ch].Com_Cfg[ 2 ] = (uint8_t)( DEF_UARTx_BAUDRATE >> 16 );
        Uart[ch].Com_Cfg[ 3 ] = (uint8_t)( DEF_UARTx_BAUDRATE >> 24 );
        Uart[ch].Com_Cfg[ 4 ] = DEF_UARTx_STOPBIT;
        Uart[ch].Com_Cfg[ 5 ] = DEF_UARTx_PARITY;
        Uart[ch].Com_Cfg[ 6 ] = DEF_UARTx_DATABIT;
        Uart[ch].Com_Cfg[ 7 ] = DEF_UARTx_RX_TIMEOUT;
    }
}


/*********************************************************************
 * @fn      UART_DMAInit
 *
 * @brief   Uart DMA configuration initialization
 *          ch       : 0 uart2 1 uart3 2 uart4 3 uart6
 *
 *          type = 0 : USART_TX
 *          type = 1 : USART_RX
 *          pbuf     : Tx/Rx Buffer, should be aligned(4)
 *          len      : buffer size of Tx/Rx Buffer
 *
 * @return  none
 */
void UART_DMAInit( uint8_t ch,uint8_t type, uint8_t *pbuf, uint32_t len )
{
    DMA_InitTypeDef DMA_InitStructure = {0};
    DMA_Channel_TypeDef *dmachanel;

    if( type == 0x00 )
    {
         switch (ch) {
            case 0:
                DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART2->DATAR);
                dmachanel=DMA1_Channel7;
                break;
            case 1:
                DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART3->DATAR);
                dmachanel=DMA1_Channel2;
                break;
            case 2:
                DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&UART4->DATAR);
                dmachanel=DMA2_Channel5;
                break;
            case 3:
                DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&UART6->DATAR);
                dmachanel=DMA2_Channel6;
                break;
            default:
                break;
        }
        /* UART2 Tx-DMA configuration */
        DMA_DeInit( dmachanel );
//        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART2->DATAR);
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pbuf;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_BufferSize = len;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init( dmachanel, &DMA_InitStructure );

        DMA_Cmd( dmachanel, ENABLE );
    }
    else
    {
        switch (ch) {
           case 0:
               DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART2->DATAR);
               dmachanel=DMA1_Channel6;
               break;
           case 1:
               DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART3->DATAR);
               dmachanel=DMA1_Channel3;
               break;
           case 2:
               DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&UART4->DATAR);
               dmachanel=DMA2_Channel3;
               break;
           case 3:
               DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&UART6->DATAR);
               dmachanel=DMA2_Channel7;
               break;
           default:
               break;
       }
        /* UART2 Rx-DMA configuration */
        DMA_DeInit( dmachanel );
//        DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART2->DATAR);
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)pbuf;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
        DMA_InitStructure.DMA_BufferSize = len;
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
        DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
        DMA_Init( dmachanel, &DMA_InitStructure );

        DMA_Cmd( dmachanel, ENABLE );
    }
}

/*********************************************************************
 * @fn      UART_Init
 *
 * @brief   Uart total initialization
 *          ch       : 0 uart2 1 uart3 2 uart4 3 uart6
 *          mode     : See the useage of UART_ParaInit( mode )
 *          baudrate : Serial port x default baud rate
 *          stopbits : Serial port x default stop bits
 *          parity   : Serial port x default parity
 *
 * @return  none
 */
void UART_Init(uint8_t ch, uint8_t mode, uint32_t baudrate, uint8_t stopbits, uint8_t parity )
{
    switch (ch) {
        case 0:
            USART_DMACmd( USART2, USART_DMAReq_Rx, DISABLE );
            DMA_Cmd( DMA1_Channel6, DISABLE );
            DMA_Cmd( DMA1_Channel7, DISABLE );

            UART2_CfgInit( baudrate, stopbits, parity );
            UART_DMAInit( ch, 0, &UART2_Tx_Buf[ 0 ], 0 );
            UART_DMAInit( ch, 1, &UART2_Rx_Buf[ 0 ], DEF_UARTx_RX_BUF_LEN );

            USART_DMACmd( USART2, USART_DMAReq_Rx, ENABLE );

            UART_ParaInit( ch, mode );
            break;
        case 1:
            USART_DMACmd( USART3, USART_DMAReq_Rx, DISABLE );
            DMA_Cmd( DMA1_Channel3, DISABLE );
            DMA_Cmd( DMA1_Channel2, DISABLE );

            UART3_CfgInit( baudrate, stopbits, parity );
            UART_DMAInit( ch, 0, &UART3_Tx_Buf[ 0 ], 0 );
            UART_DMAInit( ch, 1, &UART3_Rx_Buf[ 0 ], DEF_UARTx_RX_BUF_LEN );

            USART_DMACmd( USART3, USART_DMAReq_Rx, ENABLE );

            UART_ParaInit( ch, mode );
            break;
        case 2:
            USART_DMACmd( UART4, USART_DMAReq_Rx, DISABLE );
            DMA_Cmd( DMA2_Channel3, DISABLE );
            DMA_Cmd( DMA2_Channel5, DISABLE );

            UART4_CfgInit( baudrate, stopbits, parity );
            UART_DMAInit( ch, 0, &UART4_Tx_Buf[ 0 ], 0 );
            UART_DMAInit( ch, 1, &UART4_Rx_Buf[ 0 ], DEF_UARTx_RX_BUF_LEN );

            USART_DMACmd( UART4, USART_DMAReq_Rx, ENABLE );

            UART_ParaInit( ch, mode );
            break;
            break;
        case 3:
            USART_DMACmd( UART6, USART_DMAReq_Rx, DISABLE );
            DMA_Cmd( DMA2_Channel6, DISABLE );
            DMA_Cmd( DMA2_Channel7, DISABLE );

            UART6_CfgInit( baudrate, stopbits, parity );
            UART_DMAInit( ch, 0, &UART6_Tx_Buf[ 0 ], 0 );
            UART_DMAInit( ch, 1, &UART6_Rx_Buf[ 0 ], DEF_UARTx_RX_BUF_LEN );

            USART_DMACmd( UART6, USART_DMAReq_Rx, ENABLE );

            UART_ParaInit( ch, mode );
            break;
            break;
        default:
            break;
    }


}

/*********************************************************************
 * @fn      UART2_USB_Init
 *
 * @brief   Uart2 initialization in usb interrupt
 *
 * @return  none
 */
void UART_USB_Init( uint8_t ch)
{
    uint32_t baudrate;
    uint8_t  stopbits;
    uint8_t  parity;

    baudrate = ( uint32_t )( Uart[ch].Com_Cfg[ 3 ] << 24 ) + ( uint32_t )( Uart[ch].Com_Cfg[ 2 ] << 16 );
    baudrate += ( uint32_t )( Uart[ch].Com_Cfg[ 1 ] << 8 ) + ( uint32_t )( Uart[ch].Com_Cfg[ 0 ] );
    stopbits = Uart[ch].Com_Cfg[ 4 ];
    parity = Uart[ch].Com_Cfg[ 5 ];

    UART_Init( ch, 0, baudrate, stopbits, parity );

    switch (ch) {
        case 0:
            /* restart usb receive  */
            USBHSD->UEP2_RX_DMA = (uint32_t)(uint8_t *)&UART2_Tx_Buf[ 0 ];
            USBHSD->UEP2_RX_CTRL &= ~USBFS_UEP_R_RES_MASK;
            USBHSD->UEP2_RX_CTRL |= USBFS_UEP_R_RES_ACK;
            break;
        case 1:
            /* restart usb receive  */
            USBHSD->UEP4_RX_DMA = (uint32_t)(uint8_t *)&UART3_Tx_Buf[ 0 ];
            USBHSD->UEP4_RX_CTRL &= ~USBFS_UEP_R_RES_MASK;
            USBHSD->UEP4_RX_CTRL |= USBFS_UEP_R_RES_ACK;
            break;
        case 2:
            /* restart usb receive  */
            USBHSD->UEP6_RX_DMA = (uint32_t)(uint8_t *)&UART4_Tx_Buf[ 0 ];
            USBHSD->UEP6_RX_CTRL &= ~USBFS_UEP_R_RES_MASK;
            USBHSD->UEP6_RX_CTRL |= USBFS_UEP_R_RES_ACK;
            break;
        case 3:
            /* restart usb receive  */
            USBHSD->UEP8_RX_DMA = (uint32_t)(uint8_t *)&UART6_Tx_Buf[ 0 ];
            USBHSD->UEP8_RX_CTRL &= ~USBFS_UEP_R_RES_MASK;
            USBHSD->UEP8_RX_CTRL |= USBFS_UEP_R_RES_ACK;
            break;
        default:
            break;
    }

}

/*********************************************************************
 * @fn      UART2_DataTx_Deal
 *
 * @brief   Uart2 data transmission processing
 *
 * @return  none
 */
void UART2_DataTx_Deal( void )
{
    uint16_t  count;

    /* uart1 transmission processing */
    if( Uart[0].Tx_Flag )
    {
        /* Query whether the DMA transmission of the serial port is completed */
        if( USART2->STATR & USART_FLAG_TC )
        {
            USART2->STATR = (uint16_t)( ~USART_FLAG_TC );
            USART2->CTLR3 &= ( ~USART_DMAReq_Tx );

            Uart[0].Tx_Flag = 0x00;

            NVIC_DisableIRQ( USBHS_IRQn );
            NVIC_DisableIRQ( USBHS_IRQn );

            /* Calculate the variables of last data */
            count = Uart[0].Tx_CurPackLen - DEF_UART2_TX_DMA_CH->CNTR;
            Uart[0].Tx_CurPackLen -= count;
            Uart[0].Tx_CurPackPtr += count;
            if( Uart[0].Tx_CurPackLen == 0x00 )
            {
                Uart[0].Tx_PackLen[ Uart[0].Tx_DealNum ] = 0x0000;
                Uart[0].Tx_DealNum++;
                if( Uart[0].Tx_DealNum >= DEF_UARTx_TX_BUF_NUM_MAX )
                {
                    Uart[0].Tx_DealNum = 0x00;
                }
                Uart[0].Tx_RemainNum--;
            }

            /* If the current serial port has suspended the downlink, restart the driver downlink */
            if( ( Uart[0].USB_Down_StopFlag == 0x01 ) && ( Uart[0].Tx_RemainNum < 2 ) )
            {
                USBHSD->UEP2_RX_CTRL &= ~USBFS_UEP_R_RES_MASK;
                USBHSD->UEP2_RX_CTRL |= USBFS_UEP_R_RES_ACK;
                Uart[0].USB_Down_StopFlag = 0x00;
            }

            NVIC_EnableIRQ( USBHS_IRQn );
        }
    }
    else
    {
        /* Load data from the serial port send buffer to send  */
        if( Uart[0].Tx_RemainNum )
        {
            /* Determine whether to load from the last unsent buffer or from a new buffer */
            if( Uart[0].Tx_CurPackLen == 0x00 )
            {
                Uart[0].Tx_CurPackLen = Uart[0].Tx_PackLen[ Uart[0].Tx_DealNum ];
                Uart[0].Tx_CurPackPtr = ( Uart[0].Tx_DealNum * DEF_USB_HS_PACK_LEN );
            }
            /* Configure DMA and send */
            USART_ClearFlag( USART2, USART_FLAG_TC );
            DMA_Cmd( DEF_UART2_TX_DMA_CH, DISABLE );
            DEF_UART2_TX_DMA_CH->MADDR = (uint32_t)&UART2_Tx_Buf[ Uart[0].Tx_CurPackPtr ];
            DEF_UART2_TX_DMA_CH->CNTR = Uart[0].Tx_CurPackLen;
            DMA_Cmd( DEF_UART2_TX_DMA_CH, ENABLE );
            USART2->CTLR3 |= USART_DMAReq_Tx;
            Uart[0].Tx_Flag = 0x01;
        }
    }
}
/*********************************************************************
 * @fn      UART3_DataTx_Deal
 *
 * @brief   Uart3 data transmission processing
 *
 * @return  none
 */

void UART3_DataTx_Deal( void )
{
    uint16_t  count;

    /* uart1 transmission processing */
    if( Uart[1].Tx_Flag )
    {
        /* Query whether the DMA transmission of the serial port is completed */
        if( USART3->STATR & USART_FLAG_TC )
        {
            USART3->STATR = (uint16_t)( ~USART_FLAG_TC );
            USART3->CTLR3 &= ( ~USART_DMAReq_Tx );

            Uart[1].Tx_Flag = 0x00;

            NVIC_DisableIRQ( USBHS_IRQn );
            NVIC_DisableIRQ( USBHS_IRQn );

            /* Calculate the variables of last data */
            count = Uart[1].Tx_CurPackLen - DEF_UART3_TX_DMA_CH->CNTR;
            Uart[1].Tx_CurPackLen -= count;
            Uart[1].Tx_CurPackPtr += count;
            if( Uart[1].Tx_CurPackLen == 0x00 )
            {
                Uart[1].Tx_PackLen[ Uart[1].Tx_DealNum ] = 0x0000;
                Uart[1].Tx_DealNum++;
                if( Uart[1].Tx_DealNum >= DEF_UARTx_TX_BUF_NUM_MAX )
                {
                    Uart[1].Tx_DealNum = 0x00;
                }
                Uart[1].Tx_RemainNum--;
            }

            /* If the current serial port has suspended the downlink, restart the driver downlink */
            if( ( Uart[1].USB_Down_StopFlag == 0x01 ) && ( Uart[1].Tx_RemainNum < 2 ) )
            {
                USBHSD->UEP4_RX_CTRL &= ~USBFS_UEP_R_RES_MASK;
                USBHSD->UEP4_RX_CTRL |= USBFS_UEP_R_RES_ACK;
                Uart[1].USB_Down_StopFlag = 0x00;
            }

            NVIC_EnableIRQ( USBHS_IRQn );
        }
    }
    else
    {
        /* Load data from the serial port send buffer to send  */
        if( Uart[1].Tx_RemainNum )
        {
            /* Determine whether to load from the last unsent buffer or from a new buffer */
            if( Uart[1].Tx_CurPackLen == 0x00 )
            {
                Uart[1].Tx_CurPackLen = Uart[1].Tx_PackLen[ Uart[1].Tx_DealNum ];
                Uart[1].Tx_CurPackPtr = ( Uart[1].Tx_DealNum * DEF_USB_HS_PACK_LEN );
            }
            /* Configure DMA and send */
            USART_ClearFlag( USART3, USART_FLAG_TC );
            DMA_Cmd( DEF_UART3_TX_DMA_CH, DISABLE );
            DEF_UART3_TX_DMA_CH->MADDR = (uint32_t)&UART3_Tx_Buf[ Uart[1].Tx_CurPackPtr ];
            DEF_UART3_TX_DMA_CH->CNTR = Uart[1].Tx_CurPackLen;
            DMA_Cmd( DEF_UART3_TX_DMA_CH, ENABLE );
            USART3->CTLR3 |= USART_DMAReq_Tx;
            Uart[1].Tx_Flag = 0x01;
        }
    }
}

void UART4_DataTx_Deal( void )
{
    uint16_t  count;

    /* uart1 transmission processing */
    if( Uart[2].Tx_Flag )
    {
        /* Query whether the DMA transmission of the serial port is completed */
        if( UART4->STATR & USART_FLAG_TC )
        {
            UART4->STATR = (uint16_t)( ~USART_FLAG_TC );
            UART4->CTLR3 &= ( ~USART_DMAReq_Tx );

            Uart[2].Tx_Flag = 0x00;

            NVIC_DisableIRQ( USBHS_IRQn );
            NVIC_DisableIRQ( USBHS_IRQn );

            /* Calculate the variables of last data */
            count = Uart[2].Tx_CurPackLen - DEF_UART4_TX_DMA_CH->CNTR;
            Uart[2].Tx_CurPackLen -= count;
            Uart[2].Tx_CurPackPtr += count;
            if( Uart[2].Tx_CurPackLen == 0x00 )
            {
                Uart[2].Tx_PackLen[ Uart[2].Tx_DealNum ] = 0x0000;
                Uart[2].Tx_DealNum++;
                if( Uart[2].Tx_DealNum >= DEF_UARTx_TX_BUF_NUM_MAX )
                {
                    Uart[2].Tx_DealNum = 0x00;
                }
                Uart[2].Tx_RemainNum--;
            }

            /* If the current serial port has suspended the downlink, restart the driver downlink */
            if( ( Uart[2].USB_Down_StopFlag == 0x01 ) && ( Uart[2].Tx_RemainNum < 2 ) )
            {
                USBHSD->UEP6_RX_CTRL &= ~USBFS_UEP_R_RES_MASK;
                USBHSD->UEP6_RX_CTRL |= USBFS_UEP_R_RES_ACK;
                Uart[2].USB_Down_StopFlag = 0x00;
            }

            NVIC_EnableIRQ( USBHS_IRQn );
        }
    }
    else
    {
        /* Load data from the serial port send buffer to send  */
        if( Uart[2].Tx_RemainNum )
        {
            /* Determine whether to load from the last unsent buffer or from a new buffer */
            if( Uart[2].Tx_CurPackLen == 0x00 )
            {
                Uart[2].Tx_CurPackLen = Uart[2].Tx_PackLen[ Uart[2].Tx_DealNum ];
                Uart[2].Tx_CurPackPtr = ( Uart[2].Tx_DealNum * DEF_USB_HS_PACK_LEN );
            }
            /* Configure DMA and send */
            USART_ClearFlag( UART4, USART_FLAG_TC );
            DMA_Cmd( DEF_UART4_TX_DMA_CH, DISABLE );
            DEF_UART4_TX_DMA_CH->MADDR = (uint32_t)&UART4_Tx_Buf[ Uart[2].Tx_CurPackPtr ];
            DEF_UART4_TX_DMA_CH->CNTR = Uart[2].Tx_CurPackLen;
            DMA_Cmd( DEF_UART4_TX_DMA_CH, ENABLE );
            UART4->CTLR3 |= USART_DMAReq_Tx;
            Uart[2].Tx_Flag = 0x01;
        }
    }
}

/*********************************************************************
 * @fn      UART6_DataTx_Deal
 *
 * @brief   Uart6 data transmission processing
 *
 * @return  none
 */
void UART6_DataTx_Deal( void )
{
    uint16_t  count;

    /* uart1 transmission processing */
    if( Uart[3].Tx_Flag )
    {
        /* Query whether the DMA transmission of the serial port is completed */
        if( UART6->STATR & USART_FLAG_TC )
        {
            UART6->STATR = (uint16_t)( ~USART_FLAG_TC );
            UART6->CTLR3 &= ( ~USART_DMAReq_Tx );

            Uart[3].Tx_Flag = 0x00;

            NVIC_DisableIRQ( USBHS_IRQn );
            NVIC_DisableIRQ( USBHS_IRQn );

            /* Calculate the variables of last data */
            count = Uart[3].Tx_CurPackLen - DEF_UART6_TX_DMA_CH->CNTR;
            Uart[3].Tx_CurPackLen -= count;
            Uart[3].Tx_CurPackPtr += count;
            if( Uart[3].Tx_CurPackLen == 0x00 )
            {
                Uart[3].Tx_PackLen[ Uart[3].Tx_DealNum ] = 0x0000;
                Uart[3].Tx_DealNum++;
                if( Uart[3].Tx_DealNum >= DEF_UARTx_TX_BUF_NUM_MAX )
                {
                    Uart[3].Tx_DealNum = 0x00;
                }
                Uart[3].Tx_RemainNum--;
            }

            /* If the current serial port has suspended the downlink, restart the driver downlink */
            if( ( Uart[3].USB_Down_StopFlag == 0x01 ) && ( Uart[3].Tx_RemainNum < 2 ) )
            {
                USBHSD->UEP8_RX_CTRL &= ~USBFS_UEP_R_RES_MASK;
                USBHSD->UEP8_RX_CTRL |= USBFS_UEP_R_RES_ACK;
                Uart[3].USB_Down_StopFlag = 0x00;
            }

            NVIC_EnableIRQ( USBHS_IRQn );
        }
    }
    else
    {
        /* Load data from the serial port send buffer to send  */
        if( Uart[3].Tx_RemainNum )
        {
            /* Determine whether to load from the last unsent buffer or from a new buffer */
            if( Uart[3].Tx_CurPackLen == 0x00 )
            {
                Uart[3].Tx_CurPackLen = Uart[3].Tx_PackLen[ Uart[3].Tx_DealNum ];
                Uart[3].Tx_CurPackPtr = ( Uart[3].Tx_DealNum * DEF_USB_HS_PACK_LEN );
            }
            /* Configure DMA and send */
            USART_ClearFlag( UART6, USART_FLAG_TC );
            DMA_Cmd( DEF_UART6_TX_DMA_CH, DISABLE );
            DEF_UART6_TX_DMA_CH->MADDR = (uint32_t)&UART6_Tx_Buf[ Uart[3].Tx_CurPackPtr ];
            DEF_UART6_TX_DMA_CH->CNTR = Uart[3].Tx_CurPackLen;
            DMA_Cmd( DEF_UART6_TX_DMA_CH, ENABLE );
            UART6->CTLR3 |= USART_DMAReq_Tx;
            Uart[3].Tx_Flag = 0x01;
        }
    }
}

/*********************************************************************
 * @fn      UART2_DataRx_Deal
 *
 * @brief   Uart2 data receiving processing
 *
 * @return  none
 */
void UART2_DataRx_Deal( void )
{
    uint16_t temp16;
    uint32_t remain_len;
    uint16_t packlen;

    /* Serial port 1 data DMA receive processing */
    NVIC_DisableIRQ( USBHS_IRQn );
    NVIC_DisableIRQ( USBHS_IRQn );
    UARTx_Rx_DMACurCount[0] = DEF_UART2_RX_DMA_CH->CNTR;
    if( UARTx_Rx_DMALastCount[0] != UARTx_Rx_DMACurCount[0] )
    {
        if( UARTx_Rx_DMALastCount[0] > UARTx_Rx_DMACurCount[0] )
        {
            temp16 = UARTx_Rx_DMALastCount[0] - UARTx_Rx_DMACurCount[0];
        }
        else
        {
            temp16 = DEF_UARTx_RX_BUF_LEN - UARTx_Rx_DMACurCount[0];
            temp16 += UARTx_Rx_DMALastCount[0];
        }
        UARTx_Rx_DMALastCount[0] = UARTx_Rx_DMACurCount[0];
        if( ( Uart[0].Rx_RemainLen + temp16 ) > DEF_UARTx_RX_BUF_LEN )
        {
            /* Overflow handling */
            /* Save frame error status */
            DUG_PRINTF("U0_O:%08lx\n",(uint32_t)Uart[0].Rx_RemainLen);
        }
        else
        {
            Uart[0].Rx_RemainLen += temp16;
        }

        /* Setting reception status */
        Uart[0].Rx_TimeOut = 0x00;
    }
    NVIC_EnableIRQ( USBHS_IRQn );

    /*****************************************************************/
    /* Serial port 1 data processing via USB upload and reception */
    if( Uart[0].Rx_RemainLen )
    {
        if( Uart[0].USB_Up_IngFlag == 0 )
        {
            /* Calculate the length of this upload */
            remain_len = Uart[0].Rx_RemainLen;
            packlen = 0x00;
            if( remain_len >= DEF_USBD_HS_PACK_SIZE )
            {
                packlen = DEF_USBD_HS_PACK_SIZE;
            }
            else
            {
                if( Uart[0].Rx_TimeOut >= Uart[0].Rx_TimeOutMax )
                {
                    packlen = remain_len;
                }
            }
            if( packlen > ( DEF_UARTx_RX_BUF_LEN - Uart[0].Rx_DealPtr ) )
            {
                packlen = ( DEF_UARTx_RX_BUF_LEN - Uart[0].Rx_DealPtr );
            }

            /* Upload serial data via usb */
            if( packlen )
            {
                NVIC_DisableIRQ( USBHS_IRQn );
                NVIC_DisableIRQ( USBHS_IRQn );
                Uart[0].USB_Up_IngFlag = 0x01;
                Uart[0].USB_Up_TimeOut = 0x00;
                USBHSD->UEP2_TX_DMA = (uint32_t)(uint8_t *)&UART2_Rx_Buf[ Uart[0].Rx_DealPtr ];
                USBHSD->UEP2_TX_LEN  = packlen;
                USBHSD->UEP2_TX_CTRL &= ~USBHS_UEP_T_RES_MASK;
                USBHSD->UEP2_TX_CTRL |= USBHS_UEP_T_RES_ACK;
                NVIC_EnableIRQ( USBHS_IRQn );

                /* Calculate the variables of interest */
                Uart[0].Rx_RemainLen -= packlen;
                Uart[0].Rx_DealPtr += packlen;
                if( Uart[0].Rx_DealPtr >= DEF_UARTx_RX_BUF_LEN )
                {
                    Uart[0].Rx_DealPtr = 0x00;
                }

                /* Start 0-length packet timeout timer */
                if( packlen == DEF_USBD_HS_PACK_SIZE )
                {
                    Uart[0].USB_Up_Pack0_Flag = 0x01;
                }
            }
        }
        else
        {
            /* Set the upload success flag directly if the upload is not successful after the timeout */
            if( Uart[0].USB_Up_TimeOut >= DEF_UARTx_USB_UP_TIMEOUT )
            {
                Uart[0].USB_Up_IngFlag = 0x00;
                USBHS_Endp_Busy[ DEF_UEP2 ] = 0;
            }
        }
    }

    /*****************************************************************/
    /* Determine if a 0-length packet needs to be uploaded (required for CDC mode) */
    if( Uart[0].USB_Up_Pack0_Flag )
    {
        if( Uart[0].USB_Up_IngFlag == 0 )
        {
            if( Uart[0].USB_Up_TimeOut >= ( DEF_UARTx_RX_TIMEOUT * 20 ) )
            {
                NVIC_DisableIRQ( USBHS_IRQn );
                NVIC_DisableIRQ( USBHS_IRQn );
                Uart[0].USB_Up_IngFlag = 0x01;
                Uart[0].USB_Up_TimeOut = 0x00;
                USBHSD->UEP2_TX_LEN  = 0x00;
                USBHSD->UEP2_TX_CTRL &= ~USBHS_UEP_T_RES_MASK;
                USBHSD->UEP2_TX_CTRL |= USBHS_UEP_T_RES_ACK;
                Uart[0].USB_Up_IngFlag = 0;
                NVIC_EnableIRQ( USBHS_IRQn );
                Uart[0].USB_Up_Pack0_Flag = 0x00;
            }
        }
    }
}
/*********************************************************************
 * @fn      UART3_DataRx_Deal
 *
 * @brief   Uart3 data receiving processing
 *
 * @return  none
 */
void UART3_DataRx_Deal( void )
{
    uint16_t temp16;
    uint32_t remain_len;
    uint16_t packlen;

    /* Serial port 3 data DMA receive processing */
    NVIC_DisableIRQ( USBHS_IRQn );
    NVIC_DisableIRQ( USBHS_IRQn );
    UARTx_Rx_DMACurCount[1] = DEF_UART3_RX_DMA_CH->CNTR;
    if( UARTx_Rx_DMALastCount[1] != UARTx_Rx_DMACurCount[1] )
    {
        if( UARTx_Rx_DMALastCount[1] > UARTx_Rx_DMACurCount[1] )
        {
            temp16 = UARTx_Rx_DMALastCount[1] - UARTx_Rx_DMACurCount[1];
        }
        else
        {
            temp16 = DEF_UARTx_RX_BUF_LEN - UARTx_Rx_DMACurCount[1];
            temp16 += UARTx_Rx_DMALastCount[1];
        }
        UARTx_Rx_DMALastCount[1] = UARTx_Rx_DMACurCount[1];
        if( ( Uart[1].Rx_RemainLen + temp16 ) > DEF_UARTx_RX_BUF_LEN )
        {
            /* Overflow handling */
            /* Save frame error status */
            DUG_PRINTF("U0_O:%08lx\n",(uint32_t)Uart[1].Rx_RemainLen);
        }
        else
        {
            Uart[1].Rx_RemainLen += temp16;
        }

        /* Setting reception status */
        Uart[1].Rx_TimeOut = 0x00;
    }
    NVIC_EnableIRQ( USBHS_IRQn );

    /*****************************************************************/
    /* Serial port 1 data processing via USB upload and reception */
    if( Uart[1].Rx_RemainLen )
    {
        if( Uart[1].USB_Up_IngFlag == 0 )
        {
            /* Calculate the length of this upload */
            remain_len = Uart[1].Rx_RemainLen;
            packlen = 0x00;
            if( remain_len >= DEF_USBD_HS_PACK_SIZE )
            {
                packlen = DEF_USBD_HS_PACK_SIZE;
            }
            else
            {
                if( Uart[1].Rx_TimeOut >= Uart[1].Rx_TimeOutMax )
                {
                    packlen = remain_len;
                }
            }
            if( packlen > ( DEF_UARTx_RX_BUF_LEN - Uart[1].Rx_DealPtr ) )
            {
                packlen = ( DEF_UARTx_RX_BUF_LEN - Uart[1].Rx_DealPtr );
            }

            /* Upload serial data via usb */
            if( packlen )
            {
                NVIC_DisableIRQ( USBHS_IRQn );
                NVIC_DisableIRQ( USBHS_IRQn );
                Uart[1].USB_Up_IngFlag = 0x01;
                Uart[1].USB_Up_TimeOut = 0x00;
                USBHSD->UEP4_TX_DMA = (uint32_t)(uint8_t *)&UART3_Rx_Buf[ Uart[1].Rx_DealPtr ];
                USBHSD->UEP4_TX_LEN  = packlen;
                USBHSD->UEP4_TX_CTRL &= ~USBHS_UEP_T_RES_MASK;
                USBHSD->UEP4_TX_CTRL |= USBHS_UEP_T_RES_ACK;
                NVIC_EnableIRQ( USBHS_IRQn );

                /* Calculate the variables of interest */
                Uart[1].Rx_RemainLen -= packlen;
                Uart[1].Rx_DealPtr += packlen;
                if( Uart[1].Rx_DealPtr >= DEF_UARTx_RX_BUF_LEN )
                {
                    Uart[1].Rx_DealPtr = 0x00;
                }

                /* Start 0-length packet timeout timer */
                if( packlen == DEF_USBD_HS_PACK_SIZE )
                {
                    Uart[1].USB_Up_Pack0_Flag = 0x01;
                }
            }
        }
        else
        {
            /* Set the upload success flag directly if the upload is not successful after the timeout */
            if( Uart[1].USB_Up_TimeOut >= DEF_UARTx_USB_UP_TIMEOUT )
            {
                Uart[1].USB_Up_IngFlag = 0x00;
                USBHS_Endp_Busy[ DEF_UEP4 ] = 0;
            }
        }
    }

    /*****************************************************************/
    /* Determine if a 0-length packet needs to be uploaded (required for CDC mode) */
    if( Uart[1].USB_Up_Pack0_Flag )
    {
        if( Uart[1].USB_Up_IngFlag == 0 )
        {
            if( Uart[1].USB_Up_TimeOut >= ( DEF_UARTx_RX_TIMEOUT * 20 ) )
            {
                NVIC_DisableIRQ( USBHS_IRQn );
                NVIC_DisableIRQ( USBHS_IRQn );
                Uart[1].USB_Up_IngFlag = 0x01;
                Uart[1].USB_Up_TimeOut = 0x00;
                USBHSD->UEP4_TX_LEN  = 0x00;
                USBHSD->UEP4_TX_CTRL &= ~USBHS_UEP_T_RES_MASK;
                USBHSD->UEP4_TX_CTRL |= USBHS_UEP_T_RES_ACK;
                Uart[1].USB_Up_IngFlag = 0;
                NVIC_EnableIRQ( USBHS_IRQn );
                Uart[1].USB_Up_Pack0_Flag = 0x00;
            }
        }
    }
}
/*********************************************************************
 * @fn      UART4_DataRx_Deal
 *
 * @brief   Uart4 data receiving processing
 *
 * @return  none
 */
void UART4_DataRx_Deal( void )
{
    uint16_t temp16;
    uint32_t remain_len;
    uint16_t packlen;

    /* Serial port 1 data DMA receive processing */
    NVIC_DisableIRQ( USBHS_IRQn );
    NVIC_DisableIRQ( USBHS_IRQn );
    UARTx_Rx_DMACurCount[2] = DEF_UART4_RX_DMA_CH->CNTR;
    if( UARTx_Rx_DMALastCount[2] != UARTx_Rx_DMACurCount[2] )
    {
        if( UARTx_Rx_DMALastCount[2] > UARTx_Rx_DMACurCount[2] )
        {
            temp16 = UARTx_Rx_DMALastCount[2] - UARTx_Rx_DMACurCount[2];
        }
        else
        {
            temp16 = DEF_UARTx_RX_BUF_LEN - UARTx_Rx_DMACurCount[2];
            temp16 += UARTx_Rx_DMALastCount[2];
        }
        UARTx_Rx_DMALastCount[2] = UARTx_Rx_DMACurCount[2];
        if( ( Uart[2].Rx_RemainLen + temp16 ) > DEF_UARTx_RX_BUF_LEN )
        {
            /* Overflow handling */
            /* Save frame error status */
            DUG_PRINTF("U0_O:%08lx\n",(uint32_t)Uart[2].Rx_RemainLen);
        }
        else
        {
            Uart[2].Rx_RemainLen += temp16;
        }

        /* Setting reception status */
        Uart[2].Rx_TimeOut = 0x00;
    }
    NVIC_EnableIRQ( USBHS_IRQn );

    /*****************************************************************/
    /* Serial port 1 data processing via USB upload and reception */
    if( Uart[2].Rx_RemainLen )
    {
        if( Uart[2].USB_Up_IngFlag == 0 )
        {
            /* Calculate the length of this upload */
            remain_len = Uart[2].Rx_RemainLen;
            packlen = 0x00;
            if( remain_len >= DEF_USBD_HS_PACK_SIZE )
            {
                packlen = DEF_USBD_HS_PACK_SIZE;
            }
            else
            {
                if( Uart[2].Rx_TimeOut >= Uart[2].Rx_TimeOutMax )
                {
                    packlen = remain_len;
                }
            }
            if( packlen > ( DEF_UARTx_RX_BUF_LEN - Uart[2].Rx_DealPtr ) )
            {
                packlen = ( DEF_UARTx_RX_BUF_LEN - Uart[2].Rx_DealPtr );
            }

            /* Upload serial data via usb */
            if( packlen )
            {
                NVIC_DisableIRQ( USBHS_IRQn );
                NVIC_DisableIRQ( USBHS_IRQn );
                Uart[2].USB_Up_IngFlag = 0x01;
                Uart[2].USB_Up_TimeOut = 0x00;
                USBHSD->UEP6_TX_DMA = (uint32_t)(uint8_t *)&UART4_Rx_Buf[ Uart[2].Rx_DealPtr ];
                USBHSD->UEP6_TX_LEN  = packlen;
                USBHSD->UEP6_TX_CTRL &= ~USBHS_UEP_T_RES_MASK;
                USBHSD->UEP6_TX_CTRL |= USBHS_UEP_T_RES_ACK;
                NVIC_EnableIRQ( USBHS_IRQn );

                /* Calculate the variables of interest */
                Uart[2].Rx_RemainLen -= packlen;
                Uart[2].Rx_DealPtr += packlen;
                if( Uart[2].Rx_DealPtr >= DEF_UARTx_RX_BUF_LEN )
                {
                    Uart[2].Rx_DealPtr = 0x00;
                }

                /* Start 0-length packet timeout timer */
                if( packlen == DEF_USBD_HS_PACK_SIZE )
                {
                    Uart[2].USB_Up_Pack0_Flag = 0x01;
                }
            }
        }
        else
        {
            /* Set the upload success flag directly if the upload is not successful after the timeout */
            if( Uart[2].USB_Up_TimeOut >= DEF_UARTx_USB_UP_TIMEOUT )
            {
                Uart[2].USB_Up_IngFlag = 0x00;
                USBHS_Endp_Busy[ DEF_UEP6 ] = 0;
            }
        }
    }

    /*****************************************************************/
    /* Determine if a 0-length packet needs to be uploaded (required for CDC mode) */
    if( Uart[2].USB_Up_Pack0_Flag )
    {
        if( Uart[2].USB_Up_IngFlag == 0 )
        {
            if( Uart[2].USB_Up_TimeOut >= ( DEF_UARTx_RX_TIMEOUT * 20 ) )
            {
                NVIC_DisableIRQ( USBHS_IRQn );
                NVIC_DisableIRQ( USBHS_IRQn );
                Uart[2].USB_Up_IngFlag = 0x01;
                Uart[2].USB_Up_TimeOut = 0x00;
                USBHSD->UEP6_TX_LEN  = 0x00;
                USBHSD->UEP6_TX_CTRL &= ~USBHS_UEP_T_RES_MASK;
                USBHSD->UEP6_TX_CTRL |= USBHS_UEP_T_RES_ACK;
                Uart[2].USB_Up_IngFlag = 0;
                NVIC_EnableIRQ( USBHS_IRQn );
                Uart[2].USB_Up_Pack0_Flag = 0x00;
            }
        }
    }
}

/*********************************************************************
 * @fn      UART6_DataRx_Deal
 *
 * @brief   Uart6 data receiving processing
 *
 * @return  none
 */
void UART6_DataRx_Deal( void )
{
    uint16_t temp16;
    uint32_t remain_len;
    uint16_t packlen;

    /* Serial port 1 data DMA receive processing */
    NVIC_DisableIRQ( USBHS_IRQn );
    NVIC_DisableIRQ( USBHS_IRQn );
    UARTx_Rx_DMACurCount[3] = DEF_UART6_RX_DMA_CH->CNTR;
    if( UARTx_Rx_DMALastCount[3] != UARTx_Rx_DMACurCount[3] )
    {
        if( UARTx_Rx_DMALastCount[3] > UARTx_Rx_DMACurCount[3] )
        {
            temp16 = UARTx_Rx_DMALastCount[3] - UARTx_Rx_DMACurCount[3];
        }
        else
        {
            temp16 = DEF_UARTx_RX_BUF_LEN - UARTx_Rx_DMACurCount[3];
            temp16 += UARTx_Rx_DMALastCount[3];
        }
        UARTx_Rx_DMALastCount[3] = UARTx_Rx_DMACurCount[3];
        if( ( Uart[3].Rx_RemainLen + temp16 ) > DEF_UARTx_RX_BUF_LEN )
        {
            /* Overflow handling */
            /* Save frame error status */
            DUG_PRINTF("U0_O:%08lx\n",(uint32_t)Uart[3].Rx_RemainLen);
        }
        else
        {
            Uart[3].Rx_RemainLen += temp16;
        }

        /* Setting reception status */
        Uart[3].Rx_TimeOut = 0x00;
    }
    NVIC_EnableIRQ( USBHS_IRQn );

    /*****************************************************************/
    /* Serial port 1 data processing via USB upload and reception */
    if( Uart[3].Rx_RemainLen )
    {
        if( Uart[3].USB_Up_IngFlag == 0 )
        {
            /* Calculate the length of this upload */
            remain_len = Uart[3].Rx_RemainLen;
            packlen = 0x00;
            if( remain_len >= DEF_USBD_HS_PACK_SIZE )
            {
                packlen = DEF_USBD_HS_PACK_SIZE;
            }
            else
            {
                if( Uart[3].Rx_TimeOut >= Uart[3].Rx_TimeOutMax )
                {
                    packlen = remain_len;
                }
            }
            if( packlen > ( DEF_UARTx_RX_BUF_LEN - Uart[3].Rx_DealPtr ) )
            {
                packlen = ( DEF_UARTx_RX_BUF_LEN - Uart[3].Rx_DealPtr );
            }

            /* Upload serial data via usb */
            if( packlen )
            {
                NVIC_DisableIRQ( USBHS_IRQn );
                NVIC_DisableIRQ( USBHS_IRQn );
                Uart[3].USB_Up_IngFlag = 0x01;
                Uart[3].USB_Up_TimeOut = 0x00;
                USBHSD->UEP8_TX_DMA = (uint32_t)(uint8_t *)&UART6_Rx_Buf[ Uart[3].Rx_DealPtr ];
                USBHSD->UEP8_TX_LEN  = packlen;
                USBHSD->UEP8_TX_CTRL &= ~USBHS_UEP_T_RES_MASK;
                USBHSD->UEP8_TX_CTRL |= USBHS_UEP_T_RES_ACK;
                NVIC_EnableIRQ( USBHS_IRQn );

                /* Calculate the variables of interest */
                Uart[3].Rx_RemainLen -= packlen;
                Uart[3].Rx_DealPtr += packlen;
                if( Uart[3].Rx_DealPtr >= DEF_UARTx_RX_BUF_LEN )
                {
                    Uart[3].Rx_DealPtr = 0x00;
                }

                /* Start 0-length packet timeout timer */
                if( packlen == DEF_USBD_HS_PACK_SIZE )
                {
                    Uart[3].USB_Up_Pack0_Flag = 0x01;
                }
            }
        }
        else
        {
            /* Set the upload success flag directly if the upload is not successful after the timeout */
            if( Uart[3].USB_Up_TimeOut >= DEF_UARTx_USB_UP_TIMEOUT )
            {
                Uart[3].USB_Up_IngFlag = 0x00;
                USBHS_Endp_Busy[ DEF_UEP8 ] = 0;
            }
        }
    }

    /*****************************************************************/
    /* Determine if a 0-length packet needs to be uploaded (required for CDC mode) */
    if( Uart[3].USB_Up_Pack0_Flag )
    {
        if( Uart[3].USB_Up_IngFlag == 0 )
        {
            if( Uart[3].USB_Up_TimeOut >= ( DEF_UARTx_RX_TIMEOUT * 20 ) )
            {
                NVIC_DisableIRQ( USBHS_IRQn );
                NVIC_DisableIRQ( USBHS_IRQn );
                Uart[3].USB_Up_IngFlag = 0x01;
                Uart[3].USB_Up_TimeOut = 0x00;
                USBHSD->UEP8_TX_LEN  = 0x00;
                USBHSD->UEP8_TX_CTRL &= ~USBHS_UEP_T_RES_MASK;
                USBHSD->UEP8_TX_CTRL |= USBHS_UEP_T_RES_ACK;
                Uart[3].USB_Up_IngFlag = 0;
                NVIC_EnableIRQ( USBHS_IRQn );
                Uart[3].USB_Up_Pack0_Flag = 0x00;
            }
        }
    }
}

三、注意事项

1、采用沁恒CDC驱动中,4通道USB作为模板, VID 0x1A86   PID 0x55D5  这个是CH344的CDC驱动。
2、修改设备描述 MyDevDescr[]  中设备类型为 4 2 1 组合设备。
3、修改MyCfgDescr_HS[] ,增加三个interfece 增加IAD描述。修改每个Union Functional Descriptor
4、修改串口配置 增加 UART3 UART4 UART6的配置。
5、修改USBHS_IRQHandler()中配置串口的描述,对增加的端点进行相应的配置。其中核心的地方是需要根据不同的SetupReqIndex 去配置相应的串口设置。这块摸索的好久。
6、修改处理函数UART2_DataRx_Deal( )和UART2_DataTx_Deal( ) 增加对应的串口处理函数。

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值