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
00094
00095 #define CDC_BULK_EP_SIZE (USB_FS_BULK_EP_MAXSIZE)
00096 #define CDC_USB_RX_BUF_SIZ CDC_BULK_EP_SIZE
00097 #define CDC_USB_TX_BUF_SIZ 127
00098
00099
00100
00101 #define CDC_RX_TIMEOUT EFM32_MAX(10U, 50000 / (cdcLineCoding.dwDTERate))
00102
00103
00104
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
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
00129
00130
00131
00132
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);
00143 STATIC_UBUF(usbRxBuffer1, CDC_USB_RX_BUF_SIZ);
00144 STATIC_UBUF(uartRxBuffer0, CDC_USB_TX_BUF_SIZ);
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 ) &&
00195 ( setup->wLength == 7 ) &&
00196 ( setup->Direction == USB_SETUP_DIR_IN ) )
00197 {
00198
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 ) &&
00208 ( setup->wLength == 7 ) &&
00209 ( setup->Direction != USB_SETUP_DIR_IN ) )
00210 {
00211
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 ) &&
00220 ( setup->wLength == 0 ) )
00221 {
00222
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
00246
00247 if (oldState == USBD_STATE_SUSPENDED)
00248 {
00249 }
00250
00251
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
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
00276 USBTIMER_Stop(CDC_TIMER_ID);
00277
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
00285
00286 USBTIMER_Stop(CDC_TIMER_ID);
00287
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;
00310
00311 if ((status == USB_STATUS_OK) && (xferred > 0))
00312 {
00313 usbRxIndex ^= 1;
00314
00315 if (!dmaTxActive)
00316 {
00317
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
00325 USBD_Read(CDC_EP_DATA_OUT, (void*) usbRxBuffer[ usbRxIndex ],
00326 CDC_USB_RX_BUF_SIZ, UsbDataReceived);
00327 }
00328 else
00329 {
00330
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;
00348 (void) primary;
00349 (void) user;
00350
00351
00352
00353
00354
00355 INT_Disable();
00356
00357 if (!usbRxActive)
00358 {
00359
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
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
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;
00394 (void) remaining;
00395
00396 if (status == USB_STATUS_OK)
00397 {
00398 if (!dmaRxActive)
00399 {
00400
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
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;
00434 (void) primary;
00435 (void) user;
00436
00437
00438
00439
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
00459 usbTxActive = true;
00460 USBD_Write(CDC_EP_DATA_IN, (void*) uartRxBuffer[ uartRxIndex ^ 1],
00461 uartRxCount, UsbDataTransmitted);
00462 LastUsbTxCnt = uartRxCount;
00463
00464
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
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
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
00510
00511
00512
00513 DMA->CHENC = 1 << CDC_UART_RX_DMA_CHANNEL;
00514 dmaRxCompleted = false;
00515
00516 DmaRxComplete(CDC_UART_RX_DMA_CHANNEL, true, NULL);
00517 return;
00518 }
00519
00520 if ((cnt > 0) && (cnt == uartRxCount))
00521 {
00522
00523
00524
00525
00526
00527 DMA->CHENC = 1 << CDC_UART_RX_DMA_CHANNEL;
00528 dmaRxCompleted = false;
00529
00530 DmaRxComplete(CDC_UART_RX_DMA_CHANNEL, true, NULL);
00531 return;
00532 }
00533
00534
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
00559 if ((status == USB_STATUS_OK) && (xferred == 7))
00560 {
00561
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
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
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
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
00627 DMA_Init_TypeDef dmaInit;
00628 DMA_CfgChannel_TypeDef chnlCfgTx, chnlCfgRx;
00629 DMA_CfgDescr_TypeDef descrCfgTx, descrCfgRx;
00630
00631
00632 dmaInit.hprot = 0;
00633 dmaInit.controlBlock = dmaControlBlock;
00634 DMA_Init(&dmaInit);
00635
00636
00637
00638
00639 DmaTxCallBack.cbFunc = DmaTxComplete;
00640 DmaTxCallBack.userPtr = NULL;
00641
00642
00643 chnlCfgTx.highPri = false;
00644 chnlCfgTx.enableInt = true;
00645 chnlCfgTx.select = CDC_TX_DMA_SIGNAL;
00646 chnlCfgTx.cb = &DmaTxCallBack;
00647 DMA_CfgChannel(CDC_UART_TX_DMA_CHANNEL, &chnlCfgTx);
00648
00649
00650
00651 descrCfgTx.dstInc = dmaDataIncNone;
00652 descrCfgTx.srcInc = dmaDataInc1;
00653 descrCfgTx.size = dmaDataSize1;
00654
00655
00656 descrCfgTx.arbRate = dmaArbitrate1;
00657 descrCfgTx.hprot = 0;
00658
00659
00660 DMA_CfgDescr(CDC_UART_TX_DMA_CHANNEL, true, &descrCfgTx);
00661
00662
00663
00664
00665 DmaRxCallBack.cbFunc = DmaRxComplete;
00666 DmaRxCallBack.userPtr = NULL;
00667
00668
00669 chnlCfgRx.highPri = false;
00670 chnlCfgRx.enableInt = true;
00671 chnlCfgRx.select = CDC_RX_DMA_SIGNAL;
00672 chnlCfgRx.cb = &DmaRxCallBack;
00673 DMA_CfgChannel(CDC_UART_RX_DMA_CHANNEL, &chnlCfgRx);
00674
00675
00676
00677 descrCfgRx.dstInc = dmaDataInc1;
00678 descrCfgRx.srcInc = dmaDataIncNone;
00679 descrCfgRx.size = dmaDataSize1;
00680
00681
00682 descrCfgRx.arbRate = dmaArbitrate1;
00683 descrCfgRx.hprot = 0;
00684
00685
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
00697 CMU_ClockEnable(cmuClock_GPIO, true);
00698
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
00703 CDC_ENABLE_DK_UART_SWITCH();
00704
00705
00706 CMU_ClockEnable(cmuClock_HFPER, true);
00707 CMU_ClockEnable(CDC_UART_CLOCK, true);
00708
00709
00710 init.enable = usartDisable;
00711 USART_InitAsync(CDC_UART, &init);
00712
00713
00714 CDC_UART->ROUTE = CDC_UART_ROUTE;
00715
00716
00717 USART_Enable(CDC_UART, usartEnable);
00718 }
00719