2490 lines
109 KiB
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
|