758 lines
28 KiB
C
758 lines
28 KiB
C
/*
|
|
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
|
|
* Copyright 2016 NXP
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* o Redistributions of source code must retain the above copyright notice, this list
|
|
* of conditions and the following disclaimer.
|
|
*
|
|
* o Redistributions in binary form must reproduce the above copyright notice, this
|
|
* list of conditions and the following disclaimer in the documentation and/or
|
|
* other materials provided with the distribution.
|
|
*
|
|
* o Neither the name of the copyright holder nor the names of its
|
|
* contributors may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "fsl_device_registers.h"
|
|
#include "clock_config.h"
|
|
#include "board.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
|
|
#include "usb_device_config.h"
|
|
#include "usb.h"
|
|
#include "usb_device.h"
|
|
|
|
#include "usb_device_class.h"
|
|
#include "usb_device_cdc_acm.h"
|
|
#include "usb_device_ch9.h"
|
|
|
|
|
|
#include "build.h"
|
|
#include "types.h"
|
|
#include "sysapi.h"
|
|
#include "dll.h"
|
|
|
|
#include "usb_device_descriptor.h"
|
|
#include "CPUAbstract.h"
|
|
#include "declarations.h"
|
|
#include <VCOMHA.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(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0)
|
|
#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)
|
|
#include "fsl_smc.h"
|
|
#endif
|
|
#include "fsl_common.h"
|
|
#include "pin_mux.h"
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
/* USB clock source and frequency*/
|
|
#define USB_FS_CLK_SRC kCLOCK_UsbSrcPll0
|
|
#define USB_FS_CLK_FREQ CLOCK_GetFreq(kCLOCK_PllFllSelClk)
|
|
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
void BOARD_InitHardware(void);
|
|
void BOARD_DbgConsole_Deinit(void);
|
|
void BOARD_DbgConsole_Init(void);
|
|
usb_status_t USB_DeviceCdcVcomCallback(class_handle_t handle, uint32_t event, void *param);
|
|
usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param);
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
extern usb_device_endpoint_struct_t g_UsbDeviceCdcVcomDicEndpoints[];
|
|
extern usb_device_class_struct_t g_UsbDeviceCdcVcomConfig;
|
|
/* Data structure of virtual com device */
|
|
static usb_cdc_vcom_struct_t s_cdcVcom;
|
|
|
|
/* Line codinig of cdc device */
|
|
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 */
|
|
static uint8_t s_abstractState[COMM_FEATURE_DATA_SIZE] = {(STATUS_ABSTRACT_STATE >> 0U) & 0x00FFU,
|
|
(STATUS_ABSTRACT_STATE >> 8U) & 0x00FFU};
|
|
|
|
/* Country code of cdc device */
|
|
static uint8_t s_countryCode[COMM_FEATURE_DATA_SIZE] = {(COUNTRY_SETTING >> 0U) & 0x00FFU,
|
|
(COUNTRY_SETTING >> 8U) & 0x00FFU};
|
|
|
|
/* CDC ACM information */
|
|
USB_DATA_ALIGNMENT static usb_cdc_acm_info_t s_usbCdcAcmInfo = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0};
|
|
/* Data buffer for receiving and sending*/
|
|
USB_DATA_ALIGNMENT static uint8_t s_currRecvBuf[USB_DATA_BUFF_SIZE];
|
|
USB_DATA_ALIGNMENT static uint8_t s_currSendBuf[USB_DATA_BUFF_SIZE];
|
|
volatile static uint32_t s_recvSize = 0;
|
|
volatile static uint32_t s_sendSize = 0;
|
|
|
|
/* USB device class information */
|
|
static usb_device_class_config_struct_t s_cdcAcmConfig[1] = {{
|
|
USB_DeviceCdcVcomCallback, 0, &g_UsbDeviceCdcVcomConfig,
|
|
}};
|
|
|
|
/* USB device class configuration information */
|
|
static usb_device_class_config_list_struct_t s_cdcAcmConfigList = {
|
|
s_cdcAcmConfig, USB_DeviceCallback, 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)
|
|
volatile static uint8_t s_waitForDataReceive = 0;
|
|
volatile static uint8_t s_comOpen = 0;
|
|
#endif
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
/*!
|
|
* @brief CDC class specific callback function.
|
|
*
|
|
* This function handles the CDC class specific requests.
|
|
*
|
|
* @param handle The CDC ACM class handle.
|
|
* @param event The CDC ACM class event type.
|
|
* @param param The parameter of the class specific request.
|
|
*
|
|
* @return A USB error code or kStatus_USB_Success.
|
|
*/
|
|
usb_status_t USB_DeviceCdcVcomCallback(class_handle_t handle, uint32_t event, void *param)
|
|
{
|
|
uint32_t len;
|
|
uint16_t *uartBitmap;
|
|
usb_device_cdc_acm_request_param_struct_t *acmReqParam;
|
|
usb_device_endpoint_callback_message_struct_t *epCbParam;
|
|
usb_status_t error = kStatus_USB_Error;
|
|
usb_cdc_acm_info_t *acmInfo = &s_usbCdcAcmInfo;
|
|
acmReqParam = (usb_device_cdc_acm_request_param_struct_t *)param;
|
|
epCbParam = (usb_device_endpoint_callback_message_struct_t *)param;
|
|
switch (event)
|
|
{
|
|
case kUSB_DeviceCdcEventSendResponse:
|
|
{
|
|
if ((epCbParam->length != 0) && (!(epCbParam->length % g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize)))
|
|
{
|
|
/* 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_DeviceCdcAcmSend(handle, USB_CDC_VCOM_BULK_IN_ENDPOINT, NULL, 0);
|
|
}
|
|
//else if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
|
|
else if (1 == s_cdcVcom.attach)
|
|
{
|
|
if ((epCbParam->buffer != NULL) || ((epCbParam->buffer == NULL) && (epCbParam->length == 0)))
|
|
{
|
|
/* User: add your own code for send complete event */
|
|
/* Schedule buffer for next receive event */
|
|
error = USB_DeviceCdcAcmRecv(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf,
|
|
g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize);
|
|
#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
|
|
{
|
|
}
|
|
}
|
|
break;
|
|
case kUSB_DeviceCdcEventRecvResponse:
|
|
{
|
|
//if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
|
|
if (1 == s_cdcVcom.attach)
|
|
{
|
|
s_recvSize = epCbParam->length;
|
|
|
|
#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 (!s_recvSize)
|
|
{
|
|
/* Schedule buffer for next receive event */
|
|
error = USB_DeviceCdcAcmRecv(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf,
|
|
g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize);
|
|
#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
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case kUSB_DeviceCdcEventSerialStateNotif:
|
|
((usb_device_cdc_acm_struct_t *)handle)->hasSentState = 0;
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case kUSB_DeviceCdcEventSendEncapsulatedCommand:
|
|
break;
|
|
case kUSB_DeviceCdcEventGetEncapsulatedResponse:
|
|
break;
|
|
case kUSB_DeviceCdcEventSetCommFeature:
|
|
if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == acmReqParam->setupValue)
|
|
{
|
|
if (1 == acmReqParam->isSetup)
|
|
{
|
|
*(acmReqParam->buffer) = s_abstractState;
|
|
}
|
|
else
|
|
{
|
|
*(acmReqParam->length) = 0;
|
|
}
|
|
}
|
|
else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == acmReqParam->setupValue)
|
|
{
|
|
if (1 == acmReqParam->isSetup)
|
|
{
|
|
*(acmReqParam->buffer) = s_countryCode;
|
|
}
|
|
else
|
|
{
|
|
*(acmReqParam->length) = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
}
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case kUSB_DeviceCdcEventGetCommFeature:
|
|
if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == acmReqParam->setupValue)
|
|
{
|
|
*(acmReqParam->buffer) = s_abstractState;
|
|
*(acmReqParam->length) = COMM_FEATURE_DATA_SIZE;
|
|
}
|
|
else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == acmReqParam->setupValue)
|
|
{
|
|
*(acmReqParam->buffer) = s_countryCode;
|
|
*(acmReqParam->length) = COMM_FEATURE_DATA_SIZE;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case kUSB_DeviceCdcEventClearCommFeature:
|
|
break;
|
|
case kUSB_DeviceCdcEventGetLineCoding:
|
|
*(acmReqParam->buffer) = s_lineCoding;
|
|
*(acmReqParam->length) = LINE_CODING_SIZE;
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case kUSB_DeviceCdcEventSetLineCoding:
|
|
{
|
|
if (1 == acmReqParam->isSetup)
|
|
{
|
|
*(acmReqParam->buffer) = s_lineCoding;
|
|
}
|
|
else
|
|
{
|
|
*(acmReqParam->length) = 0;
|
|
}
|
|
}
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case kUSB_DeviceCdcEventSetControlLineState:
|
|
{
|
|
s_usbCdcAcmInfo.dteStatus = acmReqParam->setupValue;
|
|
/* 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 */
|
|
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE)
|
|
{
|
|
acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_RX_CARRIER;
|
|
}
|
|
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_NOTIF_SERIAL_STATE; /* 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;
|
|
/* Notifiy to host the line state */
|
|
acmInfo->serialStateBuf[4] = acmReqParam->interfaceIndex;
|
|
/* Lower byte of UART BITMAP */
|
|
uartBitmap = (uint16_t *)&acmInfo->serialStateBuf[NOTIF_PACKET_SIZE + UART_BITMAP_SIZE - 2];
|
|
*uartBitmap = acmInfo->uartState;
|
|
len = (uint32_t)(NOTIF_PACKET_SIZE + UART_BITMAP_SIZE);
|
|
if (0 == ((usb_device_cdc_acm_struct_t *)handle)->hasSentState)
|
|
{
|
|
error = USB_DeviceCdcAcmSend(handle, USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT, acmInfo->serialStateBuf, len);
|
|
if (kStatus_USB_Success != error)
|
|
{
|
|
usb_echo("kUSB_DeviceCdcEventSetControlLineState error!");
|
|
}
|
|
((usb_device_cdc_acm_struct_t *)handle)->hasSentState = 1;
|
|
}
|
|
|
|
/* Update status */
|
|
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION)
|
|
{
|
|
/* To do: CARRIER_ACTIVATED */
|
|
}
|
|
else
|
|
{
|
|
/* To do: CARRIER_DEACTIVATED */
|
|
}
|
|
#if 0
|
|
// Disable Transaction for .NET applications
|
|
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE)
|
|
{
|
|
/* DTE_ACTIVATED */
|
|
if (1 == 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
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* DTE_DEACTIVATED */
|
|
if (1 == s_cdcVcom.attach)
|
|
{
|
|
s_cdcVcom.startTransactions = 0;
|
|
}
|
|
}
|
|
#endif //0
|
|
}
|
|
break;
|
|
case kUSB_DeviceCdcEventSendBreak:
|
|
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_Error;
|
|
uint16_t *temp16 = (uint16_t *)param;
|
|
uint8_t *temp8 = (uint8_t *)param;
|
|
|
|
switch (event)
|
|
{
|
|
case kUSB_DeviceEventBusReset:
|
|
{
|
|
s_cdcVcom.attach = 0;
|
|
#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_DeviceClassGetSpeed(CONTROLLER_ID, &s_cdcVcom.speed))
|
|
{
|
|
USB_DeviceSetSpeed(handle, s_cdcVcom.speed);
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventSetConfiguration:
|
|
if (param)
|
|
{
|
|
s_cdcVcom.attach = 1;
|
|
s_cdcVcom.currentConfiguration = *temp8;
|
|
if (USB_CDC_VCOM_CONFIGURE_INDEX == (*temp8))
|
|
{
|
|
/* Schedule buffer for receive */
|
|
USB_DeviceCdcAcmRecv(s_cdcVcom.cdcAcmHandle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf,
|
|
g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize);
|
|
}
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventSetInterface:
|
|
if (s_cdcVcom.attach)
|
|
{
|
|
uint8_t interface = (uint8_t)((*temp16 & 0xFF00U) >> 0x08U);
|
|
uint8_t alternateSetting = (uint8_t)(*temp16 & 0x00FFU);
|
|
if (interface < USB_CDC_VCOM_INTERFACE_COUNT)
|
|
{
|
|
s_cdcVcom.currentInterfaceAlternateSetting[interface] = alternateSetting;
|
|
}
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetConfiguration:
|
|
break;
|
|
case kUSB_DeviceEventGetInterface:
|
|
break;
|
|
case kUSB_DeviceEventGetDeviceDescriptor:
|
|
if (param)
|
|
{
|
|
error = USB_DeviceGetDeviceDescriptor(handle, (usb_device_get_device_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetConfigurationDescriptor:
|
|
if (param)
|
|
{
|
|
error = USB_DeviceGetConfigurationDescriptor(handle,
|
|
(usb_device_get_configuration_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetStringDescriptor:
|
|
if (param)
|
|
{
|
|
/* Get device string descriptor request */
|
|
error = USB_DeviceGetStringDescriptor(handle, (usb_device_get_string_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/*!
|
|
* @brief USB Interrupt service routine.
|
|
*
|
|
* This function serves as the USB interrupt service routine.
|
|
*
|
|
* @return None.
|
|
*/
|
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
|
|
void USBHS_IRQHandler(void)
|
|
{
|
|
USB_DeviceEhciIsrFunction(s_cdcVcom.deviceHandle);
|
|
}
|
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 1U)
|
|
#if defined(FSL_FEATURE_SOC_USBNC_COUNT) && (FSL_FEATURE_SOC_USBNC_COUNT > 1U)
|
|
void USB1_IRQHandler(void)
|
|
{
|
|
USB_DeviceEhciIsrFunction(s_cdcVcom.deviceHandle);
|
|
}
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)
|
|
void USB0_IRQHandler(void)
|
|
{
|
|
USB_DeviceKhciIsrFunction(s_cdcVcom.deviceHandle);
|
|
}
|
|
#endif
|
|
#if (defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
|
|
void USB0_IRQHandler(void)
|
|
{
|
|
USB_DeviceLpcIp3511IsrFunction(s_cdcVcom.deviceHandle);
|
|
}
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
|
|
void USB1_IRQHandler(void)
|
|
{
|
|
USB_DeviceLpcIp3511IsrFunction(s_cdcVcom.deviceHandle);
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
* @brief Application initialization function.
|
|
*
|
|
* This function initializes the application.
|
|
*
|
|
* @return None.
|
|
*/
|
|
void VCOM_vStart(uint32* const u32Stat)
|
|
{
|
|
uint8_t irqNo;
|
|
|
|
CPU_vDisableMPROT();
|
|
|
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0)
|
|
uint8_t ehciIrq[] = USBHS_IRQS;
|
|
irqNo = ehciIrq[CONTROLLER_ID - kUSB_ControllerEhci0];
|
|
|
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 1U)
|
|
if (CONTROLLER_ID == kUSB_ControllerEhci0)
|
|
{
|
|
CLOCK_EnableUsbhs0PhyPllClock(USB_HS_PHY_CLK_SRC, USB_HS_PHY_CLK_FREQ);
|
|
CLOCK_EnableUsbhs0Clock(USB_HS_CLK_SRC, USB_HS_CLK_FREQ);
|
|
}
|
|
else
|
|
{
|
|
CLOCK_EnableUsbhs1PhyPllClock(USB_HS_PHY_CLK_SRC, USB_HS_PHY_CLK_FREQ);
|
|
CLOCK_EnableUsbhs1Clock(USB_HS_CLK_SRC, USB_HS_CLK_FREQ);
|
|
}
|
|
#else
|
|
CLOCK_EnableUsbhs0PhyPllClock(USB_HS_PHY_CLK_SRC, USB_HS_PHY_CLK_FREQ);
|
|
CLOCK_EnableUsbhs0Clock(USB_HS_CLK_SRC, USB_HS_CLK_FREQ);
|
|
#endif
|
|
|
|
USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ);
|
|
#endif
|
|
|
|
#if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0)
|
|
uint8_t khciIrq[] = USB_IRQS;
|
|
irqNo = khciIrq[CONTROLLER_ID - kUSB_ControllerKhci0];
|
|
|
|
SystemCoreClockUpdate();
|
|
|
|
CLOCK_EnableUsbfs0Clock(USB_FS_CLK_SRC, USB_FS_CLK_FREQ);
|
|
#endif
|
|
|
|
#if (defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
|
|
uint8_t usbDeviceIP3511Irq[] = USB_IRQS;
|
|
irqNo = usbDeviceIP3511Irq[CONTROLLER_ID - kUSB_ControllerLpcIp3511Fs0];
|
|
|
|
/* enable USB IP clock */
|
|
CLOCK_EnableUsbfs0DeviceClock(USB_FS_CLK_SRC, USB_FS_CLK_FREQ);
|
|
#endif
|
|
|
|
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
|
|
uint8_t usbDeviceIP3511Irq[] = USBHSD_IRQS;
|
|
irqNo = usbDeviceIP3511Irq[CONTROLLER_ID - kUSB_ControllerLpcIp3511Hs0];
|
|
/* enable USB IP clock */
|
|
CLOCK_EnableUsbhs0DeviceClock(USB_HS_CLK_SRC, USB_HS_CLK_FREQ);
|
|
#endif
|
|
|
|
#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
|
|
((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
|
|
#if defined(FSL_FEATURE_USBHSD_USB_RAM) && (FSL_FEATURE_USBHSD_USB_RAM)
|
|
for (int i = 0; i < FSL_FEATURE_USBHSD_USB_RAM; i++)
|
|
{
|
|
((uint8_t *)FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS)[i] = 0x00U;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
|
|
//SYSMPU_Enable(SYSMPU, 0);
|
|
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
|
|
|
|
/*
|
|
* If the SOC has USB KHCI dedicated RAM, the RAM memory needs to be clear after
|
|
* the KHCI clock is enabled. When the demo uses USB EHCI IP, the USB KHCI dedicated
|
|
* RAM can not be used and the memory can't be accessed.
|
|
*/
|
|
#if (defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U))
|
|
#if (defined(FSL_FEATURE_USB_KHCI_USB_RAM_BASE_ADDRESS) && (FSL_FEATURE_USB_KHCI_USB_RAM_BASE_ADDRESS > 0U))
|
|
for (int i = 0; i < FSL_FEATURE_USB_KHCI_USB_RAM; i++)
|
|
{
|
|
((uint8_t *)FSL_FEATURE_USB_KHCI_USB_RAM_BASE_ADDRESS)[i] = 0x00U;
|
|
}
|
|
#endif /* FSL_FEATURE_USB_KHCI_USB_RAM_BASE_ADDRESS */
|
|
#endif /* FSL_FEATURE_USB_KHCI_USB_RAM */
|
|
|
|
s_cdcVcom.speed = USB_SPEED_FULL;
|
|
s_cdcVcom.attach = 0;
|
|
s_cdcVcom.cdcAcmHandle = (class_handle_t)NULL;
|
|
s_cdcVcom.deviceHandle = NULL;
|
|
|
|
if (kStatus_USB_Success != USB_DeviceClassInit(CONTROLLER_ID, &s_cdcAcmConfigList, &s_cdcVcom.deviceHandle))
|
|
{
|
|
usb_echo("USB device init failed\r\n");
|
|
}
|
|
else
|
|
{
|
|
usb_echo("USB device CDC virtual com demo\r\n");
|
|
s_cdcVcom.cdcAcmHandle = s_cdcAcmConfigList.config->classHandle;
|
|
}
|
|
|
|
#if defined(__GIC_PRIO_BITS)
|
|
GIC_SetPriority((IRQn_Type)irqNo, USB_DEVICE_INTERRUPT_PRIORITY);
|
|
#else
|
|
NVIC_SetPriority((IRQn_Type)irqNo, USB_DEVICE_INTERRUPT_PRIORITY);
|
|
#endif
|
|
EnableIRQ((IRQn_Type)irqNo);
|
|
|
|
USB_DeviceRun(s_cdcVcom.deviceHandle);
|
|
}
|
|
|
|
/*!
|
|
* @brief Application task function.
|
|
*
|
|
* This function runs the task for application.
|
|
*
|
|
* @return None.
|
|
*/
|
|
void VCOM_vRun(uint32* const u32Stat)
|
|
{
|
|
usb_status_t error = kStatus_USB_Error;
|
|
//if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
|
|
if (1 == s_cdcVcom.attach)
|
|
{
|
|
if ((0 != s_recvSize) && (0xFFFFFFFFU != s_recvSize))
|
|
{
|
|
DLL_tstRXDLLData* pstRXDLLData = DLL_pstGetRXBuffer(EH_VIO_USB);
|
|
puint8 pu8RXData = pstRXDLLData->u8Data;
|
|
pstRXDLLData->u8DataCount = s_recvSize;
|
|
memcpy(pstRXDLLData->u8Data, s_currRecvBuf, s_recvSize);
|
|
|
|
/* User Code */
|
|
DLL_vFrameRXCB(EH_VIO_USB, pu8RXData);
|
|
|
|
s_recvSize = 0;
|
|
}
|
|
|
|
if (s_sendSize)
|
|
{
|
|
uint32_t size = s_sendSize;
|
|
s_sendSize = 0;
|
|
|
|
error = USB_DeviceCdcAcmSend(s_cdcVcom.cdcAcmHandle, 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 == 1)
|
|
{
|
|
/* 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)
|
|
{
|
|
__ASM("NOP"); /* delay */
|
|
}
|
|
|
|
s_comOpen = 0;
|
|
}
|
|
usb_echo("Enter lowpower\r\n");
|
|
BOARD_DbgConsole_Deinit();
|
|
USB0->INTEN &= ~USB_INTEN_TOKDNEEN_MASK;
|
|
SMC_SetPowerModeVlps(SMC);
|
|
|
|
s_waitForDataReceive = 0;
|
|
USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK;
|
|
BOARD_DbgConsole_Init();
|
|
usb_echo("Exit lowpower\r\n");
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
SYSAPI_tenSVCResult VCOM_enInitBus(IOAPI_tenEHIOResource enEHIOResource, IOAPI_tstPortConfigCB* pstPortConfigCB)
|
|
{
|
|
SYSAPI_tenSVCResult enSVCResult = SYSAPI_enBadResource;
|
|
|
|
if (TRUE == DLL_boInitDLLChannel(enEHIOResource, pstPortConfigCB))
|
|
{
|
|
enSVCResult = SYSAPI_enOK;
|
|
}
|
|
|
|
return enSVCResult;
|
|
}
|
|
|
|
|
|
void VCOM_vTerminate(uint32* const u32Stat)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
void VCOMHA_vSend(IOAPI_tenEHIOResource enEHIOResource, puint8 pu8Data, uint32 u32TXByteCount)
|
|
{
|
|
usb_status_t error = kStatus_USB_Error;
|
|
|
|
if (0 != u32TXByteCount)
|
|
{
|
|
memcpy(s_currSendBuf, pu8Data, u32TXByteCount);
|
|
error = USB_DeviceCdcAcmSend(s_cdcVcom.cdcAcmHandle, USB_CDC_VCOM_BULK_IN_ENDPOINT, s_currSendBuf, u32TXByteCount);
|
|
|
|
if (error != kStatus_USB_Success)
|
|
{
|
|
/* Failure to send Data Handling code here */
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
#if USB_DEVICE_CONFIG_USE_TASK
|
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
|
|
// USB_DeviceEhciTaskFunction(s_cdcVcom.deviceHandle);
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)
|
|
// USB_DeviceKhciTaskFunction(s_cdcVcom.deviceHandle);
|
|
#endif
|
|
#if (defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
|
|
// USB_DeviceLpcIp3511TaskFunction(s_cdcVcom.deviceHandle);
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
|
|
// USB_DeviceLpcIp3511TaskFunction(s_cdcVcom.deviceHandle);
|
|
#endif
|
|
#endif
|
|
// }
|
|
//}
|