95 #define CDC_BULK_EP_SIZE (USB_FS_BULK_EP_MAXSIZE)
96 #define CDC_USB_RX_BUF_SIZ CDC_BULK_EP_SIZE
97 #define CDC_USB_TX_BUF_SIZ 127
101 #define CDC_RX_TIMEOUT EFM32_MAX(10U, 50000 / (cdcLineCoding.dwDTERate))
113 } __attribute__ ((packed)) cdcLineCoding_TypeDef;
119 static
int UsbDataReceived(USB_Status_TypeDef status, uint32_t xferred,
121 static
void DmaSetup(
void);
122 static
int LineCodingReceived(USB_Status_TypeDef status,
125 static
void SerialPortInit(
void);
126 static
void UartRxTimeout(
void);
136 static cdcLineCoding_TypeDef __attribute__ ((aligned(4))) cdcLineCoding =
142 STATIC_UBUF(usbRxBuffer0, CDC_USB_RX_BUF_SIZ);
143 STATIC_UBUF(usbRxBuffer1, CDC_USB_RX_BUF_SIZ);
144 STATIC_UBUF(uartRxBuffer0, CDC_USB_TX_BUF_SIZ);
145 STATIC_UBUF(uartRxBuffer1, CDC_USB_TX_BUF_SIZ);
147 static const uint8_t *usbRxBuffer[ 2 ] = { usbRxBuffer0, usbRxBuffer1 };
148 static const uint8_t *uartRxBuffer[ 2 ] = { uartRxBuffer0, uartRxBuffer1 };
150 static int usbRxIndex, usbBytesReceived;
151 static int uartRxIndex, uartRxCount;
152 static int LastUsbTxCnt;
154 static bool dmaRxCompleted;
155 static bool usbRxActive, dmaTxActive;
156 static bool usbTxActive, dmaRxActive;
158 static DMA_CB_TypeDef DmaTxCallBack;
159 static DMA_CB_TypeDef DmaRxCallBack;
184 int retVal = USB_STATUS_REQ_UNHANDLED;
186 if ( ( setup->Type == USB_SETUP_TYPE_CLASS ) &&
187 ( setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE ) )
189 switch (setup->bRequest)
191 case USB_CDC_GETLINECODING:
193 if ( ( setup->wValue == 0 ) &&
194 ( setup->wIndex == CDC_CTRL_INTERFACE_NO ) &&
195 ( setup->wLength == 7 ) &&
196 ( setup->Direction == USB_SETUP_DIR_IN ) )
199 USBD_Write(0, (
void*) &cdcLineCoding, 7, NULL);
200 retVal = USB_STATUS_OK;
204 case USB_CDC_SETLINECODING:
206 if ( ( setup->wValue == 0 ) &&
207 ( setup->wIndex == CDC_CTRL_INTERFACE_NO ) &&
208 ( setup->wLength == 7 ) &&
209 ( setup->Direction != USB_SETUP_DIR_IN ) )
212 USBD_Read(0, (
void*) &cdcLineCoding, 7, LineCodingReceived);
213 retVal = USB_STATUS_OK;
217 case USB_CDC_SETCTRLLINESTATE:
219 if ( ( setup->wIndex == CDC_CTRL_INTERFACE_NO ) &&
220 ( setup->wLength == 0 ) )
223 retVal = USB_STATUS_OK;
241 USBD_State_TypeDef newState)
243 if (newState == USBD_STATE_CONFIGURED)
247 if (oldState == USBD_STATE_SUSPENDED)
255 USBD_Read(CDC_EP_DATA_OUT, (
void*) usbRxBuffer[ usbRxIndex ],
256 CDC_USB_RX_BUF_SIZ, UsbDataReceived);
264 dmaRxCompleted =
true;
265 DMA_ActivateBasic(CDC_UART_RX_DMA_CHANNEL,
true,
false,
266 (
void *) uartRxBuffer[ uartRxIndex ],
267 (
void *) &(CDC_UART->RXDATA),
268 CDC_USB_TX_BUF_SIZ - 1);
269 USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
272 else if ((oldState == USBD_STATE_CONFIGURED) &&
273 (newState != USBD_STATE_SUSPENDED))
276 USBTIMER_Stop(CDC_TIMER_ID);
278 DMA->CHENC = ( 1 << CDC_UART_TX_DMA_CHANNEL ) |
279 ( 1 << CDC_UART_RX_DMA_CHANNEL );
282 else if (newState == USBD_STATE_SUSPENDED)
286 USBTIMER_Stop(CDC_TIMER_ID);
288 DMA->CHENC = ( 1 << CDC_UART_TX_DMA_CHANNEL ) |
289 ( 1 << CDC_UART_RX_DMA_CHANNEL );
305 static int UsbDataReceived(USB_Status_TypeDef status,
311 if ((status == USB_STATUS_OK) && (xferred > 0))
319 DMA_ActivateBasic(CDC_UART_TX_DMA_CHANNEL,
true,
false,
320 (
void *) &(CDC_UART->TXDATA),
321 (
void *) usbRxBuffer[ usbRxIndex ^ 1 ],
325 USBD_Read(CDC_EP_DATA_OUT, (
void*) usbRxBuffer[ usbRxIndex ],
326 CDC_USB_RX_BUF_SIZ, UsbDataReceived);
332 usbBytesReceived = xferred;
335 return USB_STATUS_OK;
345 static void DmaTxComplete(
unsigned int channel,
bool primary,
void *user)
360 DMA_ActivateBasic(CDC_UART_TX_DMA_CHANNEL,
true,
false,
361 (
void *) &(CDC_UART->TXDATA),
362 (
void *) usbRxBuffer[ usbRxIndex ^ 1 ],
363 usbBytesReceived - 1);
367 USBD_Read(CDC_EP_DATA_OUT, (
void*) usbRxBuffer[ usbRxIndex ],
368 CDC_USB_RX_BUF_SIZ, UsbDataReceived);
389 static int UsbDataTransmitted(USB_Status_TypeDef status,
396 if (status == USB_STATUS_OK)
402 USBD_Write(CDC_EP_DATA_IN, (
void*) uartRxBuffer[ uartRxIndex ^ 1],
403 uartRxCount, UsbDataTransmitted);
404 LastUsbTxCnt = uartRxCount;
407 dmaRxCompleted =
true;
408 DMA_ActivateBasic(CDC_UART_RX_DMA_CHANNEL,
true,
false,
409 (
void *) uartRxBuffer[ uartRxIndex ],
410 (
void *) &(CDC_UART->RXDATA),
411 CDC_USB_TX_BUF_SIZ - 1);
413 USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
421 return USB_STATUS_OK;
431 static void DmaRxComplete(
unsigned int channel,
bool primary,
void *user)
447 uartRxCount = CDC_USB_TX_BUF_SIZ;
451 uartRxCount = CDC_USB_TX_BUF_SIZ - 1 -
453 >> _DMA_CTRL_N_MINUS_1_SHIFT);
460 USBD_Write(CDC_EP_DATA_IN, (
void*) uartRxBuffer[ uartRxIndex ^ 1],
461 uartRxCount, UsbDataTransmitted);
462 LastUsbTxCnt = uartRxCount;
465 dmaRxCompleted =
true;
466 DMA_ActivateBasic(CDC_UART_RX_DMA_CHANNEL,
true,
false,
467 (
void *) uartRxBuffer[ uartRxIndex ],
468 (
void *) &(CDC_UART->RXDATA),
469 CDC_USB_TX_BUF_SIZ - 1);
471 USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
477 USBTIMER_Stop(CDC_TIMER_ID);
490 static void UartRxTimeout(
void)
498 if ((dmaCtrl & _DMA_CTRL_CYCLE_CTRL_MASK) == DMA_CTRL_CYCLE_CTRL_INVALID)
503 cnt = CDC_USB_TX_BUF_SIZ - 1 -
504 ((dmaCtrl & _DMA_CTRL_N_MINUS_1_MASK) >> _DMA_CTRL_N_MINUS_1_SHIFT);
506 if ((cnt == 0) && (LastUsbTxCnt == CDC_BULK_EP_SIZE))
513 DMA->CHENC = 1 << CDC_UART_RX_DMA_CHANNEL;
514 dmaRxCompleted =
false;
516 DmaRxComplete(CDC_UART_RX_DMA_CHANNEL,
true, NULL);
520 if ((cnt > 0) && (cnt == uartRxCount))
527 DMA->CHENC = 1 << CDC_UART_RX_DMA_CHANNEL;
528 dmaRxCompleted =
false;
530 DmaRxComplete(CDC_UART_RX_DMA_CHANNEL,
true, NULL);
536 USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
551 static int LineCodingReceived(USB_Status_TypeDef status,
559 if ((status == USB_STATUS_OK) && (xferred == 7))
562 if (cdcLineCoding.bDataBits == 5)
565 else if (cdcLineCoding.bDataBits == 6)
568 else if (cdcLineCoding.bDataBits == 7)
571 else if (cdcLineCoding.bDataBits == 8)
574 else if (cdcLineCoding.bDataBits == 16)
578 return USB_STATUS_REQ_ERR;
581 if (cdcLineCoding.bParityType == 0)
584 else if (cdcLineCoding.bParityType == 1)
587 else if (cdcLineCoding.bParityType == 2)
590 else if (cdcLineCoding.bParityType == 3)
591 return USB_STATUS_REQ_ERR;
593 else if (cdcLineCoding.bParityType == 4)
594 return USB_STATUS_REQ_ERR;
597 return USB_STATUS_REQ_ERR;
600 if (cdcLineCoding.bCharFormat == 0)
603 else if (cdcLineCoding.bCharFormat == 1)
606 else if (cdcLineCoding.bCharFormat == 2)
610 return USB_STATUS_REQ_ERR;
613 CDC_UART->FRAME = frame;
616 return USB_STATUS_OK;
618 return USB_STATUS_REQ_ERR;
624 static void DmaSetup(
void)
627 DMA_Init_TypeDef dmaInit;
628 DMA_CfgChannel_TypeDef chnlCfgTx, chnlCfgRx;
629 DMA_CfgDescr_TypeDef descrCfgTx, descrCfgRx;
639 DmaTxCallBack.cbFunc = DmaTxComplete;
640 DmaTxCallBack.userPtr = NULL;
643 chnlCfgTx.highPri =
false;
644 chnlCfgTx.enableInt =
true;
645 chnlCfgTx.select = CDC_TX_DMA_SIGNAL;
646 chnlCfgTx.cb = &DmaTxCallBack;
647 DMA_CfgChannel(CDC_UART_TX_DMA_CHANNEL, &chnlCfgTx);
651 descrCfgTx.dstInc = dmaDataIncNone;
652 descrCfgTx.srcInc = dmaDataInc1;
653 descrCfgTx.size = dmaDataSize1;
656 descrCfgTx.arbRate = dmaArbitrate1;
657 descrCfgTx.hprot = 0;
660 DMA_CfgDescr(CDC_UART_TX_DMA_CHANNEL,
true, &descrCfgTx);
665 DmaRxCallBack.cbFunc = DmaRxComplete;
666 DmaRxCallBack.userPtr = NULL;
669 chnlCfgRx.highPri =
false;
670 chnlCfgRx.enableInt =
true;
671 chnlCfgRx.select = CDC_RX_DMA_SIGNAL;
672 chnlCfgRx.cb = &DmaRxCallBack;
673 DMA_CfgChannel(CDC_UART_RX_DMA_CHANNEL, &chnlCfgRx);
677 descrCfgRx.dstInc = dmaDataInc1;
678 descrCfgRx.srcInc = dmaDataIncNone;
679 descrCfgRx.size = dmaDataSize1;
682 descrCfgRx.arbRate = dmaArbitrate1;
683 descrCfgRx.hprot = 0;
686 DMA_CfgDescr(CDC_UART_RX_DMA_CHANNEL,
true, &descrCfgRx);
692 static void SerialPortInit(
void)
703 CDC_ENABLE_DK_UART_SWITCH();
714 CDC_UART->ROUTE = CDC_UART_ROUTE;
Clock management unit (CMU) API.
Board support package API definitions.
void CDC_Init(void)
CDC device initialization.
__STATIC_INLINE uint32_t INT_Enable(void)
Enable interrupts.
#define EFM32_PACK_START(x)
#define USART_FRAME_STOPBITS_ONEANDAHALF
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define USART_FRAME_DATABITS_SIXTEEN
#define USART_FRAME_DATABITS_EIGHT
Universal synchronous/asynchronous receiver/transmitter (USART/UART) peripheral API.
USART_Enable_TypeDef enable
Emlib general purpose utilities.
void CDC_StateChangeEvent(USBD_State_TypeDef oldState, USBD_State_TypeDef newState)
Callback function called each time the USB device state is changed. Starts CDC operation when device ...
#define USART_FRAME_PARITY_ODD
#define USART_FRAME_STOPBITS_ONE
#define USART_FRAME_PARITY_NONE
int CDC_SetupCmd(const USB_Setup_TypeDef *setup)
Handle USB setup commands. Implements CDC class specific commands.
void GPIO_PinModeSet(GPIO_Port_TypeDef port, unsigned int pin, GPIO_Mode_TypeDef mode, unsigned int out)
Set the mode for a GPIO pin.
General Purpose IO (GPIO) peripheral API.
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT *2]
#define USART_FRAME_DATABITS_FIVE
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
#define USART_INITASYNC_DEFAULT
USB Communication Device Class (CDC) driver.
__STATIC_INLINE uint32_t INT_Disable(void)
Disable interrupts.
void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
Enable/disable USART/UART receiver and/or transmitter.
#define USART_FRAME_STOPBITS_TWO
void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
Init USART/UART for normal asynchronous mode.
#define USART_FRAME_DATABITS_SEVEN
Direct memory access (DMA) API.
#define USART_FRAME_PARITY_EVEN
void USART_BaudrateAsyncSet(USART_TypeDef *usart, uint32_t refFreq, uint32_t baudrate, USART_OVS_TypeDef ovs)
Configure USART/UART operating in asynchronous mode to use a given baudrate (or as close as possible ...
#define USART_FRAME_DATABITS_SIX