MCUXpresso_LPC55S69/boards/lpcxpresso55s69/usb_examples/usb_device_composite_cdc_ms.../bm/cm33_core0/composite.c

463 lines
15 KiB
C

/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016 - 2017 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "usb_device_config.h"
#include "usb.h"
#include "usb_device.h"
#include "usb_device_msc.h"
#include "usb_device_cdc_acm.h"
#include "usb_device_ch9.h"
#include "usb_device_descriptor.h"
#include "fsl_device_registers.h"
#include "fsl_debug_console.h"
#include "pin_mux.h"
#include "clock_config.h"
#include "board.h"
#include "composite.h"
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
#include "fsl_sysmpu.h"
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
#include "usb_phy.h"
#endif
#include "fsl_power.h"
/*******************************************************************************
* Variables
******************************************************************************/
/* Composite device structure. */
usb_device_composite_struct_t g_composite;
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) static uint8_t s_SetupOutBuffer[8];
void BOARD_InitHardware(void);
void USB_DeviceClockInit(void);
void USB_DeviceIsrEnable(void);
#if USB_DEVICE_CONFIG_USE_TASK
void USB_DeviceTaskFn(void *deviceHandle);
#endif
/*******************************************************************************
* Definitions
******************************************************************************/
/*******************************************************************************
* Prototypes
******************************************************************************/
/*******************************************************************************
* Code
******************************************************************************/
#if (defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
void USB0_IRQHandler(void)
{
USB_DeviceLpcIp3511IsrFunction(g_composite.deviceHandle);
}
#endif
#if (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
void USB1_IRQHandler(void)
{
USB_DeviceLpcIp3511IsrFunction(g_composite.deviceHandle);
}
#endif
void USB_DeviceClockInit(void)
{
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
usb_phy_config_struct_t phyConfig = {
BOARD_USB_PHY_D_CAL,
BOARD_USB_PHY_TXCAL45DP,
BOARD_USB_PHY_TXCAL45DM,
};
#endif
#if defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)
/* enable USB IP clock */
CLOCK_EnableUsbfs0DeviceClock(kCLOCK_UsbfsSrcFro, CLOCK_GetFroHfFreq());
#if defined(FSL_FEATURE_USB_USB_RAM) && (FSL_FEATURE_USB_USB_RAM)
for (int i = 0; i < FSL_FEATURE_USB_USB_RAM; i++)
{
((uint8_t *)FSL_FEATURE_USB_USB_RAM_BASE_ADDRESS)[i] = 0x00U;
}
#endif
#endif
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
/* enable USB IP clock */
CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_UsbPhySrcExt, BOARD_XTAL0_CLK_HZ);
CLOCK_EnableUsbhs0DeviceClock(kCLOCK_UsbSrcUnused, 0U);
USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ, &phyConfig);
#if defined(FSL_FEATURE_USBHSD_USB_RAM) && (FSL_FEATURE_USBHSD_USB_RAM)
for (int i = 0; i < FSL_FEATURE_USBHSD_USB_RAM; i++)
{
((uint8_t *)FSL_FEATURE_USBHSD_USB_RAM_BASE_ADDRESS)[i] = 0x00U;
}
#endif
#endif
}
void USB_DeviceIsrEnable(void)
{
uint8_t irqNumber;
#if defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)
uint8_t usbDeviceIP3511Irq[] = USB_IRQS;
irqNumber = usbDeviceIP3511Irq[CONTROLLER_ID - kUSB_ControllerLpcIp3511Fs0];
#endif
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
uint8_t usbDeviceIP3511Irq[] = USBHSD_IRQS;
irqNumber = usbDeviceIP3511Irq[CONTROLLER_ID - kUSB_ControllerLpcIp3511Hs0];
#endif
/* Install isr, set priority, and enable IRQ. */
NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY);
EnableIRQ((IRQn_Type)irqNumber);
}
#if USB_DEVICE_CONFIG_USE_TASK
void USB_DeviceTaskFn(void *deviceHandle)
{
#if defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)
USB_DeviceLpcIp3511TaskFunction(deviceHandle);
#endif
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
USB_DeviceLpcIp3511TaskFunction(deviceHandle);
#endif
}
#endif
/*!
* @brief USB device callback function.
*
* This function handles the usb device specific requests.
*
* @param handle The USB device handle.
* @param event The USB device event type.
* @param param The parameter of the device specific request.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param)
{
usb_status_t error = kStatus_USB_InvalidRequest;
uint8_t *temp8 = (uint8_t *)param;
switch (event)
{
case kUSB_DeviceEventBusReset:
{
USB_DeviceControlPipeInit(handle);
g_composite.attach = 0;
g_composite.currentConfiguration = 0;
error = kStatus_USB_Success;
#if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) || \
(defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
/* Get USB speed to configure the device, including max packet size and interval of the endpoints. */
if (kStatus_USB_Success == USB_DeviceGetStatus(handle, kUSB_DeviceStatusSpeed, &g_composite.speed))
{
USB_DeviceSetSpeed(handle, g_composite.speed);
}
#endif
}
break;
case kUSB_DeviceEventSetConfiguration:
if (0U == (*temp8))
{
g_composite.attach = 0;
g_composite.currentConfiguration = 0U;
error = kStatus_USB_Success;
}
else if (USB_COMPOSITE_CONFIGURE_INDEX == (*temp8))
{
g_composite.attach = 1;
USB_DeviceCdcVcomSetConfigure(handle, *temp8);
USB_DeviceMscDiskSetConfigure(handle, *temp8);
g_composite.currentConfiguration = *temp8;
error = kStatus_USB_Success;
}
else
{
}
break;
case kUSB_DeviceEventSetInterface:
error = kStatus_USB_Success;
break;
default:
break;
}
return error;
}
/*!
* @brief Get the setup packet buffer.
*
* This function provides the buffer for setup packet.
*
* @param handle The USB device handle.
* @param setupBuffer The pointer to the address of setup packet buffer.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceGetSetupBuffer(usb_device_handle handle, usb_setup_struct_t **setupBuffer)
{
static uint32_t compositeSetup[2];
if (NULL == setupBuffer)
{
return kStatus_USB_InvalidParameter;
}
*setupBuffer = (usb_setup_struct_t *)&compositeSetup;
return kStatus_USB_Success;
}
/*!
* @brief Get the vendor request data buffer.
*
* This function gets the data buffer for vendor request.
*
* @param handle The USB device handle.
* @param setup The pointer to the setup packet.
* @param length The pointer to the length of the data buffer.
* @param buffer The pointer to the address of setup packet data buffer.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceGetVendorReceiveBuffer(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
return kStatus_USB_Error;
}
/*!
* @brief CDC vendor specific callback function.
*
* This function handles the CDC vendor specific requests.
*
* @param handle The USB device handle.
* @param setup The pointer to the setup packet.
* @param length The pointer to the length of the data buffer.
* @param buffer The pointer to the address of setup packet data buffer.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceProcessVendorRequest(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
return kStatus_USB_InvalidRequest;
}
/*!
* @brief Configure remote wakeup feature.
*
* This function configures the remote wakeup feature.
*
* @param handle The USB device handle.
* @param enable 1: enable, 0: disable.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceConfigureRemoteWakeup(usb_device_handle handle, uint8_t enable)
{
return kStatus_USB_InvalidRequest;
}
/*!
* @brief USB configure endpoint function.
*
* This function configure endpoint status.
*
* @param handle The USB device handle.
* @param ep Endpoint address.
* @param status A flag to indicate whether to stall the endpoint. 1: stall, 0: unstall.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceConfigureEndpointStatus(usb_device_handle handle, uint8_t ep, uint8_t status)
{
usb_status_t error = kStatus_USB_InvalidRequest;
error = USB_DeviceCdcVcomConfigureEndpointStatus(handle, ep, status);
error = USB_DeviceMscDiskConfigureEndpointStatus(handle, ep, status);
return error;
}
/*!
* @brief Get the setup packet data buffer.
*
* This function gets the data buffer for setup packet.
*
* @param handle The USB device handle.
* @param setup The pointer to the setup packet.
* @param length The pointer to the length of the data buffer.
* @param buffer The pointer to the address of setup packet data buffer.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceGetClassReceiveBuffer(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
if ((NULL == buffer) || ((*length) > sizeof(s_SetupOutBuffer)))
{
return kStatus_USB_InvalidRequest;
}
*buffer = s_SetupOutBuffer;
return kStatus_USB_Success;
}
/*!
* @brief CDC class specific callback function.
*
* This function handles the CDC class specific requests.
*
* @param handle The USB device handle.
* @param setup The pointer to the setup packet.
* @param length The pointer to the length of the data buffer.
* @param buffer The pointer to the address of setup packet data buffer.
*
* @return A USB error code or kStatus_USB_Success.
*/
usb_status_t USB_DeviceProcessClassRequest(usb_device_handle handle,
usb_setup_struct_t *setup,
uint32_t *length,
uint8_t **buffer)
{
usb_status_t error = kStatus_USB_InvalidRequest;
if (USB_CDC_VCOM_CIC_INTERFACE_INDEX == setup->wIndex)
{
return USB_DeviceCdcVcomClassRequest(handle, setup, length, buffer);
}
else if (USB_MSC_DISK_INTERFACE_INDEX == setup->wIndex)
{
return USB_DeviceMscDiskClassRequest(handle, setup, length, buffer);
}
else
{
}
return error;
}
/*!
* @brief Application initialization function.
*
* This function initializes the application.
*
* @return None.
*/
void APPInit(void)
{
USB_DeviceClockInit();
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
SYSMPU_Enable(SYSMPU, 0);
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
g_composite.speed = USB_SPEED_FULL;
g_composite.attach = 0;
g_composite.deviceHandle = NULL;
if (kStatus_USB_Success != USB_DeviceInit(CONTROLLER_ID, USB_DeviceCallback, &g_composite.deviceHandle))
{
usb_echo("USB device composite demo init failed\r\n");
return;
}
else
{
usb_echo("USB device composite demo\r\n");
}
USB_DeviceCdcVcomInit(&g_composite);
USB_DeviceMscDiskInit(&g_composite);
USB_DeviceIsrEnable();
/*Add one delay here to make the DP pull down long enough to allow host to detect the previous disconnection.*/
SDK_DelayAtLeastUs(5000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
USB_DeviceRun(g_composite.deviceHandle);
}
/*!
* @brief Application task function.
*
* This function runs the task for application.
*
* @return None.
*/
void APPTask(void)
{
USB_DeviceCdcVcomTask();
}
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION)) || defined(__GNUC__)
int main(void)
#else
void main(void)
#endif
{
/* set BOD VBAT level to 1.65V */
POWER_SetBodVbatLevel(kPOWER_BodVbatLevel1650mv, kPOWER_BodHystLevel50mv, false);
/* attach 12 MHz clock to FLEXCOMM0 (debug console) */
CLOCK_AttachClk(BOARD_DEBUG_UART_CLK_ATTACH);
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
NVIC_ClearPendingIRQ(USB0_IRQn);
NVIC_ClearPendingIRQ(USB0_NEEDCLK_IRQn);
NVIC_ClearPendingIRQ(USB1_IRQn);
NVIC_ClearPendingIRQ(USB1_NEEDCLK_IRQn);
POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB0 Phy */
POWER_DisablePD(kPDRUNCFG_PD_USB1_PHY); /*< Turn on USB1 Phy */
/* reset the IP to make sure it's in reset state. */
RESET_PeripheralReset(kUSB0D_RST_SHIFT_RSTn);
RESET_PeripheralReset(kUSB0HSL_RST_SHIFT_RSTn);
RESET_PeripheralReset(kUSB0HMR_RST_SHIFT_RSTn);
RESET_PeripheralReset(kUSB1H_RST_SHIFT_RSTn);
RESET_PeripheralReset(kUSB1D_RST_SHIFT_RSTn);
RESET_PeripheralReset(kUSB1_RST_SHIFT_RSTn);
RESET_PeripheralReset(kUSB1RAM_RST_SHIFT_RSTn);
#if (defined USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS)
CLOCK_EnableClock(kCLOCK_Usbh1);
/* Put PHY powerdown under software control */
*((uint32_t *)(USBHSH_BASE + 0x50)) = USBHSH_PORTMODE_SW_PDCOM_MASK;
/* According to reference mannual, device mode setting has to be set by access usb host register */
*((uint32_t *)(USBHSH_BASE + 0x50)) |= USBHSH_PORTMODE_DEV_ENABLE_MASK;
/* enable usb1 host clock */
CLOCK_DisableClock(kCLOCK_Usbh1);
#endif
#if (defined USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS)
POWER_DisablePD(kPDRUNCFG_PD_USB0_PHY); /*< Turn on USB Phy */
CLOCK_SetClkDiv(kCLOCK_DivUsb0Clk, 1, false);
CLOCK_AttachClk(kFRO_HF_to_USB0_CLK);
/* enable usb0 host clock */
CLOCK_EnableClock(kCLOCK_Usbhsl0);
/*According to reference mannual, device mode setting has to be set by access usb host register */
*((uint32_t *)(USBFSH_BASE + 0x5C)) |= USBFSH_PORTMODE_DEV_ENABLE_MASK;
/* disable usb0 host clock */
CLOCK_DisableClock(kCLOCK_Usbhsl0);
#endif
APPInit();
while (1)
{
#if USB_DEVICE_CONFIG_USE_TASK
USB_DeviceTaskFn(g_composite.deviceHandle);
#endif
APPTask();
}
}