MCUXpresso_MIMXRT1021xxxxx/boards/evkmimxrt1020/usb_examples/usb_device_cdc_vcom_lite/bm/virtual_com.c
2022-08-23 23:00:33 +08:00

808 lines
29 KiB
C

/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 - 2017, 2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <stdlib.h>
/*${standard_header_anchor}*/
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "usb_device_config.h"
#include "usb.h"
#include "usb_device.h"
#include "usb_device_cdc_acm.h"
#include "usb_device_ch9.h"
#include "usb_device_descriptor.h"
#include "virtual_com.h"
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
#include "fsl_sysmpu.h"
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
#include "usb_phy.h"
#endif
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
extern uint8_t USB_EnterLowpowerMode(void);
#endif
void BOARD_InitHardware(void);
void USB_DeviceClockInit(void);
void USB_DeviceIsrEnable(void);
#if USB_DEVICE_CONFIG_USE_TASK
void USB_DeviceTaskFn(void *deviceHandle);
#endif
void BOARD_DbgConsole_Deinit(void);
void BOARD_DbgConsole_Init(void);
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Variables
******************************************************************************/
/* Data structure of virtual com device */
usb_cdc_vcom_struct_t s_cdcVcom;
/* Line coding of cdc device */
USB_DMA_INIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint8_t s_lineCoding[LINE_CODING_SIZE] = {
/* E.g. 0x00,0xC2,0x01,0x00 : 0x0001C200 is 115200 bits per second */
(LINE_CODING_DTERATE >> 0U) & 0x000000FFU,
(LINE_CODING_DTERATE >> 8U) & 0x000000FFU,
(LINE_CODING_DTERATE >> 16U) & 0x000000FFU,
(LINE_CODING_DTERATE >> 24U) & 0x000000FFU,
LINE_CODING_CHARFORMAT,
LINE_CODING_PARITYTYPE,
LINE_CODING_DATABITS};
/* Abstract state of cdc device */
USB_DMA_INIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint8_t s_abstractState[COMM_FEATURE_DATA_SIZE] = {(STATUS_ABSTRACT_STATE >> 0U) & 0x00FFU,
(STATUS_ABSTRACT_STATE >> 8U) & 0x00FFU};
/* Country code of cdc device */
USB_DMA_INIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
static uint8_t s_countryCode[COMM_FEATURE_DATA_SIZE] = {(COUNTRY_SETTING >> 0U) & 0x00FFU,
(COUNTRY_SETTING >> 8U) & 0x00FFU};
/* CDC ACM information */
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static usb_cdc_acm_info_t s_usbCdcAcmInfo;
/* Data buffer for receiving and sending*/
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_currRecvBuf[DATA_BUFF_SIZE];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_currSendBuf[DATA_BUFF_SIZE];
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_SetupOutBuffer[8];
volatile static uint32_t s_recvSize = 0;
volatile static uint32_t s_sendSize = 0;
static uint32_t s_usbBulkMaxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
volatile static uint8_t s_waitForDataReceive = 0;
volatile static uint8_t s_comOpen = 0;
#endif
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
void USB_OTG1_IRQHandler(void)
{
USB_DeviceEhciIsrFunction(s_cdcVcom.deviceHandle);
}
void USB_DeviceClockInit(void)
{
usb_phy_config_struct_t phyConfig = {
BOARD_USB_PHY_D_CAL,
BOARD_USB_PHY_TXCAL45DP,
BOARD_USB_PHY_TXCAL45DM,
};
CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ, &phyConfig);
}
void USB_DeviceIsrEnable(void)
{
uint8_t irqNumber;
uint8_t usbDeviceEhciIrq[] = USBHS_IRQS;
irqNumber = usbDeviceEhciIrq[CONTROLLER_ID - kUSB_ControllerEhci0];
/* Install isr, set priority, and enable IRQ. */
NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY);
EnableIRQ((IRQn_Type)irqNumber);
}
#if USB_DEVICE_CONFIG_USE_TASK
void USB_DeviceTaskFn(void *deviceHandle)
{
USB_DeviceEhciTaskFunction(deviceHandle);
}
#endif
#if ((defined USB_DEVICE_CONFIG_CDC_CIC_EP_DISABLE) && (USB_DEVICE_CONFIG_CDC_CIC_EP_DISABLE > 0U))
#else
/*!
* @brief Interrupt in pipe callback function.
*
* This function serves as the callback function for interrupt in pipe.
*
* @param handle The USB device handle.
* @param message The endpoint callback message
* @param callbackParam The parameter of the callback.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceCdcAcmInterruptIn(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam)
{
usb_status_t error = kStatus_USB_Error;
s_cdcVcom.hasSentState = 0;
return error;
}
#endif
/*!
* @brief Bulk in pipe callback function.
*
* This function serves as the callback function for bulk in pipe.
*
* @param handle The USB device handle.
* @param message The endpoint callback message
* @param callbackParam The parameter of the callback.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceCdcAcmBulkIn(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam)
{
usb_status_t error = kStatus_USB_Error;
if ((message->length != 0) && (0U == (message->length % s_usbBulkMaxPacketSize)))
{
/* If the last packet is the size of endpoint, then send also zero-ended packet,
** meaning that we want to inform the host that we do not have any additional
** data, so it can flush the output.
*/
error = USB_DeviceSendRequest(handle, USB_CDC_VCOM_BULK_IN_ENDPOINT, NULL, 0);
}
else if ((1U == s_cdcVcom.attach) && (1U == s_cdcVcom.startTransactions))
{
if ((message->buffer != NULL) || ((message->buffer == NULL) && (message->length == 0U)))
{
/* User: add your own code for send complete event */
/* Schedule buffer for next receive event */
error =
USB_DeviceRecvRequest(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, s_usbBulkMaxPacketSize);
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
s_waitForDataReceive = 1;
USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
#endif
}
}
else
{
}
return error;
}
/*!
* @brief Bulk out pipe callback function.
*
* This function serves as the callback function for bulk out pipe.
*
* @param handle The USB device handle.
* @param message The endpoint callback message
* @param callbackParam The parameter of the callback.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceCdcAcmBulkOut(usb_device_handle handle,
usb_device_endpoint_callback_message_struct_t *message,
void *callbackParam)
{
usb_status_t error = kStatus_USB_Error;
if ((1U == s_cdcVcom.attach) && (1U == s_cdcVcom.startTransactions))
{
s_recvSize = message->length;
error = kStatus_USB_Success;
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
s_waitForDataReceive = 0;
USB0->INTEN |= USB_INTEN_SOFTOKEN_MASK;
#endif
if (0U == s_recvSize)
{
/* Schedule buffer for next receive event */
USB_DeviceRecvRequest(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, s_usbBulkMaxPacketSize);
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
s_waitForDataReceive = 1;
USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
#endif
}
}
return error;
}
/*!
* @brief Get the setup packet buffer.
*
* This function provides the buffer for setup packet.
*
* @param handle The USB device handle.
* @param setupBuffer The pointer to the address of setup packet buffer.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceGetSetupBuffer(usb_device_handle handle, usb_setup_struct_t **setupBuffer)
{
static uint32_t cdcVcomSetup[2];
if (NULL == setupBuffer)
{
return kStatus_USB_InvalidParameter;
}
*setupBuffer = (usb_setup_struct_t *)&cdcVcomSetup;
return kStatus_USB_Success;
}
/*!
* @brief Get the setup packet data buffer.
*
* This function gets the data buffer for setup packet.
*
* @param handle The USB device handle.
* @param setup The pointer to the setup packet.
* @param length The pointer to the length of the data buffer.
* @param buffer The pointer to the address of setup packet data buffer.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceGetClassReceiveBuffer(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
if ((NULL == buffer) || ((*length) > sizeof(s_SetupOutBuffer)))
{
return kStatus_USB_InvalidRequest;
}
*buffer = s_SetupOutBuffer;
return kStatus_USB_Success;
}
/*!
* @brief Configure remote wakeup feature.
*
* This function configures the remote wakeup feature.
*
* @param handle The USB device handle.
* @param enable 1: enable, 0: disable.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceConfigureRemoteWakeup(usb_device_handle handle, uint8_t enable)
{
return kStatus_USB_InvalidRequest;
}
/*!
* @brief CDC class specific callback function.
*
* This function handles the CDC class specific requests.
*
* @param handle The USB device handle.
* @param setup The pointer to the setup packet.
* @param length The pointer to the length of the data buffer.
* @param buffer The pointer to the address of setup packet data buffer.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceProcessClassRequest(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
usb_status_t error = kStatus_USB_InvalidRequest;
usb_cdc_acm_info_t *acmInfo = &s_usbCdcAcmInfo;
#if ((defined USB_DEVICE_CONFIG_CDC_CIC_EP_DISABLE) && (USB_DEVICE_CONFIG_CDC_CIC_EP_DISABLE > 0U))
#else
uint32_t len;
#endif
uint8_t *uartBitmap;
if (setup->wIndex != USB_CDC_VCOM_COMM_INTERFACE_INDEX)
{
return error;
}
switch (setup->bRequest)
{
case USB_DEVICE_CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
break;
case USB_DEVICE_CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
break;
case USB_DEVICE_CDC_REQUEST_SET_COMM_FEATURE:
if (((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT) &&
(setup->wLength != 0U))
{
if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == setup->wValue)
{
(void)memcpy(s_abstractState, *buffer, COMM_FEATURE_DATA_SIZE);
error = kStatus_USB_Success;
}
else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == setup->wValue)
{
(void)memcpy(s_countryCode, *buffer, COMM_FEATURE_DATA_SIZE);
error = kStatus_USB_Success;
}
else
{
}
}
break;
case USB_DEVICE_CDC_REQUEST_GET_COMM_FEATURE:
if (((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN) &&
(setup->wLength != 0U))
{
if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == setup->wValue)
{
*buffer = s_abstractState;
*length = COMM_FEATURE_DATA_SIZE;
error = kStatus_USB_Success;
}
else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == setup->wValue)
{
*buffer = s_countryCode;
*length = COMM_FEATURE_DATA_SIZE;
error = kStatus_USB_Success;
}
else
{
}
}
break;
case USB_DEVICE_CDC_REQUEST_CLEAR_COMM_FEATURE:
break;
case USB_DEVICE_CDC_REQUEST_GET_LINE_CODING:
if (((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN) &&
(setup->wLength != 0U))
{
*buffer = s_lineCoding;
*length = LINE_CODING_SIZE;
error = kStatus_USB_Success;
}
break;
case USB_DEVICE_CDC_REQUEST_SET_LINE_CODING:
if (((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT) &&
(setup->wLength != 0U))
{
(void)memcpy(s_lineCoding, *buffer, LINE_CODING_SIZE);
error = kStatus_USB_Success;
}
break;
case USB_DEVICE_CDC_REQUEST_SET_CONTROL_LINE_STATE:
{
if (((setup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT) &&
(setup->wLength == 0U))
{
error = kStatus_USB_Success;
acmInfo->dteStatus = setup->wValue;
/* activate/deactivate Tx carrier */
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION)
{
acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_TX_CARRIER;
}
else
{
acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_TX_CARRIER;
}
/* activate carrier and DTE. Com port of terminal tool running on PC is open now */
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE)
{
acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_RX_CARRIER;
}
/* Com port of terminal tool running on PC is closed now */
else
{
acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_RX_CARRIER;
}
/* Indicates to DCE if DTE is present or not */
acmInfo->dtePresent =
(acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE) ? true : false;
/* Initialize the serial state buffer */
acmInfo->serialStateBuf[0] = NOTIF_REQUEST_TYPE; /* bmRequestType */
acmInfo->serialStateBuf[1] = USB_DEVICE_CDC_REQUEST_SERIAL_STATE_NOTIF; /* bNotification */
acmInfo->serialStateBuf[2] = 0x00; /* wValue */
acmInfo->serialStateBuf[3] = 0x00;
acmInfo->serialStateBuf[4] = 0x00; /* wIndex */
acmInfo->serialStateBuf[5] = 0x00;
acmInfo->serialStateBuf[6] = UART_BITMAP_SIZE; /* wLength */
acmInfo->serialStateBuf[7] = 0x00;
/* Notify to host the line state */
acmInfo->serialStateBuf[4] = setup->wIndex;
/* Lower byte of UART BITMAP */
uartBitmap = (uint8_t *)&acmInfo->serialStateBuf[NOTIF_PACKET_SIZE + UART_BITMAP_SIZE - 2];
uartBitmap[0] = acmInfo->uartState & 0xFFu;
uartBitmap[1] = (acmInfo->uartState >> 8) & 0xFFu;
#if ((defined USB_DEVICE_CONFIG_CDC_CIC_EP_DISABLE) && (USB_DEVICE_CONFIG_CDC_CIC_EP_DISABLE > 0U))
#else
len = (uint32_t)(NOTIF_PACKET_SIZE + UART_BITMAP_SIZE);
if (0U == s_cdcVcom.hasSentState)
{
error =
USB_DeviceSendRequest(handle, USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT, acmInfo->serialStateBuf, len);
if (kStatus_USB_Success != error)
{
usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
}
s_cdcVcom.hasSentState = 1;
}
#endif
/* Update status */
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION)
{
/* To do: CARRIER_ACTIVATED */
}
else
{
/* To do: CARRIER_DEACTIVATED */
}
if (1U == s_cdcVcom.attach)
{
s_cdcVcom.startTransactions = 1;
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
s_waitForDataReceive = 1;
USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
s_comOpen = 1;
usb_echo("USB_APP_CDC_DTE_ACTIVATED\r\n");
#endif
}
}
}
break;
case USB_DEVICE_CDC_REQUEST_SEND_BREAK:
break;
default:
break;
}
return error;
}
/*!
* @brief USB device callback function.
*
* This function handles the usb device specific requests.
*
* @param handle The USB device handle.
* @param event The USB device event type.
* @param param The parameter of the device specific request.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param)
{
usb_status_t error = kStatus_USB_InvalidRequest;
uint8_t *temp8 = (uint8_t *)param;
switch (event)
{
case kUSB_DeviceEventBusReset:
{
USB_DeviceControlPipeInit(s_cdcVcom.deviceHandle);
s_cdcVcom.attach = 0;
s_cdcVcom.currentConfiguration = 0U;
error = kStatus_USB_Success;
#if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) || \
(defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
/* Get USB speed to configure the device, including max packet size and interval of the endpoints. */
if (kStatus_USB_Success ==
USB_DeviceGetStatus(s_cdcVcom.deviceHandle, kUSB_DeviceStatusSpeed, &s_cdcVcom.speed))
{
USB_DeviceSetSpeed(handle, s_cdcVcom.speed);
}
#endif
}
break;
case kUSB_DeviceEventSetConfiguration:
if (0U == (*temp8))
{
s_cdcVcom.attach = 0;
s_cdcVcom.currentConfiguration = 0U;
error = kStatus_USB_Success;
}
else if (USB_CDC_VCOM_CONFIGURE_INDEX == (*temp8))
{
usb_device_endpoint_init_struct_t epInitStruct;
usb_device_endpoint_callback_struct_t epCallback;
s_cdcVcom.attach = 1;
s_cdcVcom.currentConfiguration = *temp8;
#if ((defined USB_DEVICE_CONFIG_CDC_CIC_EP_DISABLE) && (USB_DEVICE_CONFIG_CDC_CIC_EP_DISABLE > 0U))
#else
/* Initiailize endpoint for interrupt pipe */
epCallback.callbackFn = USB_DeviceCdcAcmInterruptIn;
epCallback.callbackParam = handle;
epInitStruct.zlt = 0;
epInitStruct.transferType = USB_ENDPOINT_INTERRUPT;
epInitStruct.endpointAddress =
USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
if (USB_SPEED_HIGH == s_cdcVcom.speed)
{
epInitStruct.maxPacketSize = HS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE;
epInitStruct.interval = HS_CDC_VCOM_INTERRUPT_IN_INTERVAL;
}
else
{
epInitStruct.maxPacketSize = FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE;
epInitStruct.interval = FS_CDC_VCOM_INTERRUPT_IN_INTERVAL;
}
USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &epCallback);
#endif
/* Initiailize endpoints for bulk pipe */
epCallback.callbackFn = USB_DeviceCdcAcmBulkIn;
epCallback.callbackParam = handle;
epInitStruct.zlt = 0;
epInitStruct.interval = 0U;
epInitStruct.transferType = USB_ENDPOINT_BULK;
epInitStruct.endpointAddress =
USB_CDC_VCOM_BULK_IN_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
if (USB_SPEED_HIGH == s_cdcVcom.speed)
{
epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_IN_PACKET_SIZE;
}
else
{
epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_IN_PACKET_SIZE;
}
USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &epCallback);
epCallback.callbackFn = USB_DeviceCdcAcmBulkOut;
epCallback.callbackParam = handle;
epInitStruct.zlt = 0;
epInitStruct.interval = 0U;
epInitStruct.transferType = USB_ENDPOINT_BULK;
epInitStruct.endpointAddress =
USB_CDC_VCOM_BULK_OUT_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
if (USB_SPEED_HIGH == s_cdcVcom.speed)
{
epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
}
else
{
epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
}
USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &epCallback);
if (USB_SPEED_HIGH == s_cdcVcom.speed)
{
s_usbBulkMaxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
}
else
{
s_usbBulkMaxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
}
/* Schedule buffer for receive */
error = USB_DeviceRecvRequest(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf,
s_usbBulkMaxPacketSize);
}
else
{
/* no action, return kStatus_USB_InvalidRequest */
}
break;
case kUSB_DeviceEventSetInterface:
error = kStatus_USB_Success;
break;
default:
break;
}
return error;
}
/*!
* @brief USB configure endpoint function.
*
* This function configure endpoint status.
*
* @param handle The USB device handle.
* @param ep Endpoint address.
* @param status A flag to indicate whether to stall the endpoint. 1: stall, 0: unstall.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceConfigureEndpointStatus(usb_device_handle handle, uint8_t ep, uint8_t status)
{
if (status)
{
return USB_DeviceStallEndpoint(handle, ep);
}
else
{
return USB_DeviceUnstallEndpoint(handle, ep);
}
}
static void CDC_VCOM_BMEnterCritical(uint32_t *sr)
{
*sr = DisableGlobalIRQ();
}
static void CDC_VCOM_BMExitCritical(uint32_t sr)
{
EnableGlobalIRQ(sr);
}
/*!
* @brief Application initialization function.
*
* This function initializes the application.
*
* @return None.
*/
void APPInit(void)
{
USB_DeviceClockInit();
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
SYSMPU_Enable(SYSMPU, 0);
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
s_cdcVcom.speed = USB_SPEED_FULL;
s_cdcVcom.attach = 0;
s_cdcVcom.deviceHandle = NULL;
if (kStatus_USB_Success != USB_DeviceInit(CONTROLLER_ID, USB_DeviceCallback, &s_cdcVcom.deviceHandle))
{
usb_echo("USB device vcom failed\r\n");
return;
}
else
{
usb_echo("USB device CDC virtual com demo\r\n");
}
USB_DeviceIsrEnable();
/*Add one delay here to make the DP pull down long enough to allow host to detect the previous disconnection.*/
SDK_DelayAtLeastUs(5000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
USB_DeviceRun(s_cdcVcom.deviceHandle);
}
/*!
* @brief Application task function.
*
* This function runs the task for application.
*
* @return None.
*/
void APP_task(void)
{
usb_status_t error = kStatus_USB_Error;
uint32_t usbOsaCurrentSr;
if ((1U == s_cdcVcom.attach) && (1U == s_cdcVcom.startTransactions))
{
/* Enter critical can not be added here because of the loop */
/* endpoint callback length is USB_CANCELLED_TRANSFER_LENGTH (0xFFFFFFFFU) when transfer is canceled */
if ((0U != s_recvSize) && (USB_CANCELLED_TRANSFER_LENGTH != s_recvSize))
{
/* The operating timing sequence has guaranteed there is no conflict to access the s_recvSize between USB
ISR and this task. Therefore, the following code of Enter/Exit ctitical mode is useless,
only to mention users the exclusive access of s_recvSize if users implement their own
application referred to this SDK demo */
CDC_VCOM_BMEnterCritical(&usbOsaCurrentSr);
if ((0U != s_recvSize) && (USB_CANCELLED_TRANSFER_LENGTH != s_recvSize))
{
/* Copy Buffer to Send Buff */
memcpy(s_currSendBuf, s_currRecvBuf, s_recvSize);
s_sendSize = s_recvSize;
s_recvSize = 0;
}
CDC_VCOM_BMExitCritical(usbOsaCurrentSr);
}
if (0U != s_sendSize)
{
uint32_t size = s_sendSize;
s_sendSize = 0;
error = USB_DeviceSendRequest(s_cdcVcom.deviceHandle, USB_CDC_VCOM_BULK_IN_ENDPOINT, s_currSendBuf, size);
if (error != kStatus_USB_Success)
{
/* Failure to send Data Handling code here */
}
}
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
if ((s_waitForDataReceive))
{
if (s_comOpen == 1U)
{
/* Wait for all the packets been sent during opening the com port. Otherwise these packets may
* wake up the system.
*/
usb_echo("Waiting to enter lowpower ...\r\n");
for (uint32_t i = 0U; i < 16000000U; ++i)
{
__NOP(); /* delay */
}
s_comOpen = 0;
}
usb_echo("Enter lowpower\r\n");
BOARD_DbgConsole_Deinit();
USB0->INTEN &= ~USB_INTEN_TOKDNEEN_MASK;
USB_EnterLowpowerMode();
s_waitForDataReceive = 0;
USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK;
BOARD_DbgConsole_Init();
usb_echo("Exit lowpower\r\n");
}
#endif
}
}
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION)) || defined(__GNUC__)
int main(void)
#else
void main(void)
#endif
{
BOARD_ConfigMPU();
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
APPInit();
while (1)
{
APP_task();
#if USB_DEVICE_CONFIG_USE_TASK
USB_DeviceTaskFn(s_cdcVcom.deviceHandle);
#endif
}
}