cdc.c

Go to the documentation of this file.
00001 /**************************************************************************/
00015 #include "em_device.h"
00016 #include "em_common.h"
00017 #include "em_cmu.h"
00018 #include "em_dma.h"
00019 #include "em_gpio.h"
00020 #include "em_usart.h"
00021 #include "em_usb.h"
00022 #include "bsp.h"
00023 #include "dmactrl.h"
00024 #include "cdc.h"
00025 
00026 /**************************************************************************/
00093 /*** Typedef's and defines. ***/
00094 
00095 #define CDC_BULK_EP_SIZE  (USB_FS_BULK_EP_MAXSIZE) /* This is the max. ep size.    */
00096 #define CDC_USB_RX_BUF_SIZ  CDC_BULK_EP_SIZE /* Packet size when receiving on USB. */
00097 #define CDC_USB_TX_BUF_SIZ  127    /* Packet size when transmitting on USB.  */
00098 
00099 /* Calculate a timeout in ms corresponding to 5 char times on current     */
00100 /* baudrate. Minimum timeout is set to 10 ms.                             */
00101 #define CDC_RX_TIMEOUT    EFM32_MAX(10U, 50000 / (cdcLineCoding.dwDTERate))
00102 
00103 /* The serial port LINE CODING data structure, used to carry information  */
00104 /* about serial port baudrate, parity etc. between host and device.       */
00105 EFM32_PACK_START(1)
00106 typedef struct
00107 {
00108   uint32_t dwDTERate;               
00109   uint8_t  bCharFormat;             
00110   uint8_t  bParityType;             
00111   uint8_t  bDataBits;               
00112   uint8_t  dummy;                   
00113 } __attribute__ ((packed)) cdcLineCoding_TypeDef;
00114 EFM32_PACK_END()
00115 
00116 
00117 /*** Function prototypes. ***/
00118 
00119 static int  UsbDataReceived(USB_Status_TypeDef status, uint32_t xferred,
00120                             uint32_t remaining);
00121 static void DmaSetup(void);
00122 static int  LineCodingReceived(USB_Status_TypeDef status,
00123                                uint32_t xferred,
00124                                uint32_t remaining);
00125 static void SerialPortInit(void);
00126 static void UartRxTimeout(void);
00127 
00128 /*** Variables ***/
00129 
00130 /*
00131  * The LineCoding variable must be 4-byte aligned as it is used as USB
00132  * transmit and receive buffer.
00133  */
00134 EFM32_ALIGN(4)
00135 EFM32_PACK_START(1)
00136 static cdcLineCoding_TypeDef __attribute__ ((aligned(4))) cdcLineCoding =
00137 {
00138   115200, 0, 0, 8, 0
00139 };
00140 EFM32_PACK_END()
00141 
00142 STATIC_UBUF(usbRxBuffer0,  CDC_USB_RX_BUF_SIZ);   /* USB receive buffers.   */
00143 STATIC_UBUF(usbRxBuffer1,  CDC_USB_RX_BUF_SIZ);
00144 STATIC_UBUF(uartRxBuffer0, CDC_USB_TX_BUF_SIZ);   /* UART receive buffers.  */
00145 STATIC_UBUF(uartRxBuffer1, CDC_USB_TX_BUF_SIZ);
00146 
00147 static const uint8_t  *usbRxBuffer[  2 ] = { usbRxBuffer0, usbRxBuffer1 };
00148 static const uint8_t  *uartRxBuffer[ 2 ] = { uartRxBuffer0, uartRxBuffer1 };
00149 
00150 static int            usbRxIndex, usbBytesReceived;
00151 static int            uartRxIndex, uartRxCount;
00152 static int            LastUsbTxCnt;
00153 
00154 static bool           dmaRxCompleted;
00155 static bool           usbRxActive, dmaTxActive;
00156 static bool           usbTxActive, dmaRxActive;
00157 
00158 static DMA_CB_TypeDef DmaTxCallBack;    
00159 static DMA_CB_TypeDef DmaRxCallBack;
00160 
00163 /**************************************************************************/
00166 void CDC_Init( void )
00167 {
00168   SerialPortInit();
00169   DmaSetup();
00170 }
00171 
00172 /**************************************************************************/
00182 int CDC_SetupCmd(const USB_Setup_TypeDef *setup)
00183 {
00184   int retVal = USB_STATUS_REQ_UNHANDLED;
00185 
00186   if ( ( setup->Type      == USB_SETUP_TYPE_CLASS          ) &&
00187        ( setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE )    )
00188   {
00189     switch (setup->bRequest)
00190     {
00191     case USB_CDC_GETLINECODING:
00192       /********************/
00193       if ( ( setup->wValue    == 0                     ) &&
00194            ( setup->wIndex    == CDC_CTRL_INTERFACE_NO ) && /* Interface no. */
00195            ( setup->wLength   == 7                     ) && /* Length of cdcLineCoding. */
00196            ( setup->Direction == USB_SETUP_DIR_IN      )    )
00197       {
00198         /* Send current settings to USB host. */
00199         USBD_Write(0, (void*) &cdcLineCoding, 7, NULL);
00200         retVal = USB_STATUS_OK;
00201       }
00202       break;
00203 
00204     case USB_CDC_SETLINECODING:
00205       /********************/
00206       if ( ( setup->wValue    == 0                     ) &&
00207            ( setup->wIndex    == CDC_CTRL_INTERFACE_NO ) && /* Interface no. */
00208            ( setup->wLength   == 7                     ) && /* Length of cdcLineCoding. */
00209            ( setup->Direction != USB_SETUP_DIR_IN      )    )
00210       {
00211         /* Get new settings from USB host. */
00212         USBD_Read(0, (void*) &cdcLineCoding, 7, LineCodingReceived);
00213         retVal = USB_STATUS_OK;
00214       }
00215       break;
00216 
00217     case USB_CDC_SETCTRLLINESTATE:
00218       /********************/
00219       if ( ( setup->wIndex  == CDC_CTRL_INTERFACE_NO ) &&   /* Interface no.  */
00220            ( setup->wLength == 0                     )    ) /* No data.       */
00221       {
00222         /* Do nothing ( Non compliant behaviour !! ) */
00223         retVal = USB_STATUS_OK;
00224       }
00225       break;
00226     }
00227   }
00228 
00229   return retVal;
00230 }
00231 
00232 /**************************************************************************/
00240 void CDC_StateChangeEvent( USBD_State_TypeDef oldState,
00241                            USBD_State_TypeDef newState)
00242 {
00243   if (newState == USBD_STATE_CONFIGURED)
00244   {
00245     /* We have been configured, start CDC functionality ! */
00246 
00247     if (oldState == USBD_STATE_SUSPENDED)   /* Resume ?   */
00248     {
00249     }
00250 
00251     /* Start receiving data from USB host. */
00252     usbRxIndex  = 0;
00253     usbRxActive = true;
00254     dmaTxActive = false;
00255     USBD_Read(CDC_EP_DATA_OUT, (void*) usbRxBuffer[ usbRxIndex ],
00256               CDC_USB_RX_BUF_SIZ, UsbDataReceived);
00257 
00258     /* Start receiving data on UART. */
00259     uartRxIndex    = 0;
00260     LastUsbTxCnt   = 0;
00261     uartRxCount    = 0;
00262     dmaRxActive    = true;
00263     usbTxActive    = false;
00264     dmaRxCompleted = true;
00265     DMA_ActivateBasic(CDC_UART_RX_DMA_CHANNEL, true, false,
00266                       (void *) uartRxBuffer[ uartRxIndex ],
00267                       (void *) &(CDC_UART->RXDATA),
00268                       CDC_USB_TX_BUF_SIZ - 1);
00269     USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
00270   }
00271 
00272   else if ((oldState == USBD_STATE_CONFIGURED) &&
00273            (newState != USBD_STATE_SUSPENDED))
00274   {
00275     /* We have been de-configured, stop CDC functionality. */
00276     USBTIMER_Stop(CDC_TIMER_ID);
00277     /* Stop DMA channels. */
00278     DMA->CHENC = ( 1 << CDC_UART_TX_DMA_CHANNEL ) |
00279                  ( 1 << CDC_UART_RX_DMA_CHANNEL );
00280   }
00281 
00282   else if (newState == USBD_STATE_SUSPENDED)
00283   {
00284     /* We have been suspended, stop CDC functionality. */
00285     /* Reduce current consumption to below 2.5 mA.     */
00286     USBTIMER_Stop(CDC_TIMER_ID);
00287     /* Stop DMA channels. */
00288     DMA->CHENC = ( 1 << CDC_UART_TX_DMA_CHANNEL ) |
00289                  ( 1 << CDC_UART_RX_DMA_CHANNEL );
00290   }
00291 }
00292 
00295 /**************************************************************************/
00305 static int UsbDataReceived(USB_Status_TypeDef status,
00306                            uint32_t xferred,
00307                            uint32_t remaining)
00308 {
00309   (void) remaining;            /* Unused parameter. */
00310 
00311   if ((status == USB_STATUS_OK) && (xferred > 0))
00312   {
00313     usbRxIndex ^= 1;
00314 
00315     if (!dmaTxActive)
00316     {
00317       /* dmaTxActive = false means that a new UART Tx DMA can be started. */
00318       dmaTxActive = true;
00319       DMA_ActivateBasic(CDC_UART_TX_DMA_CHANNEL, true, false,
00320                         (void *) &(CDC_UART->TXDATA),
00321                         (void *) usbRxBuffer[ usbRxIndex ^ 1 ],
00322                         xferred - 1);
00323 
00324       /* Start a new USB receive transfer. */
00325       USBD_Read(CDC_EP_DATA_OUT, (void*) usbRxBuffer[ usbRxIndex ],
00326                 CDC_USB_RX_BUF_SIZ, UsbDataReceived);
00327     }
00328     else
00329     {
00330       /* The UART transmit DMA callback function will start a new DMA. */
00331       usbRxActive      = false;
00332       usbBytesReceived = xferred;
00333     }
00334   }
00335   return USB_STATUS_OK;
00336 }
00337 
00338 /**************************************************************************/
00345 static void DmaTxComplete(unsigned int channel, bool primary, void *user)
00346 {
00347   (void) channel;              /* Unused parameter. */
00348   (void) primary;              /* Unused parameter. */
00349   (void) user;                 /* Unused parameter. */
00350 
00351   /*
00352    * As nested interrupts may occur and we rely on variables usbRxActive
00353    * and dmaTxActive etc, we must handle this function as a critical region.
00354    */
00355   INT_Disable();
00356 
00357   if (!usbRxActive)
00358   {
00359     /* usbRxActive = false means that an USB receive packet has been received.*/
00360     DMA_ActivateBasic(CDC_UART_TX_DMA_CHANNEL, true, false,
00361                       (void *) &(CDC_UART->TXDATA),
00362                       (void *) usbRxBuffer[ usbRxIndex ^ 1 ],
00363                       usbBytesReceived - 1);
00364 
00365     /* Start a new USB receive transfer. */
00366     usbRxActive = true;
00367     USBD_Read(CDC_EP_DATA_OUT, (void*) usbRxBuffer[ usbRxIndex ],
00368               CDC_USB_RX_BUF_SIZ, UsbDataReceived);
00369   }
00370   else
00371   {
00372     /* The USB receive complete callback function will start a new DMA. */
00373     dmaTxActive = false;
00374   }
00375 
00376   INT_Enable();
00377 }
00378 
00379 /**************************************************************************/
00389 static int UsbDataTransmitted(USB_Status_TypeDef status,
00390                               uint32_t xferred,
00391                               uint32_t remaining)
00392 {
00393   (void) xferred;              /* Unused parameter. */
00394   (void) remaining;            /* Unused parameter. */
00395 
00396   if (status == USB_STATUS_OK)
00397   {
00398     if (!dmaRxActive)
00399     {
00400       /* dmaRxActive = false means that a new UART Rx DMA can be started. */
00401 
00402       USBD_Write(CDC_EP_DATA_IN, (void*) uartRxBuffer[ uartRxIndex ^ 1],
00403                  uartRxCount, UsbDataTransmitted);
00404       LastUsbTxCnt = uartRxCount;
00405 
00406       dmaRxActive    = true;
00407       dmaRxCompleted = true;
00408       DMA_ActivateBasic(CDC_UART_RX_DMA_CHANNEL, true, false,
00409                         (void *) uartRxBuffer[ uartRxIndex ],
00410                         (void *) &(CDC_UART->RXDATA),
00411                         CDC_USB_TX_BUF_SIZ - 1);
00412       uartRxCount = 0;
00413       USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
00414     }
00415     else
00416     {
00417       /* The UART receive DMA callback function will start a new DMA. */
00418       usbTxActive = false;
00419     }
00420   }
00421   return USB_STATUS_OK;
00422 }
00423 
00424 /**************************************************************************/
00431 static void DmaRxComplete(unsigned int channel, bool primary, void *user)
00432 {
00433   (void) channel;              /* Unused parameter. */
00434   (void) primary;              /* Unused parameter. */
00435   (void) user;                 /* Unused parameter. */
00436 
00437   /*
00438    * As nested interrupts may occur and we rely on variables usbTxActive
00439    * and dmaRxActive etc, we must handle this function as a critical region.
00440    */
00441   INT_Disable();
00442 
00443   uartRxIndex ^= 1;
00444 
00445   if (dmaRxCompleted)
00446   {
00447     uartRxCount = CDC_USB_TX_BUF_SIZ;
00448   }
00449   else
00450   {
00451     uartRxCount = CDC_USB_TX_BUF_SIZ - 1 -
00452                   ((dmaControlBlock[ 1 ].CTRL & _DMA_CTRL_N_MINUS_1_MASK)
00453                    >> _DMA_CTRL_N_MINUS_1_SHIFT);
00454   }
00455 
00456   if (!usbTxActive)
00457   {
00458     /* usbTxActive = false means that a new USB packet can be transferred. */
00459     usbTxActive = true;
00460     USBD_Write(CDC_EP_DATA_IN, (void*) uartRxBuffer[ uartRxIndex ^ 1],
00461                uartRxCount, UsbDataTransmitted);
00462     LastUsbTxCnt = uartRxCount;
00463 
00464     /* Start a new UART receive DMA. */
00465     dmaRxCompleted = true;
00466     DMA_ActivateBasic(CDC_UART_RX_DMA_CHANNEL, true, false,
00467                       (void *) uartRxBuffer[ uartRxIndex ],
00468                       (void *) &(CDC_UART->RXDATA),
00469                       CDC_USB_TX_BUF_SIZ - 1);
00470     uartRxCount = 0;
00471     USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
00472   }
00473   else
00474   {
00475     /* The USB transmit complete callback function will start a new DMA. */
00476     dmaRxActive = false;
00477     USBTIMER_Stop(CDC_TIMER_ID);
00478   }
00479 
00480   INT_Enable();
00481 }
00482 
00483 /**************************************************************************/
00490 static void UartRxTimeout(void)
00491 {
00492   int      cnt;
00493   uint32_t dmaCtrl;
00494 
00495   dmaCtrl = dmaControlBlock[ 1 ].CTRL;
00496 
00497   /* Has the DMA just completed ? */
00498   if ((dmaCtrl & _DMA_CTRL_CYCLE_CTRL_MASK) == DMA_CTRL_CYCLE_CTRL_INVALID)
00499   {
00500     return;
00501   }
00502 
00503   cnt = CDC_USB_TX_BUF_SIZ - 1 -
00504         ((dmaCtrl & _DMA_CTRL_N_MINUS_1_MASK) >> _DMA_CTRL_N_MINUS_1_SHIFT);
00505 
00506   if ((cnt == 0) && (LastUsbTxCnt == CDC_BULK_EP_SIZE))
00507   {
00508     /*
00509      * No activity on UART Rx, send a ZERO length USB package if last USB
00510      * USB package sent was CDC_BULK_EP_SIZE (max. EP size) long.
00511      */
00512     /* Stop Rx DMA channel. */
00513     DMA->CHENC     = 1 << CDC_UART_RX_DMA_CHANNEL;
00514     dmaRxCompleted = false;
00515     /* Call DMA completion callback. */
00516     DmaRxComplete(CDC_UART_RX_DMA_CHANNEL, true, NULL);
00517     return;
00518   }
00519 
00520   if ((cnt > 0) && (cnt == uartRxCount))
00521   {
00522     /*
00523      * There is curently no activity on UART Rx but some chars have been
00524      * received. Stop DMA and transmit the chars we have got so far on USB.
00525      */
00526     /* Stop Rx DMA channel. */
00527     DMA->CHENC     = 1 << CDC_UART_RX_DMA_CHANNEL;
00528     dmaRxCompleted = false;
00529     /* Call DMA completion callback. */
00530     DmaRxComplete(CDC_UART_RX_DMA_CHANNEL, true, NULL);
00531     return;
00532   }
00533 
00534   /* Restart timer to continue monitoring. */
00535   uartRxCount = cnt;
00536   USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
00537 }
00538 
00539 /**************************************************************************/
00551 static int LineCodingReceived(USB_Status_TypeDef status,
00552                               uint32_t xferred,
00553                               uint32_t remaining)
00554 {
00555   uint32_t frame = 0;
00556   (void) remaining;
00557 
00558   /* We have received new serial port communication settings from USB host. */
00559   if ((status == USB_STATUS_OK) && (xferred == 7))
00560   {
00561     /* Check bDataBits, valid values are: 5, 6, 7, 8 or 16 bits. */
00562     if (cdcLineCoding.bDataBits == 5)
00563       frame |= USART_FRAME_DATABITS_FIVE;
00564 
00565     else if (cdcLineCoding.bDataBits == 6)
00566       frame |= USART_FRAME_DATABITS_SIX;
00567 
00568     else if (cdcLineCoding.bDataBits == 7)
00569       frame |= USART_FRAME_DATABITS_SEVEN;
00570 
00571     else if (cdcLineCoding.bDataBits == 8)
00572       frame |= USART_FRAME_DATABITS_EIGHT;
00573 
00574     else if (cdcLineCoding.bDataBits == 16)
00575       frame |= USART_FRAME_DATABITS_SIXTEEN;
00576 
00577     else
00578       return USB_STATUS_REQ_ERR;
00579 
00580     /* Check bParityType, valid values are: 0=None 1=Odd 2=Even 3=Mark 4=Space  */
00581     if (cdcLineCoding.bParityType == 0)
00582       frame |= USART_FRAME_PARITY_NONE;
00583 
00584     else if (cdcLineCoding.bParityType == 1)
00585       frame |= USART_FRAME_PARITY_ODD;
00586 
00587     else if (cdcLineCoding.bParityType == 2)
00588       frame |= USART_FRAME_PARITY_EVEN;
00589 
00590     else if (cdcLineCoding.bParityType == 3)
00591       return USB_STATUS_REQ_ERR;
00592 
00593     else if (cdcLineCoding.bParityType == 4)
00594       return USB_STATUS_REQ_ERR;
00595 
00596     else
00597       return USB_STATUS_REQ_ERR;
00598 
00599     /* Check bCharFormat, valid values are: 0=1 1=1.5 2=2 stop bits */
00600     if (cdcLineCoding.bCharFormat == 0)
00601       frame |= USART_FRAME_STOPBITS_ONE;
00602 
00603     else if (cdcLineCoding.bCharFormat == 1)
00604       frame |= USART_FRAME_STOPBITS_ONEANDAHALF;
00605 
00606     else if (cdcLineCoding.bCharFormat == 2)
00607       frame |= USART_FRAME_STOPBITS_TWO;
00608 
00609     else
00610       return USB_STATUS_REQ_ERR;
00611 
00612     /* Program new UART baudrate etc. */
00613     CDC_UART->FRAME = frame;
00614     USART_BaudrateAsyncSet(CDC_UART, 0, cdcLineCoding.dwDTERate, usartOVS16);
00615 
00616     return USB_STATUS_OK;
00617   }
00618   return USB_STATUS_REQ_ERR;
00619 }
00620 
00621 /**************************************************************************/
00624 static void DmaSetup(void)
00625 {
00626   /* DMA configuration structs. */
00627   DMA_Init_TypeDef       dmaInit;
00628   DMA_CfgChannel_TypeDef chnlCfgTx, chnlCfgRx;
00629   DMA_CfgDescr_TypeDef   descrCfgTx, descrCfgRx;
00630 
00631   /* Initialize the DMA. */
00632   dmaInit.hprot        = 0;
00633   dmaInit.controlBlock = dmaControlBlock;
00634   DMA_Init(&dmaInit);
00635 
00636   /*---------- Configure DMA channel for UART Tx. ----------*/
00637 
00638   /* Setup the interrupt callback routine */
00639   DmaTxCallBack.cbFunc  = DmaTxComplete;
00640   DmaTxCallBack.userPtr = NULL;
00641 
00642   /* Setup the channel */
00643   chnlCfgTx.highPri   = false;    /* Can't use with peripherals. */
00644   chnlCfgTx.enableInt = true;     /* Interrupt needed when buffers are used. */
00645   chnlCfgTx.select    = CDC_TX_DMA_SIGNAL;
00646   chnlCfgTx.cb        = &DmaTxCallBack;
00647   DMA_CfgChannel(CDC_UART_TX_DMA_CHANNEL, &chnlCfgTx);
00648 
00649   /* Setup channel descriptor. */
00650   /* Destination is UART Tx data register and doesn't move. */
00651   descrCfgTx.dstInc = dmaDataIncNone;
00652   descrCfgTx.srcInc = dmaDataInc1;
00653   descrCfgTx.size   = dmaDataSize1;
00654 
00655   /* We have time to arbitrate again for each sample. */
00656   descrCfgTx.arbRate = dmaArbitrate1;
00657   descrCfgTx.hprot   = 0;
00658 
00659   /* Configure primary descriptor. */
00660   DMA_CfgDescr(CDC_UART_TX_DMA_CHANNEL, true, &descrCfgTx);
00661 
00662   /*---------- Configure DMA channel for UART Rx. ----------*/
00663 
00664   /* Setup the interrupt callback routine. */
00665   DmaRxCallBack.cbFunc  = DmaRxComplete;
00666   DmaRxCallBack.userPtr = NULL;
00667 
00668   /* Setup the channel */
00669   chnlCfgRx.highPri   = false;    /* Can't use with peripherals. */
00670   chnlCfgRx.enableInt = true;     /* Interrupt needed when buffers are used. */
00671   chnlCfgRx.select    = CDC_RX_DMA_SIGNAL;
00672   chnlCfgRx.cb        = &DmaRxCallBack;
00673   DMA_CfgChannel(CDC_UART_RX_DMA_CHANNEL, &chnlCfgRx);
00674 
00675   /* Setup channel descriptor. */
00676   /* Source is UART Rx data register and doesn't move. */
00677   descrCfgRx.dstInc = dmaDataInc1;
00678   descrCfgRx.srcInc = dmaDataIncNone;
00679   descrCfgRx.size   = dmaDataSize1;
00680 
00681   /* We have time to arbitrate again for each sample. */
00682   descrCfgRx.arbRate = dmaArbitrate1;
00683   descrCfgRx.hprot   = 0;
00684 
00685   /* Configure primary descriptor. */
00686   DMA_CfgDescr(CDC_UART_RX_DMA_CHANNEL, true, &descrCfgRx);
00687 }
00688 
00689 /**************************************************************************/
00692 static void SerialPortInit(void)
00693 {
00694   USART_InitAsync_TypeDef init  = USART_INITASYNC_DEFAULT;
00695 
00696   /* Configure GPIO pins. */
00697   CMU_ClockEnable(cmuClock_GPIO, true);
00698   /* To avoid false start, configure output as high. */
00699   GPIO_PinModeSet(CDC_UART_TX_PORT, CDC_UART_TX_PIN, gpioModePushPull, 1);
00700   GPIO_PinModeSet(CDC_UART_RX_PORT, CDC_UART_RX_PIN, gpioModeInput, 0);
00701 
00702   /* Enable DK mainboard RS232/UART switch. */
00703   CDC_ENABLE_DK_UART_SWITCH();
00704 
00705   /* Enable peripheral clocks. */
00706   CMU_ClockEnable(cmuClock_HFPER, true);
00707   CMU_ClockEnable(CDC_UART_CLOCK, true);
00708 
00709   /* Configure UART for basic async operation. */
00710   init.enable = usartDisable;
00711   USART_InitAsync(CDC_UART, &init);
00712 
00713   /* Enable Tx/Rx pins and set correct UART location. */
00714   CDC_UART->ROUTE = CDC_UART_ROUTE;
00715 
00716   /* Finally enable it */
00717   USART_Enable(CDC_UART, usartEnable);
00718 }
00719