/* * Copyright 2017 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include "usb_device_config.h" #include "usb.h" #include "usb_device.h" #include "usb_device_class.h" #include "usb_device_cdc_acm.h" #include "usb_device_ch9.h" #include "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" /******************************************************************************* * Definitions ******************************************************************************/ #ifndef APP_TASK_STACK_SIZE #define APP_TASK_STACK_SIZE 5000L #endif /******************************************************************************* * Prototypes ******************************************************************************/ void BOARD_InitHardware(void); void USB_DeviceClockInit(void); void USB_DeviceIsrEnable(void); #if USB_DEVICE_CONFIG_USE_TASK void USB_DeviceTaskFn(void *deviceHandle); #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); /******************************************************************************* * Variables ******************************************************************************/ /* Composite device structure. */ usb_device_composite_struct_t g_composite; extern usb_device_class_struct_t g_UsbDeviceCdcVcomConfig[2]; /* Application task handle. */ static char const *s_appName = "app task"; /* USB device class information */ usb_device_class_config_struct_t g_CompositeClassConfig[2] = {{ USB_DeviceCdcVcomCallback, (class_handle_t)NULL, &g_UsbDeviceCdcVcomConfig[0], }, { USB_DeviceCdcVcomCallback, (class_handle_t)NULL, &g_UsbDeviceCdcVcomConfig[1], }}; /* USB device class configuration information */ usb_device_class_config_list_struct_t g_UsbDeviceCompositeConfigList = { g_CompositeClassConfig, USB_DeviceCallback, 2, }; /******************************************************************************* * 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; uint16_t *temp16 = (uint16_t *)param; uint8_t *temp8 = (uint8_t *)param; switch (event) { case kUSB_DeviceEventBusReset: { g_composite.attach = 0; g_composite.currentConfiguration = 0U; error = kStatus_USB_Success; for (uint8_t i = 0; i < USB_DEVICE_CONFIG_CDC_ACM; i++) { g_composite.cdcVcom[i].recvSize = 0; g_composite.cdcVcom[i].sendSize = 0; g_composite.cdcVcom[i].attach = 0; } #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) || \ (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)) /* Get USB speed to configure the device, including max packet size and interval of the endpoints. */ if (kStatus_USB_Success == USB_DeviceClassGetSpeed(CONTROLLER_ID, &g_composite.speed)) { USB_DeviceSetSpeed(handle, g_composite.speed); } #endif } break; case kUSB_DeviceEventSetConfiguration: if (0U == (*temp8)) { g_composite.attach = 0U; g_composite.currentConfiguration = 0U; error = kStatus_USB_Success; for (uint8_t i = 0; i < USB_DEVICE_CONFIG_CDC_ACM; i++) { g_composite.cdcVcom[i].recvSize = 0; g_composite.cdcVcom[i].sendSize = 0; g_composite.cdcVcom[i].attach = 0; } } else if (USB_COMPOSITE_CONFIGURE_INDEX == (*temp8)) { g_composite.attach = 1; USB_DeviceCdcVcomSetConfigure(g_composite.cdcVcom[0].cdcAcmHandle, *temp8); g_composite.currentConfiguration = *temp8; error = kStatus_USB_Success; } else { /* no action, return kStatus_USB_InvalidRequest */ } break; case kUSB_DeviceEventSetInterface: if (g_composite.attach) { uint8_t interface = (uint8_t)((*temp16 & 0xFF00U) >> 0x08U); uint8_t alternateSetting = (uint8_t)(*temp16 & 0x00FFU); if (interface == USB_CDC_VCOM_CIC_INTERFACE_INDEX) { if (alternateSetting < USB_CDC_VCOM_CIC_INTERFACE_ALTERNATE_COUNT) { g_composite.currentInterfaceAlternateSetting[interface] = alternateSetting; error = kStatus_USB_Success; } } else if (interface == USB_CDC_VCOM_DIC_INTERFACE_INDEX) { if (alternateSetting < USB_CDC_VCOM_DIC_INTERFACE_ALTERNATE_COUNT) { g_composite.currentInterfaceAlternateSetting[interface] = alternateSetting; error = kStatus_USB_Success; } } else if (interface == USB_CDC_VCOM_CIC_INTERFACE_INDEX_2) { if (alternateSetting < USB_CDC_VCOM_CIC_INTERFACE_2_ALTERNATE_COUNT) { g_composite.currentInterfaceAlternateSetting[interface] = alternateSetting; error = kStatus_USB_Success; } } else if (interface == USB_CDC_VCOM_DIC_INTERFACE_INDEX_2) { if (alternateSetting < USB_CDC_VCOM_DIC_INTERFACE_2_ALTERNATE_COUNT) { g_composite.currentInterfaceAlternateSetting[interface] = alternateSetting; error = kStatus_USB_Success; } } else { /* no action, return kStatus_USB_InvalidRequest */ } } break; case kUSB_DeviceEventGetConfiguration: if (param) { *temp8 = g_composite.currentConfiguration; error = kStatus_USB_Success; } break; case kUSB_DeviceEventGetInterface: if (param) { uint8_t interface = (uint8_t)((*temp16 & 0xFF00U) >> 0x08U); if (interface < USB_INTERFACE_COUNT) { *temp16 = (*temp16 & 0xFF00U) | g_composite.currentInterfaceAlternateSetting[interface]; error = kStatus_USB_Success; } } break; case kUSB_DeviceEventGetDeviceDescriptor: if (param) { error = USB_DeviceGetDeviceDescriptor(handle, (usb_device_get_device_descriptor_struct_t *)param); } break; case kUSB_DeviceEventGetConfigurationDescriptor: if (param) { error = USB_DeviceGetConfigurationDescriptor(handle, (usb_device_get_configuration_descriptor_struct_t *)param); } break; #if (defined(USB_DEVICE_CONFIG_CV_TEST) && (USB_DEVICE_CONFIG_CV_TEST > 0U)) case kUSB_DeviceEventGetDeviceQualifierDescriptor: if (param) { /* Get device descriptor request */ error = USB_DeviceGetDeviceQualifierDescriptor( handle, (usb_device_get_device_qualifier_descriptor_struct_t *)param); } break; #endif case kUSB_DeviceEventGetStringDescriptor: if (param) { error = USB_DeviceGetStringDescriptor(handle, (usb_device_get_string_descriptor_struct_t *)param); } break; default: break; } return error; } /*! * @brief Application initialization function. * * This function initializes the application. * * @return None. */ void USB_DeviceApplicationInit(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; for (uint8_t i = 0; i < USB_DEVICE_CONFIG_CDC_ACM; i++) { g_composite.cdcVcom[i].cdcAcmHandle = (class_handle_t)NULL; } g_composite.deviceHandle = NULL; if (kStatus_USB_Success != USB_DeviceClassInit(CONTROLLER_ID, &g_UsbDeviceCompositeConfigList, &g_composite.deviceHandle)) { usb_echo("USB device composite demo init failed\r\n"); return; } else { usb_echo("USB device composite demo\r\n"); /*Init classhandle in cdc instance*/ for (uint8_t i = 0; i < USB_DEVICE_CONFIG_CDC_ACM; i++) { g_composite.cdcVcom[i].cdcAcmHandle = g_UsbDeviceCompositeConfigList.config[i].classHandle; } USB_DeviceCdcVcomInit(&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 USB task function. * * This function runs the task for USB device. * * @return None. */ #if USB_DEVICE_CONFIG_USE_TASK void USB_DeviceTask(void *handle) { while (1U) { USB_DeviceTaskFn(handle); } } #endif /*! * @brief Application task function. * * This function runs the task for application. * * @return None. */ void APPTask(void *handle) { USB_DeviceApplicationInit(); #if USB_DEVICE_CONFIG_USE_TASK if (g_composite.deviceHandle) { if (xTaskCreate(USB_DeviceTask, /* pointer to the task */ (char const *)"usb device task", /* task name for kernel awareness debugging */ 5000L / sizeof(portSTACK_TYPE), /* task stack size */ g_composite.deviceHandle, /* optional task startup argument */ 5, /* initial priority */ &g_composite.deviceTaskHandle /* optional task handle to create */ ) != pdPASS) { usb_echo("usb device task create failed!\r\n"); return; } } #endif while (1) { 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 if (xTaskCreate(APPTask, /* pointer to the task */ s_appName, /* task name for kernel awareness debugging */ APP_TASK_STACK_SIZE / sizeof(portSTACK_TYPE), /* task stack size */ &g_composite, /* optional task startup argument */ 4, /* initial priority */ &g_composite.applicationTaskHandle /* optional task handle to create */ ) != pdPASS) { usb_echo("app task create failed!\r\n"); #if (defined(__CC_ARM) || (defined(__ARMCC_VERSION)) || defined(__GNUC__)) return 1; #else return; #endif } vTaskStartScheduler(); #if (defined(__CC_ARM) || (defined(__ARMCC_VERSION)) || defined(__GNUC__)) return 1; #endif }