mirror of
https://libwebsockets.org/repo/libwebsockets
synced 2025-01-09 21:25:40 +00:00
2761badd0f
Adds an example for NXP RT595S eval board, using serialized SS over CDC / ACM USB composite device, one ttyACM for logs and the other for the SSS link.
379 lines
14 KiB
C
379 lines
14 KiB
C
/*
|
|
* Copyright 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_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 "composite.h"
|
|
#include "pin_mux.h"
|
|
#include "clock_config.h"
|
|
#include "board.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
|
|
******************************************************************************/
|
|
|
|
|
|
/*******************************************************************************
|
|
* 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];
|
|
|
|
/* 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
|
|
******************************************************************************/
|
|
|
|
void USB0_IRQHandler(void)
|
|
{
|
|
USB_DeviceLpcIp3511IsrFunction(g_composite.deviceHandle);
|
|
}
|
|
|
|
void USB_DeviceClockInit(void)
|
|
{
|
|
uint8_t usbClockDiv = 1;
|
|
uint32_t usbClockFreq;
|
|
usb_phy_config_struct_t phyConfig = {
|
|
BOARD_USB_PHY_D_CAL,
|
|
BOARD_USB_PHY_TXCAL45DP,
|
|
BOARD_USB_PHY_TXCAL45DM,
|
|
};
|
|
|
|
/* Make sure USDHC ram buffer and usb1 phy has power up */
|
|
POWER_DisablePD(kPDRUNCFG_APD_USBHS_SRAM);
|
|
POWER_DisablePD(kPDRUNCFG_PPD_USBHS_SRAM);
|
|
POWER_DisablePD(kPDRUNCFG_LP_HSPAD_FSPI0_VDET);
|
|
POWER_ApplyPD();
|
|
|
|
RESET_PeripheralReset(kUSBHS_PHY_RST_SHIFT_RSTn);
|
|
RESET_PeripheralReset(kUSBHS_DEVICE_RST_SHIFT_RSTn);
|
|
RESET_PeripheralReset(kUSBHS_HOST_RST_SHIFT_RSTn);
|
|
RESET_PeripheralReset(kUSBHS_SRAM_RST_SHIFT_RSTn);
|
|
|
|
/* enable usb ip clock */
|
|
CLOCK_EnableUsbHs0DeviceClock(kOSC_CLK_to_USB_CLK, usbClockDiv);
|
|
/* save usb ip clock freq*/
|
|
usbClockFreq = g_xtalFreq / usbClockDiv;
|
|
CLOCK_SetClkDiv(kCLOCK_DivPfc1Clk, 4);
|
|
/* enable usb ram clock */
|
|
CLOCK_EnableClock(kCLOCK_UsbhsSram);
|
|
/* enable USB PHY PLL clock, the phy bus clock (480MHz) source is same with USB IP */
|
|
CLOCK_EnableUsbHs0PhyPllClock(kOSC_CLK_to_USB_CLK, usbClockFreq);
|
|
|
|
/* USB PHY initialization */
|
|
USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL_SYS_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
|
|
|
|
/* the following code should run after phy initialization and should wait some microseconds to make sure utmi clock
|
|
* valid */
|
|
/* enable usb1 host clock */
|
|
CLOCK_EnableClock(kCLOCK_UsbhsHost);
|
|
/* Wait until host_needclk de-asserts */
|
|
while (SYSCTL0->USB0CLKSTAT & SYSCTL0_USB0CLKSTAT_HOST_NEED_CLKST_MASK)
|
|
{
|
|
__ASM("nop");
|
|
}
|
|
/*According to reference mannual, device mode setting has to be set by access usb host register */
|
|
USBHSH->PORTMODE |= USBHSH_PORTMODE_DEV_ENABLE_MASK;
|
|
/* disable usb1 host clock */
|
|
CLOCK_DisableClock(kCLOCK_UsbhsHost);
|
|
}
|
|
|
|
void USB_DeviceIsrEnable(void)
|
|
{
|
|
uint8_t irqNumber;
|
|
|
|
uint8_t usbDeviceIP3511Irq[] = USBHSD_IRQS;
|
|
irqNumber = usbDeviceIP3511Irq[CONTROLLER_ID - kUSB_ControllerLpcIp3511Hs0];
|
|
|
|
/* 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)
|
|
{
|
|
USB_DeviceLpcIp3511TaskFunction(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)
|
|
{
|
|
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);
|
|
}
|
|
|
|
|