96 #define CDC_BULK_EP_SIZE (USB_FS_BULK_EP_MAXSIZE)
97 #define CDC_USB_RX_BUF_SIZ CDC_BULK_EP_SIZE
98 #define CDC_USB_TX_BUF_SIZ 127
102 #define CDC_RX_TIMEOUT SL_MAX(10U, 50000 / (cdcLineCoding.dwDTERate))
120 static
int UsbDataReceived(USB_Status_TypeDef status, uint32_t xferred,
122 static
void DmaSetup(
void);
123 static
int LineCodingReceived(USB_Status_TypeDef status,
126 static
void SerialPortInit(
void);
127 static
void UartRxTimeout(
void);
143 STATIC_UBUF(usbRxBuffer0, CDC_USB_RX_BUF_SIZ);
144 STATIC_UBUF(usbRxBuffer1, CDC_USB_RX_BUF_SIZ);
145 STATIC_UBUF(uartRxBuffer0, CDC_USB_TX_BUF_SIZ);
146 STATIC_UBUF(uartRxBuffer1, CDC_USB_TX_BUF_SIZ);
148 static const uint8_t *usbRxBuffer[ 2 ] = { usbRxBuffer0, usbRxBuffer1 };
149 static const uint8_t *uartRxBuffer[ 2 ] = { uartRxBuffer0, uartRxBuffer1 };
151 static int usbRxIndex, usbBytesReceived;
152 static int uartRxIndex, uartRxCount;
153 static int LastUsbTxCnt;
155 static bool dmaRxCompleted;
156 static bool usbRxActive, dmaTxActive;
157 static bool usbTxActive, dmaRxActive;
159 static DMA_CB_TypeDef DmaTxCallBack;
160 static DMA_CB_TypeDef DmaRxCallBack;
185 int retVal = USB_STATUS_REQ_UNHANDLED;
187 if ( ( setup->Type == USB_SETUP_TYPE_CLASS ) &&
188 ( setup->Recipient == USB_SETUP_RECIPIENT_INTERFACE ) )
190 switch (setup->bRequest)
192 case USB_CDC_GETLINECODING:
194 if ( ( setup->wValue == 0 ) &&
195 ( setup->wIndex == CDC_CTRL_INTERFACE_NO ) &&
196 ( setup->wLength == 7 ) &&
197 ( setup->Direction == USB_SETUP_DIR_IN ) )
200 USBD_Write(0, (
void*) &cdcLineCoding, 7, NULL);
201 retVal = USB_STATUS_OK;
205 case USB_CDC_SETLINECODING:
207 if ( ( setup->wValue == 0 ) &&
208 ( setup->wIndex == CDC_CTRL_INTERFACE_NO ) &&
209 ( setup->wLength == 7 ) &&
210 ( setup->Direction != USB_SETUP_DIR_IN ) )
213 USBD_Read(0, (
void*) &cdcLineCoding, 7, LineCodingReceived);
214 retVal = USB_STATUS_OK;
218 case USB_CDC_SETCTRLLINESTATE:
220 if ( ( setup->wIndex == CDC_CTRL_INTERFACE_NO ) &&
221 ( setup->wLength == 0 ) )
224 retVal = USB_STATUS_OK;
242 USBD_State_TypeDef newState)
244 if (newState == USBD_STATE_CONFIGURED)
248 if (oldState == USBD_STATE_SUSPENDED)
256 USBD_Read(CDC_EP_DATA_OUT, (
void*) usbRxBuffer[ usbRxIndex ],
257 CDC_USB_RX_BUF_SIZ, UsbDataReceived);
265 dmaRxCompleted =
true;
266 DMA_ActivateBasic(CDC_UART_RX_DMA_CHANNEL,
true,
false,
267 (
void *) uartRxBuffer[ uartRxIndex ],
268 (
void *) &(CDC_UART->RXDATA),
269 CDC_USB_TX_BUF_SIZ - 1);
270 USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
273 else if ((oldState == USBD_STATE_CONFIGURED) &&
274 (newState != USBD_STATE_SUSPENDED))
277 USBTIMER_Stop(CDC_TIMER_ID);
279 DMA->CHENC = ( 1 << CDC_UART_TX_DMA_CHANNEL ) |
280 ( 1 << CDC_UART_RX_DMA_CHANNEL );
283 else if (newState == USBD_STATE_SUSPENDED)
287 USBTIMER_Stop(CDC_TIMER_ID);
289 DMA->CHENC = ( 1 << CDC_UART_TX_DMA_CHANNEL ) |
290 ( 1 << CDC_UART_RX_DMA_CHANNEL );
306 static int UsbDataReceived(USB_Status_TypeDef status,
312 if ((status == USB_STATUS_OK) && (xferred > 0))
320 DMA_ActivateBasic(CDC_UART_TX_DMA_CHANNEL,
true,
false,
321 (
void *) &(CDC_UART->TXDATA),
322 (
void *) usbRxBuffer[ usbRxIndex ^ 1 ],
326 USBD_Read(CDC_EP_DATA_OUT, (
void*) usbRxBuffer[ usbRxIndex ],
327 CDC_USB_RX_BUF_SIZ, UsbDataReceived);
333 usbBytesReceived = xferred;
336 return USB_STATUS_OK;
346 static void DmaTxComplete(
unsigned int channel,
bool primary,
void *user)
362 DMA_ActivateBasic(CDC_UART_TX_DMA_CHANNEL,
true,
false,
363 (
void *) &(CDC_UART->TXDATA),
364 (
void *) usbRxBuffer[ usbRxIndex ^ 1 ],
365 usbBytesReceived - 1);
369 USBD_Read(CDC_EP_DATA_OUT, (
void*) usbRxBuffer[ usbRxIndex ],
370 CDC_USB_RX_BUF_SIZ, UsbDataReceived);
391 static int UsbDataTransmitted(USB_Status_TypeDef status,
398 if (status == USB_STATUS_OK)
404 USBD_Write(CDC_EP_DATA_IN, (
void*) uartRxBuffer[ uartRxIndex ^ 1],
405 uartRxCount, UsbDataTransmitted);
406 LastUsbTxCnt = uartRxCount;
409 dmaRxCompleted =
true;
410 DMA_ActivateBasic(CDC_UART_RX_DMA_CHANNEL,
true,
false,
411 (
void *) uartRxBuffer[ uartRxIndex ],
412 (
void *) &(CDC_UART->RXDATA),
413 CDC_USB_TX_BUF_SIZ - 1);
415 USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
423 return USB_STATUS_OK;
433 static void DmaRxComplete(
unsigned int channel,
bool primary,
void *user)
450 uartRxCount = CDC_USB_TX_BUF_SIZ;
454 uartRxCount = CDC_USB_TX_BUF_SIZ - 1 -
455 ((dmaControlBlock[ 1 ].
CTRL & _DMA_CTRL_N_MINUS_1_MASK)
456 >> _DMA_CTRL_N_MINUS_1_SHIFT);
463 USBD_Write(CDC_EP_DATA_IN, (
void*) uartRxBuffer[ uartRxIndex ^ 1],
464 uartRxCount, UsbDataTransmitted);
465 LastUsbTxCnt = uartRxCount;
468 dmaRxCompleted =
true;
469 DMA_ActivateBasic(CDC_UART_RX_DMA_CHANNEL,
true,
false,
470 (
void *) uartRxBuffer[ uartRxIndex ],
471 (
void *) &(CDC_UART->RXDATA),
472 CDC_USB_TX_BUF_SIZ - 1);
474 USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
480 USBTIMER_Stop(CDC_TIMER_ID);
493 static void UartRxTimeout(
void)
498 dmaCtrl = dmaControlBlock[ 1 ].
CTRL;
501 if ((dmaCtrl & _DMA_CTRL_CYCLE_CTRL_MASK) == DMA_CTRL_CYCLE_CTRL_INVALID)
506 cnt = CDC_USB_TX_BUF_SIZ - 1 -
507 ((dmaCtrl & _DMA_CTRL_N_MINUS_1_MASK) >> _DMA_CTRL_N_MINUS_1_SHIFT);
509 if ((cnt == 0) && (LastUsbTxCnt == CDC_BULK_EP_SIZE))
516 DMA->CHENC = 1 << CDC_UART_RX_DMA_CHANNEL;
517 dmaRxCompleted =
false;
519 DmaRxComplete(CDC_UART_RX_DMA_CHANNEL,
true, NULL);
523 if ((cnt > 0) && (cnt == uartRxCount))
530 DMA->CHENC = 1 << CDC_UART_RX_DMA_CHANNEL;
531 dmaRxCompleted =
false;
533 DmaRxComplete(CDC_UART_RX_DMA_CHANNEL,
true, NULL);
539 USBTIMER_Start(CDC_TIMER_ID, CDC_RX_TIMEOUT, UartRxTimeout);
554 static int LineCodingReceived(USB_Status_TypeDef status,
562 if ((status == USB_STATUS_OK) && (xferred == 7))
565 if (cdcLineCoding.bDataBits == 5)
568 else if (cdcLineCoding.bDataBits == 6)
571 else if (cdcLineCoding.bDataBits == 7)
574 else if (cdcLineCoding.bDataBits == 8)
577 else if (cdcLineCoding.bDataBits == 16)
581 return USB_STATUS_REQ_ERR;
584 if (cdcLineCoding.bParityType == 0)
587 else if (cdcLineCoding.bParityType == 1)
590 else if (cdcLineCoding.bParityType == 2)
593 else if (cdcLineCoding.bParityType == 3)
594 return USB_STATUS_REQ_ERR;
596 else if (cdcLineCoding.bParityType == 4)
597 return USB_STATUS_REQ_ERR;
600 return USB_STATUS_REQ_ERR;
603 if (cdcLineCoding.bCharFormat == 0)
606 else if (cdcLineCoding.bCharFormat == 1)
609 else if (cdcLineCoding.bCharFormat == 2)
613 return USB_STATUS_REQ_ERR;
616 CDC_UART->FRAME = frame;
619 return USB_STATUS_OK;
621 return USB_STATUS_REQ_ERR;
627 static void DmaSetup(
void)
630 DMA_Init_TypeDef dmaInit;
631 DMA_CfgChannel_TypeDef chnlCfgTx, chnlCfgRx;
632 DMA_CfgDescr_TypeDef descrCfgTx, descrCfgRx;
636 dmaInit.controlBlock = dmaControlBlock;
642 DmaTxCallBack.cbFunc = DmaTxComplete;
643 DmaTxCallBack.userPtr = NULL;
646 chnlCfgTx.highPri =
false;
647 chnlCfgTx.enableInt =
true;
648 chnlCfgTx.select = CDC_TX_DMA_SIGNAL;
649 chnlCfgTx.cb = &DmaTxCallBack;
650 DMA_CfgChannel(CDC_UART_TX_DMA_CHANNEL, &chnlCfgTx);
654 descrCfgTx.dstInc = dmaDataIncNone;
655 descrCfgTx.srcInc = dmaDataInc1;
656 descrCfgTx.size = dmaDataSize1;
659 descrCfgTx.arbRate = dmaArbitrate1;
660 descrCfgTx.hprot = 0;
663 DMA_CfgDescr(CDC_UART_TX_DMA_CHANNEL,
true, &descrCfgTx);
668 DmaRxCallBack.cbFunc = DmaRxComplete;
669 DmaRxCallBack.userPtr = NULL;
672 chnlCfgRx.highPri =
false;
673 chnlCfgRx.enableInt =
true;
674 chnlCfgRx.select = CDC_RX_DMA_SIGNAL;
675 chnlCfgRx.cb = &DmaRxCallBack;
676 DMA_CfgChannel(CDC_UART_RX_DMA_CHANNEL, &chnlCfgRx);
680 descrCfgRx.dstInc = dmaDataInc1;
681 descrCfgRx.srcInc = dmaDataIncNone;
682 descrCfgRx.size = dmaDataSize1;
685 descrCfgRx.arbRate = dmaArbitrate1;
686 descrCfgRx.hprot = 0;
689 DMA_CfgDescr(CDC_UART_RX_DMA_CHANNEL,
true, &descrCfgRx);
695 static void SerialPortInit(
void)
706 CDC_ENABLE_DK_UART_SWITCH();
717 CDC_UART->ROUTE = CDC_UART_ROUTE;
Clock management unit (CMU) API.
Board support package API definitions.
#define CORE_DECLARE_IRQ_STATE
#define SL_PACK_END()
Macro for handling packed structs. Use this macro after the struct definition. With GCC...
#define USART_FRAME_PARITY_NONE
void CDC_Init(void)
CDC device initialization.
#define USART_FRAME_PARITY_ODD
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define SL_ALIGN(X)
Macro for aligning a variable. Use this macro before the variable definition. X denotes the stora...
Universal synchronous/asynchronous receiver/transmitter (USART/UART) peripheral API.
USART_Enable_TypeDef enable
General purpose utilities.
#define SL_PACK_START(x)
Macro for handling packed structs. Use this macro before the struct definition. X denotes the max...
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_DATABITS_SIXTEEN
#define CORE_ENTER_ATOMIC()
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.
#define USART_FRAME_STOPBITS_ONE
General Purpose IO (GPIO) peripheral API.
#define USART_FRAME_PARITY_EVEN
#define USART_FRAME_DATABITS_FIVE
#define SL_ATTRIBUTE_ALIGN(X)
GCC style macro for aligning a variable.
Core interrupt handling API.
void CMU_ClockEnable(CMU_Clock_TypeDef clock, bool enable)
Enable/disable a clock.
#define USART_FRAME_STOPBITS_ONEANDAHALF
#define CORE_EXIT_ATOMIC()
#define USART_FRAME_DATABITS_SEVEN
#define USART_FRAME_STOPBITS_TWO
#define USART_INITASYNC_DEFAULT
#define USART_FRAME_DATABITS_SIX
#define SL_ATTRIBUTE_PACKED
GCC style macro for handling packed structs.
USB Communication Device Class (CDC) driver.
void USART_Enable(USART_TypeDef *usart, USART_Enable_TypeDef enable)
Enable/disable USART/UART receiver and/or transmitter.
void USART_InitAsync(USART_TypeDef *usart, const USART_InitAsync_TypeDef *init)
Init USART/UART for normal asynchronous mode.
#define USART_FRAME_DATABITS_EIGHT
Direct memory access (DMA) API.
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 ...