Files
TX/usb/device/source/lpcip3511/usb_device_lpcip3511.c

2490 lines
109 KiB
C

/*
* Copyright (c) 2016, Freescale Semiconductor, Inc.
* Copyright 2016 - 2017,2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "usb_device_config.h"
#include "usb.h"
#include "usb_device.h"
#include "fsl_device_registers.h"
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
((defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U)))
#include "usb_hsdcd.h"
#endif
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
#if ((defined FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE) && (FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE > 0U))
#include "usb_phy.h"
#endif
#endif
#if (((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)) || \
((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)))
#include "usb_device_dci.h"
#include "usb_device_lpcip3511.h"
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#define USB_LPC3511IP_INTSTAT_DEV_INT_MASK USBHSD_INTSTAT_DEV_INT_MASK
#define USB_LPC3511IP_INTSTAT_FRAME_INT_MASK USBHSD_INTSTAT_FRAME_INT_MASK
#define USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AO_MASK USBHSD_DEVCMDSTAT_INTONNAK_AO_MASK
#define USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AI_MASK USBHSD_DEVCMDSTAT_INTONNAK_AI_MASK
#define USB_LPC3511IP_DEVCMDSTAT_LPM_REWP_MASK USBHSD_DEVCMDSTAT_LPM_REWP_MASK
#define USB_LPC3511IP_DEVCMDSTAT_LPM_REWP_SHIFT USBHSD_DEVCMDSTAT_LPM_REWP_SHIFT
#define USB_LPC3511IP_DEVCMDSTAT_Speed_MASK USBHSD_DEVCMDSTAT_Speed_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DCON_MASK USBHSD_DEVCMDSTAT_DCON_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DEV_EN_MASK USBHSD_DEVCMDSTAT_DEV_EN_MASK
#define USB_LPC3511IP_DEVCMDSTAT_LPM_SUP_MASK USBHSD_DEVCMDSTAT_LPM_SUP_MASK
#define USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK USBHSD_DEVCMDSTAT_FORCE_NEEDCLK_MASK
#define USB_LPC3511IP_DEVCMDSTAT_LPM_SUS_MASK USBHSD_DEVCMDSTAT_LPM_SUS_MASK
#define USB_LPC3511IP_USB_LPM_HIRD_SW USBHSD_LPM_HIRD_SW
#define USB_LPC3511IP_DEVCMDSTAT_DEV_ADDR_MASK USBHSD_DEVCMDSTAT_DEV_ADDR_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DSUS_MASK USBHSD_DEVCMDSTAT_DSUS_MASK
#define USB_LPC3511IP_INFO_ERR_CODE_MASK USBHSD_INFO_ERR_CODE_MASK
#define USB_LPC3511IP_DEVCMDSTAT_SETUP_MASK USBHSD_DEVCMDSTAT_SETUP_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DRES_C_MASK USBHSD_DEVCMDSTAT_DRES_C_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DSUS_C_MASK USBHSD_DEVCMDSTAT_DSUS_C_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DCON_C_MASK USBHSD_DEVCMDSTAT_DCON_C_MASK
#define USB_LPC3511IP_DEVCMDSTAT_VBUS_DEBOUNCED_MASK USBHSD_DEVCMDSTAT_VBUS_DEBOUNCED_MASK
#define USB_LPC3511IP_INFO_FRAME_NR_MASK USBHSD_INFO_FRAME_NR_MASK
#define USB_LPC3511IP_INFO_FRAME_NR_SHIFT USBHSD_INFO_FRAME_NR_SHIFT
#else
#define USB_LPC3511IP_INTSTAT_DEV_INT_MASK USB_INTSTAT_DEV_INT_MASK
#define USB_LPC3511IP_INTSTAT_FRAME_INT_MASK USB_INTSTAT_FRAME_INT_MASK
#define USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AO_MASK USB_DEVCMDSTAT_INTONNAK_AO_MASK
#define USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AI_MASK USB_DEVCMDSTAT_INTONNAK_AI_MASK
#define USB_LPC3511IP_DEVCMDSTAT_LPM_REWP_MASK USB_DEVCMDSTAT_LPM_REWP_MASK
#define USB_LPC3511IP_DEVCMDSTAT_LPM_REWP_SHIFT USB_DEVCMDSTAT_LPM_REWP_SHIFT
#define USB_LPC3511IP_DEVCMDSTAT_DCON_MASK USB_DEVCMDSTAT_DCON_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DEV_EN_MASK USB_DEVCMDSTAT_DEV_EN_MASK
#define USB_LPC3511IP_DEVCMDSTAT_LPM_SUP_MASK USB_DEVCMDSTAT_LPM_SUP_MASK
#define USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK USB_DEVCMDSTAT_FORCE_NEEDCLK_MASK
#define USB_LPC3511IP_DEVCMDSTAT_LPM_SUP_MASK USB_DEVCMDSTAT_LPM_SUP_MASK
#define USB_LPC3511IP_DEVCMDSTAT_LPM_SUS_MASK USB_DEVCMDSTAT_LPM_SUS_MASK
#define USB_LPC3511IP_USB_LPM_HIRD_SW USB_LPM_HIRD_SW
#define USB_LPC3511IP_DEVCMDSTAT_DEV_ADDR_MASK USB_DEVCMDSTAT_DEV_ADDR_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DSUS_MASK USB_DEVCMDSTAT_DSUS_MASK
#define USB_LPC3511IP_INFO_ERR_CODE_MASK USB_INFO_ERR_CODE_MASK
#define USB_LPC3511IP_DEVCMDSTAT_SETUP_MASK USB_DEVCMDSTAT_SETUP_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DRES_C_MASK USB_DEVCMDSTAT_DRES_C_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DSUS_C_MASK USB_DEVCMDSTAT_DSUS_C_MASK
#define USB_LPC3511IP_DEVCMDSTAT_DCON_C_MASK USB_DEVCMDSTAT_DCON_C_MASK
#define USB_LPC3511IP_DEVCMDSTAT_VBUS_DEBOUNCED_MASK USB_DEVCMDSTAT_VBUSDEBOUNCED_MASK
#define USB_LPC3511IP_INFO_FRAME_NR_MASK USB_INFO_FRAME_NR_MASK
#define USB_LPC3511IP_INFO_FRAME_NR_SHIFT USB_INFO_FRAME_NR_SHIFT
#endif
#define USB_LPC3511IP_USB_LPM_ADPPROBE_MASK (0x00100000u)
/*******************************************************************************
* Definitions
******************************************************************************/
/* on Aruba IP3511 (USB0 FS), there are 8 physical EPs, on IP3511 HS (USB1 FS), there are 10 physical EPs. */
#define USB_LPC3511IP_MAX_PHY_ENDPOINT_MASK (0xFFFFu)
/*! @brief endpoint command status, buffer address offset */
#define USB_LPC3511IPHS_ENDPOINT_BUFFER_ADDRESS_OFFSET_MASK (0x000007FFu)
#define USB_LPC3511IPHS_ENDPOINT_BUFFER_NBYTES_SHIFT (11)
#define USB_LPC3511IPHS_ENDPOINT_BUFFER_NBYTES_MASK (0x03FFF800u)
#define USB_LPC3511IPFS_ENDPOINT_BUFFER_ADDRESS_OFFSET_MASK (0x0000FFFFu)
#define USB_LPC3511IPFS_ENDPOINT_BUFFER_NBYTES_SHIFT (16)
#define USB_LPC3511IPFS_ENDPOINT_BUFFER_NBYTES_MASK (0x03FF0000u)
#define USB_LPC3511IP_ENDPOINT_ENDPOINT_TYPE_MASK (0x01UL << 26)
#define USB_LPC3511IP_ENDPOINT_RFTV_MASK (0x01UL << 27)
#define USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK (0x01UL << 28)
#define USB_LPC3511IP_ENDPOINT_STALL_MASK (0x01UL << 29)
#define USB_LPC3511IP_ENDPOINT_STALL_SHIFT (29)
#define USB_LPC3511IP_ENDPOINT_DISABLE_MASK (0x01UL << 30)
#define USB_LPC3511IP_ENDPOINT_ACTIVE_MASK (0x01UL << 31)
#define USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT (26)
#define USB_LPC3511IP_DEVCMDSTAT_INTERRUPT_WC_MASK (0x0F000000u)
#define USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND(lpcState, index, odd, value) \
*((volatile uint32_t *)(((uint32_t)((lpcState)->epCommandStatusList)) | ((uint32_t)(index) << 3) | \
((((uint32_t)(odd)) & 1UL) << 2U))) &= (value)
/*! @brief Set endpoint command/status value */
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#define USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(lpcState, index, odd, value, NBytes, address) \
\
*((volatile uint32_t *)(((uint32_t)((lpcState)->epCommandStatusList)) | ((uint32_t)(index) << 3) | \
(((((uint32_t)(odd)) & 1UL)) << 2U))) = \
((0U != lpc3511IpState->controllerSpeed) ? \
\
((uint32_t)(value) | ((uint32_t)(NBytes) << USB_LPC3511IPHS_ENDPOINT_BUFFER_NBYTES_SHIFT) | \
(((uint32_t)(address) >> 6) & USB_LPC3511IPHS_ENDPOINT_BUFFER_ADDRESS_OFFSET_MASK)) : \
\
((uint32_t)(value) | ((uint32_t)(NBytes) << USB_LPC3511IPFS_ENDPOINT_BUFFER_NBYTES_SHIFT) | \
(((uint32_t)(address) >> 6) & USB_LPC3511IPFS_ENDPOINT_BUFFER_ADDRESS_OFFSET_MASK)))
#else
#define USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(lpcState, index, odd, value, NBytes, address) \
\
*((volatile uint32_t *)(((uint32_t)((lpcState)->epCommandStatusList)) | ((uint32_t)(index) << 3) | \
(((((uint32_t)(odd)) & 1U)) << 2U))) = \
((uint32_t)(value) | ((uint32_t)(NBytes) << USB_LPC3511IPFS_ENDPOINT_BUFFER_NBYTES_SHIFT) | \
(((uint32_t)(address) >> 6) & USB_LPC3511IPFS_ENDPOINT_BUFFER_ADDRESS_OFFSET_MASK))
#endif
#define USB_LPC3511IP_ENDPOINT_DES_INDEX(endpoint) \
(((((endpoint)) & 0x0FU) << 1) + \
((0U != ((endpoint)&USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK)) ? (1U) : (0U)))
#define USB_LPC3511IP_GET_MULTIPLE_OF_64(n) ((((uint32_t)n) + 63U) & 0xFFFFFFC0U)
/*******************************************************************************
* Prototypes
******************************************************************************/
static usb_status_t USB_DeviceLpc3511IpTransaction(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
usb_device_lpc3511ip_endpoint_state_struct_t *epState,
uint8_t endpointIndex);
static usb_status_t USB_DeviceLpc3511IpControlPreSetDeviceAddress(usb_device_controller_handle controllerHandle,
void *param);
/*******************************************************************************
* Variables
******************************************************************************/
/* define the reserved buffer for endpoint max packet copy */
#define SETUP_TRANSFER_DATA_OFFSET (0U)
#define CONTROL_TRANSFER_DATA_OFFSET ((USB_DATA_ALIGN_SIZE_MULTIPLE(8U) >> 2))
#define ZERO_TRANSFER_DATA_OFFSET ((USB_DATA_ALIGN_SIZE_MULTIPLE(8U) >> 2) + (USB_DATA_ALIGN_SIZE_MULTIPLE(64U) >> 2))
#define RESERVED_EP_DATA_OFFSET \
((USB_DATA_ALIGN_SIZE_MULTIPLE(8U) >> 2) + (USB_DATA_ALIGN_SIZE_MULTIPLE(64U) >> 2) + \
(USB_DATA_ALIGN_SIZE_MULTIPLE(4U) >> 2))
#if defined(USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY) && (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY)
USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static uint32_t
s_SetupAndEpReservedData[USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY]
[USB_DATA_ALIGN_SIZE_MULTIPLE((USB_DEVICE_IP3511_ENDPOINT_RESERVED_BUFFER_SIZE >> 2)) +
RESERVED_EP_DATA_OFFSET];
#else
USB_GLOBAL USB_RAM_ADDRESS_ALIGNMENT(USB_DATA_ALIGN_SIZE) static uint32_t
s_SetupAndEpReservedData[USB_DEVICE_CONFIG_LPCIP3511FS + USB_DEVICE_CONFIG_LPCIP3511HS][RESERVED_EP_DATA_OFFSET];
#endif
static usb_device_lpc3511ip_state_struct_t
s_UsbDeviceLpc3511IpState[USB_DEVICE_CONFIG_LPCIP3511FS + USB_DEVICE_CONFIG_LPCIP3511HS];
/* LPC3511IP controller driver instances and endpoint command/status list, EPLISTSTART's value is the buffer pointer. */
#if ((USB_DEVICE_CONFIG_LPCIP3511FS + USB_DEVICE_CONFIG_LPCIP3511HS) == 1U)
USB_CONTROLLER_DATA USB_RAM_ADDRESS_ALIGNMENT(256) static uint32_t
s_EpCommandStatusList1[((USB_DEVICE_IP3511_ENDPOINTS_NUM)) * 4];
#define LPC_CONTROLLER_ENDPOINT_LIST_ARRAY \
{ \
&s_EpCommandStatusList1[0] \
}
#elif ((USB_DEVICE_CONFIG_LPCIP3511FS + USB_DEVICE_CONFIG_LPCIP3511HS) == 2U)
USB_CONTROLLER_DATA USB_RAM_ADDRESS_ALIGNMENT(256) static uint32_t
s_EpCommandStatusList1[(USB_DEVICE_IP3511_ENDPOINTS_NUM)*4];
USB_CONTROLLER_DATA USB_RAM_ADDRESS_ALIGNMENT(256) static uint32_t
s_EpCommandStatusList2[(USB_DEVICE_IP3511_ENDPOINTS_NUM)*4];
#define LPC_CONTROLLER_ENDPOINT_LIST_ARRAY \
{ \
&s_EpCommandStatusList1[0], &s_EpCommandStatusList2[0] \
}
#else
#error "increase the instance count."
#endif
#if (defined USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY)
#if (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY == (USB_DEVICE_CONFIG_LPCIP3511FS + USB_DEVICE_CONFIG_LPCIP3511HS))
#define USB_DEVICE_IP3511_ALL_IP_SUPPORT_RESERVED_BUFFER 1U
#elif ((USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY == USB_DEVICE_CONFIG_LPCIP3511FS) && \
(!USB_DEVICE_CONFIG_LPCIP3511HS))
#define USB_DEVICE_IP3511_ALL_IP_SUPPORT_RESERVED_BUFFER 1U
#elif ((USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY == USB_DEVICE_CONFIG_LPCIP3511HS) && \
(!USB_DEVICE_CONFIG_LPCIP3511FS))
#define USB_DEVICE_IP3511_ALL_IP_SUPPORT_RESERVED_BUFFER 1U
#else
#define USB_DEVICE_IP3511_ALL_IP_SUPPORT_RESERVED_BUFFER 0U
#endif
#else
#define USB_DEVICE_IP3511_ALL_IP_SUPPORT_RESERVED_BUFFER 0U
#endif
/*******************************************************************************
* Code
******************************************************************************/
#if (defined USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY) && (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY)
static inline uint8_t USB_DeviceLpcIp3511MaxPacketNeedCopy(usb_device_lpc3511ip_state_struct_t *lpc3511IpState)
{
#if (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY == (USB_DEVICE_CONFIG_LPCIP3511HS + USB_DEVICE_CONFIG_LPCIP3511FS))
return 1U;
#elif (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY == USB_DEVICE_CONFIG_LPCIP3511HS)
return (lpc3511IpState->controllerSpeed);
#elif (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY == USB_DEVICE_CONFIG_LPCIP3511FS)
#if (defined USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS)
if (0U != lpc3511IpState->controllerSpeed)
{
return 0U;
}
else
{
return 1U;
}
#else
return 1U;
#endif
#endif
}
static uint8_t *USB_DeviceLpcIp3511MallocMaxPacketBuffer(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
uint32_t multile64)
{
uint32_t bitsIndex;
uint32_t numIndex;
OSA_SR_ALLOC();
multile64 = ((multile64 + 63U) / 64U);
bitsIndex = 0U;
OSA_ENTER_CRITICAL();
do
{
numIndex = 0U;
for (; numIndex < multile64; ++numIndex)
{
if (bitsIndex >= USB_DEVICE_IP3511_BITS_FOR_RESERVED_BUFFER)
{
OSA_EXIT_CRITICAL();
return NULL; /* fail */
}
if (0U != (lpc3511IpState->epReservedBufferBits[(bitsIndex / 8U)] &
(uint8_t)(0x01U << (bitsIndex & 0x00000007U)))) /* has allocated */
{
bitsIndex++;
break;
}
bitsIndex++;
}
} while (numIndex < multile64);
if (numIndex >= multile64)
{
/* set the bits */
for (numIndex = 0U; numIndex < multile64; ++numIndex)
{
lpc3511IpState->epReservedBufferBits[((bitsIndex - multile64 + numIndex) / 8U)] |=
(uint8_t)(0x01U << ((bitsIndex - multile64 + numIndex) & 0x00000007U));
}
OSA_EXIT_CRITICAL();
return lpc3511IpState->epReservedBuffer + ((bitsIndex - multile64) * 64U);
}
else
{
OSA_EXIT_CRITICAL();
return NULL;
}
}
static void USB_DeviceLpcIp3511ReleaseMaxPacketBuffer(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
uint8_t *buffer,
uint32_t bufferSize)
{
uint32_t bitsIndex;
int32_t temp;
uint8_t bitsNum;
OSA_SR_ALLOC();
if ((buffer < lpc3511IpState->epReservedBuffer) ||
(buffer >= (lpc3511IpState->epReservedBuffer + USB_DEVICE_IP3511_ENDPOINT_RESERVED_BUFFER_SIZE)))
{
return;
}
/*misra 10.8*/
temp = ((buffer - lpc3511IpState->epReservedBuffer) / 64);
bitsIndex = (uint32_t)temp;
OSA_ENTER_CRITICAL();
for (bitsNum = 0; bitsNum < ((bufferSize + 63U) / 64U); ++bitsNum)
{
lpc3511IpState->epReservedBufferBits[((bitsIndex + bitsNum) / 8U)] &=
(uint8_t)(~(0x01U << ((bitsIndex + bitsNum) & 0x00000007U))); /* clear the bit */
}
OSA_EXIT_CRITICAL();
}
#endif
static usb_device_lpc3511ip_endpoint_state_struct_t *USB_DeviceLpc3511IpGetEndpointStateStruct(
usb_device_lpc3511ip_state_struct_t *lpc3511IpState, uint8_t endpointIndex)
{
if (endpointIndex <= ((uint32_t)USB_DEVICE_IP3511_ENDPOINTS_NUM * 2U))
{
return &(lpc3511IpState->endpointState[endpointIndex]);
}
return NULL;
}
/*!
* @brief Write the command/status entry to start a transfer.
*
* The function is used to start a transfer by writing the command/status entry.
*
* @param lpc3511IpState Pointer of the controller state structure.
* @param endpoint Endpoint number.
* @param direction The direction of the endpoint, 0U - USB_OUT, 1U - USB_IN.
* @param buffer The memory address to save the received data, or the memory address to hold the data need to
* be sent.
* @param length The length of the data.
*
* @return A USB error code or kStatus_USB_Success.
*/
static usb_status_t USB_DeviceLpc3511IpEndpointPrime(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
usb_device_lpc3511ip_endpoint_state_struct_t *epState,
uint8_t endpointIndex,
uint8_t *buffer,
uint32_t length)
{
uint8_t odd;
OSA_SR_ALLOC();
/* Enter critical */
OSA_ENTER_CRITICAL();
/* Flag the endpoint is busy. */
epState->stateUnion.stateBitField.transferring = 1U;
/* update the endpoint status */
epState->transferPrimedLength += length;
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
if ((endpointIndex >> 1U) != USB_ENDPOINT_CONTROL)
{
odd = (uint8_t)epState->stateUnion.stateBitField.producerOdd;
epState->stateUnion.stateBitField.doubleBufferBusy++;
epState->stateUnion.stateBitField.producerOdd ^= 1U;
}
else
#endif
{
odd = 0U;
}
epState->epBufferStatusUnion[odd].epBufferStatusField.transactionLength = (uint16_t)length;
/* when receive the zero length packet, the controller will set 4 bytes buffer as 0x00 */
if (buffer == NULL)
{
buffer = lpc3511IpState->zeroTransactionData;
}
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(
lpc3511IpState, endpointIndex, odd,
(epState->stateUnion.stateBitField.epControlDefault << USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT) |
USB_LPC3511IP_ENDPOINT_ACTIVE_MASK,
length, (uint32_t)buffer);
if (0U != (epState->stateUnion.stateBitField.epControlDefault &
((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT)))
{
epState->stateUnion.stateBitField.epControlDefault &=
(~((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT));
}
/* Exit critical */
OSA_EXIT_CRITICAL();
return kStatus_USB_Success;
}
#if 0
/*!
* @brief Prime a next setup transfer.
*
* The function is used to prime a buffer in control out pipe to wait for receiving the host's setup packet.
*
* @param lpc3511IpState Pointer of the controller state structure.
*
*/
static void USB_DeviceLpc3511IpPrimeNextSetup(usb_device_lpc3511ip_state_struct_t *lpc3511IpState)
{
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(lpc3511IpState, 0, 1, 0, 8, lpc3511IpState->setupData);
}
#endif
/*!
* @brief reset ip3511.
*
* @param lpc3511IpState Pointer of the controller state structure.
*
*/
static void USB_DeviceLpc3511IpSetDefaultState(usb_device_lpc3511ip_state_struct_t *lpc3511IpState)
{
uint32_t index = 0;
uint8_t usbAddress;
usb_status_t error = kStatus_USB_Error;
/* zero the command/status list buffer and disable all endpoints */
for (index = 0; index < 4U; ++index)
{
lpc3511IpState->epCommandStatusList[index] = 0x00000000U;
}
for (index = 4U; index < (uint32_t)USB_DEVICE_IP3511_ENDPOINTS_NUM * 4U; ++index)
{
lpc3511IpState->epCommandStatusList[index] = USB_LPC3511IP_ENDPOINT_DISABLE_MASK;
}
/* set address as 0 */
usbAddress = 0U;
error = USB_DeviceLpc3511IpControlPreSetDeviceAddress(lpc3511IpState, &usbAddress);
if (kStatus_USB_Success == error)
{
/*no action, just for misra4.7*/
}
lpc3511IpState->registerBase->EPLISTSTART = (uint32_t)lpc3511IpState->epCommandStatusList;
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
if (0U != lpc3511IpState->controllerSpeed)
{
if ((USBHSD_DATABUFSTART_DA_BUF_MASK & (uint32_t)lpc3511IpState->setupData) !=
lpc3511IpState->registerBase->DATABUFSTART)
{
/* please use the dedicated ram */
}
}
else
#endif
{
/* all data buffer is in the same 4M range with this setup data buffer */
lpc3511IpState->registerBase->DATABUFSTART = (uint32_t)lpc3511IpState->setupData;
}
/* reset registers */
lpc3511IpState->registerBase->EPINUSE = 0x0;
lpc3511IpState->registerBase->EPSKIP = 0x0;
/* enable all double-buffer */
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
lpc3511IpState->registerBase->EPBUFCFG = USB_LPC3511IP_MAX_PHY_ENDPOINT_MASK;
#else
lpc3511IpState->registerBase->EPBUFCFG = 0x00000000U;
#endif
/* clear interrupts
* don't clear DEV_INT because the vbus valid interrupt may occurs with keeping usb connected and reseting device.
*/
lpc3511IpState->registerBase->INTSTAT =
(USB_LPC3511IP_INTSTAT_FRAME_INT_MASK | USB_LPC3511IP_MAX_PHY_ENDPOINT_MASK);
/* enable interrupts */
lpc3511IpState->registerBase->INTEN = USB_LPC3511IP_INTSTAT_DEV_INT_MASK | USB_LPC3511IP_MAX_PHY_ENDPOINT_MASK;
/* Clear reset flag */
lpc3511IpState->isResetting = 0U;
}
/* Config and Enable endpoint */
static usb_status_t USB_DeviceLpc3511IpEndpointInit(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
usb_device_endpoint_init_struct_t *epInit)
{
uint8_t endpointIndex = USB_LPC3511IP_ENDPOINT_DES_INDEX(epInit->endpointAddress);
usb_device_lpc3511ip_endpoint_state_struct_t *epState =
USB_DeviceLpc3511IpGetEndpointStateStruct(lpc3511IpState, endpointIndex);
uint16_t maxPacketSize = epInit->maxPacketSize;
uint32_t allocateLength;
/* clear the endpoint status bits */
epState->stateUnion.state = 0x00000000U;
lpc3511IpState->registerBase->EPINUSE &= (~((uint32_t)(0x01UL << endpointIndex)));
/* Save the max packet size of the endpoint */
epState->stateUnion.stateBitField.maxPacketSize = maxPacketSize;
/* Set the ZLT field */
epState->stateUnion.stateBitField.zlt = epInit->zlt;
epState->stateUnion.stateBitField.endpointType = epInit->transferType;
/* get the endpoint default control value */
if (USB_ENDPOINT_ISOCHRONOUS == epInit->transferType)
{
epState->stateUnion.stateBitField.epControlDefault =
(USB_LPC3511IP_ENDPOINT_ENDPOINT_TYPE_MASK >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT);
}
#if (defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U))
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
else if (
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
(0U == (lpc3511IpState->hsInterruptIssue)) &&
#endif
(0U != lpc3511IpState->controllerSpeed) && (USB_ENDPOINT_INTERRUPT == epInit->transferType))
{
epState->stateUnion.stateBitField.epControlDefault =
((USB_LPC3511IP_ENDPOINT_ENDPOINT_TYPE_MASK | USB_LPC3511IP_ENDPOINT_RFTV_MASK) >>
USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT);
}
#endif
#endif
else
{
epState->stateUnion.stateBitField.epControlDefault = 0x00U;
}
/* set the command/status value */
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(
lpc3511IpState, endpointIndex, 0U,
(epState->stateUnion.stateBitField.epControlDefault << USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT), 0U, 0U);
if ((epInit->endpointAddress & USB_ENDPOINT_NUMBER_MASK) == USB_CONTROL_ENDPOINT)
{
if (0U == (epInit->endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
{
/* Prime setup packet when the endpoint is control out endpoint. */
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(lpc3511IpState, 0U, 1U, 0U, 0U, (uint32_t)lpc3511IpState->setupData);
}
}
else
{
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(
lpc3511IpState, endpointIndex, 1U,
(epState->stateUnion.stateBitField.epControlDefault << USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT), 0U,
0U);
}
if ((endpointIndex >> 1) != USB_CONTROL_ENDPOINT)
{
/* toggle reset for the toggle */
epState->stateUnion.stateBitField.epControlDefault |=
((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT);
}
epState->epPacketBuffer = NULL;
if ((endpointIndex >> 1U) == USB_CONTROL_ENDPOINT) /* control endpoint */
{
epState->epPacketBuffer = lpc3511IpState->controlData;
}
#if (defined USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY) && (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY)
else
{
if (0U != USB_DeviceLpcIp3511MaxPacketNeedCopy(lpc3511IpState))
{
#if ((defined(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX)) && \
(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX > 0U))
if ((USB_ENDPOINT_BULK == epInit->transferType) && ((endpointIndex & 0x01U) == 0x00U))
{
allocateLength = USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX;
}
else
{
allocateLength = USB_LPC3511IP_GET_MULTIPLE_OF_64(maxPacketSize);
}
#else
allocateLength = USB_LPC3511IP_GET_MULTIPLE_OF_64(maxPacketSize);
#endif
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
allocateLength *= 2U;
#endif
uint8_t *maxPacketBuffer = USB_DeviceLpcIp3511MallocMaxPacketBuffer(lpc3511IpState, allocateLength);
if (maxPacketBuffer == NULL)
{
return kStatus_USB_AllocFail;
}
epState->epPacketBuffer = maxPacketBuffer;
}
}
#endif
return kStatus_USB_Success;
}
/*!
* @brief De-initialize a specified endpoint.
*
* The function is used to de-initialize a specified endpoint.
* Current transfer of the endpoint will be canceled and the specified endpoint will be disabled.
*
* @param lpc3511IpState Pointer of the controller state structure.
* @param ep The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
*
* @return A USB error code or kStatus_USB_Success.
*/
static usb_status_t USB_DeviceLpc3511IpEndpointDeinit(usb_device_lpc3511ip_state_struct_t *lpc3511IpState, uint8_t ep)
{
uint8_t endpointIndex = USB_LPC3511IP_ENDPOINT_DES_INDEX(ep);
usb_device_lpc3511ip_endpoint_state_struct_t *epState =
USB_DeviceLpc3511IpGetEndpointStateStruct(lpc3511IpState, endpointIndex);
/* Cancel the transfer of the endpoint */
(void)USB_DeviceLpc3511IpCancel(lpc3511IpState, ep);
#if (defined USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY) && (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY)
if (0U != USB_DeviceLpcIp3511MaxPacketNeedCopy(lpc3511IpState))
{
if ((endpointIndex >> 1U) != USB_CONTROL_ENDPOINT) /* control endpoint */
{
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
#if ((defined(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX)) && \
(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX > 0U))
if ((USB_ENDPOINT_BULK == epState->stateUnion.stateBitField.endpointType) &&
((endpointIndex & 0x01U) == 0x00U))
{
USB_DeviceLpcIp3511ReleaseMaxPacketBuffer(
lpc3511IpState, epState->epPacketBuffer,
USB_LPC3511IP_GET_MULTIPLE_OF_64(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX * 2U));
}
else
{
USB_DeviceLpcIp3511ReleaseMaxPacketBuffer(
lpc3511IpState, epState->epPacketBuffer,
USB_LPC3511IP_GET_MULTIPLE_OF_64(epState->stateUnion.stateBitField.maxPacketSize) * 2U);
}
#else
USB_DeviceLpcIp3511ReleaseMaxPacketBuffer(
lpc3511IpState, epState->epPacketBuffer,
USB_LPC3511IP_GET_MULTIPLE_OF_64(epState->stateUnion.stateBitField.maxPacketSize) * 2U);
#endif
#else
USB_DeviceLpcIp3511ReleaseMaxPacketBuffer(lpc3511IpState, epState->epPacketBuffer,
epState->stateUnion.stateBitField.maxPacketSize);
#endif
}
epState->epPacketBuffer = NULL;
}
#endif
/* reset the double buffer */
lpc3511IpState->registerBase->EPINUSE &= ~((uint32_t)(0x01UL << endpointIndex));
/* Disable the endpoint */
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(lpc3511IpState, endpointIndex, 0U, USB_LPC3511IP_ENDPOINT_DISABLE_MASK, 0U, 0U);
/* Clear the max packet size */
epState->stateUnion.stateBitField.maxPacketSize = 0U;
return kStatus_USB_Success;
}
/*!
* @brief Stall a specified endpoint.
*
* The function is used to stall a specified endpoint.
* Current transfer of the endpoint will be canceled and the specified endpoint will be stalled.
*
* @param lpc3511IpState Pointer of the controller state structure.
* @param ep The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
*
* @return A USB error code or kStatus_USB_Success.
*/
static usb_status_t USB_DeviceLpc3511IpEndpointStall(usb_device_lpc3511ip_state_struct_t *lpc3511IpState, uint8_t ep)
{
uint8_t endpointIndex = USB_LPC3511IP_ENDPOINT_DES_INDEX(ep);
usb_device_lpc3511ip_endpoint_state_struct_t *epState =
USB_DeviceLpc3511IpGetEndpointStateStruct(lpc3511IpState, endpointIndex);
/* Set endpoint stall flag. */
epState->stateUnion.stateBitField.stalled = 1U;
/* lpc3511IpState->registerBase->EPINUSE &= (~(0x01u << endpointIndex)); */
/* stall the endpoint */
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(lpc3511IpState, endpointIndex, 0U, USB_LPC3511IP_ENDPOINT_STALL_MASK, 0U, 0U);
if ((ep & USB_ENDPOINT_NUMBER_MASK) != USB_CONTROL_ENDPOINT)
{
/* toggle reset for the toggle */
epState->stateUnion.stateBitField.epControlDefault |=
((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT);
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(lpc3511IpState, endpointIndex, 1U, USB_LPC3511IP_ENDPOINT_STALL_MASK, 0U,
0U);
}
#if (defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U)) && \
(!(defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK)))
#else
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
if (0U != lpc3511IpState->hsInterruptIssue)
{
#endif
if ((0U != lpc3511IpState->controllerSpeed) &&
(USB_ENDPOINT_INTERRUPT == epState->stateUnion.stateBitField.endpointType))
{
lpc3511IpState->registerBase->DEVCMDSTAT |=
(USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AO_MASK | USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AI_MASK);
epState->stateUnion.stateBitField.epControlDefault &=
(~((USB_LPC3511IP_ENDPOINT_ENDPOINT_TYPE_MASK | USB_LPC3511IP_ENDPOINT_RFTV_MASK) >>
USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT));
}
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
}
#endif
#endif
#endif
/* cancel the transfer in the endpoint */
(void)USB_DeviceLpc3511IpCancel(lpc3511IpState, ep);
return kStatus_USB_Success;
}
/*!
* @brief Un-stall a specified endpoint.
*
* The function is used to un-stall a specified endpoint.
* Current transfer of the endpoint will be canceled and the specified endpoint will be un-stalled.
*
* @param lpc3511IpState Pointer of the controller state structure.
* @param ep The endpoint address, Bit7, 0U - USB_OUT, 1U - USB_IN.
*
* @return A USB error code or kStatus_USB_Success.
*/
static usb_status_t USB_DeviceLpc3511IpEndpointUnstall(usb_device_lpc3511ip_state_struct_t *lpc3511IpState, uint8_t ep)
{
uint8_t endpointIndex = USB_LPC3511IP_ENDPOINT_DES_INDEX(ep);
usb_device_lpc3511ip_endpoint_state_struct_t *epState =
USB_DeviceLpc3511IpGetEndpointStateStruct(lpc3511IpState, endpointIndex);
/* Clear the endpoint stall state, the hardware resets the endpoint
* toggle to one for both directions when a setup token is received */
epState->stateUnion.stateBitField.stalled = 0U;
/* unstall the endpoint for double buffers */
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND(lpc3511IpState, endpointIndex, 0, (~USB_LPC3511IP_ENDPOINT_STALL_MASK));
if ((ep & USB_ENDPOINT_NUMBER_MASK) != USB_CONTROL_ENDPOINT)
{
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND(lpc3511IpState, endpointIndex, 1, (~USB_LPC3511IP_ENDPOINT_STALL_MASK));
/* toggle reset for the toggle */
epState->stateUnion.stateBitField.epControlDefault |=
((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT);
#if (defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U)) && \
(!(defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK)))
#else
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
if (0U != lpc3511IpState->hsInterruptIssue)
{
#endif
if ((0U != lpc3511IpState->controllerSpeed) &&
(USB_ENDPOINT_INTERRUPT == epState->stateUnion.stateBitField.endpointType))
{
epState->stateUnion.stateBitField.epControlDefault &=
(~((USB_LPC3511IP_ENDPOINT_ENDPOINT_TYPE_MASK | USB_LPC3511IP_ENDPOINT_RFTV_MASK) >>
USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT));
}
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
}
#endif
#endif
#endif
}
if (0U != epState->stateUnion.stateBitField.stallPrimed)
{
epState->stateUnion.stateBitField.stallPrimed = 0u;
(void)USB_DeviceLpc3511IpTransaction(lpc3511IpState, epState, endpointIndex);
}
/* cancel the transfer in the endpoint */
(void)USB_DeviceLpc3511IpCancel(lpc3511IpState, ep);
return kStatus_USB_Success;
}
#if ((defined(USB_DEVICE_CONFIG_LOW_POWER_MODE)) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
/*!
* @brief Un-stall a specified endpoint.
*
* The function is used to un-stall a specified endpoint.
* Current transfer of the endpoint will be canceled and the specified endpoint will be un-stalled.
*
* @param lpc3511IpState Pointer of the controller state structure.
*
* @return A USB error code or kStatus_USB_Success.
*/
static usb_status_t USB_DeviceLpc3511IpInterruptSuspend(usb_device_lpc3511ip_state_struct_t *lpc3511IpState)
{
usb_device_callback_message_struct_t message;
message.buffer = (uint8_t *)NULL;
message.code = (uint8_t)kUSB_DeviceNotifySuspend;
message.length = 0U;
message.isSetup = 0U;
/* Notify up layer the USB suspend signal detected. */
(void)USB_DeviceNotificationTrigger(lpc3511IpState->deviceHandle, &message);
return kStatus_USB_Success;
}
/*!
* @brief Un-stall a specified endpoint.
*
* The function is used to un-stall a specified endpoint.
* Current transfer of the endpoint will be canceled and the specified endpoint will be un-stalled.
*
* @param lpc3511IpState Pointer of the controller state structure.
*
* @return A USB error code or kStatus_USB_Success.
*/
static usb_status_t USB_DeviceLpc3511IpInterruptResume(usb_device_lpc3511ip_state_struct_t *lpc3511IpState)
{
usb_device_callback_message_struct_t message;
message.buffer = (uint8_t *)NULL;
message.code = (uint8_t)kUSB_DeviceNotifyResume;
message.length = 0U;
message.isSetup = 0U;
/* Notify up layer the USB suspend signal detected. */
(void)USB_DeviceNotificationTrigger(lpc3511IpState->deviceHandle, &message);
return kStatus_USB_Success;
}
#if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
/*!
* @brief Un-stall a specified endpoint.
*
* The function is used to un-stall a specified endpoint.
* Current transfer of the endpoint will be canceled and the specified endpoint will be un-stalled.
*
* @param lpc3511IpState Pointer of the controller state structure.
*
* @return A USB error code or kStatus_USB_Success.
*/
static usb_status_t USB_DeviceLpc3511IpInterruptLPMSleep(usb_device_lpc3511ip_state_struct_t *lpc3511IpState)
{
usb_device_callback_message_struct_t message;
message.buffer = &lpc3511IpState->lpmRemoteWakeUp;
message.code = (uint8_t)kUSB_DeviceNotifyLPMSleep;
message.length = 0U;
message.isSetup = 0U;
lpc3511IpState->lpmRemoteWakeUp =
(uint8_t)((lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_LPM_REWP_MASK) >>
USB_LPC3511IP_DEVCMDSTAT_LPM_REWP_SHIFT);
/* Notify up layer the USB suspend signal detected. */
(void)USB_DeviceNotificationTrigger(lpc3511IpState->deviceHandle, &message);
return kStatus_USB_Success;
}
#endif
#endif
/* need copy the data before the trasaction buffer is used again */
static void USB_DeviceLpc3511IpDoPreviousTransactionMemcpy(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
usb_device_lpc3511ip_endpoint_state_struct_t *epState,
uint32_t length,
uint8_t endpointIndex,
uint8_t odd)
{
uint8_t *destBuffer;
uint8_t *sourceBuffer;
#if ((defined(USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY)) && (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY > 0U))
/*control out doesn't support buffer toggle*/
if (0U == endpointIndex)
{
odd = 0u;
}
#if USB_DEVICE_IP3511_ALL_IP_SUPPORT_RESERVED_BUFFER
if ((0U != epState->epBufferStatusUnion[odd].epBufferStatusField.epPacketCopyed) && (length > 0U) &&
((endpointIndex & 0x01U) == 0U))
#else
if ((0U != USB_DeviceLpcIp3511MaxPacketNeedCopy(lpc3511IpState)) &&
(0U != epState->epBufferStatusUnion[odd].epBufferStatusField.epPacketCopyed) && (length > 0U) &&
((endpointIndex & 0x01U) == 0U))
#endif
#else
/* control data buffer align is used */
if (((endpointIndex >> 1U) == USB_CONTROL_ENDPOINT) &&
(epState->epBufferStatusUnion[odd].epBufferStatusField.epPacketCopyed) && (length > 0U) &&
((endpointIndex & 0x01u) == 0U))
#endif
{
#if ((defined(USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER)) && (USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER > 0U))
destBuffer = &(epState->transferBuffer[epState->transferDone - length]);
#else
destBuffer = &(epState->transferBuffer[epState->transferDone]);
#endif
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
#if (defined USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX) && \
(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX)
if ((USB_ENDPOINT_BULK == epState->stateUnion.stateBitField.endpointType) && ((endpointIndex & 0x01U) == 0x00U))
{
sourceBuffer = epState->epPacketBuffer + odd * USB_LPC3511IP_GET_MULTIPLE_OF_64(
USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX);
}
else
{
sourceBuffer = epState->epPacketBuffer +
odd * USB_LPC3511IP_GET_MULTIPLE_OF_64(epState->stateUnion.stateBitField.maxPacketSize);
}
#else
sourceBuffer = epState->epPacketBuffer +
odd * USB_LPC3511IP_GET_MULTIPLE_OF_64(epState->stateUnion.stateBitField.maxPacketSize);
#endif
#else
sourceBuffer = epState->epPacketBuffer;
#endif
(void)memcpy(destBuffer, sourceBuffer, length);
}
}
static uint32_t USB_DeviceLpc3511IpTokenUpdate(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
usb_device_lpc3511ip_endpoint_state_struct_t *epState,
uint8_t endpointIndex,
uint8_t changedOdd)
{
uint32_t length;
uint8_t odd;
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
if (0U != changedOdd)
{
odd = (uint8_t)epState->stateUnion.stateBitField.consumerOdd;
epState->stateUnion.stateBitField.consumerOdd ^= 1U;
epState->stateUnion.stateBitField.doubleBufferBusy--;
}
else
#endif
{
odd = 0U;
}
/* for OUT packet, compute the actual packet size. */
#if ((defined(FSL_FEATURE_USB_VERSION) && (FSL_FEATURE_USB_VERSION >= 200U)) || \
(defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U)))
#else
if ((endpointIndex & 0x01U) == 0x00u) /* OUT */
#endif
{
/* get the transaction length */
length = *(lpc3511IpState->epCommandStatusList + endpointIndex * 2U + odd);
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
if (0U != lpc3511IpState->controllerSpeed)
{
length =
(length & USB_LPC3511IPHS_ENDPOINT_BUFFER_NBYTES_MASK) >> USB_LPC3511IPHS_ENDPOINT_BUFFER_NBYTES_SHIFT;
}
else
#endif
{
length =
(length & USB_LPC3511IPFS_ENDPOINT_BUFFER_NBYTES_MASK) >> USB_LPC3511IPFS_ENDPOINT_BUFFER_NBYTES_SHIFT;
}
length = epState->epBufferStatusUnion[odd].epBufferStatusField.transactionLength - length;
}
#if ((defined(FSL_FEATURE_USB_VERSION) && (FSL_FEATURE_USB_VERSION >= 200U)) || \
(defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U)))
#else
else /* for IN packet, if there is no error, the packet lenght is the primed length. */
{
/* don't judge the actual packet size */
length = epState->epBufferStatusUnion[odd].epBufferStatusField.transactionLength;
}
#endif
#if !((defined(USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER)) && (USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER > 0U))
USB_DeviceLpc3511IpDoPreviousTransactionMemcpy(lpc3511IpState, epState, length, endpointIndex, odd);
#endif
/* update the transferred length */
epState->transferDone += length;
return length;
}
static void USB_DeviceLpc3511IpInterruptToken(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
uint8_t endpointIndex,
uint8_t isSetup,
uint32_t errorStatus)
{
usb_device_callback_message_struct_t message;
uint32_t length;
uint32_t remainLength;
usb_setup_struct_t *setupPacket;
void *temp;
usb_device_lpc3511ip_endpoint_state_struct_t *epState =
USB_DeviceLpc3511IpGetEndpointStateStruct(lpc3511IpState, endpointIndex);
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
uint32_t len = 0;
#endif
#if (defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U)) && \
(!(defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK)))
#else
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
if (0U != lpc3511IpState->hsInterruptIssue)
{
#endif
if ((0U != (epState->stateUnion.stateBitField.epControlDefault &
((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT))) &&
(USB_ENDPOINT_INTERRUPT == epState->stateUnion.stateBitField.endpointType) &&
(0U != lpc3511IpState->controllerSpeed) &&
(0U != (lpc3511IpState->epCommandStatusList[epState->stateUnion.stateBitField.consumerOdd +
(((uint32_t)endpointIndex) * 2U)] &
USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK)))
{
if (0U == (lpc3511IpState->registerBase->EPTOGGLE & ((uint32_t)(0x01UL << endpointIndex))))
{
uint32_t index;
length = 0U;
for (index = 0U; index < ((uint32_t)USB_DEVICE_IP3511_ENDPOINTS_NUM) * 4U; ++index)
{
if ((0U !=
(lpc3511IpState->epCommandStatusList[index] & USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK)) &&
(USB_ENDPOINT_INTERRUPT ==
lpc3511IpState->endpointState[index / 2U].stateUnion.stateBitField.endpointType))
{
length++;
}
}
if (length <= 1U)
{
lpc3511IpState->registerBase->DEVCMDSTAT &=
~(USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AO_MASK | USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AI_MASK);
}
epState->stateUnion.stateBitField.epControlDefault &=
(~((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT));
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
/* high-speed */
epState->stateUnion.stateBitField.epControlDefault |=
((USB_LPC3511IP_ENDPOINT_RFTV_MASK | USB_LPC3511IP_ENDPOINT_ENDPOINT_TYPE_MASK) >>
USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT);
(void)USB_DeviceLpc3511IpTransaction(lpc3511IpState, epState, endpointIndex);
#endif
}
return;
}
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
}
#endif
#endif
#endif
if ((0U == isSetup) && (0U == epState->stateUnion.stateBitField.transferring))
{
return;
}
if (0U != isSetup)
{
message.length = 8U;
message.buffer = (lpc3511IpState->setupData);
/* clear the primed control transactions */
if (0U != (epState->stateUnion.stateBitField.transferring))
{
epState->stateUnion.stateBitField.transferring = 0U;
if (0U != (lpc3511IpState->epCommandStatusList[0] & USB_LPC3511IP_ENDPOINT_ACTIVE_MASK))
{
(void)USB_DeviceLpc3511IpCancel(lpc3511IpState, USB_CONTROL_ENDPOINT);
}
}
if (0U != (lpc3511IpState->endpointState[1].stateUnion.stateBitField.transferring))
{
lpc3511IpState->endpointState[1].stateUnion.stateBitField.transferring = 0U;
if (0U != (lpc3511IpState->epCommandStatusList[2] & USB_LPC3511IP_ENDPOINT_ACTIVE_MASK))
{
(void)USB_DeviceLpc3511IpCancel(lpc3511IpState, (0x80u | USB_CONTROL_ENDPOINT));
}
}
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND(
lpc3511IpState, 0, 0, (~(USB_LPC3511IP_ENDPOINT_STALL_MASK | USB_LPC3511IP_ENDPOINT_ACTIVE_MASK)));
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND(
lpc3511IpState, 1, 0, (~(USB_LPC3511IP_ENDPOINT_STALL_MASK | USB_LPC3511IP_ENDPOINT_ACTIVE_MASK)));
lpc3511IpState->registerBase->INTSTAT = 0x03u; /* clear interrupt */
/* W1 to clear the setup flag */
lpc3511IpState->registerBase->DEVCMDSTAT |= USB_LPC3511IP_DEVCMDSTAT_SETUP_MASK;
}
else
{
length = 0U;
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
if (0U != (lpc3511IpState->epCommandStatusList[epState->stateUnion.stateBitField.consumerOdd +
(((uint32_t)endpointIndex) * 2U)] &
USB_LPC3511IP_ENDPOINT_ACTIVE_MASK))
{
return;
}
#else
if (0U != (lpc3511IpState->epCommandStatusList[endpointIndex * 2U] & USB_LPC3511IP_ENDPOINT_ACTIVE_MASK))
{
return;
}
#endif
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
if ((endpointIndex >> 1U) != USB_CONTROL_ENDPOINT)
{
len = USB_DeviceLpc3511IpTokenUpdate(lpc3511IpState, epState, endpointIndex, 1U);
length += len;
if ((epState->stateUnion.stateBitField.doubleBufferBusy > 0U) &&
(0U == (lpc3511IpState->epCommandStatusList[epState->stateUnion.stateBitField.consumerOdd +
(((uint32_t)endpointIndex) * 2U)] &
USB_LPC3511IP_ENDPOINT_ACTIVE_MASK)))
{
#if ((defined(USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER)) && (USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER > 0U))
USB_DeviceLpc3511IpDoPreviousTransactionMemcpy(
lpc3511IpState, epState, len, endpointIndex,
(uint8_t)(epState->stateUnion.stateBitField.consumerOdd ^ 1U));
#endif
len = USB_DeviceLpc3511IpTokenUpdate(lpc3511IpState, epState, endpointIndex, 1U);
length += len;
}
}
else
#endif
{
length = USB_DeviceLpc3511IpTokenUpdate(lpc3511IpState, epState, endpointIndex, 0U);
len = length;
}
/* update remaining length */
remainLength = epState->transferLength - epState->transferDone;
/* Whether the transfer is completed or not.
* The transfer is completed when one of the following conditions meet:
* 1. The remaining length is zero.
* 2. The length of current tansaction is not the multiple of max packet size.
*/
if ((length > 0U) && (0U == (length % epState->stateUnion.stateBitField.maxPacketSize)) && (remainLength > 0U))
{
(void)USB_DeviceLpc3511IpTransaction(lpc3511IpState, epState, endpointIndex);
#if ((defined(USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER)) && (USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER > 0U))
USB_DeviceLpc3511IpDoPreviousTransactionMemcpy(
lpc3511IpState, epState, len, endpointIndex,
(uint8_t)(epState->stateUnion.stateBitField.consumerOdd ^ 1U));
#endif
return;
}
else
{
epState->stateUnion.stateBitField.transferring = 0U;
message.length = epState->transferDone;
message.buffer = epState->transferBuffer;
/* process ZLT
* 1. IN endpoint;
* 2. transfer length is the multiple of max packet size.
*/
if ((0U != (endpointIndex & 0x01U)) && (0U != length) &&
(0U == (length % epState->stateUnion.stateBitField.maxPacketSize)))
{
if ((endpointIndex >> 1U) == USB_CONTROL_ENDPOINT)
{
temp = (void *)(&(lpc3511IpState->setupData[0]));
setupPacket = (usb_setup_struct_t *)temp;
/*
* Send ZLT transaction if setup transfer and the required length is longer than actual length
*/
if (USB_SHORT_FROM_LITTLE_ENDIAN(setupPacket->wLength) > epState->transferLength)
{
(void)USB_DeviceLpc3511IpEndpointPrime(lpc3511IpState, epState, 1U, NULL, 0U);
return;
}
}
else if ((0U != epState->stateUnion.stateBitField.zlt))
{
(void)USB_DeviceLpc3511IpEndpointPrime(lpc3511IpState, epState, endpointIndex, NULL, 0U);
return;
}
else
{
/*no action*/
}
}
}
}
message.isSetup = isSetup;
message.code = ((uint8_t)(endpointIndex >> 1) | (uint8_t)(((endpointIndex & 0x01U) << 0x07U)));
#if ((defined(USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER)) && (USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER > 0U))
USB_DeviceLpc3511IpDoPreviousTransactionMemcpy(lpc3511IpState, epState, len, endpointIndex,
(uint8_t)(epState->stateUnion.stateBitField.consumerOdd ^ 1U));
#endif
/* Notify the up layer the controller status changed. */
(void)USB_DeviceNotificationTrigger(lpc3511IpState->deviceHandle, &message);
}
/*!
* @brief Handle the USB bus reset interrupt.
*
* The function is used to handle the USB bus reset interrupt.
*
* @param lpc3511IpState Pointer of the controller state structure.
*
*/
static void USB_DeviceLpc3511IpInterruptReset(usb_device_lpc3511ip_state_struct_t *lpc3511IpState)
{
usb_device_callback_message_struct_t message;
/* Set reset flag */
lpc3511IpState->isResetting = 1U;
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
if (0U != lpc3511IpState->controllerSpeed)
{
if (((lpc3511IpState->registerBase->DEVCMDSTAT & USBHSD_DEVCMDSTAT_Speed_MASK) >>
USBHSD_DEVCMDSTAT_Speed_SHIFT) == 0x02U)
{
lpc3511IpState->deviceSpeed = USB_SPEED_HIGH;
}
else if (((lpc3511IpState->registerBase->DEVCMDSTAT & USBHSD_DEVCMDSTAT_Speed_MASK) >>
USBHSD_DEVCMDSTAT_Speed_SHIFT) == 0x01U)
{
lpc3511IpState->deviceSpeed = USB_SPEED_FULL;
}
else
{
/*no action*/
}
}
else
#endif
{
lpc3511IpState->deviceSpeed = USB_SPEED_FULL;
}
message.buffer = (uint8_t *)NULL;
message.code = (uint8_t)kUSB_DeviceNotifyBusReset;
message.length = 0U;
message.isSetup = 0U;
/* Notify up layer the USB bus reset signal detected. */
(void)USB_DeviceNotificationTrigger(lpc3511IpState->deviceHandle, &message);
}
#if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE))
/*!
* @brief Handle detach interrupt.
*
* The function is used to handle the detach interrupt.
*
* @param lpc3511IpState Pointer of the controller state structure.
*
*/
static void USB_DeviceLpc3511IpInterruptDetach(usb_device_lpc3511ip_state_struct_t *lpc3511IpState)
{
usb_device_callback_message_struct_t message;
message.buffer = (uint8_t *)NULL;
message.code = (uint8_t)kUSB_DeviceNotifyDetach;
message.length = 0U;
message.isSetup = 0U;
/* Notify up layer the USB VBUS falling signal detected. */
(void)USB_DeviceNotificationTrigger(lpc3511IpState->deviceHandle, &message);
}
/*!
* @brief Handle Attach interrupt.
*
* The function is used to handle the attach interrupt.
*
* @param lpc3511IpState Pointer of the controller state structure.
*
*/
static void USB_DeviceLpc3511IpInterruptAttach(usb_device_lpc3511ip_state_struct_t *lpc3511IpState)
{
usb_device_callback_message_struct_t message;
message.buffer = (uint8_t *)NULL;
message.code = (uint8_t)kUSB_DeviceNotifyAttach;
message.length = 0U;
message.isSetup = 0U;
/* Notify up layer the USB VBUS rising signal detected. */
(void)USB_DeviceNotificationTrigger(lpc3511IpState->deviceHandle, &message);
}
#endif
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
/* The device dcd callback */
static usb_hsdcd_status_t USB_DeviceLpcIp3511IsrHSDCDCallback(void *handle, uint32_t event, void *param)
{
usb_hsdcd_status_t error = kStatus_hsdcd_Success;
usb_device_callback_message_struct_t message;
usb_device_lpc3511ip_state_struct_t *lpc3511IpState = (usb_device_lpc3511ip_state_struct_t *)handle;
if (lpc3511IpState == NULL)
{
return kStatus_hsdcd_Error;
}
/*messsgae buffer contain event information*/
message.buffer = (uint8_t *)param;
message.length = 0U;
message.isSetup = 0U;
message.code = (uint8_t)kUSB_DeviceNotifyDcdDetectFinished;
(void)USB_DeviceNotificationTrigger(lpc3511IpState->deviceHandle, &message);
return error;
}
void USB_DeviceLpcIp3511IsrDCDFunction(void *deviceHandle)
{
usb_device_struct_t *handle = (usb_device_struct_t *)deviceHandle;
usb_device_lpc3511ip_state_struct_t *lpc3511IpState;
if (NULL == deviceHandle)
{
return;
}
lpc3511IpState = (usb_device_lpc3511ip_state_struct_t *)(handle->controllerHandle);
USB_HSDcdIsrFunction(lpc3511IpState->dcdHandle);
}
#endif
usb_status_t USB_DeviceLpc3511IpInit(uint8_t controllerId,
usb_device_handle handle,
usb_device_controller_handle *controllerHandle)
{
usb_device_lpc3511ip_state_struct_t *lpc3511IpState = NULL;
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
uint32_t ip3511FsBases[] = USB_BASE_ADDRS;
#endif
uint32_t *endpointListArray[] = LPC_CONTROLLER_ENDPOINT_LIST_ARRAY;
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
uint32_t hsdcd_base[] = USBHSDCD_BASE_ADDRS;
USBHSDCD_Type *base;
usb_hsdcd_config_struct_t dcdParamConfig;
usb_hsdcd_status_t dcdError = kStatus_hsdcd_Success;
#endif
uint32_t ip3511HsBases[] = USBHSD_BASE_ADDRS;
if ((controllerId >= (uint8_t)kUSB_ControllerLpcIp3511Hs0) &&
(controllerId <= (uint8_t)kUSB_ControllerLpcIp3511Hs1))
{
if (((uint32_t)controllerId - (uint32_t)kUSB_ControllerLpcIp3511Hs0) >=
(sizeof(ip3511HsBases) / sizeof(uint32_t)))
{
return kStatus_USB_ControllerNotFound;
}
lpc3511IpState = &s_UsbDeviceLpc3511IpState[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0 +
USB_DEVICE_CONFIG_LPCIP3511FS];
lpc3511IpState->controlData =
(uint8_t *)&s_SetupAndEpReservedData[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0 +
USB_DEVICE_CONFIG_LPCIP3511FS][CONTROL_TRANSFER_DATA_OFFSET];
lpc3511IpState->setupData =
(uint8_t *)&s_SetupAndEpReservedData[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0 +
USB_DEVICE_CONFIG_LPCIP3511FS][SETUP_TRANSFER_DATA_OFFSET];
lpc3511IpState->zeroTransactionData =
(uint8_t *)&s_SetupAndEpReservedData[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0 +
USB_DEVICE_CONFIG_LPCIP3511FS][ZERO_TRANSFER_DATA_OFFSET];
/* set the endpoint list */
lpc3511IpState->epCommandStatusList =
endpointListArray[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0 + USB_DEVICE_CONFIG_LPCIP3511FS];
/* get the ip base address */
lpc3511IpState->registerBase =
(USB_LPC3511IP_Type *)ip3511HsBases[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0];
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
base = (USBHSDCD_Type *)hsdcd_base[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0];
dcdParamConfig.dcdCallback = USB_DeviceLpcIp3511IsrHSDCDCallback;
dcdParamConfig.dcdCallbackParam = (void *)lpc3511IpState;
dcdError = USB_HSDCD_Init(base, &dcdParamConfig, &lpc3511IpState->dcdHandle);
if (kStatus_hsdcd_Success != dcdError)
{
return kStatus_USB_Error;
}
#endif
}
else
#endif
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
{
/* get the controller instance */
if ((controllerId < (uint8_t)kUSB_ControllerLpcIp3511Fs0) ||
((controllerId - (uint8_t)kUSB_ControllerLpcIp3511Fs0) >= (uint8_t)USB_DEVICE_CONFIG_LPCIP3511FS) ||
(((uint32_t)controllerId - (uint32_t)kUSB_ControllerLpcIp3511Fs0) >=
(sizeof(ip3511FsBases) / sizeof(uint32_t))))
{
return kStatus_USB_ControllerNotFound;
}
lpc3511IpState = &s_UsbDeviceLpc3511IpState[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Fs0];
lpc3511IpState->controlData =
(uint8_t *)&s_SetupAndEpReservedData[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Fs0]
[CONTROL_TRANSFER_DATA_OFFSET];
lpc3511IpState->setupData =
(uint8_t *)&s_SetupAndEpReservedData[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Fs0]
[SETUP_TRANSFER_DATA_OFFSET];
lpc3511IpState->zeroTransactionData =
(uint8_t *)&s_SetupAndEpReservedData[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Fs0]
[ZERO_TRANSFER_DATA_OFFSET];
/* set the endpoint list */
lpc3511IpState->epCommandStatusList = endpointListArray[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Fs0];
/* get the ip base address */
lpc3511IpState->registerBase =
(USB_LPC3511IP_Type *)ip3511FsBases[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Fs0];
}
#else
{
return kStatus_USB_ControllerNotFound;
}
#endif
lpc3511IpState->controllerId = controllerId;
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
if ((lpc3511IpState->controllerId >= (uint8_t)kUSB_ControllerLpcIp3511Hs0) &&
(lpc3511IpState->controllerId <= (uint8_t)kUSB_ControllerLpcIp3511Hs1))
{
lpc3511IpState->controllerSpeed = 1U;
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
lpc3511IpState->hsInterruptIssue = ((Chip_GetVersion() == FSL_ROM_VERSION_1B) ? 0U : 1U);
#endif
}
else
{
lpc3511IpState->controllerSpeed = 0U;
}
#endif
#if ((defined(USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY)) && (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY > 0U))
/* this controller need max packet buffer copy */
if (0U != USB_DeviceLpcIp3511MaxPacketNeedCopy(lpc3511IpState))
{
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
/* fix coverity and misra 14.3 */
if (controllerId >= (uint8_t)kUSB_ControllerLpcIp3511Hs0)
{
#if (USB_DEVICE_IP3511_ALL_IP_SUPPORT_RESERVED_BUFFER)
/* for allocating the max packet buffer */
lpc3511IpState->epReservedBuffer =
(uint8_t *)&s_SetupAndEpReservedData[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0 +
USB_DEVICE_CONFIG_LPCIP3511FS][RESERVED_EP_DATA_OFFSET];
#else
lpc3511IpState->epReservedBuffer =
(uint8_t *)&s_SetupAndEpReservedData[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Hs0]
[RESERVED_EP_DATA_OFFSET];
#endif
}
else
#endif
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511FS)) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
{
lpc3511IpState->epReservedBuffer =
(uint8_t *)&s_SetupAndEpReservedData[controllerId - (uint8_t)kUSB_ControllerLpcIp3511Fs0]
[RESERVED_EP_DATA_OFFSET];
}
#else
{
/* no action */
}
#endif
}
for (controllerId = 0; controllerId < ((USB_DEVICE_IP3511_BITS_FOR_RESERVED_BUFFER + 7U) / 8U); ++controllerId)
{
lpc3511IpState->epReservedBufferBits[controllerId] = 0U;
}
#endif
/* disable the controller */
lpc3511IpState->registerBase->DEVCMDSTAT &=
(~(USB_LPC3511IP_DEVCMDSTAT_DCON_MASK | USB_LPC3511IP_DEVCMDSTAT_DEV_EN_MASK |
USB_LPC3511IP_DEVCMDSTAT_LPM_SUP_MASK));
/* reset and enalbe the controller */
USB_DeviceLpc3511IpSetDefaultState(lpc3511IpState);
/* enable USB */
lpc3511IpState->registerBase->DEVCMDSTAT |= (USB_LPC3511IP_DEVCMDSTAT_DEV_EN_MASK
#if ((defined(USB_DEVICE_CONFIG_LOW_POWER_MODE)) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
#else
| USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK
#endif
);
#if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
lpc3511IpState->registerBase->DEVCMDSTAT |= USB_LPC3511IP_DEVCMDSTAT_LPM_SUP_MASK;
lpc3511IpState->registerBase->LPM |= USB_LPC3511IP_USB_LPM_HIRD_SW(4);
lpc3511IpState->registerBase->DEVCMDSTAT &= ~(USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK);
#endif
lpc3511IpState->deviceHandle = handle;
*controllerHandle = lpc3511IpState;
return kStatus_USB_Success;
}
usb_status_t USB_DeviceLpc3511IpDeinit(usb_device_controller_handle controllerHandle)
{
usb_device_lpc3511ip_state_struct_t *lpc3511IpState = (usb_device_lpc3511ip_state_struct_t *)controllerHandle;
uint32_t usbAddress;
usb_status_t status = kStatus_USB_Success;
if (controllerHandle == NULL)
{
return kStatus_USB_InvalidHandle;
}
/* Clear all interrupt flags. */
lpc3511IpState->registerBase->INTSTAT = (USB_LPC3511IP_INTSTAT_DEV_INT_MASK | USB_LPC3511IP_INTSTAT_FRAME_INT_MASK |
USB_LPC3511IP_MAX_PHY_ENDPOINT_MASK);
/* Disable all interrupts. */
lpc3511IpState->registerBase->INTEN = 0U;
/* Clear device address. */
usbAddress = 0U;
status = USB_DeviceLpc3511IpControlPreSetDeviceAddress(controllerHandle, &usbAddress);
if (kStatus_USB_Success == status)
{
/*no action, just for misra4.7*/
}
#if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
lpc3511IpState->registerBase->DEVCMDSTAT &= ~USB_LPC3511IP_DEVCMDSTAT_LPM_SUP_MASK;
#endif
/* disable the controller */
lpc3511IpState->registerBase->DEVCMDSTAT &=
(~(USB_LPC3511IP_DEVCMDSTAT_DCON_MASK | USB_LPC3511IP_DEVCMDSTAT_DEV_EN_MASK |
USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK));
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
(void)USB_HSDCD_Deinit(lpc3511IpState->dcdHandle);
#endif
return status;
}
static usb_status_t USB_DeviceLpc3511IpGetActualBufferAndPrime(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
usb_device_lpc3511ip_endpoint_state_struct_t *epState,
uint8_t endpointIndex,
uint8_t changedOdd)
{
uint8_t *destBuffer;
uint8_t *actualBuffer;
uint32_t length;
uint8_t odd;
uint8_t index;
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
if (0U != changedOdd)
{
odd = (uint8_t)epState->stateUnion.stateBitField.producerOdd;
}
else
#endif
{
odd = 0;
}
actualBuffer = epState->transferBuffer + epState->transferPrimedLength;
length = epState->transferLength - epState->transferPrimedLength;
/* Data length needs to less than max packet size. */
#if ((defined(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX)) && \
(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX > 0U))
if ((USB_ENDPOINT_BULK == epState->stateUnion.stateBitField.endpointType) && ((endpointIndex & 0x01U) == 0x00U))
{
if (length > USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX)
{
length = USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX;
}
}
else
{
if (length > epState->stateUnion.stateBitField.maxPacketSize)
{
length = epState->stateUnion.stateBitField.maxPacketSize;
}
}
#else
if (length > epState->stateUnion.stateBitField.maxPacketSize)
{
length = epState->stateUnion.stateBitField.maxPacketSize;
}
#endif
epState->epBufferStatusUnion[odd].epBufferStatusField.epPacketCopyed = 0;
index = (endpointIndex & 0x01u); /* index mean IN endpoint here */
if (length > 0U)
{
#if ((defined(USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY)) && (USB_DEVICE_IP3511_RESERVED_BUFFER_FOR_COPY > 0U))
/* if all the enabled IP support the reserved buffer, then don't need the judgement. */
#if (!USB_DEVICE_IP3511_ALL_IP_SUPPORT_RESERVED_BUFFER)
#define USB_DEVICE_IP3511_NEED_CHECK_BUFFER (1u)
/* lengt > 0 && ((buffer not align with 64) || (buffer is not in the deticated ram))) */
if (USB_DeviceLpcIp3511MaxPacketNeedCopy(lpc3511IpState))
#endif
#else
#define USB_DEVICE_IP3511_NEED_CHECK_BUFFER (1u)
/* align the buffer for control transfer */
if (((endpointIndex >> 1U) == USB_CONTROL_ENDPOINT))
#endif
{
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if ((defined(FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS)) && (FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS))
uint32_t bufferValue = (uint32_t)actualBuffer;
#if ((defined(__SAUREGION_PRESENT)) && (__SAUREGION_PRESENT > 0U))
bufferValue &= (0xEFFFFFFFu); /* bit28 is the secure address label */
#endif
#endif
#endif
/* not 64 bytes align || not in the dedicated ram || ( OUT && not mutiple of 4 ) */
if ((((uint32_t)actualBuffer & 0x0000003FU) != 0U) ||
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if ((defined(FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS)) && (FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS))
(
#endif
#endif
(((uint32_t)actualBuffer & 0xFFC00000U) !=
(lpc3511IpState->registerBase->DATABUFSTART & 0xFFC00000U))
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if ((defined(FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS)) && (FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS))
|| ((0U != lpc3511IpState->controllerSpeed) &&
((bufferValue < (uint32_t)FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS) ||
(bufferValue >
((uint32_t)FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS + (uint32_t)FSL_FEATURE_USBHSD_USB_RAM))))
#endif
#endif
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if ((defined(FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS)) && (FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS))
)
#endif
#endif
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|| ((0U != lpc3511IpState->controllerSpeed) && (0U == index) &&
(length != epState->stateUnion.stateBitField.maxPacketSize)))
#else
)
#endif
{
epState->epBufferStatusUnion[odd].epBufferStatusField.epPacketCopyed = 1U;
/* usb copy buffer for this packet */
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
#if ((defined(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX)) && \
(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX > 0U))
if ((USB_ENDPOINT_BULK == epState->stateUnion.stateBitField.endpointType) &&
((endpointIndex & 0x01U) == 0x00U))
{
destBuffer = (uint8_t *)(epState->epPacketBuffer +
(odd * USB_LPC3511IP_GET_MULTIPLE_OF_64(
USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX)));
}
else
{
destBuffer = (uint8_t *)(epState->epPacketBuffer +
(odd * USB_LPC3511IP_GET_MULTIPLE_OF_64(
epState->stateUnion.stateBitField.maxPacketSize)));
}
#else
destBuffer =
(uint8_t *)(epState->epPacketBuffer + (odd * USB_LPC3511IP_GET_MULTIPLE_OF_64(
epState->stateUnion.stateBitField.maxPacketSize)));
#endif
#else
destBuffer = (uint8_t *)(epState->epPacketBuffer);
#endif
if (0U != index) /* USB_IN */
{
(void)memcpy(destBuffer, actualBuffer, length);
}
else
{
#if ((defined(FSL_FEATURE_USB_VERSION) && (FSL_FEATURE_USB_VERSION >= 200U)) || \
(defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U)))
#else
#if ((defined(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX)) && \
(USB_DEVICE_IP3511HS_BULK_OUT_ONE_TIME_TRANSFER_SIZE_MAX > 0U))
if (length < epState->stateUnion.stateBitField.maxPacketSize)
{
length = epState->stateUnion.stateBitField.maxPacketSize;
}
else
{
length = ((length + epState->stateUnion.stateBitField.maxPacketSize - 1) /
epState->stateUnion.stateBitField.maxPacketSize) *
(epState->stateUnion.stateBitField.maxPacketSize);
}
#else
length = epState->stateUnion.stateBitField.maxPacketSize;
#endif
#endif
}
actualBuffer = destBuffer;
}
}
#if (defined USB_DEVICE_IP3511_NEED_CHECK_BUFFER) && (USB_DEVICE_IP3511_NEED_CHECK_BUFFER)
else /* cannot do memory copy */
{
/* not 64 bytes align || not in the dedicated ram || ( OUT && HS && not mutiple of 4 ) */
if ((((uint32_t)actualBuffer & 0x0000003FU) != 0U) ||
(((uint32_t)actualBuffer & 0xFFC00000U) != (lpc3511IpState->registerBase->DATABUFSTART & 0xFFC00000U))
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|| ((0U != lpc3511IpState->controllerSpeed) && (0U == index) && ((length & 0x00000003u) != 0U)))
#else
)
#endif
{
return kStatus_USB_Error;
}
}
#endif
}
/* Send/Receive data when the device is not resetting. */
if (0U == lpc3511IpState->isResetting)
{
return USB_DeviceLpc3511IpEndpointPrime(lpc3511IpState, epState, endpointIndex, actualBuffer, length);
}
else
{
return kStatus_USB_Error;
}
}
static usb_status_t USB_DeviceLpc3511IpTransaction(usb_device_lpc3511ip_state_struct_t *lpc3511IpState,
usb_device_lpc3511ip_endpoint_state_struct_t *epState,
uint8_t endpointIndex)
{
usb_status_t status = kStatus_USB_Error;
OSA_SR_ALLOC();
#if (defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U)) && \
(!(defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK)))
#else
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
if (lpc3511IpState->hsInterruptIssue)
{
#endif
/* high-speed */
if ((0U != (epState->stateUnion.stateBitField.epControlDefault &
((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT))) &&
(USB_ENDPOINT_INTERRUPT == epState->stateUnion.stateBitField.endpointType) &&
(0U != lpc3511IpState->controllerSpeed))
{
/* users can use NVIC to disable/enable the USB interrupt to improve the system performance */
OSA_ENTER_CRITICAL();
lpc3511IpState->registerBase->DEVCMDSTAT |=
(USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AO_MASK | USB_LPC3511IP_DEVCMDSTAT_INTONNAK_AI_MASK);
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(
lpc3511IpState, endpointIndex, epState->stateUnion.stateBitField.producerOdd,
(epState->stateUnion.stateBitField.epControlDefault << USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT) |
(epState->stateUnion.stateBitField.stalled << USB_LPC3511IP_ENDPOINT_STALL_SHIFT),
0U, (uint32_t)lpc3511IpState->zeroTransactionData);
#else
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT(
lpc3511IpState, endpointIndex, 0,
(epState->stateUnion.stateBitField.epControlDefault << USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT) |
(epState->stateUnion.stateBitField.stalled << USB_LPC3511IP_ENDPOINT_STALL_SHIFT),
0U, (uint32_t)lpc3511IpState->zeroTransactionData);
#endif
/* users can use NVIC to disable/enable the USB interrupt to improve the system performance */
OSA_EXIT_CRITICAL();
return kStatus_USB_Success;
}
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
}
#endif
#endif
#endif
/* Enter critical */
OSA_ENTER_CRITICAL();
if (0U != epState->stateUnion.stateBitField.stalled)
{
if ((endpointIndex >> 1U) != USB_ENDPOINT_CONTROL)
{
epState->stateUnion.stateBitField.stallPrimed = 1u;
status = kStatus_USB_Success;
}
status = kStatus_USB_Error;
OSA_EXIT_CRITICAL();
return status;
}
OSA_EXIT_CRITICAL();
/* 1. transfer size is 0; 2. All are primed */
if ((epState->transferLength <= epState->transferPrimedLength) && (epState->transferLength != 0U))
{
return kStatus_USB_Success;
}
#if (defined USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE) && (USB_DEVICE_IP3511_DOUBLE_BUFFER_ENABLE)
if ((endpointIndex >> 1U) != USB_CONTROL_ENDPOINT)
{
/* disable endpoint interrupts, users can use NVIC to disable/enable the USB interrupt to improve the system
* performance */
OSA_ENTER_CRITICAL();
/* lpc3511IpState->registerBase->INTEN &= (uint32_t)(~(USB_LPC3511IP_MAX_PHY_ENDPOINT_MASK)); */
#if ((defined(USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER)) && (USB_DEVICE_IP3511_DISABLE_OUT_DOUBLE_BUFFER > 0U))
/* for out endpoint,only use buffer toggle, disable prime double buffer at the same time*/
/*host send data less than maxpacket size and in endpoint prime length more more than maxpacketsize, there will
* be state mismtach*/
if (0U == (endpointIndex & 0x1U))
{
status = USB_DeviceLpc3511IpGetActualBufferAndPrime(lpc3511IpState, epState, endpointIndex, 1U);
}
else
#endif
{
do
{
status = USB_DeviceLpc3511IpGetActualBufferAndPrime(lpc3511IpState, epState, endpointIndex, 1U);
if (status != kStatus_USB_Success)
{
break;
}
} while ((epState->transferLength > epState->transferPrimedLength) &&
(epState->stateUnion.stateBitField.doubleBufferBusy < 2U));
}
/* enable endpoint interrupt again, users can use NVIC to disable/enable the USB interrupt to improve the system
* performance */
OSA_EXIT_CRITICAL();
}
else
#endif
{
status = USB_DeviceLpc3511IpGetActualBufferAndPrime(lpc3511IpState, epState, endpointIndex, 0U);
}
return status;
}
usb_status_t USB_DeviceLpc3511IpSend(usb_device_controller_handle controllerHandle,
uint8_t endpointAddress,
uint8_t *buffer,
uint32_t length)
{
usb_device_lpc3511ip_state_struct_t *lpc3511IpState = (usb_device_lpc3511ip_state_struct_t *)controllerHandle;
uint8_t endpointIndex = USB_LPC3511IP_ENDPOINT_DES_INDEX(endpointAddress);
usb_device_lpc3511ip_endpoint_state_struct_t *epState =
USB_DeviceLpc3511IpGetEndpointStateStruct(lpc3511IpState, endpointIndex);
if (1U == epState->stateUnion.stateBitField.transferring)
{
return kStatus_USB_Error;
}
/* Save the transfer information */
epState->transferDone = 0U;
epState->transferBuffer = buffer;
epState->transferLength = length;
epState->transferPrimedLength = 0U;
return USB_DeviceLpc3511IpTransaction(lpc3511IpState, epState, endpointIndex);
/* prime the control setup transfer if it is control in endpoint and data length is zero
* For IP3511 there is no need to prime, the buffer is always in the command/status list
*/
#if 0
if ((0U == length) && (USB_CONTROL_ENDPOINT == (endpointAddress & USB_ENDPOINT_NUMBER_MASK)))
{
USB_DeviceLpc3511IpPrimeNextSetup(lpc3511IpState);
}
#endif
}
usb_status_t USB_DeviceLpc3511IpRecv(usb_device_controller_handle controllerHandle,
uint8_t endpointAddress,
uint8_t *buffer,
uint32_t length)
{
return USB_DeviceLpc3511IpSend(controllerHandle, endpointAddress, buffer, length);
}
usb_status_t USB_DeviceLpc3511IpCancel(usb_device_controller_handle controllerHandle, uint8_t ep)
{
/* users can use NVIC to disable/enable the USB interrupt to improve the system performance */
OSA_SR_ALLOC();
usb_device_lpc3511ip_state_struct_t *lpc3511IpState = (usb_device_lpc3511ip_state_struct_t *)controllerHandle;
usb_device_callback_message_struct_t message;
uint8_t endpointIndex = USB_LPC3511IP_ENDPOINT_DES_INDEX(ep);
usb_device_lpc3511ip_endpoint_state_struct_t *epState =
USB_DeviceLpc3511IpGetEndpointStateStruct(lpc3511IpState, endpointIndex);
/* disable endpoint interrupts, users can use NVIC to disable/enable the USB interrupt to improve the system
* performance */
OSA_ENTER_CRITICAL();
/* Cancel the transfer and notify the up layer when the endpoint is busy. */
if ((0U != epState->stateUnion.stateBitField.transferring)
#if (defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U)) && \
(!(defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK)))
#else
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|| (
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
(0U != lpc3511IpState->hsInterruptIssue) &&
#endif
(0U != (epState->stateUnion.stateBitField.epControlDefault &
((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT))) &&
(USB_ENDPOINT_INTERRUPT == epState->stateUnion.stateBitField.endpointType) &&
(0U != lpc3511IpState->controllerSpeed) &&
(0U != (lpc3511IpState->epCommandStatusList[epState->stateUnion.stateBitField.consumerOdd +
(((uint32_t)endpointIndex) * 2U)] &
USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK)) &&
(0U == (lpc3511IpState->registerBase->EPTOGGLE & ((uint32_t)(0x01UL << endpointIndex)))))
#endif
#endif
)
{
#if (defined(FSL_FEATURE_USBHSD_VERSION) && (FSL_FEATURE_USBHSD_VERSION >= 300U)) && \
(!(defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK)))
#else
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
if (0U != lpc3511IpState->hsInterruptIssue)
{
#endif
epState->stateUnion.stateBitField.epControlDefault &=
(~((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT));
#if (defined(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK) && \
(FSL_FEATURE_USBHSD_INTERRUPT_DATAX_ISSUE_VERSION_CHECK))
}
#endif
#endif
#endif
if ((((lpc3511IpState->epCommandStatusList[(uint32_t)endpointIndex * 2U] &
USB_LPC3511IP_ENDPOINT_ACTIVE_MASK) != 0U) &&
((lpc3511IpState->epCommandStatusList[(uint32_t)endpointIndex * 2U] &
USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) != 0U)) ||
(((lpc3511IpState->epCommandStatusList[(uint32_t)endpointIndex * 2U + 1U] &
USB_LPC3511IP_ENDPOINT_ACTIVE_MASK) != 0U) &&
((lpc3511IpState->epCommandStatusList[(uint32_t)endpointIndex * 2U + 1U] &
USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) != 0U)))
{
epState->stateUnion.stateBitField.epControlDefault |=
((USB_LPC3511IP_ENDPOINT_TOGGLE_RESET_MASK) >> USB_LPC3511IP_ENDPOINT_CONFIGURE_BITS_SHIFT);
}
if ((lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_DCON_MASK) != 0U)
{
while (1U == 1U)
{
if ((lpc3511IpState->epCommandStatusList[(uint32_t)endpointIndex * 2U +
((lpc3511IpState->registerBase->EPINUSE &
(((uint32_t)0x00000001U << endpointIndex))) >>
endpointIndex)] &
USB_LPC3511IP_ENDPOINT_ACTIVE_MASK) != 0U)
{
/* cancel the transfer in the endpoint command/status */
lpc3511IpState->registerBase->EPSKIP |= ((uint32_t)0x00000001U << endpointIndex);
while (((lpc3511IpState->registerBase->EPSKIP & ((uint32_t)0x00000001U << endpointIndex)) != 0U) &&
((lpc3511IpState->epCommandStatusList[(uint32_t)endpointIndex * 2U +
((lpc3511IpState->registerBase->EPINUSE &
(((uint32_t)0x00000001U << endpointIndex))) >>
endpointIndex)] &
USB_LPC3511IP_ENDPOINT_ACTIVE_MASK) != 0U))
{
}
if ((lpc3511IpState->registerBase->EPSKIP & ((uint32_t)0x00000001U << endpointIndex)) != 0U)
{
lpc3511IpState->registerBase->EPSKIP &= (~((uint32_t)0x00000001U << endpointIndex));
}
}
if (((lpc3511IpState->epCommandStatusList[endpointIndex * 2U] & USB_LPC3511IP_ENDPOINT_ACTIVE_MASK) !=
0U) ||
((lpc3511IpState->epCommandStatusList[endpointIndex * 2U + 1U] &
USB_LPC3511IP_ENDPOINT_ACTIVE_MASK) != 0U))
{
if ((lpc3511IpState->registerBase->EPINUSE & (((uint32_t)0x00000001U << endpointIndex))) != 0U)
{
lpc3511IpState->registerBase->EPINUSE &= ~((uint32_t)0x00000001U << endpointIndex);
}
else
{
lpc3511IpState->registerBase->EPINUSE |= ((uint32_t)0x00000001U << endpointIndex);
}
}
else
{
break;
}
}
}
else
{
/* Make sure the device is detached from host, host will not send any transaction to device.
* Then the endpoint status entry can be modified directly by software.
*/
lpc3511IpState->epCommandStatusList[endpointIndex * 2U] = USB_LPC3511IP_ENDPOINT_DISABLE_MASK;
lpc3511IpState->epCommandStatusList[endpointIndex * 2U + 1U] = USB_LPC3511IP_ENDPOINT_DISABLE_MASK;
}
epState->stateUnion.stateBitField.transferring = 0U;
epState->stateUnion.stateBitField.producerOdd =
((lpc3511IpState->registerBase->EPINUSE & ((uint32_t)((uint32_t)0x00000001U << endpointIndex))) >>
endpointIndex);
epState->stateUnion.stateBitField.consumerOdd =
((lpc3511IpState->registerBase->EPINUSE & ((uint32_t)((uint32_t)0x00000001U << endpointIndex))) >>
endpointIndex);
epState->stateUnion.stateBitField.doubleBufferBusy = 0U;
/* clear interrupt status, enable endpoint interrupt again */
lpc3511IpState->registerBase->INTSTAT = ((uint32_t)0x00000001U << endpointIndex);
/* users can use NVIC to disable/enable the USB interrupt to improve the system performance */
OSA_EXIT_CRITICAL();
message.length = USB_CANCELLED_TRANSFER_LENGTH;
message.buffer = epState->transferBuffer;
message.code = ep;
message.isSetup = 0U;
(void)USB_DeviceNotificationTrigger(lpc3511IpState->deviceHandle, &message);
}
else
{
/* users can use NVIC to disable/enable the USB interrupt to improve the system performance */
OSA_EXIT_CRITICAL();
}
return kStatus_USB_Success;
}
/*seperate this function from USB_DeviceLpc3511IpControl for misra17.2 recursive */
static usb_status_t USB_DeviceLpc3511IpControlPreSetDeviceAddress(usb_device_controller_handle controllerHandle,
void *param)
{
usb_device_lpc3511ip_state_struct_t *lpc3511IpState = (usb_device_lpc3511ip_state_struct_t *)controllerHandle;
usb_status_t error = kStatus_USB_Error;
uint32_t tmp32Value;
uint8_t tmp8Value;
if (NULL != param)
{
tmp8Value = *((uint8_t *)param);
tmp32Value = lpc3511IpState->registerBase->DEVCMDSTAT;
tmp32Value &= (~USB_LPC3511IP_DEVCMDSTAT_DEV_ADDR_MASK);
tmp32Value |= ((uint32_t)tmp8Value & USB_LPC3511IP_DEVCMDSTAT_DEV_ADDR_MASK);
lpc3511IpState->registerBase->DEVCMDSTAT = tmp32Value;
error = kStatus_USB_Success;
}
return error;
}
usb_status_t USB_DeviceLpc3511IpControl(usb_device_controller_handle controllerHandle,
usb_device_control_type_t type,
void *param)
{
usb_device_lpc3511ip_state_struct_t *lpc3511IpState = (usb_device_lpc3511ip_state_struct_t *)controllerHandle;
usb_status_t error = kStatus_USB_Error;
uint32_t tmp32Value;
uint8_t tmp8Value;
#if defined(USB_DEVICE_CONFIG_GET_SOF_COUNT) && (USB_DEVICE_CONFIG_GET_SOF_COUNT > 0U)
uint32_t *tmp32Pointer;
#endif
#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
usb_device_struct_t *deviceHandle;
#endif
usb_device_lpc3511ip_endpoint_state_struct_t *epState;
if (controllerHandle == NULL)
{
return kStatus_USB_InvalidHandle;
}
#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
deviceHandle = (usb_device_struct_t *)lpc3511IpState->deviceHandle;
#endif
switch (type)
{
case kUSB_DeviceControlRun:
lpc3511IpState->registerBase->DEVCMDSTAT |= (USB_LPC3511IP_DEVCMDSTAT_DCON_MASK);
lpc3511IpState->registerBase->DEVCMDSTAT &= ~(USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK);
break;
case kUSB_DeviceControlStop:
lpc3511IpState->registerBase->DEVCMDSTAT |= USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK;
lpc3511IpState->registerBase->DEVCMDSTAT &= (~USB_LPC3511IP_DEVCMDSTAT_DCON_MASK);
break;
case kUSB_DeviceControlEndpointInit:
if (NULL != param)
{
error = USB_DeviceLpc3511IpEndpointInit(lpc3511IpState, (usb_device_endpoint_init_struct_t *)param);
}
break;
case kUSB_DeviceControlEndpointDeinit:
if (NULL != param)
{
tmp8Value = *((uint8_t *)param);
error = USB_DeviceLpc3511IpEndpointDeinit(lpc3511IpState, tmp8Value);
}
break;
case kUSB_DeviceControlEndpointStall:
if (NULL != param)
{
tmp8Value = *((uint8_t *)param);
error = USB_DeviceLpc3511IpEndpointStall(lpc3511IpState, tmp8Value);
}
break;
case kUSB_DeviceControlEndpointUnstall:
if (NULL != param)
{
tmp8Value = *((uint8_t *)param);
error = USB_DeviceLpc3511IpEndpointUnstall(lpc3511IpState, tmp8Value);
}
break;
case kUSB_DeviceControlGetDeviceStatus:
if (NULL != param)
{
*((uint16_t *)param) =
(USB_DEVICE_CONFIG_SELF_POWER << (USB_REQUEST_STANDARD_GET_STATUS_DEVICE_SELF_POWERED_SHIFT))
#if ((defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP)) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U))
| ((uint16_t)(((uint32_t)deviceHandle->remotewakeup)
<< (USB_REQUEST_STANDARD_GET_STATUS_DEVICE_REMOTE_WARKUP_SHIFT)))
#endif
;
error = kStatus_USB_Success;
}
break;
case kUSB_DeviceControlGetEndpointStatus:
if (NULL != param)
{
usb_device_endpoint_status_struct_t *endpointStatus = (usb_device_endpoint_status_struct_t *)param;
if ((((endpointStatus->endpointAddress) & USB_ENDPOINT_NUMBER_MASK)) <
(uint8_t)USB_DEVICE_IP3511_ENDPOINTS_NUM)
{
epState = USB_DeviceLpc3511IpGetEndpointStateStruct(
lpc3511IpState, USB_LPC3511IP_ENDPOINT_DES_INDEX(endpointStatus->endpointAddress));
endpointStatus->endpointStatus =
(uint16_t)((epState->stateUnion.stateBitField.stalled == 1U) ? kUSB_DeviceEndpointStateStalled :
kUSB_DeviceEndpointStateIdle);
error = kStatus_USB_Success;
}
}
break;
case kUSB_DeviceControlPreSetDeviceAddress:
error = USB_DeviceLpc3511IpControlPreSetDeviceAddress(controllerHandle, param);
if (kStatus_USB_Success == error)
{
/*no action, just for misra4.7*/
}
break;
case kUSB_DeviceControlSetDeviceAddress:
error = kStatus_USB_Success;
break;
case kUSB_DeviceControlGetSynchFrame:
break;
#if defined(USB_DEVICE_CONFIG_REMOTE_WAKEUP) && (USB_DEVICE_CONFIG_REMOTE_WAKEUP > 0U)
case kUSB_DeviceControlResume:
/* todo: turn on USB clock and enable the USB clock source */
lpc3511IpState->registerBase->DEVCMDSTAT |= USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK;
lpc3511IpState->registerBase->DEVCMDSTAT &= ~USB_LPC3511IP_DEVCMDSTAT_DSUS_MASK;
while (0U != (lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_DSUS_MASK))
{
}
/* the W1C bits */
lpc3511IpState->registerBase->DEVCMDSTAT &=
~(USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK | USB_LPC3511IP_DEVCMDSTAT_INTERRUPT_WC_MASK);
error = kStatus_USB_Success;
break;
#if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
case kUSB_DeviceControlSleepResume:
/* todo: turn on USB clock and enable the USB clock source */
lpc3511IpState->registerBase->DEVCMDSTAT |= USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK;
lpc3511IpState->registerBase->DEVCMDSTAT &= ~USB_LPC3511IP_DEVCMDSTAT_LPM_SUS_MASK;
while (0U != (lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_LPM_SUS_MASK))
{
__NOP();
}
/* the W1C bits */
lpc3511IpState->registerBase->DEVCMDSTAT &=
~(USB_LPC3511IP_DEVCMDSTAT_FORCE_NEEDCLK_MASK | USB_LPC3511IP_DEVCMDSTAT_INTERRUPT_WC_MASK);
error = kStatus_USB_Success;
break;
#endif
case kUSB_DeviceControlGetRemoteWakeUp:
*((uint8_t *)param) =
(uint8_t)((lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_LPM_REWP_MASK) >>
USB_LPC3511IP_DEVCMDSTAT_LPM_REWP_SHIFT);
break;
#endif /* USB_DEVICE_CONFIG_REMOTE_WAKEUP */
case kUSB_DeviceControlSetDefaultStatus:
for (tmp32Value = 0U; tmp32Value < (uint32_t)USB_DEVICE_IP3511_ENDPOINTS_NUM; tmp32Value++)
{
(void)USB_DeviceLpc3511IpEndpointDeinit(lpc3511IpState, (uint8_t)(tmp32Value | (USB_IN << 0x07U)));
(void)USB_DeviceLpc3511IpEndpointDeinit(lpc3511IpState, (uint8_t)(tmp32Value | (USB_OUT << 0x07U)));
}
USB_DeviceLpc3511IpSetDefaultState(lpc3511IpState);
error = kStatus_USB_Success;
break;
case kUSB_DeviceControlGetSpeed:
if (NULL != param)
{
*((uint8_t *)param) = lpc3511IpState->deviceSpeed;
error = kStatus_USB_Success;
}
break;
case kUSB_DeviceControlGetOtgStatus:
break;
case kUSB_DeviceControlSetOtgStatus:
break;
#if (defined(USB_DEVICE_CONFIG_USB20_TEST_MODE) && (USB_DEVICE_CONFIG_USB20_TEST_MODE > 0U))
case kUSB_DeviceControlSetTestMode:
if (NULL != param)
{
tmp8Value = *((uint8_t *)param);
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
lpc3511IpState->registerBase->DEVCMDSTAT |=
((uint32_t)(tmp8Value) << USBHSD_DEVCMDSTAT_PHY_TEST_MODE_SHIFT);
#endif
error = kStatus_USB_Success;
}
break;
#endif
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
case kUSB_DeviceControlDcdEnable:
if (kStatus_hsdcd_Success == USB_HSDCD_Control(lpc3511IpState->dcdHandle, kUSB_DeviceHSDcdEnable, NULL))
{
error = kStatus_USB_Success;
}
break;
case kUSB_DeviceControlDcdDisable:
if (kStatus_hsdcd_Success == USB_HSDCD_Control(lpc3511IpState->dcdHandle, kUSB_DeviceHSDcdDisable, NULL))
{
error = kStatus_USB_Success;
}
break;
case kUSB_DeviceControlUpdateHwTick:
/*udpate 1ms time tick*/
error = kStatus_USB_Success;
break;
#endif
#if defined(USB_DEVICE_CONFIG_GET_SOF_COUNT) && (USB_DEVICE_CONFIG_GET_SOF_COUNT > 0U)
case kUSB_DeviceControlGetCurrentFrameCount:
if (NULL != param)
{
tmp32Pointer = (uint32_t *)param;
if (USB_SPEED_HIGH == lpc3511IpState->deviceSpeed) /* if high speed, change to use microframe count */
{
*tmp32Pointer =
((uint32_t)(((lpc3511IpState->registerBase->INFO >> USB_LPC3511IP_INFO_FRAME_NR_SHIFT) &
USB_LPC3511IP_INFO_FRAME_NR_MASK) &
(USB_DEVICE_MAX_FRAME_COUNT))) *
8U;
}
else
{
*tmp32Pointer =
((uint32_t)(((lpc3511IpState->registerBase->INFO >> USB_LPC3511IP_INFO_FRAME_NR_SHIFT) &
USB_LPC3511IP_INFO_FRAME_NR_MASK) &
(USB_DEVICE_MAX_FRAME_COUNT)));
}
error = kStatus_USB_Success;
}
break;
#endif
default:
/*no action*/
break;
}
return error;
}
void USB_DeviceLpcIp3511IsrFunction(void *deviceHandle)
{
usb_device_struct_t *handle = (usb_device_struct_t *)deviceHandle;
usb_device_lpc3511ip_state_struct_t *lpc3511IpState;
uint32_t interruptStatus;
uint32_t usbErrorCode;
uint32_t devState;
if (NULL == deviceHandle)
{
return;
}
lpc3511IpState = (usb_device_lpc3511ip_state_struct_t *)(handle->controllerHandle);
/* get and clear interrupt status */
interruptStatus = lpc3511IpState->registerBase->INTSTAT;
lpc3511IpState->registerBase->INTSTAT = interruptStatus;
interruptStatus &= lpc3511IpState->registerBase->INTEN;
usbErrorCode = (lpc3511IpState->registerBase->INFO & USB_LPC3511IP_INFO_ERR_CODE_MASK);
/* device status change interrupt */
if (0U != (interruptStatus & USB_LPC3511IP_INTSTAT_DEV_INT_MASK))
{
/* get and clear device state change status */
devState = lpc3511IpState->registerBase->DEVCMDSTAT;
devState &= ~(USB_LPC3511IP_DEVCMDSTAT_SETUP_MASK);
lpc3511IpState->registerBase->DEVCMDSTAT = (devState | USB_LPC3511IP_DEVCMDSTAT_INTERRUPT_WC_MASK);
/* For HS: there is interrupt with DEV_INT=1, OTG_C=1 and ADPPROBE=1 when vbus rising.
* For FS: there is no interrupt when vbus rising. The only way is: check the VBUS_DEBOUNCED in the DRES_C
* interrupt with DCON set.
*/
#if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE))
if ((0U == lpc3511IpState->deviceState) &&
((0U != (devState & USB_LPC3511IP_DEVCMDSTAT_VBUS_DEBOUNCED_MASK))
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|| ((0U != (lpc3511IpState->registerBase->LPM & USB_LPC3511IP_USB_LPM_ADPPROBE_MASK)) &&
(1U == lpc3511IpState->controllerSpeed))
#endif
))
{
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
#if ((defined(USB_DEVICE_IP3511HS_LPM_ADPPROBE_ATTACH_DEBOUNCE_COUNT)) && \
(USB_DEVICE_IP3511HS_LPM_ADPPROBE_ATTACH_DEBOUNCE_COUNT > 0U))
/* add one little debounce for HS's attach detection because ADPPROBE is undebounced value */
uint32_t debounceCount = USB_DEVICE_IP3511HS_LPM_ADPPROBE_ATTACH_DEBOUNCE_COUNT;
if (1U == lpc3511IpState->controllerSpeed)
{
while ((0U != debounceCount) && (0U == (devState & USB_LPC3511IP_DEVCMDSTAT_VBUS_DEBOUNCED_MASK)))
{
if (0U == (lpc3511IpState->registerBase->LPM & USB_LPC3511IP_USB_LPM_ADPPROBE_MASK))
{
break;
}
debounceCount--;
}
}
if ((debounceCount == 0U) || (0U != (devState & USB_LPC3511IP_DEVCMDSTAT_VBUS_DEBOUNCED_MASK)))
#endif
#endif
{
lpc3511IpState->deviceState = 1U;
USB_DeviceLpc3511IpInterruptAttach(lpc3511IpState);
#if (defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U)) && \
(defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U))
(void)USB_HSDCD_Control(lpc3511IpState->dcdHandle, kUSB_DeviceHSDcdRun, NULL);
#endif
}
}
/* For HS: there is interrupt with DEV_INT=1, OTG_C=1 and ADPPROBE=0 when vbus falling.
* For HS and FS: there is interrupt when vbus falling if DCON is set.
*/
else if ((1U == lpc3511IpState->deviceState) &&
(((0U != (lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_DCON_MASK)) &&
(0U == (devState & USB_LPC3511IP_DEVCMDSTAT_VBUS_DEBOUNCED_MASK)))
#if ((defined(USB_DEVICE_CONFIG_LPCIP3511HS)) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|| ((0U == (lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_DCON_MASK)) &&
(0U == (lpc3511IpState->registerBase->LPM & USB_LPC3511IP_USB_LPM_ADPPROBE_MASK)) &&
(1U == lpc3511IpState->controllerSpeed))
#endif
))
{
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
#if ((defined FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE) && (FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE > 0U))
#if ((defined USB_DEVICE_IP3511HS_FORCE_EXIT_HS_MODE_ENABLE) && (USB_DEVICE_IP3511HS_FORCE_EXIT_HS_MODE_ENABLE > 0U))
uint32_t delay = 100000U;
#endif
#endif
#endif
lpc3511IpState->deviceState = 0U;
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
#if ((defined FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE) && (FSL_FEATURE_USBHSD_HAS_EXIT_HS_ISSUE > 0U))
#if ((defined USB_DEVICE_IP3511HS_FORCE_EXIT_HS_MODE_ENABLE) && (USB_DEVICE_IP3511HS_FORCE_EXIT_HS_MODE_ENABLE > 0U))
/* wait at least 125us to let the host to detect the detach */
USB_PhyDeviceForceEnterFSMode(lpc3511IpState->controllerId, 1);
while (delay--)
{
__NOP();
}
USB_PhyDeviceForceEnterFSMode(lpc3511IpState->controllerId, 0);
#endif
#endif
#endif
USB_DeviceLpc3511IpInterruptDetach(lpc3511IpState);
}
else
{
/*no action*/
}
#endif
/* reset change */
if (0U != (devState & USB_LPC3511IP_DEVCMDSTAT_DRES_C_MASK))
{
USB_DeviceLpc3511IpInterruptReset(lpc3511IpState);
}
/* Suspend/Resume */
#if ((defined(USB_DEVICE_CONFIG_LOW_POWER_MODE)) && (USB_DEVICE_CONFIG_LOW_POWER_MODE > 0U))
if (0U != (devState & USB_LPC3511IP_DEVCMDSTAT_DSUS_C_MASK))
{
if (0U != (lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_DSUS_MASK))
{
(void)USB_DeviceLpc3511IpInterruptSuspend(lpc3511IpState);
}
#if (defined(USB_DEVICE_CONFIG_LPM_L1) && (USB_DEVICE_CONFIG_LPM_L1 > 0U))
else if (0U != (lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_LPM_SUS_MASK))
{
(void)USB_DeviceLpc3511IpInterruptLPMSleep(lpc3511IpState);
}
#endif
else
{
(void)USB_DeviceLpc3511IpInterruptResume(lpc3511IpState);
}
}
#endif
#if 0U /* some soc don't support this bit, need check according to the feature macro */
/* OTG Status change */
if (lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_OTG_C_MASK)
{
}
#endif
}
/* endpoint transfers interrupt */
if (0U != (interruptStatus & USB_LPC3511IP_MAX_PHY_ENDPOINT_MASK))
{
devState = 0; /* devState means index here */
if (0U != (interruptStatus & 0x01U)) /* control OUT */
{
if (0U != (lpc3511IpState->registerBase->DEVCMDSTAT & USB_LPC3511IP_DEVCMDSTAT_SETUP_MASK))
{
devState = 2U;
if ((lpc3511IpState->endpointState[0].stateUnion.stateBitField.stalled == 1U) ||
(lpc3511IpState->endpointState[1].stateUnion.stateBitField.stalled == 1U))
{
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND(
lpc3511IpState, 0, 0,
(~(USB_LPC3511IP_ENDPOINT_STALL_MASK | USB_LPC3511IP_ENDPOINT_ACTIVE_MASK)));
USB_LPC3511IP_ENDPOINT_SET_ENDPOINT_AND(
lpc3511IpState, 1, 0,
(~(USB_LPC3511IP_ENDPOINT_STALL_MASK | USB_LPC3511IP_ENDPOINT_ACTIVE_MASK)));
lpc3511IpState->endpointState[0].stateUnion.stateBitField.stalled = 0U;
lpc3511IpState->endpointState[1].stateUnion.stateBitField.stalled = 0U;
}
/* todo: setup token interrupt */
USB_DeviceLpc3511IpInterruptToken(lpc3511IpState, 0U, 1, usbErrorCode);
}
}
for (; devState < ((uint32_t)USB_DEVICE_IP3511_ENDPOINTS_NUM * 2U); ++devState)
{
/* check the endpoint interrupt */
if (0U != (interruptStatus & (0x01UL << devState)))
{
USB_DeviceLpc3511IpInterruptToken(lpc3511IpState, (uint8_t)devState, 0U, usbErrorCode);
}
}
}
#if 0U
if (interruptStatus & USB_LPC3511IP_INTSTAT_FRAME_INT_MASK)
{
}
#endif
}
#endif