mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #1287 from stevew817/usb-device-rel3
Silicon Labs - Add support for USBDevicepull/1277/head^2
commit
376d6a73e3
|
@ -0,0 +1,999 @@
|
|||
/***************************************************************************//**
|
||||
* @file em_usb.h
|
||||
* @brief USB protocol stack library API for EFM32.
|
||||
* @version 3.20.14
|
||||
*******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __EM_USB_H
|
||||
#define __EM_USB_H
|
||||
|
||||
#include "em_device.h"
|
||||
#include "em_assert.h"
|
||||
#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
|
||||
#include "usbconfig.h"
|
||||
#if defined( USB_DEVICE ) || defined( USB_HOST )
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include "em_common.h"
|
||||
#include "em_int.h"
|
||||
|
||||
#if defined( USB_USE_PRINTF )
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __CC_ARM
|
||||
#pragma anon_unions
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup USB
|
||||
* @brief USB HOST and DEVICE protocol stacks.
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup USB_COMMON
|
||||
* @brief Common parts for both HOST and DEVICE USB stacks, see @ref usb_device
|
||||
* and @ref usb_host pages for device and host library documentation.
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
#define SILABS_USB_VID 0x10C4 /**< Silicon Labs Vendor ID, supplied by USB-IF. */
|
||||
|
||||
/* SETUP request, direction of data stage */
|
||||
#define USB_SETUP_DIR_OUT 0 /**< Setup request data stage OUT direction value. */
|
||||
#define USB_SETUP_DIR_IN 1 /**< Setup request data stage IN direction value. */
|
||||
#define USB_SETUP_DIR_MASK 0x80 /**< Setup request data stage direction mask. */
|
||||
#define USB_SETUP_DIR_D2H 0x80 /**< Setup request data stage IN direction mask. */
|
||||
#define USB_SETUP_DIR_H2D 0x00 /**< Setup request data stage OUT direction mask. */
|
||||
|
||||
/* SETUP request type */
|
||||
#define USB_SETUP_TYPE_STANDARD 0 /**< Standard setup request value. */
|
||||
#define USB_SETUP_TYPE_CLASS 1 /**< Class setup request value. */
|
||||
#define USB_SETUP_TYPE_VENDOR 2 /**< Vendor setup request value. */
|
||||
#define USB_SETUP_TYPE_STANDARD_MASK 0x00 /**< Standard setup request mask. */
|
||||
#define USB_SETUP_TYPE_CLASS_MASK 0x20 /**< Class setup request mask. */
|
||||
#define USB_SETUP_TYPE_VENDOR_MASK 0x40 /**< Vendor setup request mask. */
|
||||
|
||||
/* SETUP request recipient */
|
||||
#define USB_SETUP_RECIPIENT_DEVICE 0 /**< Setup request device recipient value. */
|
||||
#define USB_SETUP_RECIPIENT_INTERFACE 1 /**< Setup request interface recipient value. */
|
||||
#define USB_SETUP_RECIPIENT_ENDPOINT 2 /**< Setup request endpoint recipient value. */
|
||||
#define USB_SETUP_RECIPIENT_OTHER 3 /**< Setup request other recipient value. */
|
||||
|
||||
/* SETUP standard request codes for Full Speed devices */
|
||||
#define GET_STATUS 0 /**< Standard setup request GET_STATUS. */
|
||||
#define CLEAR_FEATURE 1 /**< Standard setup request CLEAR_FEATURE. */
|
||||
#define SET_FEATURE 3 /**< Standard setup request SET_FEATURE. */
|
||||
#define SET_ADDRESS 5 /**< Standard setup request SET_ADDRESS. */
|
||||
#define GET_DESCRIPTOR 6 /**< Standard setup request GET_DESCRIPTOR. */
|
||||
#define SET_DESCRIPTOR 7 /**< Standard setup request SET_DESCRIPTOR. */
|
||||
#define GET_CONFIGURATION 8 /**< Standard setup request GET_CONFIGURATION. */
|
||||
#define SET_CONFIGURATION 9 /**< Standard setup request SET_CONFIGURATION. */
|
||||
#define GET_INTERFACE 10 /**< Standard setup request GET_INTERFACE. */
|
||||
#define SET_INTERFACE 11 /**< Standard setup request SET_INTERFACE. */
|
||||
#define SYNCH_FRAME 12 /**< Standard setup request SYNCH_FRAME. */
|
||||
|
||||
/* SETUP class request codes */
|
||||
#define USB_HID_GET_REPORT 0x01 /**< HID class setup request GET_REPORT. */
|
||||
#define USB_HID_GET_IDLE 0x02 /**< HID class setup request GET_IDLE. */
|
||||
#define USB_HID_SET_REPORT 0x09 /**< HID class setup request SET_REPORT. */
|
||||
#define USB_HID_SET_IDLE 0x0A /**< HID class setup request SET_IDLE. */
|
||||
#define USB_HID_SET_PROTOCOL 0x0B /**< HID class setup request SET_PROTOCOL. */
|
||||
#define USB_CDC_SETLINECODING 0x20 /**< CDC class setup request SET_LINE_CODING. */
|
||||
#define USB_CDC_GETLINECODING 0x21 /**< CDC class setup request GET_LINE_CODING. */
|
||||
#define USB_CDC_SETCTRLLINESTATE 0x22 /**< CDC class setup request SET_CONTROL_LINE_STATE. */
|
||||
#define USB_MSD_BOTRESET 0xFF /**< MSD class setup request Bulk only transfer reset. */
|
||||
#define USB_MSD_GETMAXLUN 0xFE /**< MSD class setup request Get Max LUN. */
|
||||
#define USB_AUDIO_GET_CUR 0x81 /**< Audio class setup request GET_CUR. */
|
||||
#define USB_AUDIO_SET_CUR 0x01 /**< Audio class setup request SET_CUR. */
|
||||
#define USB_AUDIO_GET_CUR 0x81 /**< Audio class setup request GET_CUR. */
|
||||
#define USB_AUDIO_SET_MIN 0x02 /**< Audio class setup request SET_MIN. */
|
||||
#define USB_AUDIO_GET_MIN 0x82 /**< Audio class setup request GET_MIN. */
|
||||
#define USB_AUDIO_SET_MAX 0x03 /**< Audio class setup request SET_MAX. */
|
||||
#define USB_AUDIO_GET_MAX 0x83 /**< Audio class setup request GET_MAX. */
|
||||
#define USB_AUDIO_SET_RES 0x04 /**< Audio class setup request SET_RES. */
|
||||
#define USB_AUDIO_GET_RES 0x84 /**< Audio class setup request GET_RES. */
|
||||
#define USB_AUDIO_SET_MEM 0x05 /**< Audio class setup request SET_MEM. */
|
||||
#define USB_AUDIO_GET_MEM 0x85 /**< Audio class setup request GET_MEM. */
|
||||
#define USB_AUDIO_GET_STAT 0xFF /**< Audio class setup request GET_STAT. */
|
||||
|
||||
/* SETUP command GET/SET_DESCRIPTOR decriptor types */
|
||||
#define USB_DEVICE_DESCRIPTOR 1 /**< DEVICE descriptor value. */
|
||||
#define USB_CONFIG_DESCRIPTOR 2 /**< CONFIGURATION descriptor value. */
|
||||
#define USB_STRING_DESCRIPTOR 3 /**< STRING descriptor value. */
|
||||
#define USB_MAX_STRING_DESCRIPTOR_CHARS 126 /**< Maximum STRING descriptor bString length. */
|
||||
#define USB_INTERFACE_DESCRIPTOR 4 /**< INTERFACE descriptor value. */
|
||||
#define USB_ENDPOINT_DESCRIPTOR 5 /**< ENDPOINT descriptor value. */
|
||||
#define USB_DEVICE_QUALIFIER_DESCRIPTOR 6 /**< DEVICE_QUALIFIER descriptor value. */
|
||||
#define USB_OTHER_SPEED_CONFIG_DESCRIPTOR 7 /**< OTHER_SPEED_CONFIGURATION descriptor value. */
|
||||
#define USB_INTERFACE_POWER_DESCRIPTOR 8 /**< INTERFACE_POWER descriptor value. */
|
||||
#define USB_INTERFACE_ASSOCIATION_DESCRIPTOR 11 /**< INTERFACE_ASSOCIATION descriptor value. */
|
||||
#define USB_HID_DESCRIPTOR 0x21 /**< HID descriptor value. */
|
||||
#define USB_SMARTCARD_DESCRIPTOR 0x21 /**< Smartcard usb-ccid-specific Descriptor Type. */
|
||||
#define USB_HID_REPORT_DESCRIPTOR 0x22 /**< HID REPORT descriptor value. */
|
||||
#define USB_CS_INTERFACE_DESCRIPTOR 0x24 /**< Audio Class-specific interface Descriptor Type. */
|
||||
#define USB_CS_ENDPOINT_DESCRIPTOR 0x25 /**< Audio Class-specific endpoint Descriptor Type. */
|
||||
#define USB_HUB_DESCRIPTOR 0x29 /**< HUB descriptor value. */
|
||||
#define USB_CA_HEADER_DESCRIPTOR 1 /**< Audio Class-Specific AC Interface Header descriptor.*/
|
||||
#define USB_CA_INPUT_TERMINAL_DESCRIPTOR 2 /**< Audio Class-Specific AC Interface Input Terminal desc. */
|
||||
#define USB_CA_OUTPUT_TERMINAL_DESCRIPTOR 3 /**< Audio Class-Specific AC Interface Output Terminal desc.*/
|
||||
#define USB_CA_MIXER_UNIT_DESCRIPTOR 4 /**< Audio Class-Specific AC Interface Mixer descriptor.*/
|
||||
#define USB_CA_SELECTOR_UNIT_DESCRIPTOR 5 /**< Audio Class-Specific AC Interface Selector desc. */
|
||||
#define USB_CA_FEATURE_UNIT_DESCRIPTOR 6 /**< Audio Class-Specific AC Interface Feature desc. */
|
||||
#define USB_CA_PROCESSING_UNIT_DESCRIPTOR 7 /**< Audio Class-Specific AC Interface Processing desc.*/
|
||||
#define USB_CA_EXTENSION_UNIT_DESCRIPTOR 8 /**< Audio Class-Specific AC Interface Extension desc. */
|
||||
#define USB_CA_EP_GENERAL_DESCRIPTOR 1 /**< Audio Class-Specific general descriptor subtype code.*/
|
||||
#define USB_CA_AS_GENERAL_DESCRIPTOR 1 /**< Audio Class-Specific AS Interface General descriptor.*/
|
||||
#define USB_CA_FORMAT_TYPE_DESCRIPTOR 2 /**< Audio Class-Specific AS Interface Format Type desc. */
|
||||
|
||||
#define USB_DEVICE_DESCSIZE 18 /**< Device descriptor size. */
|
||||
#define USB_CONFIG_DESCSIZE 9 /**< Configuration descriptor size. */
|
||||
#define USB_INTERFACE_DESCSIZE 9 /**< Interface descriptor size. */
|
||||
#define USB_ENDPOINT_DESCSIZE 7 /**< Endpoint descriptor size. */
|
||||
#define USB_DEVICE_QUALIFIER_DESCSIZE 10 /**< Device qualifier descriptor size. */
|
||||
#define USB_OTHER_SPEED_CONFIG_DESCSIZE 9 /**< Device other speed configuration descriptor size. */
|
||||
#define USB_INTERFACE_ASSOCIATION_DESCSIZE 8 /**< INTERFACE_ASSOCIATION descriptor size. */
|
||||
#define USB_HID_DESCSIZE 9 /**< HID descriptor size. */
|
||||
#define USB_SMARTCARD_DESCSIZE 54 /**< CCID descriptor size. */
|
||||
#define USB_CDC_HEADER_FND_DESCSIZE 5 /**< CDC Header functional descriptor size. */
|
||||
#define USB_CDC_CALLMNG_FND_DESCSIZE 5 /**< CDC Call Management functional descriptor size. */
|
||||
#define USB_CDC_ACM_FND_DESCSIZE 4 /**< CDC Abstract Control Management functional descriptor size.*/
|
||||
#define USB_CA_INPUT_TERMINAL_DESCSIZE 12 /**< Audio Input Terminal descriptor size. */
|
||||
#define USB_CA_OUTPUT_TERMINAL_DESCSIZE 9 /**< Audio Output Terminal descriptor size. */
|
||||
#define USB_CA_EP_GENERAL_DESCSIZE 7 /**< Audio Class-Specific general descriptor subtype size.*/
|
||||
#define USB_CA_AS_GENERAL_DESCSIZE 7 /**< Audio Class-Specific AS Interface General desc size.*/
|
||||
#define USB_CA_STD_AS_ENDPOINT_DESCSZIE 9 /**< Audio-class standard audio stream descriptor size.*/
|
||||
|
||||
/* Misc. USB definitions */
|
||||
#define USB_LS_CTRL_EP_MAXSIZE 8 /**< The max size of low speed control endpoints. */
|
||||
#define USB_LS_INTR_EP_MAXSIZE 8 /**< The max size of low speed interrupt endpoints. */
|
||||
#define USB_FS_CTRL_EP_MAXSIZE 64 /**< The max size of full speed control endpoints. */
|
||||
#define USB_FS_INTR_EP_MAXSIZE 64 /**< The max size of full speed interrupt endpoints. */
|
||||
#define USB_FS_BULK_EP_MAXSIZE 64 /**< The max size of full speed bulk endpoints. */
|
||||
#define USB_FS_ISOC_EP_MAXSIZE 1023 /**< The max size of full speed isochronous endpoints. */
|
||||
#define USB_EPTYPE_CTRL 0 /**< Endpoint type control. */
|
||||
#define USB_EPTYPE_ISOC 1 /**< Endpoint type isochron. */
|
||||
#define USB_EPTYPE_BULK 2 /**< Endpoint type bulk. */
|
||||
#define USB_EPTYPE_INTR 3 /**< Endpoint type interrupt. */
|
||||
#define USB_EPSYNC_NO (0 << 2) /**< Endpoint synchronization type, none. */
|
||||
#define USB_EPSYNC_ASYNC (1 << 2) /**< Endpoint synchronization type, asynchronous. */
|
||||
#define USB_EPSYNC_ADAPTIVE (2 << 2) /**< Endpoint synchronization type, adaptive. */
|
||||
#define USB_EPSYNC_SYNC (3 << 2) /**< Endpoint synchronization type, synchronous. */
|
||||
#define USB_EP_DIR_IN 0x80 /**< Endpoint direction mask. */
|
||||
#define USB_SETUP_PKT_SIZE 8 /**< Setup request packet size. */
|
||||
#define USB_EPNUM_MASK 0x0F /**< Endpoint number mask. */
|
||||
#define USB_LANGID_ENUS 0x0409 /**< English-United States language id. */
|
||||
#define USB_MAX_DEVICE_ADDRESS 127 /**< Maximum allowable device address. */
|
||||
|
||||
#define CONFIG_DESC_BM_REMOTEWAKEUP 0x20 /**< Configuration descriptor attribute macro. */
|
||||
#define CONFIG_DESC_BM_SELFPOWERED 0x40 /**< Configuration descriptor attribute macro. */
|
||||
#define CONFIG_DESC_BM_RESERVED_D7 0x80 /**< Configuration descriptor attribute macro. */
|
||||
#define CONFIG_DESC_BM_TRANSFERTYPE 0x03 /**< Configuration descriptor transfer type bitmask. */
|
||||
#define CONFIG_DESC_MAXPOWER_mA(x) (((x)+1)/2) /**< Configuration descriptor power macro. */
|
||||
|
||||
#define DEVICE_IS_SELFPOWERED 0x0001 /**< Standard request GET_STATUS bitmask. */
|
||||
#define REMOTE_WAKEUP_ENABLED 0x0002 /**< Standard request GET_STATUS bitmask. */
|
||||
#define USB_FEATURE_ENDPOINT_HALT 0 /**< Standard request CLEAR/SET_FEATURE bitmask. */
|
||||
#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 /**< Standard request CLEAR/SET_FEATURE bitmask. */
|
||||
|
||||
#define HUB_FEATURE_PORT_RESET 4 /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
|
||||
#define HUB_FEATURE_PORT_POWER 8 /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
|
||||
#define HUB_FEATURE_C_PORT_CONNECTION 16 /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
|
||||
#define HUB_FEATURE_C_PORT_RESET 20 /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
|
||||
#define HUB_FEATURE_PORT_INDICATOR 22 /**< HUB class request CLEAR/SET_PORT_FEATURE feature selector. */
|
||||
|
||||
#define USB_CLASS_CDC 2 /**< CDC device/interface class code. */
|
||||
#define USB_CLASS_CDC_DATA 0x0A /**< CDC Data interface class code. */
|
||||
#define USB_CLASS_CDC_ACM 2 /**< CDC Abstract Control Model interface subclass code. */
|
||||
#define USB_CLASS_CDC_HFN 0 /**< CDC class Header Functional Descriptor subtype. */
|
||||
#define USB_CLASS_CDC_CMNGFN 1 /**< CDC class Call Management Functional Descriptor subtype.*/
|
||||
#define USB_CLASS_CDC_ACMFN 2 /**< CDC class Abstract Control Management Functional Descriptor subtype.*/
|
||||
#define USB_CLASS_CDC_UNIONFN 6 /**< CDC class Union Functional Descriptor subtype. */
|
||||
|
||||
#define USB_CLASS_HID 3 /**< HID device/interface class code. */
|
||||
#define USB_CLASS_HID_KEYBOARD 1 /**< HID keyboard interface protocol code. */
|
||||
#define USB_CLASS_HID_MOUSE 2 /**< HID mouse interface protocol code. */
|
||||
|
||||
#define USB_CLASS_HUB 9 /**< HUB device/interface class code. */
|
||||
|
||||
#define USB_CLASS_MSD 8 /**< MSD device/interface class code. */
|
||||
#define USB_CLASS_MSD_BOT_TRANSPORT 0x50 /**< MSD Bulk Only Transport protocol. */
|
||||
#define USB_CLASS_MSD_SCSI_CMDSET 6 /**< MSD Subclass SCSI transparent command set. */
|
||||
#define USB_CLASS_MSD_CSW_CMDPASSED 0 /**< MSD BOT Command status wrapper command passed code. */
|
||||
#define USB_CLASS_MSD_CSW_CMDFAILED 1 /**< MSD BOT Command status wrapper command failed code. */
|
||||
#define USB_CLASS_MSD_CSW_PHASEERROR 2 /**< MSD BOT Command status wrapper cmd phase error code.*/
|
||||
|
||||
#define USB_CLASS_AUDIO 1 /**< Audio interface class code. */
|
||||
#define USB_CLASS_AUDIO_CONTROL 1 /**< Audio subclass code for control interface. */
|
||||
#define USB_CLASS_AUDIO_STREAMING 2 /**< Audio subclass code for streaming interface. */
|
||||
#define USB_CLASS_AUDIO_MIDISTREAMING 3 /**< Audio subclass code for midi streaming interface. */
|
||||
|
||||
/*** Triplet for the device descriptor of a composite device using IAD descriptors. ***/
|
||||
#define USB_CLASS_MISCELLANEOUS 0xEF /**< MISCELLANEOUS device class code. */
|
||||
#define USB_CLASS_MISC_COMMON_SUBCLASS 2 /**< MISCELLANEOUS Common sub class code. */
|
||||
#define USB_CLASS_MISC_IAD_PROTOCOL 1 /**< MISCELLANEOUS Interface Association Descriptor protocol code. */
|
||||
|
||||
#define PORT_FULL_SPEED 1 /**< Full speed return value for USBH_GetPortSpeed(). */
|
||||
#define PORT_LOW_SPEED 2 /**< Low speed return value for USBH_GetPortSpeed(). */
|
||||
|
||||
#if defined( __GNUC__ ) /* GCC compilers */
|
||||
#if defined( __CHAR16_TYPE__ )
|
||||
typedef __CHAR16_TYPE__ char16_t;
|
||||
#else
|
||||
typedef unsigned short char16_t;
|
||||
#endif
|
||||
|
||||
#elif defined( __ICCARM__ ) /* IAR compiler */
|
||||
#include <uchar.h>
|
||||
|
||||
#elif defined( __CC_ARM ) /* MDK-ARM compiler */
|
||||
typedef unsigned short char16_t;
|
||||
#endif
|
||||
|
||||
/** Macro for creating USB compliant UTF-16LE UNICODE string descriptors.
|
||||
* @n Example: STATIC_CONST_STRING_DESC( iManufacturer, 'E','n','e','r','g','y',' ','M','i','c','r','o',' ','A','S' );
|
||||
* @note The size of the resulting struct will be two byte larger than a USB string
|
||||
* descriptor. This is to accommodate a terminating null char for the string.
|
||||
* The value assigned to the 'len' member does not take this into account
|
||||
* and is therefore correct usb wise.
|
||||
*/
|
||||
#define STATIC_CONST_STRING_DESC( _name, ... ) \
|
||||
EFM32_PACK_START( 1 ) \
|
||||
typedef struct \
|
||||
{ \
|
||||
uint8_t len; \
|
||||
uint8_t type; \
|
||||
char16_t name[ 1 + sizeof( (char16_t[]){__VA_ARGS__} ) / 2]; \
|
||||
} __attribute__ ((packed)) _##_name; \
|
||||
EFM32_PACK_END() \
|
||||
EFM32_ALIGN( 4 ) \
|
||||
EFM32_PACK_START( 1 ) \
|
||||
static const _##_name _name __attribute__ ((aligned(4)))= \
|
||||
{ \
|
||||
.len = sizeof( _##_name ) - 2, \
|
||||
.type = USB_STRING_DESCRIPTOR, \
|
||||
.name = {__VA_ARGS__}, \
|
||||
.name[ ( ( sizeof( _##_name ) - 2 ) / 2 ) - 1 ] = '\0' \
|
||||
} \
|
||||
EFM32_PACK_END()
|
||||
|
||||
/** Macro for creating USB compliant language string descriptors.
|
||||
* @n Example: STATIC_CONST_STRING_DESC_LANGID( langID, 0x04, 0x09 );
|
||||
*/
|
||||
#define STATIC_CONST_STRING_DESC_LANGID( _name, x, y ) \
|
||||
EFM32_PACK_START( 1 ) \
|
||||
typedef struct \
|
||||
{ \
|
||||
uint8_t len; \
|
||||
uint8_t type; \
|
||||
uint8_t name[ 2 ]; \
|
||||
} __attribute__ ((packed)) _##_name; \
|
||||
EFM32_PACK_END() \
|
||||
EFM32_ALIGN( 4 ) \
|
||||
EFM32_PACK_START( 1 ) \
|
||||
static const _##_name _name __attribute__ ((aligned(4)))= \
|
||||
{ \
|
||||
.len = 4, \
|
||||
.type = USB_STRING_DESCRIPTOR, \
|
||||
.name = { y, x } \
|
||||
} \
|
||||
EFM32_PACK_END()
|
||||
|
||||
/** Macro for creating WORD (4 byte) aligned uint8_t array with size which
|
||||
* is a multiple of WORD size.
|
||||
* @n Example: @n UBUF( rxBuffer, 37 ); => uint8_t rxBuffer[ 40 ];
|
||||
*/
|
||||
#if !defined(__GNUC__)
|
||||
#define UBUF( x, y ) EFM32_ALIGN( 4 ) uint8_t x[((y)+3)&~3]
|
||||
#define STATIC_UBUF( x, y ) EFM32_ALIGN( 4 ) static uint8_t x[((y)+3)&~3]
|
||||
#else
|
||||
#define UBUF( x, y ) uint8_t x[((y)+3)&~3] __attribute__ ((aligned(4)))
|
||||
|
||||
/** Macro for creating WORD (4 byte) aligned static uint8_t arrays with size which
|
||||
* is a multiple of WORD size.
|
||||
* @n Example: @n STATIC_UBUF( rxBuffer, 37 ); => static uint8_t rxBuffer[ 40 ];
|
||||
*/
|
||||
#define STATIC_UBUF( x, y ) static uint8_t x[((y)+3)&~3] __attribute__ ((aligned(4)))
|
||||
#endif
|
||||
|
||||
|
||||
/** @brief USB transfer status enumerator. */
|
||||
typedef enum
|
||||
{
|
||||
/* NOTE: Please keep in sync with table errMsg[] in em_usbhal.c */
|
||||
USB_STATUS_OK = 0, /**< No errors detected. */
|
||||
USB_STATUS_REQ_ERR = -1, /**< Setup request error. */
|
||||
USB_STATUS_EP_BUSY = -2, /**< Endpoint is busy. */
|
||||
USB_STATUS_REQ_UNHANDLED = -3, /**< Setup request not handled. */
|
||||
USB_STATUS_ILLEGAL = -4, /**< Illegal operation attempted. */
|
||||
USB_STATUS_EP_STALLED = -5, /**< Endpoint is stalled. */
|
||||
USB_STATUS_EP_ABORTED = -6, /**< Endpoint transfer was aborted. */
|
||||
USB_STATUS_EP_ERROR = -7, /**< Endpoint transfer error. */
|
||||
USB_STATUS_EP_NAK = -8, /**< Endpoint NAK'ed transfer request. */
|
||||
USB_STATUS_DEVICE_UNCONFIGURED = -9, /**< Device is unconfigured. */
|
||||
USB_STATUS_DEVICE_SUSPENDED = -10, /**< Device is suspended. */
|
||||
USB_STATUS_DEVICE_RESET = -11, /**< Device is/was reset. */
|
||||
USB_STATUS_TIMEOUT = -12, /**< Transfer timeout. */
|
||||
USB_STATUS_DEVICE_REMOVED = -13, /**< Device was removed. */
|
||||
USB_STATUS_HC_BUSY = -14, /**< Host channel is busy. */
|
||||
USB_STATUS_DEVICE_MALFUNCTION = -15, /**< Malfunctioning device attached. */
|
||||
USB_STATUS_PORT_OVERCURRENT = -16, /**< VBUS shortcircuit/overcurrent failure. */
|
||||
} USB_Status_TypeDef;
|
||||
/** @} (end addtogroup USB_COMMON) */
|
||||
|
||||
|
||||
#if defined( USB_DEVICE )
|
||||
/***************************************************************************//**
|
||||
* @addtogroup USB_DEVICE
|
||||
* @brief USB DEVICE protocol stack, see @ref usb_device page for detailed documentation.
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
#define USB_PWRSAVE_MODE_OFF 0 /**< No energy saving mode selected. */
|
||||
#define USB_PWRSAVE_MODE_ONSUSPEND 1 /**< Enter USB power-save mode on suspend. */
|
||||
#define USB_PWRSAVE_MODE_ONVBUSOFF 2 /**< Enter USB power-save mode when not attached to host. */
|
||||
#define USB_PWRSAVE_MODE_ENTEREM2 4 /**< Enter EM2 while in power-save mode. */
|
||||
|
||||
#define USB_USBC_32kHz_CLK_LFXO 0 /**< Use 32kHz LFXO clock while in powersave mode. */
|
||||
#define USB_USBC_32kHz_CLK_LFRCO 1 /**< Use 32kHz LFRCO clock while in powersave mode. */
|
||||
|
||||
/** @brief USB device state enumerator. */
|
||||
typedef enum
|
||||
{
|
||||
USBD_STATE_NONE = 0, /**< Device state is undefined/unknown. */
|
||||
USBD_STATE_ATTACHED = 1, /**< Device state is ATTACHED. */
|
||||
USBD_STATE_POWERED = 2, /**< Device state is POWERED. */
|
||||
USBD_STATE_DEFAULT = 3, /**< Device state is DEFAULT. */
|
||||
USBD_STATE_ADDRESSED = 4, /**< Device state is ADDRESSED. */
|
||||
USBD_STATE_CONFIGURED = 5, /**< Device state is CONFIGURED. */
|
||||
USBD_STATE_SUSPENDED = 6, /**< Device state is SUSPENDED. */
|
||||
USBD_STATE_LASTMARKER = 7, /**< Device state enum end marker. */
|
||||
} USBD_State_TypeDef;
|
||||
/** @} (end addtogroup USB_DEVICE) */
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
|
||||
/** @addtogroup USB_COMMON
|
||||
* @{*/
|
||||
|
||||
/** @brief USB Setup request package. */
|
||||
EFM32_PACK_START( 1 )
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t Recipient : 5; /**< Request recipient (device, interface, endpoint or other).*/
|
||||
uint8_t Type : 2; /**< Request type (standard, class or vendor). */
|
||||
uint8_t Direction : 1; /**< Transfer direction of SETUP data phase. */
|
||||
};
|
||||
uint8_t bmRequestType; /**< Request characteristics. */
|
||||
};
|
||||
uint8_t bRequest; /**< Request code. */
|
||||
uint16_t wValue; /**< Varies according to request. */
|
||||
uint16_t wIndex; /**< Index or offset, varies according to request. */
|
||||
uint16_t wLength; /**< Number of bytes to transfer if there is a data stage.*/
|
||||
};
|
||||
uint32_t dw[2];
|
||||
};
|
||||
} __attribute__ ((packed)) USB_Setup_TypeDef;
|
||||
EFM32_PACK_END()
|
||||
|
||||
|
||||
/** @brief USB Device Descriptor. */
|
||||
EFM32_PACK_START( 1 )
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; /**< Size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /**< Constant DEVICE Descriptor Type */
|
||||
uint16_t bcdUSB; /**< USB Specification Release Number in Binary-Coded
|
||||
Decimal */
|
||||
uint8_t bDeviceClass; /**< Class code (assigned by the USB-IF) */
|
||||
uint8_t bDeviceSubClass; /**< Subclass code (assigned by the USB-IF) */
|
||||
uint8_t bDeviceProtocol; /**< Protocol code (assigned by the USB-IF) */
|
||||
uint8_t bMaxPacketSize0; /**< Maximum packet size for endpoint zero */
|
||||
uint16_t idVendor; /**< Vendor ID (assigned by the USB-IF) */
|
||||
uint16_t idProduct; /**< Product ID (assigned by the manufacturer) */
|
||||
uint16_t bcdDevice; /**< Device release number in binary-coded decimal */
|
||||
uint8_t iManufacturer; /**< Index of string descriptor describing manufacturer*/
|
||||
uint8_t iProduct; /**< Index of string descriptor describing product */
|
||||
uint8_t iSerialNumber; /**< Index of string descriptor describing the device
|
||||
serialnumber */
|
||||
uint8_t bNumConfigurations; /**< Number of possible configurations */
|
||||
} __attribute__ ((packed)) USB_DeviceDescriptor_TypeDef;
|
||||
EFM32_PACK_END()
|
||||
|
||||
|
||||
/** @brief USB Configuration Descriptor. */
|
||||
EFM32_PACK_START( 1 )
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; /**< Size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /**< Constant CONFIGURATION Descriptor Type */
|
||||
uint16_t wTotalLength; /**< Total length of data returned for this
|
||||
configuration. Includes the combined length of all
|
||||
descriptors (configuration, interface, endpoint,
|
||||
and class- or vendor-specific) returned for this
|
||||
configuration. */
|
||||
uint8_t bNumInterfaces; /**< Number of interfaces supported by this
|
||||
configuration */
|
||||
uint8_t bConfigurationValue; /**< Value to use as an argument to the
|
||||
SetConfiguration request to select this
|
||||
configuration. */
|
||||
uint8_t iConfiguration; /**< Index of string descriptor describing this
|
||||
configuration. */
|
||||
uint8_t bmAttributes; /**< Configuration characteristics.
|
||||
@n D7: Reserved (set to one)
|
||||
@n D6: Self-powered
|
||||
@n D5: Remote Wakeup
|
||||
@n D4...0: Reserved (reset to zero) */
|
||||
uint8_t bMaxPower; /**< Maximum power consumption of the USB device, unit
|
||||
is 2mA per LSB */
|
||||
} __attribute__ ((packed)) USB_ConfigurationDescriptor_TypeDef;
|
||||
EFM32_PACK_END()
|
||||
|
||||
|
||||
/** @brief USB Interface Descriptor. */
|
||||
EFM32_PACK_START( 1 )
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; /**< Size of this descriptor in bytes. */
|
||||
uint8_t bDescriptorType; /**< Constant INTERFACE Descriptor Type. */
|
||||
uint8_t bInterfaceNumber; /**< Number of this interface. Zero-based value
|
||||
identifying the index in the array of concurrent
|
||||
interfaces supported by this configuration. */
|
||||
uint8_t bAlternateSetting; /**< Value used to select this alternate setting for
|
||||
the interface identified in the prior field. */
|
||||
uint8_t bNumEndpoints; /**< Number of endpoints used by this interface
|
||||
(excluding endpoint zero). If this value is zero,
|
||||
this interface only uses the Default Control Pipe.*/
|
||||
uint8_t bInterfaceClass; /**< Class code (assigned by the USB-IF). A value
|
||||
of zero is reserved for future standardization. If
|
||||
this field is set to FFH, the interface class is
|
||||
vendor-specific. All other values are reserved for
|
||||
assignment by the USB-IF. */
|
||||
uint8_t bInterfaceSubClass; /**< Subclass code (assigned by the USB-IF). These codes
|
||||
are qualified by the value of the bInterfaceClass
|
||||
field. If the bInterfaceClass field is reset to
|
||||
zero, this field must also be reset to zero. If
|
||||
the bInterfaceClass field is not set to FFH, all
|
||||
values are reserved forassignment by the USB-IF. */
|
||||
uint8_t bInterfaceProtocol; /**< Protocol code (assigned by the USB). These codes
|
||||
are qualified by the value of the bInterfaceClass
|
||||
and the bInterfaceSubClass fields. If an interface
|
||||
supports class-specific requests, this code
|
||||
identifies the protocols that the device uses as
|
||||
defined by the specification of the device class.
|
||||
If this field is reset to zero, the device does
|
||||
not use a class-specific protocol on this
|
||||
interface. If this field is set to FFH, the device
|
||||
uses a vendor-specific protocol for this interface*/
|
||||
uint8_t iInterface; /**< Index of string descriptor describing this
|
||||
interface. */
|
||||
} __attribute__ ((packed)) USB_InterfaceDescriptor_TypeDef;
|
||||
EFM32_PACK_END()
|
||||
|
||||
|
||||
/** @brief USB Endpoint Descriptor. */
|
||||
EFM32_PACK_START( 1 )
|
||||
typedef struct
|
||||
{
|
||||
uint8_t bLength; /**< Size of this descriptor in bytes */
|
||||
uint8_t bDescriptorType; /**< Constant ENDPOINT Descriptor Type */
|
||||
uint8_t bEndpointAddress; /**< The address of the endpoint */
|
||||
uint8_t bmAttributes; /**< This field describes the endpoint attributes */
|
||||
uint16_t wMaxPacketSize; /**< Maximum packet size for the endpoint */
|
||||
uint8_t bInterval; /**< Interval for polling EP for data transfers */
|
||||
} __attribute__ ((packed)) USB_EndpointDescriptor_TypeDef;
|
||||
EFM32_PACK_END()
|
||||
|
||||
|
||||
/** @brief USB String Descriptor. */
|
||||
EFM32_PACK_START( 1 )
|
||||
typedef struct
|
||||
{
|
||||
uint8_t len; /**< Size of this descriptor in bytes. */
|
||||
uint8_t type; /**< Constant STRING Descriptor Type. */
|
||||
char16_t name[]; /**< The string encoded with UTF-16LE UNICODE charset. */
|
||||
} __attribute__ ((packed)) USB_StringDescriptor_TypeDef;
|
||||
EFM32_PACK_END()
|
||||
|
||||
/** @} (end addtogroup USB_COMMON) */
|
||||
|
||||
/*** -------------------- Serial port debug configuration ---------------- ***/
|
||||
|
||||
#if defined( DOXY_DOC_ONLY )
|
||||
/** @addtogroup USB_COMMON
|
||||
* @{*/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Transmit a single char on the debug serial port.
|
||||
*
|
||||
* @note
|
||||
* This function is enabled with \#define DEBUG_USB_API when configuring the
|
||||
* protocol stack in "usbconfig.h".
|
||||
* This is convenient when debugging code, no need to remove use of this
|
||||
* function when debugging has completed.
|
||||
*
|
||||
* @param[in] c
|
||||
* Char to transmit.
|
||||
*
|
||||
* @return
|
||||
* The char transmitted.
|
||||
******************************************************************************/
|
||||
int USB_PUTCHAR( char c );
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Transmit a zero terminated string on the debug serial port.
|
||||
*
|
||||
* @note
|
||||
* This function is enabled with \#define DEBUG_USB_API when configuring the
|
||||
* protocol stack in "usbconfig.h".
|
||||
* This is convenient when debugging code, no need to remove use of this
|
||||
* function when debugging has completed.
|
||||
*
|
||||
* @param[in] p
|
||||
* Pointer to string to transmit.
|
||||
******************************************************************************/
|
||||
void USB_PUTS( const char *p );
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Transmit "printf" formated data on the debug serial port.
|
||||
*
|
||||
* @note
|
||||
* This function is enabled with \#define USB_USE_PRINTF when configuring the
|
||||
* protocol stack in "usbconfig.h".
|
||||
* This is convenient when debugging code, no need to remove use of this
|
||||
* function when debugging has completed.
|
||||
*
|
||||
* @param[in] format
|
||||
* Format string (as in printf). No floating point format support.
|
||||
******************************************************************************/
|
||||
int USB_PRINTF( const char *format, ... );
|
||||
|
||||
/** @} (end addtogroup USB_COMMON) */
|
||||
#endif /* defined( DOXY_DOC_ONLY ) */
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
/* Hardware constraint, do not change. */
|
||||
#define MAX_NUM_HOSTCHANNELS 14
|
||||
|
||||
/* The DMA engine use one FIFO ram word for each host channel. */
|
||||
#define MAX_HOST_FIFO_SIZE_INWORDS (512-MAX_NUM_HOSTCHANNELS)/*Unit is 4 bytes*/
|
||||
|
||||
#if defined ( USER_PUTCHAR )
|
||||
void USB_Puts( const char *p );
|
||||
#define USB_PUTS( s ) USB_Puts( s )
|
||||
#define USB_PUTCHAR( c ) USER_PUTCHAR( c )
|
||||
#else
|
||||
#define USB_PUTS( s )
|
||||
#define USB_PUTCHAR( c )
|
||||
#endif
|
||||
|
||||
#if defined( USB_USE_PRINTF )
|
||||
/* Use a printf which don't support floating point formatting */
|
||||
#if defined(__ICCARM__) || defined (__CC_ARM) || defined (__CROSSWORKS_ARM)
|
||||
#define USB_PRINTF printf
|
||||
#else
|
||||
#define USB_PRINTF iprintf
|
||||
#endif
|
||||
#else
|
||||
#define USB_PRINTF(...)
|
||||
#endif /* defined( USB_USE_PRINTF ) */
|
||||
|
||||
#if defined( DEBUG_USB_API )
|
||||
#define DEBUG_USB_API_PUTS( s ) USB_PUTS( s )
|
||||
#define DEBUG_USB_API_PUTCHAR( c ) USB_PUTCHAR( c )
|
||||
#else
|
||||
#define DEBUG_USB_API_PUTS( s )
|
||||
#define DEBUG_USB_API_PUTCHAR( c )
|
||||
#endif /* defined( DEBUG_USB_API ) */
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/*** -------------------- Common API definitions ------------------------- ***/
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
#if defined( USB_HOST )
|
||||
#if defined( NUM_APP_TIMERS )
|
||||
#define NUM_QTIMERS ( NUM_HC_USED + 2 + NUM_APP_TIMERS + 1 )
|
||||
#else
|
||||
#define NUM_QTIMERS ( NUM_HC_USED + 2 + 1 )
|
||||
#endif
|
||||
/* + 2 for default ctrl. host ch. 0 & 1, + 1 for host port timer */
|
||||
#else
|
||||
#if defined( NUM_APP_TIMERS )
|
||||
#define NUM_QTIMERS ( NUM_APP_TIMERS )
|
||||
#else
|
||||
#define NUM_QTIMERS 0
|
||||
#endif
|
||||
#endif /* defined( USB_HOST ) */
|
||||
/** @endcond */
|
||||
|
||||
/** @addtogroup USB_COMMON
|
||||
* @{*/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* USB transfer callback function.
|
||||
*
|
||||
* @details
|
||||
* The callback function is called when a transfer has completed. An application
|
||||
* should check the status, xferred and optionally the remaining parameters
|
||||
* before deciding if the transfer is usable. In the case where the transfer
|
||||
* is part of a control request data stage, the callback function should
|
||||
* return an appropriate @ref USB_Status_TypeDef status.
|
||||
*
|
||||
* @param[in] status
|
||||
* The transfer status. See @ref USB_Status_TypeDef.
|
||||
*
|
||||
* @param[in] xferred
|
||||
* Number of bytes actually transferred.
|
||||
*
|
||||
* @param[in] remaining
|
||||
* Number of bytes not transferred.
|
||||
*
|
||||
* @return
|
||||
* @ref USB_STATUS_OK on success, else an appropriate error code.
|
||||
******************************************************************************/
|
||||
typedef int (*USB_XferCompleteCb_TypeDef)( USB_Status_TypeDef status, uint32_t xferred, uint32_t remaining );
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* USBTIMER callback function.
|
||||
*
|
||||
* @details
|
||||
* The callback function is called when an USBTIMER has expired. The callback
|
||||
* is done with interrupts disabled.
|
||||
******************************************************************************/
|
||||
typedef void (*USBTIMER_Callback_TypeDef)( void );
|
||||
|
||||
char *USB_GetErrorMsgString( int error );
|
||||
|
||||
#if defined( USB_USE_PRINTF )
|
||||
void USB_PrintErrorMsgString( char *pre, int error );
|
||||
#else
|
||||
#define USB_PrintErrorMsgString( pre, error )
|
||||
#endif
|
||||
|
||||
void USBTIMER_DelayMs( uint32_t msec );
|
||||
void USBTIMER_DelayUs( uint32_t usec );
|
||||
void USBTIMER_Init( void );
|
||||
|
||||
#if ( NUM_QTIMERS > 0 )
|
||||
void USBTIMER_Start( uint32_t id, uint32_t timeout, USBTIMER_Callback_TypeDef callback );
|
||||
void USBTIMER_Stop( uint32_t id );
|
||||
#endif /* ( NUM_QTIMERS > 0 ) */
|
||||
/** @} (end addtogroup USB_COMMON) */
|
||||
|
||||
#if defined( USB_DEVICE )
|
||||
/** @addtogroup USB_DEVICE
|
||||
* @{*/
|
||||
/*** -------------------- DEVICE mode API definitions -------------------- ***/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* USB Reset callback function.
|
||||
* @details
|
||||
* Called whenever USB reset signalling is detected on the USB port.
|
||||
******************************************************************************/
|
||||
typedef void (*USBD_UsbResetCb_TypeDef)( void );
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* USB Start Of Frame (SOF) interrupt callback function.
|
||||
*
|
||||
* @details
|
||||
* Called at each SOF interrupt (if enabled),
|
||||
*
|
||||
* @param[in] sofNr
|
||||
* Current frame number. The value rolls over to 0 after 16383 (0x3FFF).
|
||||
******************************************************************************/
|
||||
typedef void (*USBD_SofIntCb_TypeDef)( uint16_t sofNr );
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* USB State change callback function.
|
||||
*
|
||||
* @details
|
||||
* Called whenever the device change state.
|
||||
*
|
||||
* @param[in] oldState
|
||||
* The device USB state just leaved. See @ref USBD_State_TypeDef.
|
||||
*
|
||||
* @param[in] newState
|
||||
* New (the current) USB device state. See @ref USBD_State_TypeDef.
|
||||
******************************************************************************/
|
||||
typedef void (*USBD_DeviceStateChangeCb_TypeDef)( USBD_State_TypeDef oldState, USBD_State_TypeDef newState );
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* USB power mode callback function.
|
||||
*
|
||||
* @details
|
||||
* Called whenever the device stack needs to query if the device is currently
|
||||
* self- or bus-powered. Typically when host has issued an @ref GET_STATUS
|
||||
* setup command.
|
||||
*
|
||||
* @return
|
||||
* True if self-powered, false otherwise.
|
||||
******************************************************************************/
|
||||
typedef bool (*USBD_IsSelfPoweredCb_TypeDef)( void );
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* USB setup request callback function.
|
||||
*
|
||||
* @details
|
||||
* Called on each setup request received from host. This gives the application a
|
||||
* possibility to extend or override standard requests, and to implement class
|
||||
* or vendor specific requests. Return @ref USB_STATUS_OK if the request is
|
||||
* handled, return @ref USB_STATUS_REQ_ERR if it is an illegal request or
|
||||
* return @ref USB_STATUS_REQ_UNHANDLED to pass the request on to the default
|
||||
* request handler.
|
||||
*
|
||||
* @param[in] setup
|
||||
* Pointer to an USB setup packet. See @ref USB_Setup_TypeDef.
|
||||
*
|
||||
* @return
|
||||
* An appropriate status/error code. See @ref USB_Status_TypeDef.
|
||||
******************************************************************************/
|
||||
typedef int (*USBD_SetupCmdCb_TypeDef)( const USB_Setup_TypeDef *setup );
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
struct USBD_Callbacks_TypeDef;
|
||||
typedef struct USBD_Callbacks_TypeDef const *USBD_Callbacks_TypeDef_Pointer;
|
||||
/** @endcond */
|
||||
|
||||
|
||||
/** @brief USB Device stack initialization structure.
|
||||
* @details This structure is passed to @ref USBD_Init() when starting up
|
||||
* the device. */
|
||||
typedef struct
|
||||
{
|
||||
const USB_DeviceDescriptor_TypeDef *deviceDescriptor; /**< Pointer to a device descriptor. */
|
||||
const uint8_t *configDescriptor; /**< Pointer to a configuration descriptor. */
|
||||
const void * const *stringDescriptors; /**< Pointer to an array of string descriptor pointers.*/
|
||||
const uint8_t numberOfStrings; /**< Number of strings in string descriptor array. */
|
||||
const uint8_t *bufferingMultiplier; /**< Pointer to an array defining the size of the
|
||||
endpoint buffers. The size is given in
|
||||
multiples of endpoint size. Generally a value
|
||||
of 1 (single) or 2 (double) buffering should be
|
||||
used. */
|
||||
USBD_Callbacks_TypeDef_Pointer callbacks; /**< Pointer to struct with callbacks
|
||||
(@ref USBD_Callbacks_TypeDef). These callbacks
|
||||
are used by the device stack to signal events
|
||||
to or query the application. */
|
||||
const uint32_t reserved; /**< Reserved for future use. */
|
||||
} USBD_Init_TypeDef;
|
||||
|
||||
|
||||
/** @brief USB Device stack callback structure.
|
||||
* @details Callback functions used by the device stack to signal events or
|
||||
* query status to/from the application. See @ref USBD_Init_TypeDef. Assign
|
||||
* members to NULL if your application don't need a specific callback. */
|
||||
typedef struct USBD_Callbacks_TypeDef
|
||||
{
|
||||
const USBD_UsbResetCb_TypeDef usbReset; /**< Called whenever USB reset signalling is detected
|
||||
on the USB port. */
|
||||
const USBD_DeviceStateChangeCb_TypeDef usbStateChange; /**< Called whenever the device change state. */
|
||||
const USBD_SetupCmdCb_TypeDef setupCmd; /**< Called on each setup request received from host.*/
|
||||
const USBD_IsSelfPoweredCb_TypeDef isSelfPowered; /**< Called whenever the device stack needs to query
|
||||
if the device is currently self- or bus-powered.
|
||||
Applies to devices which can operate in both modes.*/
|
||||
const USBD_SofIntCb_TypeDef sofInt; /**< Called at each SOF interrupt. If NULL, the device
|
||||
stack will not enable the SOF interrupt. */
|
||||
} USBD_Callbacks_TypeDef;
|
||||
|
||||
|
||||
/*** -------------------- DEVICE mode API -------------------------------- ***/
|
||||
|
||||
void USBD_AbortAllTransfers( void );
|
||||
int USBD_AbortTransfer( int epAddr );
|
||||
void USBD_Connect( void );
|
||||
void USBD_Disconnect( void );
|
||||
bool USBD_EpIsBusy( int epAddr );
|
||||
USBD_State_TypeDef USBD_GetUsbState( void );
|
||||
const char * USBD_GetUsbStateName( USBD_State_TypeDef state );
|
||||
int USBD_Init( const USBD_Init_TypeDef *p );
|
||||
int USBD_Read( int epAddr, void *data, int byteCount, USB_XferCompleteCb_TypeDef callback );
|
||||
int USBD_RemoteWakeup( void );
|
||||
bool USBD_SafeToEnterEM2( void );
|
||||
int USBD_StallEp( int epAddr );
|
||||
void USBD_Stop( void );
|
||||
int USBD_UnStallEp( int epAddr );
|
||||
int USBD_Write( int epAddr, void *data, int byteCount, USB_XferCompleteCb_TypeDef callback );
|
||||
|
||||
#ifdef __MBED__
|
||||
int USBD_SetAddress( uint8_t addr );
|
||||
int USBD_AddEndpoint( int epAddr, int transferType, int maxPacketSize, int bufferMult );
|
||||
int USBD_EpIsStalled( int epAddr );
|
||||
void USBD_StallEp0( void );
|
||||
#endif
|
||||
|
||||
/** @} (end addtogroup USB_DEVICE) */
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
|
||||
|
||||
#if defined( USB_HOST )
|
||||
/***************************************************************************//**
|
||||
* @addtogroup USB_HOST
|
||||
* @brief USB HOST protocol stack, see @ref usb_host page for detailed documentation.
|
||||
* @{
|
||||
******************************************************************************/
|
||||
/*** -------------------- HOST mode API definitions ---------------------- ***/
|
||||
|
||||
#define USB_VBUSOVRCUR_PORT_NONE -1 /**< No overcurrent flag functionality. */
|
||||
#define USB_VBUSOVRCUR_POLARITY_LOW 0 /**< Overcurrent flag pin polarity is low. */
|
||||
#define USB_VBUSOVRCUR_POLARITY_HIGH 1 /**< Overcurrent flag pin polarity is high. */
|
||||
|
||||
/** USB HOST endpoint status enumerator. */
|
||||
typedef enum
|
||||
{
|
||||
H_EP_IDLE = 0, /**< The endpoint is idle. */
|
||||
H_EP_SETUP = 1, /**< The endpoint is in SETUP stage. */
|
||||
H_EP_DATA_IN = 2, /**< The endpoint is in DATA IN stage. */
|
||||
H_EP_DATA_OUT = 3, /**< The endpoint is in DATA OUT stage. */
|
||||
H_EP_STATUS_IN = 4, /**< The endpoint is in STATUS IN stage. */
|
||||
H_EP_STATUS_OUT = 5, /**< The endpoint is in STATUS OUT stage. */
|
||||
} USBH_EpState_TypeDef;
|
||||
|
||||
|
||||
/** @brief USB HOST endpoint status data.
|
||||
* @details A host application should not manipulate the contents of
|
||||
* this struct. */
|
||||
typedef struct
|
||||
{
|
||||
USB_Setup_TypeDef setup; /**< A SETUP package. */
|
||||
uint8_t setupErrCnt; /**< Error counter for SETUP transfers. */
|
||||
USB_EndpointDescriptor_TypeDef epDesc; /**< Endpoint descriptor. */
|
||||
struct USBH_Device_TypeDef *parentDevice; /**< The device the endpoint belongs to. */
|
||||
uint8_t type; /**< Endpoint type. */
|
||||
uint16_t packetSize; /**< Packet size, current transfer. */
|
||||
uint8_t hcOut; /**< Host channel number assigned for OUT transfers. */
|
||||
uint8_t hcIn; /**< Host channel number assigned for IN transfers. */
|
||||
bool in; /**< Endpoint direction. */
|
||||
uint8_t toggle; /**< Endpoint data toggle. */
|
||||
USBH_EpState_TypeDef state; /**< Endpoint state. */
|
||||
uint8_t addr; /**< Endpoint address. */
|
||||
uint8_t *buf; /**< Transfer buffer. */
|
||||
volatile bool xferCompleted; /**< Transfer completion flag. */
|
||||
USB_Status_TypeDef xferStatus; /**< Transfer status. */
|
||||
USB_XferCompleteCb_TypeDef xferCompleteCb; /**< Transfer completion callback function. */
|
||||
uint32_t xferred; /**< Number of bytes transferred. */
|
||||
uint32_t remaining; /**< Number of bytes remaining. */
|
||||
uint32_t timeout; /**< Transfer timeout. */
|
||||
} USBH_Ep_TypeDef;
|
||||
|
||||
|
||||
/** @brief USB HOST device definition.
|
||||
* @details A host application should not manipulate the contents of
|
||||
* this struct. */
|
||||
typedef struct USBH_Device_TypeDef
|
||||
{
|
||||
USB_DeviceDescriptor_TypeDef devDesc; /**< The device device descriptor. */
|
||||
USB_ConfigurationDescriptor_TypeDef confDesc; /**< The device configuration descriptor. */
|
||||
USB_InterfaceDescriptor_TypeDef itfDesc; /**< The device interface descriptor. */
|
||||
USBH_Ep_TypeDef ep0; /**< Endpoint 0 status data. */
|
||||
USBH_Ep_TypeDef *ep; /**< Array of endpoint status data. */
|
||||
int numEp; /**< Number of endpoints. */
|
||||
uint8_t addr; /**< The device address. */
|
||||
uint8_t speed; /**< The device speed (low or full speed). */
|
||||
} USBH_Device_TypeDef;
|
||||
|
||||
|
||||
/** @brief USB Host stack initialization structure.
|
||||
* @details This structure is passed to @ref USBH_Init() when starting up the
|
||||
* device. Max accumulated FIFO size is 2K bytes. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t rxFifoSize; /**< Number of FIFO bytes set aside for IN endpoints. */
|
||||
uint32_t nptxFifoSize; /**< Number of FIFO bytes set aside for OUT CTRL/BULK endoints. */
|
||||
uint32_t ptxFifoSize; /**< Number of FIFO bytes set aside for OUT INTR/ISO endoints. */
|
||||
uint32_t reserved; /**< Reserved for future use. */
|
||||
} USBH_Init_TypeDef;
|
||||
|
||||
|
||||
/** Default @ref USBH_Init_TypeDef values, provides reasonable Tx/Rx FIFO
|
||||
* partitioning. */
|
||||
/* In DMA mode the total available FIFO space is smaller. */
|
||||
/* The DMA controller use one FIFO word pr. channel for status. */
|
||||
/* The unit in the table is byte. */
|
||||
#define USBH_INIT_DEFAULT \
|
||||
{ \
|
||||
MAX_HOST_FIFO_SIZE_INWORDS * 2,/* 1024 bytes Rx FIFO size. */ \
|
||||
MAX_HOST_FIFO_SIZE_INWORDS, /* 512 bytes non-periodic Tx FIFO size. */ \
|
||||
MAX_HOST_FIFO_SIZE_INWORDS, /* 512 bytes periodic Tx FIFO size. */ \
|
||||
0 /* Reserved. */ \
|
||||
}
|
||||
|
||||
/*** -------------------- HOST mode API ---------------------------------- ***/
|
||||
|
||||
int USBH_AssignHostChannel( USBH_Ep_TypeDef *ep, uint8_t hcnum );
|
||||
int USBH_ControlMsg( USBH_Ep_TypeDef *ep, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, void *data, int timeout, USB_XferCompleteCb_TypeDef callback );
|
||||
int USBH_ControlMsgB( USBH_Ep_TypeDef *ep, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint16_t wLength, void *data, int timeout );
|
||||
bool USBH_DeviceConnected( void );
|
||||
int USBH_GetConfigurationDescriptorB( USBH_Device_TypeDef *device, void *buf, int len, uint8_t configIndex );
|
||||
int USBH_GetDeviceDescriptorB( USBH_Device_TypeDef *device, void *buf, int len );
|
||||
uint8_t USBH_GetPortSpeed( void );
|
||||
int USBH_GetStringB( USBH_Device_TypeDef *device, uint8_t *buf, int bufLen, uint8_t stringIndex, uint16_t langID );
|
||||
int USBH_Init( const USBH_Init_TypeDef *p );
|
||||
int USBH_InitDeviceData( USBH_Device_TypeDef *device, const uint8_t *buf, USBH_Ep_TypeDef *ep, int numEp, uint8_t deviceSpeed );
|
||||
int USBH_PortReset( void );
|
||||
int USBH_PortResume( void );
|
||||
void USBH_PortSuspend( void );
|
||||
void USBH_PrintString( const char *pre, const USB_StringDescriptor_TypeDef *s, const char *post );
|
||||
|
||||
#if defined( USB_USE_PRINTF )
|
||||
int USBH_PrintConfigurationDescriptor( const USB_ConfigurationDescriptor_TypeDef *config, int maxLen );
|
||||
int USBH_PrintDeviceDescriptor( const USB_DeviceDescriptor_TypeDef *device );
|
||||
int USBH_PrintEndpointDescriptor( const USB_EndpointDescriptor_TypeDef *endpoint );
|
||||
int USBH_PrintInterfaceDescriptor( const USB_InterfaceDescriptor_TypeDef *interface );
|
||||
#else
|
||||
#define USBH_PrintConfigurationDescriptor( config, maxLen )
|
||||
#define USBH_PrintDeviceDescriptor( device )
|
||||
#define USBH_PrintEndpointDescriptor( endpoint )
|
||||
#define USBH_PrintInterfaceDescriptor( interface )
|
||||
#endif /* defined( USB_USE_PRINTF ) */
|
||||
|
||||
int USBH_QueryDeviceB( uint8_t *buf, size_t bufsize, uint8_t deviceSpeed );
|
||||
USB_ConfigurationDescriptor_TypeDef* USBH_QGetConfigurationDescriptor( const uint8_t *buf, int configIndex );
|
||||
USB_DeviceDescriptor_TypeDef* USBH_QGetDeviceDescriptor( const uint8_t *buf );
|
||||
USB_EndpointDescriptor_TypeDef* USBH_QGetEndpointDescriptor( const uint8_t *buf, int configIndex, int interfaceIndex, int endpointIndex );
|
||||
USB_InterfaceDescriptor_TypeDef* USBH_QGetInterfaceDescriptor( const uint8_t *buf, int configIndex, int interfaceIndex );
|
||||
|
||||
int USBH_Read( USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout, USB_XferCompleteCb_TypeDef callback );
|
||||
int USBH_ReadB( USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout );
|
||||
int USBH_SetAddressB( USBH_Device_TypeDef *device, uint8_t deviceAddress );
|
||||
int USBH_SetAltInterfaceB( USBH_Device_TypeDef *device, uint8_t interfaceIndex, uint8_t alternateSetting );
|
||||
int USBH_SetConfigurationB( USBH_Device_TypeDef *device, uint8_t configValue );
|
||||
int USBH_StallEpB( USBH_Ep_TypeDef *ep );
|
||||
void USBH_Stop( void );
|
||||
int USBH_UnStallEpB( USBH_Ep_TypeDef *ep );
|
||||
int USBH_WaitForDeviceConnectionB( uint8_t *buf, int timeoutInSeconds );
|
||||
int USBH_Write( USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout, USB_XferCompleteCb_TypeDef callback );
|
||||
int USBH_WriteB( USBH_Ep_TypeDef *ep, void *data, int byteCount, int timeout );
|
||||
|
||||
/** @} (end addtogroup USB_HOST) */
|
||||
#endif /* defined( USB_HOST ) */
|
||||
/** @} (end addtogroup USB) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
|
||||
#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
|
||||
#endif /* __EM_USB_H */
|
|
@ -0,0 +1,206 @@
|
|||
/***************************************************************************//**
|
||||
* @file em_usbd.h
|
||||
* @brief USB protocol stack library API for EFM32.
|
||||
* @version 3.20.14
|
||||
*******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __EM_USBD_H
|
||||
#define __EM_USBD_H
|
||||
|
||||
#include "em_device.h"
|
||||
#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
|
||||
#include "em_usb.h"
|
||||
#if defined( USB_DEVICE )
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
#if defined( DEBUG_USB_API )
|
||||
#define DEBUG_TRACE_ABORT( x ) \
|
||||
{ \
|
||||
if ( x == USB_STATUS_EP_STALLED ) \
|
||||
{ DEBUG_USB_API_PUTS( "\nEP cb(), EP stalled" ); } \
|
||||
else if ( x == USB_STATUS_EP_ABORTED ) \
|
||||
{ DEBUG_USB_API_PUTS( "\nEP cb(), EP aborted" ); } \
|
||||
else if ( x == USB_STATUS_DEVICE_UNCONFIGURED ) \
|
||||
{ DEBUG_USB_API_PUTS( "\nEP cb(), device unconfigured" ); } \
|
||||
else if ( x == USB_STATUS_DEVICE_SUSPENDED ) \
|
||||
{ DEBUG_USB_API_PUTS( "\nEP cb(), device suspended" ); } \
|
||||
else /* ( x == USB_STATUS_DEVICE_RESET ) */ \
|
||||
{ DEBUG_USB_API_PUTS( "\nEP cb(), device reset" ); } \
|
||||
}
|
||||
#else
|
||||
#define DEBUG_TRACE_ABORT( x )
|
||||
#endif
|
||||
|
||||
extern USBD_Device_TypeDef *dev;
|
||||
extern volatile bool USBD_poweredDown;
|
||||
|
||||
__STATIC_INLINE void USBD_ArmEp0( USBD_Ep_TypeDef *ep );
|
||||
__STATIC_INLINE void USBD_ArmEpN( USBD_Ep_TypeDef *ep );
|
||||
__STATIC_INLINE void USBD_AbortEp( USBD_Ep_TypeDef *ep );
|
||||
|
||||
void USBD_SetUsbState( USBD_State_TypeDef newState );
|
||||
|
||||
int USBDCH9_SetupCmd( USBD_Device_TypeDef *device );
|
||||
|
||||
void USBDEP_Ep0Handler( USBD_Device_TypeDef *device );
|
||||
void USBDEP_EpHandler( uint8_t epAddr );
|
||||
|
||||
__STATIC_INLINE void USBD_ActivateAllEps( bool forceIdle )
|
||||
{
|
||||
int i;
|
||||
|
||||
for ( i = 1; i <= NUM_EP_USED; i++ )
|
||||
{
|
||||
USBDHAL_ActivateEp( &dev->ep[ i ], forceIdle );
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBD_ArmEp( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
if ( ep->num == 0 )
|
||||
{
|
||||
USBD_ArmEp0( ep );
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_ArmEpN( ep );
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBD_ArmEp0( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
if ( ep->in )
|
||||
{
|
||||
if ( ep->remaining == 0 ) /* Zero Length Packet? */
|
||||
{
|
||||
ep->zlp = 1;
|
||||
}
|
||||
|
||||
USBDHAL_SetEp0InDmaPtr( ep->buf );
|
||||
USBDHAL_StartEp0In( EFM32_MIN( ep->remaining, ep->packetSize ),
|
||||
dev->ep0MpsCode );
|
||||
}
|
||||
else
|
||||
{
|
||||
USBDHAL_SetEp0OutDmaPtr( ep->buf );
|
||||
USBDHAL_StartEp0Out( ep->packetSize, dev->ep0MpsCode );
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBD_ArmEpN( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
if ( ep->in )
|
||||
{
|
||||
USBDHAL_StartEpIn( ep );
|
||||
}
|
||||
else
|
||||
{
|
||||
USBDHAL_StartEpOut( ep );
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBD_DeactivateAllEps( USB_Status_TypeDef reason )
|
||||
{
|
||||
int i;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
|
||||
for ( i = 1; i <= NUM_EP_USED; i++ )
|
||||
{
|
||||
ep = &dev->ep[ i ];
|
||||
|
||||
if ( ep->state == D_EP_IDLE )
|
||||
{
|
||||
USBDHAL_DeactivateEp( ep );
|
||||
}
|
||||
}
|
||||
|
||||
USBDHAL_AbortAllTransfers( reason );
|
||||
}
|
||||
|
||||
__STATIC_INLINE USBD_Ep_TypeDef *USBD_GetEpFromAddr( uint8_t epAddr )
|
||||
{
|
||||
int epIndex;
|
||||
USBD_Ep_TypeDef *ep = NULL;
|
||||
|
||||
if ( epAddr & USB_SETUP_DIR_MASK )
|
||||
{
|
||||
epIndex = dev->inEpAddr2EpIndex[ epAddr & USB_EPNUM_MASK ];
|
||||
}
|
||||
else
|
||||
{
|
||||
epIndex = dev->outEpAddr2EpIndex[ epAddr & USB_EPNUM_MASK ];
|
||||
}
|
||||
|
||||
if ( epIndex )
|
||||
{
|
||||
ep = &dev->ep[ epIndex ];
|
||||
}
|
||||
else if ( ( epAddr & USB_EPNUM_MASK ) == 0 )
|
||||
{
|
||||
ep = &dev->ep[ 0 ];
|
||||
}
|
||||
|
||||
return ep;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBD_ReArmEp0( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
if ( ep->in )
|
||||
{
|
||||
USBDHAL_StartEp0In( EFM32_MIN( ep->remaining, ep->packetSize ),
|
||||
dev->ep0MpsCode );
|
||||
}
|
||||
else
|
||||
{
|
||||
USBDHAL_StartEp0Out( ep->packetSize, dev->ep0MpsCode );
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBD_AbortEp( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
if ( ep->state == D_EP_IDLE )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ep->in )
|
||||
{
|
||||
USBDHAL_AbortEpIn( ep );
|
||||
}
|
||||
else
|
||||
{
|
||||
USBDHAL_AbortEpOut( ep );
|
||||
}
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
|
||||
#endif /* __EM_USBD_H */
|
|
@ -0,0 +1,75 @@
|
|||
/***************************************************************************//**
|
||||
* @file em_usbh.h
|
||||
* @brief USB protocol stack library API for EFM32.
|
||||
* @version 3.20.14
|
||||
*******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __EM_USBH_H
|
||||
#define __EM_USBH_H
|
||||
|
||||
#include "em_device.h"
|
||||
#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
|
||||
#include "em_usb.h"
|
||||
#if defined( USB_HOST )
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
extern USBH_Hc_TypeDef hcs[];
|
||||
extern int USBH_attachRetryCount;
|
||||
extern const USBH_AttachTiming_TypeDef USBH_attachTiming[];
|
||||
extern USBH_Init_TypeDef USBH_initData;
|
||||
extern volatile USBH_PortState_TypeDef USBH_portStatus;
|
||||
|
||||
USB_Status_TypeDef USBH_CtlSendSetup( USBH_Ep_TypeDef *ep );
|
||||
USB_Status_TypeDef USBH_CtlSendData( USBH_Ep_TypeDef *ep, uint16_t length );
|
||||
USB_Status_TypeDef USBH_CtlReceiveData( USBH_Ep_TypeDef *ep, uint16_t length );
|
||||
|
||||
#if defined( USB_RAW_API )
|
||||
int USBH_CtlRxRaw( uint8_t pid, USBH_Ep_TypeDef *ep, void *data, int byteCount );
|
||||
int USBH_CtlTxRaw( uint8_t pid, USBH_Ep_TypeDef *ep, void *data, int byteCount );
|
||||
#endif
|
||||
|
||||
void USBHEP_EpHandler( USBH_Ep_TypeDef *ep, USB_Status_TypeDef result );
|
||||
void USBHEP_CtrlEpHandler( USBH_Ep_TypeDef *ep, USB_Status_TypeDef result );
|
||||
void USBHEP_TransferDone( USBH_Ep_TypeDef *ep, USB_Status_TypeDef result );
|
||||
|
||||
__STATIC_INLINE uint16_t USBH_GetFrameNum( void )
|
||||
{
|
||||
return USBHHAL_GetFrameNum();
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool USBH_FrameNumIsEven( void )
|
||||
{
|
||||
return ( USBHHAL_GetFrameNum() & 1 ) == 0;
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined( USB_HOST ) */
|
||||
#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
|
||||
#endif /* __EM_USBH_H */
|
|
@ -0,0 +1,757 @@
|
|||
/***************************************************************************//**
|
||||
* @file em_usbhal.h
|
||||
* @brief USB protocol stack library, low level USB peripheral access.
|
||||
* @version 3.20.14
|
||||
*******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __EM_USBHAL_H
|
||||
#define __EM_USBHAL_H
|
||||
|
||||
#include "em_device.h"
|
||||
#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
|
||||
#include "em_usb.h"
|
||||
#if defined( USB_DEVICE ) || defined( USB_HOST )
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
#define USB_PID_DATA0 0
|
||||
#define USB_PID_DATA2 1
|
||||
#define USB_PID_DATA1 2
|
||||
#define USB_PID_SETUP 3
|
||||
|
||||
#define HPRT_F_SPEED ( 1 << _USB_HPRT_PRTSPD_SHIFT )
|
||||
#define HPRT_L_SPEED ( 2 << _USB_HPRT_PRTSPD_SHIFT )
|
||||
#define HCFG_PHYCLK_48MHZ 1
|
||||
#define HCFG_PHYCLK_6MHZ 2
|
||||
|
||||
#define DOEP0_XFERSIZE_PKTCNT_MASK ( _USB_DOEP0TSIZ_XFERSIZE_MASK | \
|
||||
_USB_DOEP0TSIZ_PKTCNT_MASK )
|
||||
#define DOEP_XFERSIZE_PKTCNT_MASK ( _USB_DOEP_TSIZ_XFERSIZE_MASK | \
|
||||
_USB_DOEP_TSIZ_PKTCNT_MASK )
|
||||
|
||||
#define DIEP0_XFERSIZE_PKTCNT_MASK ( _USB_DIEP0TSIZ_XFERSIZE_MASK | \
|
||||
_USB_DIEP0TSIZ_PKTCNT_MASK )
|
||||
#define DIEP_XFERSIZE_PKTCNT_MASK ( _USB_DIEP_TSIZ_XFERSIZE_MASK | \
|
||||
_USB_DIEP_TSIZ_PKTCNT_MASK | \
|
||||
_USB_DIEP_TSIZ_MC_MASK )
|
||||
|
||||
#define DIEPCTL_EPTYPE_CONTROL (0 << _USB_DIEP_CTL_EPTYPE_SHIFT )
|
||||
#define DIEPCTL_EPTYPE_ISOC (1 << _USB_DIEP_CTL_EPTYPE_SHIFT )
|
||||
#define DIEPCTL_EPTYPE_BULK (2 << _USB_DIEP_CTL_EPTYPE_SHIFT )
|
||||
#define DIEPCTL_EPTYPE_INTR (3 << _USB_DIEP_CTL_EPTYPE_SHIFT )
|
||||
|
||||
#define DOEPCTL_EPTYPE_CONTROL (0 << _USB_DOEP_CTL_EPTYPE_SHIFT )
|
||||
#define DOEPCTL_EPTYPE_ISOC (1 << _USB_DOEP_CTL_EPTYPE_SHIFT )
|
||||
#define DOEPCTL_EPTYPE_BULK (2 << _USB_DOEP_CTL_EPTYPE_SHIFT )
|
||||
#define DOEPCTL_EPTYPE_INTR (3 << _USB_DOEP_CTL_EPTYPE_SHIFT )
|
||||
|
||||
#define HCCHAR_EPTYPE_CTRL (0 << _USB_HC_CHAR_EPTYPE_SHIFT )
|
||||
#define HCCHAR_EPTYPE_ISOC (1 << _USB_HC_CHAR_EPTYPE_SHIFT )
|
||||
#define HCCHAR_EPTYPE_BULK (2 << _USB_HC_CHAR_EPTYPE_SHIFT )
|
||||
#define HCCHAR_EPTYPE_INTR (3 << _USB_HC_CHAR_EPTYPE_SHIFT )
|
||||
|
||||
#define GRXSTSP_PKTSTS_DEVICE_GOTNAK ( 1 << _USB_GRXSTSP_PKTSTS_SHIFT )
|
||||
#define GRXSTSP_PKTSTS_DEVICE_DATAOUTRECEIVED ( 2 << _USB_GRXSTSP_PKTSTS_SHIFT )
|
||||
#define GRXSTSP_PKTSTS_DEVICE_DATAOUTCOMPLETE ( 3 << _USB_GRXSTSP_PKTSTS_SHIFT )
|
||||
#define GRXSTSP_PKTSTS_DEVICE_SETUPCOMPLETE ( 4 << _USB_GRXSTSP_PKTSTS_SHIFT )
|
||||
#define GRXSTSP_PKTSTS_DEVICE_SETUPRECEIVED ( 6 << _USB_GRXSTSP_PKTSTS_SHIFT )
|
||||
|
||||
#define GRXSTSP_PKTSTS_HOST_DATAINRECEIVED ( 2 << _USB_GRXSTSP_PKTSTS_SHIFT )
|
||||
#define GRXSTSP_PKTSTS_HOST_DATAINCOMPLETE ( 3 << _USB_GRXSTSP_PKTSTS_SHIFT )
|
||||
#define GRXSTSP_PKTSTS_HOST_DATATOGGLEERROR ( 5 << _USB_GRXSTSP_PKTSTS_SHIFT )
|
||||
#define GRXSTSP_PKTSTS_HOST_CHANNELHALTED ( 7 << _USB_GRXSTSP_PKTSTS_SHIFT )
|
||||
|
||||
#define DCTL_WO_BITMASK \
|
||||
( _USB_DCTL_CGOUTNAK_MASK | _USB_DCTL_SGOUTNAK_MASK | \
|
||||
_USB_DCTL_CGNPINNAK_MASK | _USB_DCTL_SGNPINNAK_MASK )
|
||||
#define GUSBCFG_WO_BITMASK ( USB_GUSBCFG_CORRUPTTXPKT )
|
||||
#define DEPCTL_WO_BITMASK \
|
||||
( USB_DIEP_CTL_CNAK | USB_DIEP_CTL_SNAK | \
|
||||
USB_DIEP_CTL_SETD0PIDEF | USB_DIEP_CTL_SETD1PIDOF )
|
||||
|
||||
#define HPRT_WC_MASK ( USB_HPRT_PRTCONNDET | USB_HPRT_PRTENA | \
|
||||
USB_HPRT_PRTENCHNG | USB_HPRT_PRTOVRCURRCHNG )
|
||||
|
||||
typedef __IO uint32_t USB_FIFO_TypeDef[ 0x1000 / sizeof( uint32_t ) ];
|
||||
typedef __IO uint32_t USB_DIEPTXF_TypeDef;
|
||||
|
||||
#define USB_DINEPS ((USB_DIEP_TypeDef *) &USB->DIEP0CTL )
|
||||
#define USB_DOUTEPS ((USB_DOEP_TypeDef *) &USB->DOEP0CTL )
|
||||
#define USB_FIFOS ((USB_FIFO_TypeDef *) &USB->FIFO0D )
|
||||
#define USB_DIEPTXFS ((USB_DIEPTXF_TypeDef *) &USB->DIEPTXF1 )
|
||||
|
||||
void USBHAL_CoreReset( void );
|
||||
|
||||
#if defined( USB_DEVICE )
|
||||
void USBDHAL_AbortAllTransfers( USB_Status_TypeDef reason );
|
||||
USB_Status_TypeDef USBDHAL_CoreInit( const uint32_t totalRxFifoSize,
|
||||
const uint32_t totalTxFifoSize );
|
||||
void USBDHAL_Connect( void );
|
||||
void USBDHAL_Disconnect( void );
|
||||
void USBDHAL_AbortAllEps( void );
|
||||
void USBDHAL_AbortEpIn( USBD_Ep_TypeDef *ep );
|
||||
void USBDHAL_AbortEpOut( USBD_Ep_TypeDef *ep );
|
||||
|
||||
__STATIC_INLINE USB_Status_TypeDef USBDHAL_GetStallStatusEp(
|
||||
USBD_Ep_TypeDef *ep, uint16_t *halt );
|
||||
__STATIC_INLINE uint32_t USBDHAL_GetInEpInts( USBD_Ep_TypeDef *ep );
|
||||
__STATIC_INLINE uint32_t USBDHAL_GetOutEpInts( USBD_Ep_TypeDef *ep );
|
||||
__STATIC_INLINE void USBDHAL_SetEPDISNAK( USBD_Ep_TypeDef *ep );
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
|
||||
#if defined( USB_HOST )
|
||||
USB_Status_TypeDef USBHHAL_CoreInit( const uint32_t rxFifoSize,
|
||||
const uint32_t nptxFifoSize,
|
||||
const uint32_t ptxFifoSize );
|
||||
void USBHHAL_HCHalt( int hcnum, uint32_t hcchar );
|
||||
void USBHHAL_HCInit( int hcnum );
|
||||
void USBHHAL_HCStart( int hcnum );
|
||||
#endif /* defined( USB_HOST ) */
|
||||
|
||||
__STATIC_INLINE void USBHAL_DisableGlobalInt( void )
|
||||
{
|
||||
USB->GAHBCFG &= ~USB_GAHBCFG_GLBLINTRMSK;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHAL_DisablePhyPins( void )
|
||||
{
|
||||
USB->ROUTE = _USB_ROUTE_RESETVALUE;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHAL_DisableUsbInt( void )
|
||||
{
|
||||
USB->IEN = _USB_IEN_RESETVALUE;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHAL_EnableGlobalInt( void )
|
||||
{
|
||||
USB->GAHBCFG |= USB_GAHBCFG_GLBLINTRMSK;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHAL_FlushRxFifo( void )
|
||||
{
|
||||
USB->GRSTCTL = USB_GRSTCTL_RXFFLSH;
|
||||
while ( USB->GRSTCTL & USB_GRSTCTL_RXFFLSH ) {}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHAL_FlushTxFifo( uint8_t fifoNum )
|
||||
{
|
||||
USB->GRSTCTL = USB_GRSTCTL_TXFFLSH | ( fifoNum << _USB_GRSTCTL_TXFNUM_SHIFT );
|
||||
while ( USB->GRSTCTL & USB_GRSTCTL_TXFFLSH ) {}
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t USBHAL_GetCoreInts( void )
|
||||
{
|
||||
uint32_t retVal;
|
||||
|
||||
retVal = USB->GINTSTS;
|
||||
retVal &= USB->GINTMSK;
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool USBHAL_VbusIsOn( void )
|
||||
{
|
||||
return ( USB->STATUS & USB_STATUS_VREGOS ) != 0;
|
||||
}
|
||||
|
||||
#if defined( USB_DEVICE )
|
||||
__STATIC_INLINE void USBDHAL_ActivateEp( USBD_Ep_TypeDef *ep, bool forceIdle )
|
||||
{
|
||||
#define DIEP_MPS_EPTYPE_TXFNUM_MASK ( _USB_DIEP_CTL_MPS_MASK | \
|
||||
_USB_DIEP_CTL_EPTYPE_MASK | \
|
||||
_USB_DIEP_CTL_TXFNUM_MASK )
|
||||
#define DOEP_MPS_EPTYPE_MASK ( _USB_DOEP_CTL_MPS_MASK | \
|
||||
_USB_DOEP_CTL_EPTYPE_MASK )
|
||||
uint32_t daintmask, depctl;
|
||||
|
||||
if ( forceIdle )
|
||||
ep->state = D_EP_IDLE;
|
||||
|
||||
if ( ep->in )
|
||||
{
|
||||
daintmask = ep->mask;
|
||||
depctl = USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
|
||||
|
||||
if ( !( depctl & USB_DIEP_CTL_USBACTEP ) )
|
||||
{
|
||||
depctl = ( depctl &
|
||||
~( DIEP_MPS_EPTYPE_TXFNUM_MASK |
|
||||
USB_DIEP_CTL_STALL ) ) |
|
||||
( ep->packetSize << _USB_DIEP_CTL_MPS_SHIFT ) |
|
||||
( ep->type << _USB_DIEP_CTL_EPTYPE_SHIFT ) |
|
||||
( ep->txFifoNum << _USB_DIEP_CTL_TXFNUM_SHIFT ) |
|
||||
USB_DIEP_CTL_SETD0PIDEF |
|
||||
USB_DIEP_CTL_USBACTEP |
|
||||
USB_DIEP_CTL_SNAK;
|
||||
}
|
||||
else
|
||||
{
|
||||
depctl |= USB_DIEP_CTL_SETD0PIDEF;
|
||||
}
|
||||
USB_DINEPS[ ep->num ].CTL = depctl;
|
||||
}
|
||||
else
|
||||
{
|
||||
daintmask = ep->mask << _USB_DAINTMSK_OUTEPMSK0_SHIFT;
|
||||
depctl = USB_DOUTEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
|
||||
|
||||
if ( !( depctl & USB_DOEP_CTL_USBACTEP ) )
|
||||
{
|
||||
depctl = ( depctl &
|
||||
~( DOEP_MPS_EPTYPE_MASK |
|
||||
USB_DOEP_CTL_STALL ) ) |
|
||||
( ep->packetSize << _USB_DOEP_CTL_MPS_SHIFT ) |
|
||||
( ep->type << _USB_DOEP_CTL_EPTYPE_SHIFT ) |
|
||||
USB_DOEP_CTL_SETD0PIDEF |
|
||||
USB_DOEP_CTL_USBACTEP |
|
||||
USB_DOEP_CTL_SNAK;
|
||||
}
|
||||
else
|
||||
{
|
||||
depctl |= USB_DOEP_CTL_SETD0PIDEF;
|
||||
}
|
||||
USB_DOUTEPS[ ep->num ].CTL = depctl;
|
||||
}
|
||||
|
||||
/* Enable interrupt for this EP */
|
||||
USB->DAINTMSK |= daintmask;
|
||||
|
||||
#undef DIEP_MPS_EPTYPE_TXFNUM_MASK
|
||||
#undef DOEP_MPS_EPTYPE_MASK
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_ClearRemoteWakeup( void )
|
||||
{
|
||||
USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_RMTWKUPSIG );
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_DeactivateEp( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
uint32_t daintmask;
|
||||
|
||||
if ( ep->in )
|
||||
{
|
||||
USB_DINEPS[ ep->num ].CTL = 0;
|
||||
daintmask = ep->mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_DOUTEPS[ ep->num ].CTL = 0;
|
||||
daintmask = ep->mask << _USB_DAINTMSK_OUTEPMSK0_SHIFT;
|
||||
}
|
||||
|
||||
/* Disable interrupt for this EP */
|
||||
USB->DAINTMSK &= ~daintmask;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_EnableInts( USBD_Device_TypeDef *dev )
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
/* Disable all interrupts. */
|
||||
USB->GINTMSK = 0;
|
||||
|
||||
/* Clear pending interrupts */
|
||||
USB->GINTSTS = 0xFFFFFFFF;
|
||||
|
||||
mask = USB_GINTMSK_USBSUSPMSK |
|
||||
USB_GINTMSK_USBRSTMSK |
|
||||
USB_GINTMSK_ENUMDONEMSK |
|
||||
USB_GINTMSK_IEPINTMSK |
|
||||
USB_GINTMSK_OEPINTMSK |
|
||||
USB_GINTMSK_WKUPINTMSK;
|
||||
|
||||
if ( dev->callbacks->sofInt )
|
||||
{
|
||||
mask |= USB_GINTMSK_SOFMSK;
|
||||
}
|
||||
|
||||
USB->GINTMSK = mask;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_EnableUsbResetAndSuspendInt( void )
|
||||
{
|
||||
/* Disable all interrupts. */
|
||||
USB->GINTMSK = 0;
|
||||
|
||||
USB->GINTMSK = USB_GINTMSK_USBRSTMSK | USB_GINTMSK_USBSUSPMSK;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_Ep0Activate( uint32_t ep0mps )
|
||||
{
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGNPINNAK;
|
||||
|
||||
USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
|
||||
| USB_DOEP0CTL_CNAK | USB_DOEP0CTL_EPENA
|
||||
| ep0mps;
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool USBDHAL_EpIsStalled( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
bool retVal = false;
|
||||
uint16_t stallStatus;
|
||||
|
||||
if ( USBDHAL_GetStallStatusEp( ep, &stallStatus ) == USB_STATUS_OK )
|
||||
{
|
||||
retVal = stallStatus & 1 ? true : false;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t USBDHAL_GetAllInEpInts( void )
|
||||
{
|
||||
uint32_t retVal;
|
||||
|
||||
retVal = USB->DAINT;
|
||||
retVal &= USB->DAINTMSK;
|
||||
return retVal & 0xFFFF;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t USBDHAL_GetAllOutEpInts( void )
|
||||
{
|
||||
uint32_t retVal;
|
||||
|
||||
retVal = USB->DAINT;
|
||||
retVal &= USB->DAINTMSK;
|
||||
return retVal >> 16;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t USBDHAL_GetInEpInts( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
uint32_t retVal, msk;
|
||||
|
||||
msk = USB->DIEPMSK;
|
||||
retVal = USB_DINEPS[ ep->num ].INT;
|
||||
|
||||
return retVal & msk;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t USBDHAL_GetOutEpInts( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
uint32_t retVal;
|
||||
|
||||
retVal = USB_DOUTEPS[ ep->num ].INT;
|
||||
#if defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
retVal &= USB->DOEPMSK | USB_DOEP0INT_STUPPKTRCVD;
|
||||
#else
|
||||
retVal &= USB->DOEPMSK;
|
||||
#endif
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
__STATIC_INLINE USB_Status_TypeDef USBDHAL_GetStallStatusEp(
|
||||
USBD_Ep_TypeDef *ep, uint16_t *halt )
|
||||
{
|
||||
uint32_t depctl, eptype;
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if ( ep->in == true )
|
||||
{
|
||||
depctl = USB_DINEPS[ ep->num ].CTL;
|
||||
eptype = depctl & _USB_DIEP_CTL_EPTYPE_MASK;
|
||||
|
||||
if (( eptype == DIEPCTL_EPTYPE_INTR ) || ( eptype == DIEPCTL_EPTYPE_BULK ))
|
||||
{
|
||||
*halt = depctl & USB_DIEP_CTL_STALL ? 1 : 0;
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
depctl = USB_DOUTEPS[ ep->num ].CTL;
|
||||
eptype = depctl & _USB_DOEP_CTL_EPTYPE_MASK;
|
||||
|
||||
if (( eptype == DOEPCTL_EPTYPE_INTR ) || ( eptype == DOEPCTL_EPTYPE_BULK ))
|
||||
{
|
||||
*halt = depctl & USB_DOEP_CTL_STALL ? 1 : 0;
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_ReenableEp0Setup( USBD_Device_TypeDef *dev )
|
||||
|
||||
{
|
||||
USB->DOEP0DMAADDR = (uint32_t)dev->setupPkt;
|
||||
USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
|
||||
| USB_DOEP0CTL_EPENA
|
||||
| dev->ep0MpsCode;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_SetAddr( uint8_t addr )
|
||||
{
|
||||
USB->DCFG = ( USB->DCFG &
|
||||
~_USB_DCFG_DEVADDR_MASK ) |
|
||||
(addr << _USB_DCFG_DEVADDR_SHIFT );
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_SetEp0InDmaPtr( uint8_t* addr )
|
||||
{
|
||||
USB->DIEP0DMAADDR = (uint32_t)addr;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_SetEp0OutDmaPtr( uint8_t* addr )
|
||||
{
|
||||
USB->DOEP0DMAADDR = (uint32_t)addr;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_SetEPDISNAK( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
if ( ep->in )
|
||||
{
|
||||
USB_DINEPS[ ep->num ].CTL = ( USB_DINEPS[ ep->num ].CTL &
|
||||
~DEPCTL_WO_BITMASK ) |
|
||||
USB_DIEP_CTL_SNAK |
|
||||
USB_DIEP_CTL_EPDIS;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_DOUTEPS[ ep->num ].CTL = ( USB_DOUTEPS[ ep->num ].CTL &
|
||||
~DEPCTL_WO_BITMASK ) |
|
||||
USB_DOEP_CTL_EPENA;
|
||||
|
||||
USB_DOUTEPS[ ep->num ].CTL = ( USB_DOUTEPS[ ep->num ].CTL &
|
||||
~DEPCTL_WO_BITMASK ) |
|
||||
USB_DOEP_CTL_SNAK |
|
||||
USB_DOEP_CTL_EPDIS;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_SetRemoteWakeup( void )
|
||||
{
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_RMTWKUPSIG;
|
||||
}
|
||||
|
||||
__STATIC_INLINE USB_Status_TypeDef USBDHAL_StallEp( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
uint32_t depctl, eptype;
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if ( ep->in == true )
|
||||
{
|
||||
depctl = USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
|
||||
eptype = depctl & _USB_DIEP_CTL_EPTYPE_MASK;
|
||||
|
||||
if ( eptype != DIEPCTL_EPTYPE_ISOC )
|
||||
{
|
||||
if ( depctl & USB_DIEP_CTL_EPENA )
|
||||
{
|
||||
depctl |= USB_DIEP_CTL_EPDIS;
|
||||
}
|
||||
USB_DINEPS[ ep->num ].CTL = depctl | USB_DIEP_CTL_STALL;
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
depctl = USB_DOUTEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
|
||||
eptype = depctl & _USB_DOEP_CTL_EPTYPE_MASK;
|
||||
|
||||
if ( eptype != DIEPCTL_EPTYPE_ISOC )
|
||||
{
|
||||
USB_DOUTEPS[ ep->num ].CTL = depctl | USB_DOEP_CTL_STALL;
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_StartEp0In( uint32_t len, uint32_t ep0mps )
|
||||
{
|
||||
USB->DIEP0TSIZ = ( len << _USB_DIEP0TSIZ_XFERSIZE_SHIFT ) |
|
||||
( 1 << _USB_DIEP0TSIZ_PKTCNT_SHIFT );
|
||||
|
||||
USB->DIEP0CTL = ( USB->DIEP0CTL & ~DEPCTL_WO_BITMASK )
|
||||
| USB_DIEP0CTL_CNAK | USB_DIEP0CTL_EPENA
|
||||
| ep0mps;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_StartEp0Out( uint32_t len, uint32_t ep0mps )
|
||||
{
|
||||
USB->DOEP0TSIZ = ( len << _USB_DOEP0TSIZ_XFERSIZE_SHIFT ) |
|
||||
( 1 << _USB_DOEP0TSIZ_PKTCNT_SHIFT );
|
||||
|
||||
USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
|
||||
| USB_DOEP0CTL_CNAK | USB_DOEP0CTL_EPENA
|
||||
| ep0mps;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_StartEp0Setup( USBD_Device_TypeDef *dev )
|
||||
{
|
||||
dev->ep[ 0 ].in = false;
|
||||
|
||||
#if defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
USB->DOEP0TSIZ = ( 8*3 << _USB_DOEP0TSIZ_XFERSIZE_SHIFT ) |
|
||||
( 1 << _USB_DOEP0TSIZ_PKTCNT_SHIFT ) |
|
||||
( 3 << _USB_DOEP0TSIZ_SUPCNT_SHIFT );
|
||||
#else
|
||||
USB->DOEP0TSIZ = 3 << _USB_DOEP0TSIZ_SUPCNT_SHIFT;
|
||||
#endif
|
||||
|
||||
dev->setup = dev->setupPkt;
|
||||
USB->DOEP0DMAADDR = (uint32_t)dev->setup;
|
||||
|
||||
#if defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
|
||||
| USB_DOEP0CTL_EPENA
|
||||
| dev->ep0MpsCode;
|
||||
#else
|
||||
USB->DOEP0CTL = ( USB->DOEP0CTL & ~DEPCTL_WO_BITMASK )
|
||||
| USB_DOEP0CTL_CNAK | USB_DOEP0CTL_EPENA
|
||||
| dev->ep0MpsCode;
|
||||
#endif
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_StartEpIn( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
uint32_t pktcnt, xfersize;
|
||||
|
||||
if ( ep->remaining == 0 ) /* ZLP ? */
|
||||
{
|
||||
pktcnt = 1;
|
||||
xfersize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pktcnt = ( ep->remaining - 1 + ep->packetSize ) / ep->packetSize;
|
||||
xfersize = ep->remaining;
|
||||
}
|
||||
|
||||
USB_DINEPS[ ep->num ].TSIZ =
|
||||
( USB_DINEPS[ ep->num ].TSIZ &
|
||||
~DIEP_XFERSIZE_PKTCNT_MASK ) |
|
||||
( xfersize << _USB_DIEP_TSIZ_XFERSIZE_SHIFT ) |
|
||||
( pktcnt << _USB_DIEP_TSIZ_PKTCNT_SHIFT );
|
||||
|
||||
USB_DINEPS[ ep->num ].DMAADDR = (uint32_t)ep->buf;
|
||||
USB_DINEPS[ ep->num ].CTL =
|
||||
( USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK ) |
|
||||
USB_DIEP_CTL_CNAK |
|
||||
USB_DIEP_CTL_EPENA;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBDHAL_StartEpOut( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
uint32_t pktcnt, xfersize;
|
||||
|
||||
if ( ep->remaining == 0 ) /* ZLP ? */
|
||||
{
|
||||
pktcnt = 1;
|
||||
xfersize = ep->packetSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
pktcnt = ( ep->remaining - 1 + ep->packetSize ) / ep->packetSize;
|
||||
xfersize = pktcnt * ep->packetSize;
|
||||
}
|
||||
|
||||
USB_DOUTEPS[ ep->num ].TSIZ =
|
||||
( USB_DOUTEPS[ ep->num ].TSIZ &
|
||||
~DOEP_XFERSIZE_PKTCNT_MASK ) |
|
||||
( xfersize << _USB_DOEP_TSIZ_XFERSIZE_SHIFT ) |
|
||||
( pktcnt << _USB_DOEP_TSIZ_PKTCNT_SHIFT );
|
||||
|
||||
ep->hwXferSize = xfersize;
|
||||
USB_DOUTEPS[ ep->num ].DMAADDR = (uint32_t)ep->buf;
|
||||
USB_DOUTEPS[ ep->num ].CTL =
|
||||
( USB_DOUTEPS[ ep->num ].CTL &
|
||||
~DEPCTL_WO_BITMASK ) |
|
||||
USB_DOEP_CTL_CNAK |
|
||||
USB_DOEP_CTL_EPENA;
|
||||
}
|
||||
|
||||
__STATIC_INLINE USB_Status_TypeDef USBDHAL_UnStallEp( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
uint32_t depctl, eptype;
|
||||
USB_Status_TypeDef retVal = USB_STATUS_REQ_ERR;
|
||||
|
||||
if ( ep->in == true )
|
||||
{
|
||||
depctl = USB_DINEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
|
||||
eptype = depctl & _USB_DIEP_CTL_EPTYPE_MASK;
|
||||
|
||||
if (( eptype == DIEPCTL_EPTYPE_INTR ) || ( eptype == DIEPCTL_EPTYPE_BULK ))
|
||||
{
|
||||
depctl |= USB_DIEP_CTL_SETD0PIDEF;
|
||||
depctl &= ~USB_DIEP_CTL_STALL;
|
||||
USB_DINEPS[ ep->num ].CTL = depctl;
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
depctl = USB_DOUTEPS[ ep->num ].CTL & ~DEPCTL_WO_BITMASK;
|
||||
eptype = depctl & _USB_DOEP_CTL_EPTYPE_MASK;
|
||||
|
||||
if (( eptype == DIEPCTL_EPTYPE_INTR ) || ( eptype == DIEPCTL_EPTYPE_BULK ))
|
||||
{
|
||||
depctl |= USB_DOEP_CTL_SETD0PIDEF;
|
||||
depctl &= ~USB_DOEP_CTL_STALL;
|
||||
USB_DOUTEPS[ ep->num ].CTL = depctl;
|
||||
retVal = USB_STATUS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
|
||||
#if defined( USB_HOST )
|
||||
__STATIC_INLINE void USBHHAL_HCActivate( int hcnum, uint32_t hcchar, bool intep )
|
||||
{
|
||||
uint32_t oddframe;
|
||||
|
||||
if ( intep )
|
||||
{
|
||||
oddframe = USB->HFNUM & 1;
|
||||
|
||||
USB->HC[ hcnum ].CHAR =
|
||||
( hcchar &
|
||||
~( USB_HC_CHAR_CHDIS | _USB_HC_CHAR_ODDFRM_MASK ) ) |
|
||||
|
||||
/* Schedule INT transfers to start in next frame. */
|
||||
( oddframe & 1 ? 0 : USB_HC_CHAR_ODDFRM ) |
|
||||
|
||||
USB_HC_CHAR_CHENA;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB->HC[ hcnum ].CHAR = ( hcchar & ~USB_HC_CHAR_CHDIS ) |
|
||||
USB_HC_CHAR_CHENA;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE bool USBHHAL_InitializedAndPowered( void )
|
||||
{
|
||||
if ( ( USB->ROUTE & USB_ROUTE_PHYPEN ) &&
|
||||
( USB->HPRT & USB_HPRT_PRTPWR ) )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHHAL_EnableInts( void )
|
||||
{
|
||||
/* Disable all interrupts. */
|
||||
USB->GINTMSK = 0;
|
||||
|
||||
/* Clear pending OTG interrupts */
|
||||
USB->GOTGINT = 0xFFFFFFFF;
|
||||
|
||||
/* Clear pending interrupts */
|
||||
USB->GINTSTS = 0xFFFFFFFF;
|
||||
|
||||
USB->GINTMSK = USB_GINTMSK_PRTINTMSK |
|
||||
USB_GINTMSK_HCHINTMSK |
|
||||
USB_GINTMSK_DISCONNINTMSK;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint16_t USBHHAL_GetFrameNum( void )
|
||||
{
|
||||
return USB->HFNUM;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t USBHHAL_GetHcChar( uint8_t hcnum )
|
||||
{
|
||||
return USB->HC[ hcnum ].CHAR;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t USBHHAL_GetHcInts( uint8_t hcnum )
|
||||
{
|
||||
uint32_t retVal;
|
||||
|
||||
retVal = USB->HC[ hcnum ].INT;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t USBHHAL_GetHostChannelInts( void )
|
||||
{
|
||||
return USB->HAINT;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint8_t USBHHAL_GetPortSpeed( void )
|
||||
{
|
||||
return ( USB->HPRT & _USB_HPRT_PRTSPD_MASK ) >> _USB_HPRT_PRTSPD_SHIFT;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHHAL_PortReset( bool on )
|
||||
{
|
||||
if ( on )
|
||||
{
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '+' );
|
||||
USB->HPRT = ( USB->HPRT & ~HPRT_WC_MASK ) | USB_HPRT_PRTRST;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '-' );
|
||||
USB->HPRT &= ~( HPRT_WC_MASK | USB_HPRT_PRTRST );
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHHAL_PortResume( bool on )
|
||||
{
|
||||
if ( on )
|
||||
{
|
||||
USB->HPRT = ( USB->HPRT & ~( HPRT_WC_MASK | USB_HPRT_PRTSUSP ) ) |
|
||||
USB_HPRT_PRTRES;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB->HPRT &= ~( HPRT_WC_MASK | USB_HPRT_PRTSUSP | USB_HPRT_PRTRES );
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHHAL_PortSuspend( void )
|
||||
{
|
||||
USB->HPRT = ( USB->HPRT & ~HPRT_WC_MASK ) | USB_HPRT_PRTSUSP;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void USBHHAL_VbusOn( bool on )
|
||||
{
|
||||
if ( on )
|
||||
{
|
||||
USB->HPRT = ( USB->HPRT & ~HPRT_WC_MASK ) | USB_HPRT_PRTPWR;
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '/' );
|
||||
}
|
||||
else
|
||||
{
|
||||
USB->HPRT &= ~( HPRT_WC_MASK | USB_HPRT_PRTPWR );
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '\\' );
|
||||
}
|
||||
}
|
||||
#endif /* defined( USB_HOST ) */
|
||||
|
||||
/** @endcond */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
|
||||
#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
|
||||
#endif /* __EM_USBHAL_H */
|
|
@ -0,0 +1,230 @@
|
|||
/***************************************************************************//**
|
||||
* @file em_usbtypes.h
|
||||
* @brief USB protocol stack library, internal type definitions.
|
||||
* @version 3.20.14
|
||||
*******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __EM_USBTYPES_H
|
||||
#define __EM_USBTYPES_H
|
||||
|
||||
#include "em_device.h"
|
||||
#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
|
||||
#include "em_usb.h"
|
||||
#if defined( USB_DEVICE ) || defined( USB_HOST )
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
/* Limits imposed by the USB peripheral */
|
||||
#define NP_RX_QUE_DEPTH 8
|
||||
#define HP_RX_QUE_DEPTH 8
|
||||
#define MAX_XFER_LEN 524287L /* 2^19 - 1 bytes */
|
||||
#define MAX_PACKETS_PR_XFER 1023 /* 2^10 - 1 packets */
|
||||
#if defined( _USB_DIEPTXF6_MASK )
|
||||
#define MAX_NUM_TX_FIFOS 6 /* In addition to EP0 Tx FIFO */
|
||||
#define MAX_NUM_IN_EPS 6 /* In addition to EP0 */
|
||||
#define MAX_NUM_OUT_EPS 6 /* In addition to EP0 */
|
||||
#define MAX_DEVICE_FIFO_SIZE_INWORDS 512U
|
||||
#else
|
||||
#define MAX_NUM_TX_FIFOS 3 /* In addition to EP0 Tx FIFO */
|
||||
#define MAX_NUM_IN_EPS 3 /* In addition to EP0 */
|
||||
#define MAX_NUM_OUT_EPS 3 /* In addition to EP0 */
|
||||
#define MAX_DEVICE_FIFO_SIZE_INWORDS 384U
|
||||
#endif
|
||||
#define MIN_EP_FIFO_SIZE_INWORDS 16U /* Unit is words (32bit) */
|
||||
#define MIN_EP_FIFO_SIZE_INBYTES 64U /* Unit is bytes (8bit) */
|
||||
|
||||
/* For MCU's without USB host capability. */
|
||||
#if !defined( USB_ROUTE_VBUSENPEN )
|
||||
#define USB_VBUS_SWITCH_NOT_PRESENT
|
||||
#endif
|
||||
|
||||
/* Limit imposed by the USB standard */
|
||||
#define MAX_USB_EP_NUM 15
|
||||
|
||||
#if defined( USB_DEVICE )
|
||||
/* Check power saving modes. */
|
||||
#ifndef USB_PWRSAVE_MODE
|
||||
/* Default powersave-mode is OFF. */
|
||||
#define USB_PWRSAVE_MODE USB_PWRSAVE_MODE_OFF
|
||||
#else
|
||||
#if ( USB_PWRSAVE_MODE & \
|
||||
~( USB_PWRSAVE_MODE_ONSUSPEND | USB_PWRSAVE_MODE_ONVBUSOFF | \
|
||||
USB_PWRSAVE_MODE_ENTEREM2 ) )
|
||||
#error "Illegal USB powersave mode."
|
||||
#endif
|
||||
#endif /* ifndef USB_PWRSAVE_MODE */
|
||||
|
||||
/* Check power saving low frequency clock selection. */
|
||||
#ifndef USB_USBC_32kHz_CLK
|
||||
/* Default clock source is LFXO. */
|
||||
#define USB_USBC_32kHz_CLK USB_USBC_32kHz_CLK_LFXO
|
||||
#else
|
||||
#if ( ( USB_USBC_32kHz_CLK != USB_USBC_32kHz_CLK_LFXO ) && \
|
||||
( USB_USBC_32kHz_CLK != USB_USBC_32kHz_CLK_LFRCO ) )
|
||||
#error "Illegal USB 32kHz powersave clock selection."
|
||||
#endif
|
||||
#endif /* ifndef USB_USBC_32kHz_CLK */
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
|
||||
#if defined( USB_HOST )
|
||||
/* Check VBUS overcurrent definitions. */
|
||||
#ifndef USB_VBUSOVRCUR_PORT
|
||||
#define USB_VBUSOVRCUR_PORT gpioPortE
|
||||
#define USB_VBUSOVRCUR_PIN 2
|
||||
#define USB_VBUSOVRCUR_POLARITY USB_VBUSOVRCUR_POLARITY_LOW
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Developer mode debugging macro's */
|
||||
#if defined( DEBUG_USB_INT_LO )
|
||||
#define DEBUG_USB_INT_LO_PUTS( s ) USB_PUTS( s )
|
||||
#define DEBUG_USB_INT_LO_PUTCHAR( c ) USB_PUTCHAR( c )
|
||||
#else
|
||||
#define DEBUG_USB_INT_LO_PUTS( s )
|
||||
#define DEBUG_USB_INT_LO_PUTCHAR( c )
|
||||
#endif /* defined( DEBUG_USB_INT_LO ) */
|
||||
|
||||
#if defined( DEBUG_USB_INT_HI )
|
||||
#define DEBUG_USB_INT_HI_PUTS( s ) USB_PUTS( s )
|
||||
#define DEBUG_USB_INT_HI_PUTCHAR( c ) USB_PUTCHAR( c )
|
||||
#else
|
||||
#define DEBUG_USB_INT_HI_PUTS( s )
|
||||
#define DEBUG_USB_INT_HI_PUTCHAR( c )
|
||||
#endif /* defined( DEBUG_USB_INT_HI ) */
|
||||
|
||||
#if defined( USB_HOST )
|
||||
#if defined( NUM_APP_TIMERS )
|
||||
#define HOSTPORT_TIMER_INDEX (NUM_APP_TIMERS)
|
||||
#else
|
||||
#define HOSTPORT_TIMER_INDEX (0)
|
||||
#endif
|
||||
#define HOSTCH_TIMER_INDEX (HOSTPORT_TIMER_INDEX + 1 )
|
||||
#endif
|
||||
|
||||
/* Macros for selecting a hardware timer. */
|
||||
#define USB_TIMER0 0
|
||||
#define USB_TIMER1 1
|
||||
#define USB_TIMER2 2
|
||||
#define USB_TIMER3 3
|
||||
|
||||
#if defined( USB_HOST )
|
||||
#define HCS_NAK 0x01
|
||||
#define HCS_STALL 0x02
|
||||
#define HCS_XACT 0x04
|
||||
#define HCS_TGLERR 0x08
|
||||
#define HCS_BABBLE 0x10
|
||||
#define HCS_TIMEOUT 0x20
|
||||
#define HCS_COMPLETED 0x40
|
||||
#define HCS_RETRY 0x80
|
||||
#endif
|
||||
|
||||
#if defined( USB_DEVICE )
|
||||
typedef enum
|
||||
{
|
||||
D_EP_IDLE = 0,
|
||||
D_EP_TRANSMITTING = 1,
|
||||
D_EP_RECEIVING = 2,
|
||||
D_EP0_IN_STATUS = 3,
|
||||
D_EP0_OUT_STATUS = 4
|
||||
} USBD_EpState_TypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool in;
|
||||
uint8_t zlp;
|
||||
uint8_t num;
|
||||
uint8_t addr;
|
||||
uint8_t type;
|
||||
uint8_t txFifoNum;
|
||||
uint8_t *buf;
|
||||
uint16_t packetSize;
|
||||
uint16_t mask;
|
||||
uint32_t remaining;
|
||||
uint32_t xferred;
|
||||
uint32_t hwXferSize;
|
||||
uint32_t fifoSize;
|
||||
USBD_EpState_TypeDef state;
|
||||
USB_XferCompleteCb_TypeDef xferCompleteCb;
|
||||
} USBD_Ep_TypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
USB_Setup_TypeDef *setup;
|
||||
USB_Setup_TypeDef setupPkt[3];
|
||||
uint8_t configurationValue; /* Must be DWORD aligned */
|
||||
bool remoteWakeupEnabled;
|
||||
uint8_t numberOfStrings;
|
||||
uint8_t numberOfInterfaces;
|
||||
USBD_State_TypeDef state;
|
||||
USBD_State_TypeDef savedState;
|
||||
USBD_State_TypeDef lastState;
|
||||
const USB_DeviceDescriptor_TypeDef *deviceDescriptor;
|
||||
const USB_ConfigurationDescriptor_TypeDef *configDescriptor;
|
||||
const void * const *stringDescriptors;
|
||||
const USBD_Callbacks_TypeDef *callbacks;
|
||||
USBD_Ep_TypeDef ep[ NUM_EP_USED + 1 ];
|
||||
uint8_t inEpAddr2EpIndex[ MAX_USB_EP_NUM + 1 ];
|
||||
uint8_t outEpAddr2EpIndex[ MAX_USB_EP_NUM + 1 ];
|
||||
uint32_t ep0MpsCode;
|
||||
} USBD_Device_TypeDef;
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
|
||||
#if defined( USB_HOST )
|
||||
typedef enum
|
||||
{
|
||||
H_PORT_DISCONNECTED = 0,
|
||||
H_PORT_CONNECTED_DEBOUNCING = 1,
|
||||
H_PORT_CONNECTED_RESETTING = 2,
|
||||
H_PORT_CONNECTED = 3,
|
||||
H_PORT_OVERCURRENT = 4
|
||||
} USBH_PortState_TypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int debounceTime;
|
||||
int resetTime;
|
||||
} USBH_AttachTiming_TypeDef;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *buf;
|
||||
int errorCnt;
|
||||
uint32_t remaining;
|
||||
uint32_t xferred;
|
||||
uint32_t hwXferSize;
|
||||
uint8_t status;
|
||||
bool idle;
|
||||
USBH_Ep_TypeDef *ep;
|
||||
} USBH_Hc_TypeDef;
|
||||
#endif /* defined( USB_HOST ) */
|
||||
|
||||
/** @endcond */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
|
||||
#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
|
||||
#endif /* __EM_USBTYPES_H */
|
|
@ -0,0 +1,88 @@
|
|||
/***************************************************************************//**
|
||||
* @file usbconfig.h
|
||||
* @brief USB protocol stack library, application supplied configuration options.
|
||||
* @version 3.20.12
|
||||
*******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __USBCONFIG_H
|
||||
#define __USBCONFIG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Compile stack for device mode. */
|
||||
#define USB_DEVICE
|
||||
|
||||
/* Maximum number of endpoint used, EP0 excluded. If you change this, you must
|
||||
also change USBEndpoints_EFM32.h to match. */
|
||||
#define NUM_EP_USED 6
|
||||
|
||||
/* Power management modes. The following can be or'd toghether. See comments in
|
||||
em_usbd.c under "Energy-saving modes" for more details.
|
||||
|
||||
USB_PWRSAVE_MODE_ONSUSPEND Set USB peripheral in low power mode on suspend
|
||||
|
||||
USB_PWRSAVE_MODE_ONVBUSOFF Set USB peripheral in low power mode when not
|
||||
attached to a host. While this mode assumes that the internal voltage regulator
|
||||
is used and that the VREGI pin of the chip is connected to VBUS it should
|
||||
be safe to use given that VREGOSEN is always enabled. If you disable VREGOSEN
|
||||
you must turn this off.
|
||||
|
||||
USB_PWRSAVE_MODE_ENTEREM2 Enter EM2 when USB peripheral is in low power mode.
|
||||
On Mbed this allows the sleep() and deepsleep() calls to enter EM2, but
|
||||
does not automatically enter any sleep states. Entering EM1 is always allowed.
|
||||
|
||||
Note for Happy Gecko, errata USB_E111: Entering EM2 when both the system clock
|
||||
(HFCLK) and the USB core clock (USBCCLK) is running on USHFRCO will result in
|
||||
a lock-up.
|
||||
*/
|
||||
#define USB_PWRSAVE_MODE (USB_PWRSAVE_MODE_ONSUSPEND|USB_PWRSAVE_MODE_ONVBUSOFF|USB_PWRSAVE_MODE_ENTEREM2)
|
||||
|
||||
/* Use dynamic memory to allocate rx/tx buffers in the HAL. Saves memory
|
||||
as buffers are only allocated for used endpoints. The system malloc
|
||||
must return memory that is aligned by 4.
|
||||
|
||||
Note: if you disable this, using isochronous endpoints with packet
|
||||
sizes that are larger than the maximum for other EP types (64) will
|
||||
not work. */
|
||||
#define USB_USE_DYNAMIC_MEMORY
|
||||
|
||||
/* When the USB peripheral is set in low power mode, it must be clocked by a 32kHz
|
||||
clock. Both LFXO and LFRCO can be used, but only LFXO guarantee USB specification
|
||||
compliance. */
|
||||
#define USB_USBC_32kHz_CLK USB_USBC_32kHz_CLK_LFXO
|
||||
|
||||
/* Uncomment to get some debugging information. Default value for USER_PUTCHAR
|
||||
should work for SiLabs Gecko boards. Printf requires a working retarget
|
||||
implementation for write(). */
|
||||
//#define DEBUG_USB_API
|
||||
//#define USB_USE_PRINTF
|
||||
//#define USER_PUTCHAR ITM_SendChar
|
||||
//#define DEBUG_USB_INT_HI
|
||||
//#define DEBUG_USB_INT_LO
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __USBCONFIG_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,446 @@
|
|||
/**************************************************************************//**
|
||||
* @file em_usbdep.c
|
||||
* @brief USB protocol stack library, USB device endpoint handlers.
|
||||
* @version 3.20.14
|
||||
******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "em_device.h"
|
||||
#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
|
||||
#include "em_usb.h"
|
||||
#if defined( USB_DEVICE )
|
||||
|
||||
#include "em_usbtypes.h"
|
||||
#include "em_usbhal.h"
|
||||
#include "em_usbd.h"
|
||||
|
||||
#ifdef USB_USE_PRINTF
|
||||
static const char *epStatusStr[] = {
|
||||
"IDLE","TRANS","RECV","IN_S","OUT_S"
|
||||
};
|
||||
#endif
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
/*
|
||||
* USBDEP_Ep0Handler() is called each time a packet has been transmitted
|
||||
* or recieved on the default endpoint.
|
||||
* A state machine navigate us through the phases of a control transfer
|
||||
* according to "chapter 9" in the USB spec.
|
||||
*/
|
||||
#if !defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
void USBDEP_Ep0Handler( USBD_Device_TypeDef *device )
|
||||
{
|
||||
int status;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
static bool statusIn;
|
||||
static uint32_t xferred;
|
||||
static USB_XferCompleteCb_TypeDef callback;
|
||||
|
||||
ep = &device->ep[ 0 ];
|
||||
|
||||
#ifdef __MBED__
|
||||
|
||||
(void)xferred;
|
||||
(void)statusIn;
|
||||
(void)status;
|
||||
|
||||
USB_PRINTF("USBDEP: ep0 %s, rem %ld, z %d\n", epStatusStr[ep->state], ep->remaining, ep->zlp);
|
||||
|
||||
if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) )
|
||||
{
|
||||
ep->state = D_EP_IDLE;
|
||||
|
||||
if ( ep->xferCompleteCb )
|
||||
{
|
||||
callback = ep->xferCompleteCb;
|
||||
ep->xferCompleteCb = NULL;
|
||||
callback( USB_STATUS_OK, ep->xferred, ep->remaining );
|
||||
}
|
||||
|
||||
USBDHAL_ReenableEp0Setup(device);
|
||||
}
|
||||
else
|
||||
{
|
||||
device->callbacks->setupCmd(device->setup);
|
||||
}
|
||||
|
||||
#else /* not __MBED__ */
|
||||
|
||||
switch ( ep->state )
|
||||
{
|
||||
case D_EP_IDLE:
|
||||
ep->remaining = 0;
|
||||
ep->zlp = 0;
|
||||
callback = NULL;
|
||||
statusIn = false;
|
||||
|
||||
status = USBDCH9_SetupCmd( device );
|
||||
|
||||
if ( status == USB_STATUS_REQ_ERR )
|
||||
{
|
||||
ep->in = true;
|
||||
USBDHAL_StallEp( ep ); /* Stall Ep0 IN */
|
||||
ep->in = false; /* OUT for next SETUP */
|
||||
USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */
|
||||
USBDHAL_ReenableEp0Setup( device ); /* Prepare for next SETUP packet*/
|
||||
}
|
||||
else /* ( Status == USB_STATUS_OK ) */
|
||||
{
|
||||
if ( (ep->state == D_EP_RECEIVING) || (ep->state == D_EP_TRANSMITTING) )
|
||||
{
|
||||
callback = ep->xferCompleteCb;
|
||||
}
|
||||
|
||||
if ( ep->state != D_EP_RECEIVING )
|
||||
{
|
||||
if ( ep->remaining )
|
||||
{
|
||||
/* Data will be sent to host, check if a ZLP must be appended */
|
||||
if ( ( ep->remaining < device->setup->wLength ) &&
|
||||
( ep->remaining % ep->packetSize == 0 ) )
|
||||
{
|
||||
ep->zlp = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Prepare for next SETUP packet*/
|
||||
USBDHAL_ReenableEp0Setup( device );
|
||||
|
||||
/* No data stage, a ZLP may have been sent. If not, send one */
|
||||
|
||||
xferred = 0;
|
||||
if ( ep->zlp == 0 )
|
||||
{
|
||||
USBD_Write( 0, NULL, 0, NULL ); /* ACK to host */
|
||||
ep->state = D_EP0_IN_STATUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->state = D_EP_IDLE;
|
||||
ep->in = false; /* OUT for next SETUP */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D_EP_RECEIVING:
|
||||
if ( ep->remaining )
|
||||
{
|
||||
/* There is more data to receive */
|
||||
USBD_ReArmEp0( ep );
|
||||
}
|
||||
else
|
||||
{
|
||||
status = USB_STATUS_OK;
|
||||
if ( callback != NULL )
|
||||
{
|
||||
status = callback( USB_STATUS_OK, ep->xferred, 0 );
|
||||
callback = NULL;
|
||||
}
|
||||
|
||||
if ( status != USB_STATUS_OK )
|
||||
{
|
||||
ep->in = true;
|
||||
USBDHAL_StallEp( ep ); /* Stall Ep0 IN */
|
||||
ep->in = false; /* OUT for next SETUP */
|
||||
USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */
|
||||
USBDHAL_ReenableEp0Setup( device ); /* Prepare for next SETUP pkt. */
|
||||
ep->state = D_EP_IDLE;
|
||||
}
|
||||
else /* Everything OK, send a ZLP (ACK) to host */
|
||||
{
|
||||
USBDHAL_ReenableEp0Setup( device );/* Prepare for next SETUP packet*/
|
||||
|
||||
ep->state = D_EP_IDLE; /* USBD_Write() sets state back*/
|
||||
/* to EP_TRANSMITTING */
|
||||
USBD_Write( 0, NULL, 0, NULL );
|
||||
ep->state = D_EP0_IN_STATUS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D_EP_TRANSMITTING:
|
||||
if ( ep->remaining )
|
||||
{
|
||||
/* There is more data to transmit */
|
||||
USBD_ReArmEp0( ep );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* All data transferred, is a ZLP packet needed ? */
|
||||
if ( ep->zlp == 1 )
|
||||
{
|
||||
xferred = ep->xferred;
|
||||
ep->state = D_EP_IDLE; /* USBD_Write() sets state back */
|
||||
/* to EP_TRANSMITTING */
|
||||
USBD_Write( 0, NULL, 0, NULL ); /* Send ZLP */
|
||||
ep->zlp = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ep->zlp == 0 )
|
||||
{
|
||||
xferred = ep->xferred;
|
||||
}
|
||||
|
||||
ep->state = D_EP_IDLE;
|
||||
USBD_Read( 0, NULL, 0, NULL ); /* Get ZLP packet (ACK) from host */
|
||||
statusIn = true;
|
||||
ep->state = D_EP0_OUT_STATUS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D_EP0_IN_STATUS:
|
||||
case D_EP0_OUT_STATUS:
|
||||
if ( statusIn )
|
||||
{
|
||||
USBDHAL_ReenableEp0Setup( device );
|
||||
}
|
||||
|
||||
if ( callback != NULL )
|
||||
{
|
||||
callback( USB_STATUS_OK, xferred, 0 );
|
||||
}
|
||||
|
||||
ep->state = D_EP_IDLE;
|
||||
ep->in = false; /* OUT for next SETUP */
|
||||
break;
|
||||
|
||||
default:
|
||||
EFM_ASSERT( false );
|
||||
break;
|
||||
}
|
||||
#endif /* __MBED__ */
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
void USBDEP_Ep0Handler( USBD_Device_TypeDef *device )
|
||||
{
|
||||
int status;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
static uint32_t xferred;
|
||||
static USB_XferCompleteCb_TypeDef callback;
|
||||
|
||||
#ifdef __MBED__
|
||||
|
||||
(void)xferred;
|
||||
(void)status;
|
||||
|
||||
ep = &device->ep[ 0 ];
|
||||
|
||||
if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) )
|
||||
{
|
||||
ep->state = D_EP_IDLE;
|
||||
|
||||
if ( ep->xferCompleteCb )
|
||||
{
|
||||
callback = ep->xferCompleteCb;
|
||||
ep->xferCompleteCb = NULL;
|
||||
callback( USB_STATUS_OK, ep->xferred, ep->remaining );
|
||||
}
|
||||
|
||||
USBDHAL_StartEp0Setup( dev );
|
||||
}
|
||||
else
|
||||
{
|
||||
device->callbacks->setupCmd(device->setup);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
ep = &device->ep[ 0 ];
|
||||
|
||||
switch ( ep->state )
|
||||
{
|
||||
case D_EP_IDLE:
|
||||
ep->zlp = 0;
|
||||
ep->remaining = 0;
|
||||
callback = NULL;
|
||||
|
||||
status = USBDCH9_SetupCmd( device );
|
||||
|
||||
if ( status == USB_STATUS_REQ_ERR )
|
||||
{
|
||||
ep->in = true;
|
||||
USBDHAL_StallEp( ep ); /* Stall Ep0 IN */
|
||||
ep->in = false; /* OUT for next SETUP */
|
||||
USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */
|
||||
USBDHAL_StartEp0Setup( dev ); /* Prepare for next SETUP packet*/
|
||||
}
|
||||
else /* ( Status == USB_STATUS_OK ) */
|
||||
{
|
||||
if ( (ep->state == D_EP_RECEIVING) || (ep->state == D_EP_TRANSMITTING) )
|
||||
{
|
||||
callback = ep->xferCompleteCb;
|
||||
}
|
||||
|
||||
if ( ep->state != D_EP_RECEIVING )
|
||||
{
|
||||
if ( ep->remaining )
|
||||
{
|
||||
/* Data will be sent to host, check if a ZLP must be appended */
|
||||
if ( ( ep->remaining < device->setup->wLength ) &&
|
||||
( ep->remaining % ep->packetSize == 0 ) )
|
||||
{
|
||||
ep->zlp = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No data stage, a ZLP may have been sent. If not, send one */
|
||||
xferred = 0;
|
||||
if ( ep->zlp == 0 )
|
||||
{
|
||||
ep->state = D_EP_IDLE;
|
||||
USBD_Write( 0, NULL, 0, NULL ); /* ACK to host */
|
||||
ep->state = D_EP0_IN_STATUS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D_EP_RECEIVING:
|
||||
if ( ep->remaining )
|
||||
{
|
||||
ep->in = false;
|
||||
USBD_ReArmEp0( ep );
|
||||
}
|
||||
else
|
||||
{
|
||||
status = USB_STATUS_OK;
|
||||
if ( callback != NULL )
|
||||
{
|
||||
status = callback( USB_STATUS_OK, ep->xferred, 0 );
|
||||
callback = NULL;
|
||||
}
|
||||
|
||||
if ( status != USB_STATUS_OK )
|
||||
{
|
||||
ep->in = true;
|
||||
USBDHAL_StallEp( ep ); /* Stall Ep0 IN */
|
||||
ep->in = false; /* OUT for next SETUP */
|
||||
USBDHAL_StallEp( ep ); /* Stall Ep0 OUT */
|
||||
USBDHAL_StartEp0Setup( dev ); /* Prepare for next SETUP pkt. */
|
||||
ep->state = D_EP_IDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
USBDHAL_StartEp0Setup( dev ); /* Prepare for next SETUP packet*/
|
||||
ep->state = D_EP_IDLE; /* USBD_Write() sets state back */
|
||||
/* to EP_TRANSMITTING */
|
||||
USBD_Write( 0, NULL, 0, NULL );
|
||||
ep->state = D_EP0_IN_STATUS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D_EP_TRANSMITTING:
|
||||
if ( ep->remaining )
|
||||
{
|
||||
ep->in = true;
|
||||
USBD_ReArmEp0( ep );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ep->zlp == 1 )
|
||||
{
|
||||
xferred = ep->xferred;
|
||||
ep->state = D_EP_IDLE; /* USBD_Write() sets state back */
|
||||
/* to EP_TRANSMITTING */
|
||||
USBD_Write( 0, NULL, 0, NULL ); /* Send ZLP */
|
||||
ep->zlp = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( ep->zlp == 0 )
|
||||
{
|
||||
xferred = ep->xferred;
|
||||
}
|
||||
|
||||
ep->state = D_EP_IDLE;
|
||||
USBD_Read( 0, NULL, 0, NULL ); /* Get ZLP packet (ACK) from host */
|
||||
ep->state = D_EP0_OUT_STATUS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case D_EP0_IN_STATUS:
|
||||
if ( ( USB->DOEP0CTL & USB_DOEP0CTL_EPENA ) == 0 )
|
||||
{
|
||||
/* Prepare for more SETUP Packets */
|
||||
USBDHAL_StartEp0Setup( dev );
|
||||
}
|
||||
if ( callback != NULL )
|
||||
{
|
||||
callback( USB_STATUS_OK, xferred, 0 );
|
||||
}
|
||||
ep->state = D_EP_IDLE;
|
||||
ep->in = false; /* OUT for next SETUP */
|
||||
break;
|
||||
|
||||
case D_EP0_OUT_STATUS:
|
||||
USBDHAL_StartEp0Setup( dev ); /* Prepare for more SETUP Packets */
|
||||
if ( callback != NULL )
|
||||
{
|
||||
callback( USB_STATUS_OK, xferred, 0 );
|
||||
}
|
||||
ep->state = D_EP_IDLE;
|
||||
ep->in = false; /* OUT for next SETUP */
|
||||
break;
|
||||
}
|
||||
#endif /* __MBED__ */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* USBDEP_EpHandler() is called each time a packet has been transmitted
|
||||
* or recieved on an endpoint other than the default endpoint.
|
||||
*/
|
||||
void USBDEP_EpHandler( uint8_t epAddr )
|
||||
{
|
||||
USB_XferCompleteCb_TypeDef callback;
|
||||
USBD_Ep_TypeDef *ep = USBD_GetEpFromAddr( epAddr );
|
||||
|
||||
if ( ( ep->state == D_EP_TRANSMITTING ) || ( ep->state == D_EP_RECEIVING ) )
|
||||
{
|
||||
ep->state = D_EP_IDLE;
|
||||
if ( ep->xferCompleteCb )
|
||||
{
|
||||
callback = ep->xferCompleteCb;
|
||||
ep->xferCompleteCb = NULL;
|
||||
callback( USB_STATUS_OK, ep->xferred, ep->remaining );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EFM_ASSERT( false );
|
||||
}
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
|
|
@ -0,0 +1,946 @@
|
|||
/**************************************************************************//**
|
||||
* @file em_usbdint.c
|
||||
* @brief USB protocol stack library, USB device peripheral interrupt handlers.
|
||||
* @version 3.20.14
|
||||
******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "em_device.h"
|
||||
#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
|
||||
#include "em_usb.h"
|
||||
#if defined( USB_DEVICE )
|
||||
|
||||
#include "em_cmu.h"
|
||||
#include "em_usbtypes.h"
|
||||
#include "em_usbhal.h"
|
||||
#include "em_usbd.h"
|
||||
|
||||
#ifdef __MBED__
|
||||
extern void usbhal_allow_em2(bool em2_allow);
|
||||
#endif
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
#define HANDLE_INT( x ) if ( status & x ) { Handle_##x(); status &= ~x; }
|
||||
|
||||
static void Handle_USB_GINTSTS_ENUMDONE ( void );
|
||||
static void Handle_USB_GINTSTS_IEPINT ( void );
|
||||
static void Handle_USB_GINTSTS_OEPINT ( void );
|
||||
static void Handle_USB_GINTSTS_RESETDET ( void );
|
||||
static void Handle_USB_GINTSTS_SOF ( void );
|
||||
static void Handle_USB_GINTSTS_USBRST ( void );
|
||||
static void Handle_USB_GINTSTS_USBSUSP ( void );
|
||||
static void Handle_USB_GINTSTS_WKUPINT ( void );
|
||||
#if defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
static void HandleOutEpIntr( uint32_t status, USBD_Ep_TypeDef *ep );
|
||||
#else
|
||||
static void ProcessSetup ( void );
|
||||
static void ProcessOepData ( USBD_Ep_TypeDef *ep );
|
||||
#endif
|
||||
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
/* Variables and prototypes for USB powerdown (suspend) functionality. */
|
||||
static bool UsbPowerDown( void );
|
||||
static bool UsbPowerUp( void );
|
||||
|
||||
volatile bool USBD_poweredDown = false;
|
||||
|
||||
/* Storage for backing up USB core registers. */
|
||||
static uint32_t x_USB_GINTMSK;
|
||||
#if defined(_USB_GOTGCTL_MASK)
|
||||
static uint32_t x_USB_GOTGCTL;
|
||||
#endif
|
||||
static uint32_t x_USB_GAHBCFG;
|
||||
static uint32_t x_USB_GUSBCFG;
|
||||
static uint32_t x_USB_GRXFSIZ;
|
||||
static uint32_t x_USB_GNPTXFSIZ;
|
||||
static uint32_t x_USB_DCFG;
|
||||
static uint32_t x_USB_DCTL;
|
||||
static uint32_t x_USB_DAINTMSK;
|
||||
static uint32_t x_USB_DIEPMSK;
|
||||
static uint32_t x_USB_DOEPMSK;
|
||||
static uint32_t x_USB_PCGCCTL;
|
||||
|
||||
#if ( NUM_EP_USED > 0 )
|
||||
static uint32_t x_USB_EP_CTL[ NUM_EP_USED ];
|
||||
static uint32_t x_USB_EP_TSIZ[ NUM_EP_USED ];
|
||||
static uint32_t x_USB_EP_DMAADDR[ NUM_EP_USED ];
|
||||
#endif
|
||||
|
||||
#if ( NUM_EP_USED > MAX_NUM_TX_FIFOS )
|
||||
#define FIFO_CNT MAX_NUM_TX_FIFOS
|
||||
#else
|
||||
#define FIFO_CNT NUM_EP_USED
|
||||
#endif
|
||||
|
||||
#if ( FIFO_CNT > 0 )
|
||||
static uint32_t x_USB_DIEPTXFS[ FIFO_CNT ];
|
||||
#endif
|
||||
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
static uint32_t cmuStatus = 0;
|
||||
#endif
|
||||
|
||||
#endif /* if ( USB_PWRSAVE_MODE ) */
|
||||
|
||||
/*
|
||||
* USB_IRQHandler() is the first level handler for the USB peripheral interrupt.
|
||||
*/
|
||||
void USB_IRQHandler( void )
|
||||
{
|
||||
uint32_t status;
|
||||
bool servedVbusInterrupt = false;
|
||||
|
||||
INT_Disable();
|
||||
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
if ( USBD_poweredDown )
|
||||
{
|
||||
/* Switch USBC clock from 32kHz to a 48MHz clock to be able to */
|
||||
/* read USB peripheral registers. */
|
||||
/* If we woke up from EM2, HFCLK is now HFRCO. */
|
||||
|
||||
/* Restore clock oscillators.*/
|
||||
#if defined( CMU_OSCENCMD_USHFRCOEN )
|
||||
if ( ( CMU->STATUS & CMU_STATUS_USHFRCOENS ) == 0 )/*Wakeup from EM2 ?*/
|
||||
{
|
||||
CMU->OSCENCMD = ( cmuStatus
|
||||
& ( CMU_STATUS_AUXHFRCOENS | CMU_STATUS_HFXOENS ) )
|
||||
| CMU_OSCENCMD_USHFRCOEN;
|
||||
}
|
||||
#else
|
||||
if ( ( CMU->STATUS & CMU_STATUS_HFXOENS ) == 0 ) /* Wakeup from EM2 ? */
|
||||
{
|
||||
CMU->OSCENCMD = cmuStatus
|
||||
& ( CMU_STATUS_AUXHFRCOENS | CMU_STATUS_HFXOENS );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Select correct USBC clock.*/
|
||||
#if defined( CMU_OSCENCMD_USHFRCOEN )
|
||||
CMU->CMD = CMU_CMD_USBCCLKSEL_USHFRCO;
|
||||
while ( ( CMU->STATUS & CMU_STATUS_USBCUSHFRCOSEL ) == 0 ){}
|
||||
#else
|
||||
CMU->CMD = CMU_CMD_USBCCLKSEL_HFCLKNODIV;
|
||||
while ( ( CMU->STATUS & CMU_STATUS_USBCHFCLKSEL ) == 0 ){}
|
||||
#endif
|
||||
}
|
||||
#endif /* if ( USB_PWRSAVE_MODE ) */
|
||||
|
||||
if ( USB->IF && ( USB->CTRL & USB_CTRL_VREGOSEN ) )
|
||||
{
|
||||
if ( USB->IF & USB_IF_VREGOSH )
|
||||
{
|
||||
USB->IFC = USB_IFC_VREGOSH;
|
||||
|
||||
if ( USB->STATUS & USB_STATUS_VREGOS )
|
||||
{
|
||||
servedVbusInterrupt = true;
|
||||
DEBUG_USB_INT_LO_PUTS( "\nVboN" );
|
||||
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
if ( UsbPowerUp() )
|
||||
{
|
||||
USBDHAL_EnableUsbResetAndSuspendInt();
|
||||
}
|
||||
USBD_SetUsbState( USBD_STATE_POWERED );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if ( USB->IF & USB_IF_VREGOSL )
|
||||
{
|
||||
USB->IFC = USB_IFC_VREGOSL;
|
||||
|
||||
if ( ( USB->STATUS & USB_STATUS_VREGOS ) == 0 )
|
||||
{
|
||||
servedVbusInterrupt = true;
|
||||
DEBUG_USB_INT_LO_PUTS( "\nVboF" );
|
||||
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
|
||||
if ( !USBD_poweredDown )
|
||||
{
|
||||
USB->GINTMSK = 0;
|
||||
USB->GINTSTS = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
UsbPowerDown();
|
||||
#endif
|
||||
USBD_SetUsbState( USBD_STATE_NONE );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status = USBHAL_GetCoreInts();
|
||||
if ( status == 0 )
|
||||
{
|
||||
INT_Enable();
|
||||
if ( !servedVbusInterrupt )
|
||||
{
|
||||
DEBUG_USB_INT_LO_PUTS( "\nSinT" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
HANDLE_INT( USB_GINTSTS_RESETDET )
|
||||
HANDLE_INT( USB_GINTSTS_WKUPINT )
|
||||
HANDLE_INT( USB_GINTSTS_USBSUSP )
|
||||
HANDLE_INT( USB_GINTSTS_SOF )
|
||||
HANDLE_INT( USB_GINTSTS_ENUMDONE )
|
||||
HANDLE_INT( USB_GINTSTS_USBRST )
|
||||
HANDLE_INT( USB_GINTSTS_IEPINT )
|
||||
HANDLE_INT( USB_GINTSTS_OEPINT )
|
||||
|
||||
INT_Enable();
|
||||
|
||||
if ( status != 0 )
|
||||
{
|
||||
DEBUG_USB_INT_LO_PUTS( "\nUinT" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle port enumeration interrupt. This has nothing to do with normal
|
||||
* device enumeration.
|
||||
*/
|
||||
static void Handle_USB_GINTSTS_ENUMDONE( void )
|
||||
{
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
UsbPowerUp();
|
||||
#endif
|
||||
|
||||
USBDHAL_Ep0Activate( dev->ep0MpsCode );
|
||||
dev->ep[ 0 ].state = D_EP_IDLE;
|
||||
USBDHAL_EnableInts( dev );
|
||||
DEBUG_USB_INT_LO_PUTS( "EnumD" );
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle IN endpoint transfer interrupt.
|
||||
*/
|
||||
static void Handle_USB_GINTSTS_IEPINT( void )
|
||||
{
|
||||
int epnum;
|
||||
uint16_t epint;
|
||||
uint16_t epmask;
|
||||
uint32_t status;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
|
||||
DEBUG_USB_INT_HI_PUTCHAR( 'i' );
|
||||
|
||||
epint = USBDHAL_GetAllInEpInts();
|
||||
for ( epnum = 0, epmask = 1;
|
||||
epnum <= MAX_NUM_IN_EPS;
|
||||
epnum++, epmask <<= 1 )
|
||||
{
|
||||
if ( epint & epmask )
|
||||
{
|
||||
ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | epnum );
|
||||
status = USBDHAL_GetInEpInts( ep );
|
||||
|
||||
if ( status & USB_DIEP_INT_XFERCOMPL )
|
||||
{
|
||||
USB_DINEPS[ epnum ].INT = USB_DIEP_INT_XFERCOMPL;
|
||||
|
||||
DEBUG_USB_INT_HI_PUTCHAR( 'c' );
|
||||
|
||||
if ( epnum == 0 )
|
||||
{
|
||||
if ( ep->remaining > ep->packetSize )
|
||||
{
|
||||
ep->remaining -= ep->packetSize;
|
||||
ep->xferred += ep->packetSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xferred += ep->remaining;
|
||||
ep->remaining = 0;
|
||||
}
|
||||
USBDEP_Ep0Handler( dev );
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xferred = ep->remaining -
|
||||
( ( USB_DINEPS[ epnum ].TSIZ &
|
||||
_USB_DIEP_TSIZ_XFERSIZE_MASK ) >>
|
||||
_USB_DIEP_TSIZ_XFERSIZE_SHIFT );
|
||||
ep->remaining -= ep->xferred;
|
||||
|
||||
USBDEP_EpHandler( ep->addr );
|
||||
#if defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
if ( USB_DINEPS[ ep->num ].INT & USB_DIEP_INT_NAKINTRPT )
|
||||
{
|
||||
USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_NAKINTRPT;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle OUT endpoint transfer interrupt.
|
||||
*/
|
||||
static void Handle_USB_GINTSTS_OEPINT( void )
|
||||
{
|
||||
int epnum;
|
||||
uint16_t epint;
|
||||
uint16_t epmask;
|
||||
uint32_t status;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
|
||||
DEBUG_USB_INT_HI_PUTCHAR( 'o' );
|
||||
|
||||
epint = USBDHAL_GetAllOutEpInts();
|
||||
for ( epnum = 0, epmask = 1;
|
||||
epnum <= MAX_NUM_OUT_EPS;
|
||||
epnum++, epmask <<= 1 )
|
||||
{
|
||||
if ( epint & epmask )
|
||||
{
|
||||
ep = USBD_GetEpFromAddr( epnum );
|
||||
status = USBDHAL_GetOutEpInts( ep );
|
||||
|
||||
#if defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
HandleOutEpIntr( status, ep );
|
||||
#else
|
||||
if ( status & USB_DOEP_INT_XFERCOMPL )
|
||||
{
|
||||
USB_DOUTEPS[ epnum ].INT = USB_DOEP_INT_XFERCOMPL;
|
||||
DEBUG_USB_INT_HI_PUTCHAR( 'c' );
|
||||
ProcessOepData( ep );
|
||||
}
|
||||
|
||||
/* Setup Phase Done */
|
||||
if ( status & USB_DOEP0INT_SETUP )
|
||||
{
|
||||
ProcessSetup();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
static void ProcessOepData( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
if ( ep->num == 0 )
|
||||
{
|
||||
|
||||
#ifdef __MBED__
|
||||
int xfer_size = ep->packetSize - (( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_XFERSIZE_MASK )
|
||||
>> _USB_DOEP0TSIZ_XFERSIZE_SHIFT);
|
||||
int setup_pkt_received = USBDHAL_GetOutEpInts( ep ) & USB_DOEP0INT_SETUP;
|
||||
|
||||
if ( (!setup_pkt_received && xfer_size == 0) ||
|
||||
(setup_pkt_received && xfer_size == 8) )
|
||||
{
|
||||
/* Higher levels need to see the correct transfer amount for ZLPs */
|
||||
ep->remaining = 0;
|
||||
ep->xferred = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME - does not work if actual read size > 56 */
|
||||
if ( setup_pkt_received ) xfer_size -= 8;
|
||||
|
||||
ep->xferred = xfer_size;
|
||||
ep->remaining -= xfer_size;
|
||||
}
|
||||
#else
|
||||
if ( ep->remaining > ep->packetSize )
|
||||
{
|
||||
ep->remaining -= ep->packetSize;
|
||||
ep->xferred += ep->packetSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xferred += ep->remaining;
|
||||
ep->remaining = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
USBDEP_Ep0Handler( dev );
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xferred = ep->hwXferSize -
|
||||
( ( USB_DOUTEPS[ ep->num ].TSIZ & _USB_DOEP_TSIZ_XFERSIZE_MASK )>>
|
||||
_USB_DOEP_TSIZ_XFERSIZE_SHIFT );
|
||||
ep->remaining -= ep->xferred;
|
||||
USBDEP_EpHandler( ep->addr );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
static void ProcessSetup( void )
|
||||
{
|
||||
DEBUG_USB_INT_LO_PUTS( "\nS" );
|
||||
|
||||
if ( USB->DOEP0INT & USB_DOEP0INT_BACK2BACKSETUP )
|
||||
{ /* Back to back setup packets received */
|
||||
USB->DOEP0INT = USB_DOEP0INT_BACK2BACKSETUP;
|
||||
DEBUG_USB_INT_LO_PUTS( "B2B" );
|
||||
|
||||
dev->setup = (USB_Setup_TypeDef*)( USB->DOEP0DMAADDR - USB_SETUP_PKT_SIZE );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read SETUP packet counter from hw. */
|
||||
int supCnt = ( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_SUPCNT_MASK )
|
||||
>> _USB_DOEP0TSIZ_SUPCNT_SHIFT;
|
||||
|
||||
if ( supCnt == 3 )
|
||||
supCnt = 2;
|
||||
|
||||
dev->setup = &dev->setupPkt[ 2 - supCnt ];
|
||||
}
|
||||
USB->DOEP0TSIZ |= 3 << _USB_DOEP0TSIZ_SUPCNT_SHIFT;
|
||||
USB->DOEP0DMAADDR = (uint32_t)dev->setupPkt;
|
||||
USB->DOEP0INT = USB_DOEP0INT_SETUP;
|
||||
|
||||
USBDEP_Ep0Handler( dev ); /* Call the SETUP handler for EP0 */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle USB reset detected interrupt in suspend mode.
|
||||
*/
|
||||
static void Handle_USB_GINTSTS_RESETDET ( void )
|
||||
{
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
if ( ! USBD_poweredDown )
|
||||
{
|
||||
USB->GINTSTS = USB_GINTSTS_RESETDET;
|
||||
}
|
||||
|
||||
if ( UsbPowerUp() )
|
||||
{
|
||||
USB->GINTSTS = USB_GINTSTS_RESETDET;
|
||||
}
|
||||
|
||||
#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ONVBUSOFF )
|
||||
/* Power down immediately if VBUS is off. */
|
||||
if ( ! ( USB->STATUS & USB_STATUS_VREGOS ) )
|
||||
{
|
||||
UsbPowerDown();
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
USB->GINTSTS = USB_GINTSTS_RESETDET;
|
||||
#endif /* if ( USB_PWRSAVE_MODE ) */
|
||||
|
||||
if ( USB->STATUS & USB_STATUS_VREGOS )
|
||||
{
|
||||
USBD_SetUsbState( USBD_STATE_DEFAULT );
|
||||
}
|
||||
else
|
||||
{
|
||||
USBD_SetUsbState( USBD_STATE_NONE );
|
||||
}
|
||||
DEBUG_USB_INT_LO_PUTS( "RsuP\n" );
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle Start Of Frame (SOF) interrupt.
|
||||
*/
|
||||
static void Handle_USB_GINTSTS_SOF( void )
|
||||
{
|
||||
USB->GINTSTS = USB_GINTSTS_SOF;
|
||||
|
||||
if ( dev->callbacks->sofInt )
|
||||
{
|
||||
dev->callbacks->sofInt(
|
||||
( USB->DSTS & _USB_DSTS_SOFFN_MASK ) >> _USB_DSTS_SOFFN_SHIFT );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle USB port reset interrupt.
|
||||
*/
|
||||
static void Handle_USB_GINTSTS_USBRST( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
DEBUG_USB_INT_LO_PUTS( "ReseT" );
|
||||
|
||||
/* Clear Remote Wakeup Signalling */
|
||||
USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_RMTWKUPSIG );
|
||||
USBHAL_FlushTxFifo( 0 );
|
||||
|
||||
/* Clear pending interrupts */
|
||||
for ( i = 0; i <= MAX_NUM_IN_EPS; i++ )
|
||||
{
|
||||
USB_DINEPS[ i ].INT = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
for ( i = 0; i <= MAX_NUM_OUT_EPS; i++ )
|
||||
{
|
||||
USB_DOUTEPS[ i ].INT = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
USB->DAINTMSK = USB_DAINTMSK_INEPMSK0 | USB_DAINTMSK_OUTEPMSK0;
|
||||
#if defined( USB_DOEPMSK_STSPHSERCVDMSK )
|
||||
USB->DOEPMSK = USB_DOEPMSK_SETUPMSK | USB_DOEPMSK_XFERCOMPLMSK
|
||||
| USB_DOEPMSK_STSPHSERCVDMSK;
|
||||
#else
|
||||
USB->DOEPMSK = USB_DOEPMSK_SETUPMSK | USB_DOEPMSK_XFERCOMPLMSK;
|
||||
#endif
|
||||
USB->DIEPMSK = USB_DIEPMSK_XFERCOMPLMSK;
|
||||
|
||||
/* Reset Device Address */
|
||||
USB->DCFG &= ~_USB_DCFG_DEVADDR_MASK;
|
||||
|
||||
/* Setup EP0 to receive SETUP packets */
|
||||
USBDHAL_StartEp0Setup( dev );
|
||||
USBDHAL_EnableInts( dev );
|
||||
|
||||
if ( dev->callbacks->usbReset )
|
||||
{
|
||||
dev->callbacks->usbReset();
|
||||
}
|
||||
|
||||
USBD_SetUsbState( USBD_STATE_DEFAULT );
|
||||
USBDHAL_AbortAllTransfers( USB_STATUS_DEVICE_RESET );
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle USB port suspend interrupt.
|
||||
*/
|
||||
static void Handle_USB_GINTSTS_USBSUSP( void )
|
||||
{
|
||||
USBD_State_TypeDef state;
|
||||
|
||||
USB->GINTSTS = USB_GINTSTS_USBSUSP;
|
||||
USBDHAL_AbortAllTransfers( USB_STATUS_DEVICE_SUSPENDED );
|
||||
DEBUG_USB_INT_LO_PUTS( "\nSusP" );
|
||||
|
||||
if ( USBD_GetUsbState() == USBD_STATE_NONE )
|
||||
{
|
||||
USBD_SetUsbState( USBD_STATE_POWERED );
|
||||
}
|
||||
|
||||
state = USBD_GetUsbState();
|
||||
if ( ( state == USBD_STATE_POWERED ) ||
|
||||
( state == USBD_STATE_DEFAULT ) ||
|
||||
( state == USBD_STATE_ADDRESSED ) ||
|
||||
( state == USBD_STATE_CONFIGURED ) )
|
||||
{
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
UsbPowerDown();
|
||||
#endif
|
||||
USBD_SetUsbState( USBD_STATE_SUSPENDED );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle USB port wakeup interrupt.
|
||||
*/
|
||||
static void Handle_USB_GINTSTS_WKUPINT( void )
|
||||
{
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
if ( ! USBD_poweredDown )
|
||||
{
|
||||
USB->GINTSTS = USB_GINTSTS_WKUPINT;
|
||||
}
|
||||
|
||||
if ( UsbPowerUp() )
|
||||
{
|
||||
USB->GINTSTS = USB_GINTSTS_WKUPINT;
|
||||
USBDHAL_StartEp0Setup( dev );
|
||||
USBDHAL_Ep0Activate( dev->ep0MpsCode );
|
||||
}
|
||||
#else
|
||||
USB->GINTSTS = USB_GINTSTS_WKUPINT;
|
||||
#endif
|
||||
|
||||
USBD_SetUsbState( dev->savedState );
|
||||
DEBUG_USB_INT_LO_PUTS( "WkuP\n" );
|
||||
}
|
||||
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
/*
|
||||
* Backup essential USB core registers, and set the core in partial powerdown
|
||||
* mode. Optionally prepare entry into EM2.
|
||||
*/
|
||||
static bool UsbPowerDown( void )
|
||||
{
|
||||
#if ( NUM_EP_USED > 0 ) || ( FIFO_CNT > 0 )
|
||||
int i;
|
||||
#endif
|
||||
#if ( NUM_EP_USED > 0 )
|
||||
int epNum;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
#endif
|
||||
|
||||
if ( !USBD_poweredDown )
|
||||
{
|
||||
USBD_poweredDown = true;
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '\\' );
|
||||
|
||||
/* Backup USB core registers. */
|
||||
x_USB_GINTMSK = USB->GINTMSK;
|
||||
#if defined(_USB_GOTGCTL_MASK)
|
||||
x_USB_GOTGCTL = USB->GOTGCTL;
|
||||
#endif
|
||||
x_USB_GAHBCFG = USB->GAHBCFG;
|
||||
x_USB_GUSBCFG = USB->GUSBCFG;
|
||||
x_USB_GRXFSIZ = USB->GRXFSIZ;
|
||||
x_USB_GNPTXFSIZ = USB->GNPTXFSIZ;
|
||||
x_USB_DCFG = USB->DCFG;
|
||||
x_USB_DCTL = USB->DCTL;
|
||||
x_USB_DAINTMSK = USB->DAINTMSK;
|
||||
x_USB_DIEPMSK = USB->DIEPMSK;
|
||||
x_USB_DOEPMSK = USB->DOEPMSK;
|
||||
x_USB_PCGCCTL = USB->PCGCCTL;
|
||||
|
||||
#if ( NUM_EP_USED > 0 )
|
||||
for ( i = 0; i < NUM_EP_USED; i++ )
|
||||
{
|
||||
ep = &dev->ep[ i+1 ];
|
||||
epNum = ep->num;
|
||||
if ( ep->in )
|
||||
{
|
||||
x_USB_EP_CTL[ i ] = USB_DINEPS[ epNum ].CTL;
|
||||
x_USB_EP_TSIZ[ i ] = USB_DINEPS[ epNum ].TSIZ;
|
||||
x_USB_EP_DMAADDR[ i ] = USB_DINEPS[ epNum ].DMAADDR;
|
||||
}
|
||||
else
|
||||
{
|
||||
x_USB_EP_CTL[ i ] = USB_DOUTEPS[ epNum ].CTL;
|
||||
x_USB_EP_TSIZ[ i ] = USB_DOUTEPS[ epNum ].TSIZ;
|
||||
x_USB_EP_DMAADDR[ i ] = USB_DOUTEPS[ epNum ].DMAADDR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( FIFO_CNT > 0 )
|
||||
for ( i = 0; i < FIFO_CNT; i++ )
|
||||
{
|
||||
x_USB_DIEPTXFS[ i ] = USB_DIEPTXFS[ i ];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Prepare for wakeup on resume and reset. */
|
||||
USB->DCFG = (USB->DCFG & ~_USB_DCFG_RESVALID_MASK) |
|
||||
(4 << _USB_DCFG_RESVALID_SHIFT);
|
||||
USB->DCFG |= USB_DCFG_ENA32KHZSUSP;
|
||||
USB->GINTMSK = USB_GINTMSK_RESETDETMSK | USB_GINTMSK_WKUPINTMSK;
|
||||
|
||||
/* Enter partial powerdown mode. */
|
||||
USB->PCGCCTL |= USB_PCGCCTL_PWRCLMP;
|
||||
USB->PCGCCTL |= USB_PCGCCTL_RSTPDWNMODULE;
|
||||
USB->PCGCCTL |= USB_PCGCCTL_STOPPCLK;
|
||||
|
||||
/* Record current clock settings. */
|
||||
cmuStatus = CMU->STATUS;
|
||||
|
||||
#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ENTEREM2 )
|
||||
#ifndef __MBED__
|
||||
/* Enter EM2 on interrupt exit. */
|
||||
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk;
|
||||
#else
|
||||
usbhal_allow_em2(true);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Switch USBC clock to 32 kHz. */
|
||||
#if ( USB_USBC_32kHz_CLK == USB_USBC_32kHz_CLK_LFXO )
|
||||
CMU->CMD = CMU_CMD_USBCCLKSEL_LFXO;
|
||||
while ( ( CMU->STATUS & CMU_STATUS_USBCLFXOSEL ) == 0 ){}
|
||||
#else
|
||||
CMU->CMD = CMU_CMD_USBCCLKSEL_LFRCO;
|
||||
while ( ( CMU->STATUS & CMU_STATUS_USBCLFRCOSEL ) == 0 ){}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif /* if ( USB_PWRSAVE_MODE ) */
|
||||
|
||||
#if ( USB_PWRSAVE_MODE )
|
||||
/*
|
||||
* Exit USB core partial powerdown mode, restore essential USB core registers.
|
||||
* Will prevent re-entry back to EM2.
|
||||
* Returns true if a powerup sequence was performed.
|
||||
*/
|
||||
static bool UsbPowerUp( void )
|
||||
{
|
||||
#if ( NUM_EP_USED > 0 ) || ( FIFO_CNT > 0 )
|
||||
int i;
|
||||
#endif
|
||||
#if ( NUM_EP_USED > 0 )
|
||||
int epNum;
|
||||
uint32_t tmp;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
#endif
|
||||
|
||||
if ( USBD_poweredDown )
|
||||
{
|
||||
USBD_poweredDown = false;
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '/' );
|
||||
|
||||
#if !defined( USB_CORECLK_HFRCO ) || !defined( CMU_OSCENCMD_USHFRCOEN )
|
||||
/* Switch HFCLK from HFRCO to HFXO. */
|
||||
CMU_ClockSelectSet( cmuClock_HF, cmuSelect_HFXO );
|
||||
#endif
|
||||
|
||||
/* Turn off HFRCO when not needed. */
|
||||
if ( ( cmuStatus & CMU_STATUS_HFRCOENS ) == 0 )
|
||||
{
|
||||
CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS;
|
||||
}
|
||||
|
||||
/* Exit partial powerdown mode. */
|
||||
USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK;
|
||||
USB->PCGCCTL &= ~(USB_PCGCCTL_PWRCLMP | USB_PCGCCTL_RSTPDWNMODULE);
|
||||
|
||||
if (( USB->GINTSTS & ( USB_GINTSTS_WKUPINT | USB_GINTSTS_RESETDET ) ) == 0)
|
||||
{
|
||||
USB->DCTL = x_USB_DCTL | USB_DCTL_RMTWKUPSIG;
|
||||
USB->DCTL = x_USB_DCTL;
|
||||
}
|
||||
|
||||
/* Restore USB core registers. */
|
||||
USB->GUSBCFG = x_USB_GUSBCFG;
|
||||
USB->DCFG = x_USB_DCFG;
|
||||
|
||||
#if ( FIFO_CNT > 0 )
|
||||
for ( i = 0; i < FIFO_CNT; i++ )
|
||||
{
|
||||
USB_DIEPTXFS[ i ] = x_USB_DIEPTXFS[ i ];
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ( NUM_EP_USED > 0 )
|
||||
for ( i = 0; i < NUM_EP_USED; i++ )
|
||||
{
|
||||
ep = &dev->ep[ i+1 ];
|
||||
epNum = ep->num;
|
||||
|
||||
tmp = x_USB_EP_CTL[ i ] &
|
||||
~( USB_DIEP_CTL_CNAK | USB_DIEP_CTL_SNAK |
|
||||
USB_DIEP_CTL_SETD0PIDEF | USB_DIEP_CTL_SETD1PIDOF );
|
||||
|
||||
if ( x_USB_EP_CTL[ i ] & USB_DIEP_CTL_DPIDEOF )
|
||||
tmp |= USB_DIEP_CTL_SETD1PIDOF;
|
||||
else
|
||||
tmp |= USB_DIEP_CTL_SETD0PIDEF;
|
||||
|
||||
if ( x_USB_EP_CTL[ i ] & USB_DIEP_CTL_NAKSTS )
|
||||
tmp |= USB_DIEP_CTL_SNAK;
|
||||
else
|
||||
tmp |= USB_DIEP_CTL_CNAK;
|
||||
|
||||
if ( ep->in )
|
||||
{
|
||||
USB_DINEPS[ epNum ].CTL = tmp;
|
||||
USB_DINEPS[ epNum ].TSIZ = x_USB_EP_TSIZ[ i ];
|
||||
USB_DINEPS[ epNum ].DMAADDR = x_USB_EP_DMAADDR[ i ];
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_DOUTEPS[ epNum ].CTL = tmp;
|
||||
USB_DOUTEPS[ epNum ].TSIZ = x_USB_EP_TSIZ[ i ];
|
||||
USB_DOUTEPS[ epNum ].DMAADDR = x_USB_EP_DMAADDR[ i ];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
USB->PCGCCTL = x_USB_PCGCCTL;
|
||||
USB->DOEPMSK = x_USB_DOEPMSK;
|
||||
USB->DIEPMSK = x_USB_DIEPMSK;
|
||||
USB->DAINTMSK = x_USB_DAINTMSK;
|
||||
USB->DCTL = x_USB_DCTL;
|
||||
USB->GNPTXFSIZ = x_USB_GNPTXFSIZ;
|
||||
USB->GRXFSIZ = x_USB_GRXFSIZ;
|
||||
USB->GAHBCFG = x_USB_GAHBCFG;
|
||||
#if defined(_USB_GOTGCTL_MASK)
|
||||
USB->GOTGCTL = x_USB_GOTGCTL;
|
||||
#endif
|
||||
USB->GINTMSK = x_USB_GINTMSK;
|
||||
|
||||
USB->DCTL |= USB_DCTL_PWRONPRGDONE;
|
||||
|
||||
#if ( USB_PWRSAVE_MODE & USB_PWRSAVE_MODE_ENTEREM2 )
|
||||
#ifndef __MBED__
|
||||
/* Do not reenter EM2 on interrupt exit. */
|
||||
SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk);
|
||||
#else
|
||||
usbhal_allow_em2(false);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif /* if ( USB_PWRSAVE_MODE ) */
|
||||
|
||||
#if defined( USB_DOEP0INT_STUPPKTRCVD )
|
||||
static void HandleOutEpIntr( uint32_t status, USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
uint32_t doeptsiz;
|
||||
|
||||
if ( ep->num == 0 )
|
||||
{
|
||||
if ( status & USB_DOEP0INT_XFERCOMPL )
|
||||
{
|
||||
USB->DOEP0INT = USB_DOEP0INT_XFERCOMPL;
|
||||
doeptsiz = USB->DOEP0TSIZ;
|
||||
|
||||
if ( ep->state == D_EP_IDLE )
|
||||
{
|
||||
if ( status & USB_DOEP0INT_STUPPKTRCVD )
|
||||
{
|
||||
USB->DOEP0INT = USB_DOEP0INT_STUPPKTRCVD;
|
||||
}
|
||||
status = USBDHAL_GetOutEpInts( ep );
|
||||
doeptsiz = USB->DOEP0TSIZ;
|
||||
|
||||
if ( status & USB_DOEP0INT_SETUP )
|
||||
{
|
||||
retry:
|
||||
/* Already started data stage, clear setup */
|
||||
USB->DOEP0INT = USB_DOEP0INT_SETUP;
|
||||
status &= ~USB_DOEP0INT_SETUP;
|
||||
{
|
||||
int supCnt = ( doeptsiz & _USB_DOEP0TSIZ_SUPCNT_MASK )
|
||||
>> _USB_DOEP0TSIZ_SUPCNT_SHIFT;
|
||||
|
||||
if ( supCnt == 3 )
|
||||
supCnt = 2;
|
||||
|
||||
dev->setup = &dev->setupPkt[ 2 - supCnt ];
|
||||
}
|
||||
DEBUG_USB_INT_LO_PUTS( "\nS" );
|
||||
USBDEP_Ep0Handler( dev );
|
||||
|
||||
/* Prepare for more setup packets */
|
||||
if ( ep->state == D_EP0_IN_STATUS || ep->state == D_EP_TRANSMITTING )
|
||||
{
|
||||
USBDHAL_StartEp0Setup( dev );
|
||||
}
|
||||
}
|
||||
else /* xfercompl && idle && !setup */
|
||||
{
|
||||
status = USBDHAL_GetOutEpInts( ep );
|
||||
if ( status & USB_DOEP0INT_SETUP )
|
||||
goto retry;
|
||||
USBDHAL_StartEp0Setup( dev );
|
||||
}
|
||||
}
|
||||
else /* ep0state != EP0_IDLE */
|
||||
{
|
||||
#ifdef __MBED__
|
||||
if ( ep->state == D_EP_RECEIVING )
|
||||
{
|
||||
int xfer_size = ep->packetSize - (( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_XFERSIZE_MASK )
|
||||
>> _USB_DOEP0TSIZ_XFERSIZE_SHIFT);
|
||||
int setup_pkt_received = status & USB_DOEP0INT_SETUP;
|
||||
|
||||
if ( (!setup_pkt_received && xfer_size == 0) ||
|
||||
(setup_pkt_received && xfer_size == 8) )
|
||||
{
|
||||
/* Higher levels need to see the correct transfer amount for ZLPs */
|
||||
ep->remaining = 0;
|
||||
ep->xferred = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME - does not work if actual read size > 56 */
|
||||
if ( setup_pkt_received ) xfer_size -= 8;
|
||||
|
||||
ep->xferred = xfer_size;
|
||||
ep->remaining -= xfer_size;
|
||||
}
|
||||
|
||||
USBDEP_Ep0Handler( dev );
|
||||
}
|
||||
#else
|
||||
if ( ep->state == D_EP_RECEIVING )
|
||||
{
|
||||
if ( ep->remaining > ep->packetSize )
|
||||
{
|
||||
ep->remaining -= ep->packetSize;
|
||||
ep->xferred += ep->packetSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xferred += ep->remaining;
|
||||
ep->remaining = 0;
|
||||
}
|
||||
USBDEP_Ep0Handler( dev );
|
||||
}
|
||||
else if ( ep->state == D_EP0_OUT_STATUS )
|
||||
{
|
||||
USBDEP_Ep0Handler( dev );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} /* if ( status & USB_DOEP0INT_XFERCOMPL ) */
|
||||
|
||||
if ( status & USB_DOEP0INT_STSPHSERCVD )
|
||||
{
|
||||
USB->DOEP0INT = USB_DOEP0INT_STSPHSERCVD;
|
||||
}
|
||||
|
||||
if ( status & USB_DOEP0INT_SETUP )
|
||||
{
|
||||
USB->DOEP0INT = USB_DOEP0INT_SETUP;
|
||||
{
|
||||
int supCnt = ( USB->DOEP0TSIZ & _USB_DOEP0TSIZ_SUPCNT_MASK )
|
||||
>> _USB_DOEP0TSIZ_SUPCNT_SHIFT;
|
||||
|
||||
if ( supCnt == 3 )
|
||||
supCnt = 2;
|
||||
|
||||
dev->setup = &dev->setupPkt[ 2 - supCnt ];
|
||||
}
|
||||
DEBUG_USB_INT_LO_PUTS( "\nS" );
|
||||
USBDEP_Ep0Handler( dev );
|
||||
}
|
||||
}
|
||||
else /* epnum != 0 */
|
||||
{
|
||||
if ( status & USB_DOEP_INT_XFERCOMPL )
|
||||
{
|
||||
USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_XFERCOMPL;
|
||||
|
||||
ep->xferred = ep->hwXferSize -
|
||||
( ( USB_DOUTEPS[ ep->num ].TSIZ & _USB_DOEP_TSIZ_XFERSIZE_MASK )>>
|
||||
_USB_DOEP_TSIZ_XFERSIZE_SHIFT );
|
||||
ep->remaining -= ep->xferred;
|
||||
|
||||
USBDEP_EpHandler( ep->addr );
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @endcond */
|
||||
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
|
|
@ -0,0 +1,799 @@
|
|||
/**************************************************************************//**
|
||||
* @file em_usbhal.c
|
||||
* @brief USB protocol stack library, low level USB peripheral access.
|
||||
* @version 3.20.14
|
||||
******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "em_device.h"
|
||||
#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
|
||||
#include "em_usb.h"
|
||||
#if defined( USB_DEVICE ) || defined( USB_HOST )
|
||||
|
||||
#include "em_usbtypes.h"
|
||||
#include "em_usbhal.h"
|
||||
#if defined( USB_DEVICE )
|
||||
#include "em_usbd.h"
|
||||
#endif
|
||||
#if defined( USB_HOST )
|
||||
#include "em_usbh.h"
|
||||
#endif
|
||||
#include "em_cmu.h"
|
||||
#include "em_gpio.h"
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
#define EPABORT_BREAK_LOOP_COUNT 15000 /* Approx. 100 ms */
|
||||
|
||||
/* NOTE: The sequence of error message strings must agree with the */
|
||||
/* definition of USB_Status_TypeDef enum. */
|
||||
static const char * const errMsg[] =
|
||||
{
|
||||
[ USB_STATUS_OK ] = "No errors",
|
||||
[ -USB_STATUS_REQ_ERR ] = "Setup request error",
|
||||
[ -USB_STATUS_EP_BUSY ] = "Endpoint is busy",
|
||||
[ -USB_STATUS_REQ_UNHANDLED ] = "Setup request not handled",
|
||||
[ -USB_STATUS_ILLEGAL ] = "Illegal operation attempted",
|
||||
[ -USB_STATUS_EP_STALLED ] = "Endpoint is stalled",
|
||||
[ -USB_STATUS_EP_ABORTED ] = "Transfer aborted",
|
||||
[ -USB_STATUS_EP_ERROR ] = "Transfer error",
|
||||
[ -USB_STATUS_EP_NAK ] = "Endpoint NAK",
|
||||
[ -USB_STATUS_DEVICE_UNCONFIGURED ] = "Device is not configured",
|
||||
[ -USB_STATUS_DEVICE_SUSPENDED ] = "Device is suspended",
|
||||
[ -USB_STATUS_DEVICE_RESET ] = "Device has been reset",
|
||||
[ -USB_STATUS_TIMEOUT ] = "Transfer timeout",
|
||||
[ -USB_STATUS_DEVICE_REMOVED ] = "Device removed",
|
||||
[ -USB_STATUS_HC_BUSY ] = "Host channel is busy",
|
||||
[ -USB_STATUS_DEVICE_MALFUNCTION ] = "Device malfunction",
|
||||
[ -USB_STATUS_PORT_OVERCURRENT ] = "VBUS overcurrent",
|
||||
};
|
||||
/** @endcond */
|
||||
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Return an error message string for a given error code.
|
||||
*
|
||||
* @param[in] error
|
||||
* Error code, see \ref USB_Status_TypeDef.
|
||||
*
|
||||
* @return
|
||||
* Error message string pointer.
|
||||
******************************************************************************/
|
||||
char *USB_GetErrorMsgString( int error )
|
||||
{
|
||||
if ( error >= 0 )
|
||||
return (char*)errMsg[ 0 ];
|
||||
|
||||
return (char*)errMsg[ -error ];
|
||||
}
|
||||
|
||||
|
||||
#if defined( USB_USE_PRINTF )
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Format and print a text string given an error code, prepends an optional user
|
||||
* supplied leader string.
|
||||
*
|
||||
* @param[in] pre
|
||||
* Optional leader string to prepend to error message string.
|
||||
*
|
||||
* @param[in] error
|
||||
* Error code, see \ref USB_Status_TypeDef.
|
||||
******************************************************************************/
|
||||
void USB_PrintErrorMsgString( char *pre, int error )
|
||||
{
|
||||
if ( pre )
|
||||
{
|
||||
USB_PRINTF( "%s", pre );
|
||||
}
|
||||
|
||||
if ( error > USB_STATUS_OK )
|
||||
{
|
||||
USB_PRINTF( "%d", error );
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_PRINTF( "%s", USB_GetErrorMsgString( error ) );
|
||||
}
|
||||
}
|
||||
#endif /* defined( USB_USE_PRINTF ) */
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
#if defined( DEBUG_EFM_USER )
|
||||
static void PrintI( int i )
|
||||
{
|
||||
#if !defined ( USER_PUTCHAR )
|
||||
(void)i;
|
||||
#else
|
||||
if ( i >= 10 )
|
||||
{
|
||||
PrintI( i / 10 );
|
||||
}
|
||||
|
||||
DEBUG_USB_API_PUTCHAR( ( i % 10 ) + '0' );
|
||||
#endif
|
||||
}
|
||||
|
||||
void assertEFM( const char *file, int line )
|
||||
{
|
||||
#if !defined ( USER_PUTCHAR )
|
||||
(void)file;
|
||||
#endif
|
||||
|
||||
DEBUG_USB_API_PUTS( "\nASSERT " );
|
||||
DEBUG_USB_API_PUTS( file );
|
||||
DEBUG_USB_API_PUTCHAR( ' ' );
|
||||
PrintI( line );
|
||||
for(;;){}
|
||||
}
|
||||
#endif /* defined( DEBUG_EFM_USER ) */
|
||||
|
||||
#if defined ( USER_PUTCHAR )
|
||||
void USB_Puts( const char *p )
|
||||
{
|
||||
while( *p )
|
||||
USB_PUTCHAR( *p++ );
|
||||
}
|
||||
#endif /* defined ( USER_PUTCHAR ) */
|
||||
|
||||
void USBHAL_CoreReset( void )
|
||||
{
|
||||
USB->PCGCCTL &= ~USB_PCGCCTL_STOPPCLK;
|
||||
USB->PCGCCTL &= ~(USB_PCGCCTL_PWRCLMP | USB_PCGCCTL_RSTPDWNMODULE);
|
||||
|
||||
/* Core Soft Reset */
|
||||
USB->GRSTCTL |= USB_GRSTCTL_CSFTRST;
|
||||
while ( USB->GRSTCTL & USB_GRSTCTL_CSFTRST ) {}
|
||||
|
||||
USBTIMER_DelayUs( 1 );
|
||||
|
||||
/* Wait for AHB master IDLE state. */
|
||||
while ( !( USB->GRSTCTL & USB_GRSTCTL_AHBIDLE ) ) {}
|
||||
}
|
||||
|
||||
#ifdef USB_DEVICE
|
||||
void USBDHAL_Connect( void )
|
||||
{
|
||||
USB->DCTL &= ~( DCTL_WO_BITMASK | USB_DCTL_SFTDISCON );
|
||||
}
|
||||
|
||||
USB_Status_TypeDef USBDHAL_CoreInit( uint32_t totalRxFifoSize,
|
||||
uint32_t totalTxFifoSize )
|
||||
{
|
||||
uint8_t i, j;
|
||||
uint16_t start, depth;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
|
||||
#if !defined( USB_VBUS_SWITCH_NOT_PRESENT )
|
||||
CMU_ClockEnable( cmuClock_GPIO, true );
|
||||
GPIO_PinModeSet( gpioPortF, 5, gpioModePushPull, 0 ); /* Enable VBUSEN pin */
|
||||
USB->ROUTE = USB_ROUTE_PHYPEN | USB_ROUTE_VBUSENPEN; /* Enable PHY pins. */
|
||||
#else
|
||||
USB->ROUTE = USB_ROUTE_PHYPEN; /* Enable PHY pins. */
|
||||
#endif
|
||||
|
||||
USBHAL_CoreReset(); /* Reset USB core */
|
||||
|
||||
#if defined( USB_GUSBCFG_FORCEHSTMODE )
|
||||
/* Force Device Mode */
|
||||
USB->GUSBCFG = ( USB->GUSBCFG &
|
||||
~(GUSBCFG_WO_BITMASK | USB_GUSBCFG_FORCEHSTMODE ) ) |
|
||||
USB_GUSBCFG_FORCEDEVMODE;
|
||||
#endif
|
||||
|
||||
INT_Enable();
|
||||
USBTIMER_DelayMs( 50 );
|
||||
INT_Disable();
|
||||
|
||||
/* Set device speed */
|
||||
USB->DCFG = ( USB->DCFG & ~_USB_DCFG_DEVSPD_MASK ) | 3; /* Full speed PHY */
|
||||
|
||||
/* Stall on non-zero len status OUT packets (ctrl transfers). */
|
||||
USB->DCFG |= USB_DCFG_NZSTSOUTHSHK;
|
||||
|
||||
/* Set periodic frame interval to 80% */
|
||||
USB->DCFG &= ~_USB_DCFG_PERFRINT_MASK;
|
||||
|
||||
USB->GAHBCFG = ( USB->GAHBCFG & ~_USB_GAHBCFG_HBSTLEN_MASK ) |
|
||||
USB_GAHBCFG_DMAEN | USB_GAHBCFG_HBSTLEN_INCR;
|
||||
|
||||
/* Ignore frame numbers on ISO transfers. */
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_IGNRFRMNUM;
|
||||
|
||||
/* Set Rx FIFO size */
|
||||
start = EFM32_MAX( totalRxFifoSize, MIN_EP_FIFO_SIZE_INWORDS );
|
||||
USB->GRXFSIZ = ( start << _USB_GRXFSIZ_RXFDEP_SHIFT ) &
|
||||
_USB_GRXFSIZ_RXFDEP_MASK;
|
||||
|
||||
/* Set Tx EP0 FIFO size */
|
||||
depth = EFM32_MAX( dev->ep[ 0 ].fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
|
||||
USB->GNPTXFSIZ = ( ( depth << _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT ) &
|
||||
_USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_MASK ) |
|
||||
( ( start << _USB_GNPTXFSIZ_NPTXFSTADDR_SHIFT ) &
|
||||
_USB_GNPTXFSIZ_NPTXFSTADDR_MASK );
|
||||
|
||||
|
||||
/* Set Tx EP FIFO sizes for all IN ep's */
|
||||
for ( j = 1; j <= MAX_NUM_TX_FIFOS; j++ )
|
||||
{
|
||||
for ( i = 1; i <= MAX_NUM_IN_EPS; i++ )
|
||||
{
|
||||
ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | i );
|
||||
if ( ep ) /* Is EP in use ? */
|
||||
{
|
||||
if ( ep->txFifoNum == j ) /* Is it correct FIFO number ? */
|
||||
{
|
||||
start += depth;
|
||||
depth = EFM32_MAX( ep->fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
|
||||
USB_DIEPTXFS[ ep->txFifoNum - 1 ] =
|
||||
( depth << _USB_DIEPTXF1_INEPNTXFDEP_SHIFT ) |
|
||||
( start & _USB_DIEPTXF1_INEPNTXFSTADDR_MASK );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( totalRxFifoSize + totalTxFifoSize > MAX_DEVICE_FIFO_SIZE_INWORDS )
|
||||
return USB_STATUS_ILLEGAL;
|
||||
|
||||
if ( start > MAX_DEVICE_FIFO_SIZE_INWORDS )
|
||||
return USB_STATUS_ILLEGAL;
|
||||
|
||||
/* Flush the FIFO's */
|
||||
USBHAL_FlushTxFifo( 0x10 ); /* All Tx FIFO's */
|
||||
USBHAL_FlushRxFifo(); /* The Rx FIFO */
|
||||
|
||||
/* Disable all device interrupts */
|
||||
USB->DIEPMSK = 0;
|
||||
USB->DOEPMSK = 0;
|
||||
USB->DAINTMSK = 0;
|
||||
USB->DIEPEMPMSK = 0;
|
||||
|
||||
/* Disable all EP's, clear all EP ints. */
|
||||
for ( i = 0; i <= MAX_NUM_IN_EPS; i++ )
|
||||
{
|
||||
USB_DINEPS[ i ].CTL = 0;
|
||||
USB_DINEPS[ i ].TSIZ = 0;
|
||||
USB_DINEPS[ i ].INT = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
for ( i = 0; i <= MAX_NUM_OUT_EPS; i++ )
|
||||
{
|
||||
USB_DOUTEPS[ i ].CTL = 0;
|
||||
USB_DOUTEPS[ i ].TSIZ = 0;
|
||||
USB_DOUTEPS[ i ].INT = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
#if ( USB_DCTL_SFTDISCON_DEFAULT != 0 )
|
||||
USBD_Connect();
|
||||
#endif
|
||||
|
||||
/* Enable VREGO sense. */
|
||||
USB->CTRL |= USB_CTRL_VREGOSEN;
|
||||
USB->IFC = USB_IFC_VREGOSH | USB_IFC_VREGOSL;
|
||||
USB->IEN = USB_IFC_VREGOSH | USB_IFC_VREGOSL;
|
||||
/* Force a VREGO interrupt. */
|
||||
if ( USB->STATUS & USB_STATUS_VREGOS)
|
||||
USB->IFS = USB_IFS_VREGOSH;
|
||||
else
|
||||
USB->IFS = USB_IFS_VREGOSL;
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
USB_Status_TypeDef USBDHAL_ReconfigureFifos( uint32_t totalRxFifoSize,
|
||||
uint32_t totalTxFifoSize )
|
||||
{
|
||||
uint8_t i, j;
|
||||
uint16_t start, depth;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
|
||||
/* Set Rx FIFO size */
|
||||
start = EFM32_MAX( totalRxFifoSize, MIN_EP_FIFO_SIZE_INWORDS );
|
||||
USB->GRXFSIZ = ( start << _USB_GRXFSIZ_RXFDEP_SHIFT ) &
|
||||
_USB_GRXFSIZ_RXFDEP_MASK;
|
||||
|
||||
/* Set Tx EP0 FIFO size */
|
||||
depth = EFM32_MAX( dev->ep[ 0 ].fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
|
||||
USB->GNPTXFSIZ = ( ( depth << _USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT ) &
|
||||
_USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_MASK ) |
|
||||
( ( start << _USB_GNPTXFSIZ_NPTXFSTADDR_SHIFT ) &
|
||||
_USB_GNPTXFSIZ_NPTXFSTADDR_MASK );
|
||||
|
||||
|
||||
/* Set Tx EP FIFO sizes for all IN ep's */
|
||||
for ( j = 1; j <= MAX_NUM_TX_FIFOS; j++ )
|
||||
{
|
||||
for ( i = 1; i <= MAX_NUM_IN_EPS; i++ )
|
||||
{
|
||||
ep = USBD_GetEpFromAddr( USB_SETUP_DIR_MASK | i );
|
||||
if ( ep ) /* Is EP in use ? */
|
||||
{
|
||||
if ( ep->txFifoNum == j ) /* Is it correct FIFO number ? */
|
||||
{
|
||||
start += depth;
|
||||
depth = EFM32_MAX( ep->fifoSize, MIN_EP_FIFO_SIZE_INWORDS );
|
||||
USB_DIEPTXFS[ ep->txFifoNum - 1 ] =
|
||||
( depth << _USB_DIEPTXF1_INEPNTXFDEP_SHIFT ) |
|
||||
( start & _USB_DIEPTXF1_INEPNTXFSTADDR_MASK );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( totalRxFifoSize + totalTxFifoSize > MAX_DEVICE_FIFO_SIZE_INWORDS )
|
||||
return USB_STATUS_ILLEGAL;
|
||||
|
||||
if ( start > MAX_DEVICE_FIFO_SIZE_INWORDS )
|
||||
return USB_STATUS_ILLEGAL;
|
||||
|
||||
/* Flush the FIFO's */
|
||||
USBHAL_FlushTxFifo( 0x10 ); /* All Tx FIFO's */
|
||||
USBHAL_FlushRxFifo(); /* The Rx FIFO */
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
void USBDHAL_Disconnect( void )
|
||||
{
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_SFTDISCON;
|
||||
}
|
||||
|
||||
void USBDHAL_AbortEpIn( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
/* Clear epdis & inepnakeff INT's */
|
||||
USB_DINEPS[ ep->num ].INT |= USB_DIEP_INT_EPDISBLD |
|
||||
USB_DIEP_INT_INEPNAKEFF;
|
||||
|
||||
/* Enable epdis & inepnakeff INT's */
|
||||
USB->DIEPMSK |= USB_DIEPMSK_EPDISBLDMSK | USB_DIEPMSK_INEPNAKEFFMSK;
|
||||
USB_DINEPS[ ep->num ].CTL = ( USB_DINEPS[ ep->num ].CTL &
|
||||
~DEPCTL_WO_BITMASK ) |
|
||||
USB_DIEP_CTL_SNAK;
|
||||
|
||||
/* Wait for inepnakeff INT */
|
||||
while ( !( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_INEPNAKEFF ) ) {}
|
||||
USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_INEPNAKEFF;
|
||||
USB->DIEPMSK &= ~USB_DIEPMSK_INEPNAKEFFMSK;
|
||||
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '.' );
|
||||
|
||||
USBDHAL_SetEPDISNAK( ep );
|
||||
/* Wait for epdis INT */
|
||||
while ( !( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_EPDISBLD ) ) {}
|
||||
USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_EPDISBLD;
|
||||
USB->DIEPMSK &= ~USB_DIEPMSK_EPDISBLDMSK;
|
||||
USBHAL_FlushTxFifo( ep->txFifoNum );
|
||||
|
||||
/* Clear any interrupts generated by the abort sequence. */
|
||||
NVIC_ClearPendingIRQ( USB_IRQn );
|
||||
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '.' );
|
||||
}
|
||||
|
||||
void USBDHAL_AbortEpOut( USBD_Ep_TypeDef *ep )
|
||||
{
|
||||
int cnt;
|
||||
|
||||
/* Clear epdis INT's */
|
||||
USB_DOUTEPS[ ep->num ].INT |= USB_DOEP_INT_EPDISBLD;
|
||||
|
||||
/* Clear Global OUT NAK if already set */
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
|
||||
USB->GINTMSK |= USB_GINTMSK_GOUTNAKEFFMSK; /* Enable GOUTNAKEFF int */
|
||||
|
||||
/* Set Global OUT NAK */
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_SGOUTNAK;
|
||||
|
||||
/* Wait for goutnakeff */
|
||||
cnt = EPABORT_BREAK_LOOP_COUNT;
|
||||
while ( !( USB->GINTSTS & USB_GINTSTS_GOUTNAKEFF ) && cnt )
|
||||
{
|
||||
cnt--;
|
||||
}
|
||||
|
||||
USB->GINTMSK &= ~USB_GINTMSK_GOUTNAKEFFMSK; /* Disable GOUTNAKEFF int */
|
||||
USB->DOEPMSK |= USB_DOEPMSK_EPDISBLDMSK; /* Enable EPDIS interrupt */
|
||||
|
||||
DEBUG_USB_INT_LO_PUTCHAR( ',' );
|
||||
|
||||
USBDHAL_SetEPDISNAK( ep ); /* Disable ep */
|
||||
|
||||
/* Wait for epdis INT */
|
||||
cnt = EPABORT_BREAK_LOOP_COUNT;
|
||||
while ( !( USBDHAL_GetOutEpInts( ep ) & USB_DOEP_INT_EPDISBLD ) && cnt )
|
||||
{
|
||||
cnt--;
|
||||
}
|
||||
|
||||
USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_EPDISBLD;
|
||||
USB->DOEPMSK &= ~USB_DOEPMSK_EPDISBLDMSK; /* Disable EPDIS interrupt */
|
||||
|
||||
/* Clear Global OUT NAK */
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
|
||||
|
||||
/* Clear any interrupts generated by the abort sequence. */
|
||||
NVIC_ClearPendingIRQ( USB_IRQn );
|
||||
|
||||
DEBUG_USB_INT_LO_PUTCHAR( ',' );
|
||||
}
|
||||
|
||||
void USBDHAL_AbortAllEps( void )
|
||||
{
|
||||
int i, cnt;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
uint16_t im, om, inmask=0, outmask=0;
|
||||
|
||||
/* Clear epdis & inepnakeff INT's */
|
||||
for ( i = 1; i <= NUM_EP_USED; i++ )
|
||||
{
|
||||
ep = &dev->ep[i];
|
||||
if ( ep->state != D_EP_IDLE )
|
||||
{
|
||||
if ( ep->in )
|
||||
{
|
||||
inmask |= ep->mask;
|
||||
USB_DINEPS[ ep->num ].INT |= USB_DIEP_INT_EPDISBLD |
|
||||
USB_DIEP_INT_INEPNAKEFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
outmask |= ep->mask;
|
||||
USB_DOUTEPS[ ep->num ].INT |= USB_DOEP_INT_EPDISBLD;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( inmask )
|
||||
{
|
||||
/* Enable epdis & inepnakeff INT's */
|
||||
USB->DIEPMSK |= USB_DIEPMSK_EPDISBLDMSK | USB_DIEPMSK_INEPNAKEFFMSK;
|
||||
|
||||
/* Set NAK on all IN ep's */
|
||||
im = inmask;
|
||||
for ( i = 1; i <= NUM_EP_USED; i++ )
|
||||
{
|
||||
ep = &dev->ep[i];
|
||||
if ( im & ep->mask )
|
||||
{
|
||||
USB_DINEPS[ ep->num ].CTL = ( USB_DINEPS[ ep->num ].CTL &
|
||||
~DEPCTL_WO_BITMASK ) |
|
||||
USB_DIEP_CTL_SNAK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( outmask )
|
||||
{
|
||||
/* Clear Global OUT NAK if already set */
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
|
||||
|
||||
USB->GINTMSK |= USB_GINTMSK_GOUTNAKEFFMSK; /* Enable GOUTNAKEFF int */
|
||||
|
||||
/* Set Global OUT NAK */
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_SGOUTNAK;
|
||||
|
||||
/* Wait for goutnakeff */
|
||||
cnt = EPABORT_BREAK_LOOP_COUNT;
|
||||
while ( !( USB->GINTSTS & USB_GINTSTS_GOUTNAKEFF ) && cnt )
|
||||
{
|
||||
cnt--;
|
||||
}
|
||||
USB->GINTMSK &= ~USB_GINTMSK_GOUTNAKEFFMSK; /* Disable GOUTNAKEFF int */
|
||||
USB->DOEPMSK |= USB_DOEPMSK_EPDISBLDMSK; /* Enable EPDIS interrupt */
|
||||
}
|
||||
|
||||
if ( inmask )
|
||||
{
|
||||
/* Wait for inepnakeff INT on all IN ep's */
|
||||
im = inmask;
|
||||
cnt = EPABORT_BREAK_LOOP_COUNT;
|
||||
do
|
||||
{
|
||||
for ( i = 1; i <= NUM_EP_USED; i++ )
|
||||
{
|
||||
ep = &dev->ep[i];
|
||||
if ( im & ep->mask )
|
||||
{
|
||||
if ( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_INEPNAKEFF )
|
||||
{
|
||||
USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_INEPNAKEFF;
|
||||
im &= ~ep->mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
cnt--;
|
||||
} while ( im && cnt );
|
||||
USB->DIEPMSK &= ~USB_DIEPMSK_INEPNAKEFFMSK;
|
||||
}
|
||||
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '\'' );
|
||||
|
||||
/* Disable ep's */
|
||||
for ( i = 1; i <= NUM_EP_USED; i++ )
|
||||
{
|
||||
ep = &dev->ep[i];
|
||||
if ( ep->state != D_EP_IDLE )
|
||||
{
|
||||
USBDHAL_SetEPDISNAK( ep );
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for epdis INT */
|
||||
im = inmask;
|
||||
om = outmask;
|
||||
cnt = EPABORT_BREAK_LOOP_COUNT;
|
||||
do
|
||||
{
|
||||
for ( i = 1; i <= NUM_EP_USED; i++ )
|
||||
{
|
||||
ep = &dev->ep[i];
|
||||
if ( ep->in && ( im & ep->mask ) )
|
||||
{
|
||||
if ( USBDHAL_GetInEpInts( ep ) & USB_DIEP_INT_EPDISBLD )
|
||||
{
|
||||
USB_DINEPS[ ep->num ].INT = USB_DIEP_INT_EPDISBLD;
|
||||
im &= ~ep->mask;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !ep->in && ( om & ep->mask ) )
|
||||
{
|
||||
if ( USBDHAL_GetOutEpInts( ep ) & USB_DOEP_INT_EPDISBLD )
|
||||
{
|
||||
USB_DOUTEPS[ ep->num ].INT = USB_DOEP_INT_EPDISBLD;
|
||||
om &= ~ep->mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
cnt--;
|
||||
} while ( ( im || om ) && cnt );
|
||||
|
||||
if ( inmask )
|
||||
{
|
||||
USB->DIEPMSK &= ~USB_DIEPMSK_EPDISBLDMSK; /* Disable EPDIS interrupt */
|
||||
USBHAL_FlushTxFifo( 0x10 ); /* Flush all Tx FIFO's */
|
||||
}
|
||||
|
||||
if ( outmask )
|
||||
{
|
||||
USB->DOEPMSK &= ~USB_DOEPMSK_EPDISBLDMSK; /* Disable EPDIS interrupt */
|
||||
/* Clear Global OUT NAK */
|
||||
USB->DCTL = ( USB->DCTL & ~DCTL_WO_BITMASK ) | USB_DCTL_CGOUTNAK;
|
||||
}
|
||||
|
||||
DEBUG_USB_INT_LO_PUTCHAR( '\'' );
|
||||
}
|
||||
|
||||
void USBDHAL_AbortAllTransfers( USB_Status_TypeDef reason )
|
||||
{
|
||||
int i;
|
||||
USBD_Ep_TypeDef *ep;
|
||||
USB_XferCompleteCb_TypeDef callback;
|
||||
|
||||
if ( reason != USB_STATUS_DEVICE_RESET )
|
||||
{
|
||||
USBDHAL_AbortAllEps();
|
||||
}
|
||||
|
||||
for ( i = 1; i <= NUM_EP_USED; i++ )
|
||||
{
|
||||
ep = &(dev->ep[i]);
|
||||
if ( ep->state != D_EP_IDLE )
|
||||
{
|
||||
ep->state = D_EP_IDLE;
|
||||
if ( ep->xferCompleteCb )
|
||||
{
|
||||
callback = ep->xferCompleteCb;
|
||||
ep->xferCompleteCb = NULL;
|
||||
|
||||
if ( ( dev->lastState == USBD_STATE_CONFIGURED ) &&
|
||||
( dev->state == USBD_STATE_ADDRESSED ) )
|
||||
{
|
||||
USBDHAL_DeactivateEp( ep );
|
||||
}
|
||||
|
||||
DEBUG_TRACE_ABORT( reason );
|
||||
callback( reason, ep->xferred, ep->remaining );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear any interrupts generated by the abort sequence. */
|
||||
NVIC_ClearPendingIRQ( USB_IRQn );
|
||||
}
|
||||
#endif /* defined( USB_DEVICE ) */
|
||||
|
||||
#if defined( USB_HOST )
|
||||
USB_Status_TypeDef USBHHAL_CoreInit( uint32_t rxFifoSize,
|
||||
uint32_t nptxFifoSize,
|
||||
uint32_t ptxFifoSize )
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
rxFifoSize /= 4; /* Convert from byte count to word count. */
|
||||
nptxFifoSize /= 4;
|
||||
ptxFifoSize /= 4;
|
||||
|
||||
CMU_ClockEnable( cmuClock_GPIO, true );
|
||||
GPIO_PinModeSet( gpioPortF, 5, gpioModePushPull, 0 ); /* Enable VBUSEN pin */
|
||||
|
||||
#if ( USB_VBUSOVRCUR_PORT != USB_VBUSOVRCUR_PORT_NONE )
|
||||
/* Enable VBUS overcurrent flag pin. */
|
||||
GPIO_PinModeSet( USB_VBUSOVRCUR_PORT, USB_VBUSOVRCUR_PIN, gpioModeInput, 0 );
|
||||
#endif
|
||||
|
||||
USB->ROUTE = USB_ROUTE_PHYPEN | USB_ROUTE_VBUSENPEN; /* Enable PHY pins. */
|
||||
USBHAL_CoreReset(); /* Reset USB core */
|
||||
|
||||
/* Force Host Mode */
|
||||
USB->GUSBCFG = ( USB->GUSBCFG &
|
||||
~(GUSBCFG_WO_BITMASK | USB_GUSBCFG_FORCEDEVMODE ) ) |
|
||||
USB_GUSBCFG_FORCEHSTMODE;
|
||||
|
||||
INT_Enable();
|
||||
USBTIMER_DelayMs( 100 );
|
||||
INT_Disable();
|
||||
|
||||
/* Set 48 MHz PHY clock, FS/LS mode */
|
||||
USB->HCFG = ( USB->HCFG & ~_USB_HCFG_FSLSPCLKSEL_MASK ) |
|
||||
( 1 << _USB_HCFG_FSLSPCLKSEL_SHIFT ) |
|
||||
( USB_HCFG_FSLSSUPP );
|
||||
|
||||
USB->GAHBCFG = ( USB->GAHBCFG & ~_USB_GAHBCFG_HBSTLEN_MASK ) |
|
||||
USB_GAHBCFG_DMAEN | USB_GAHBCFG_HBSTLEN_INCR;
|
||||
|
||||
/* Set Rx FIFO size */
|
||||
USB->GRXFSIZ = ( rxFifoSize << _USB_GRXFSIZ_RXFDEP_SHIFT ) &
|
||||
_USB_GRXFSIZ_RXFDEP_MASK;
|
||||
|
||||
/* Set Tx FIFO sizes */
|
||||
USB->GNPTXFSIZ = ( ( nptxFifoSize <<
|
||||
_USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_SHIFT ) &
|
||||
_USB_GNPTXFSIZ_NPTXFINEPTXF0DEP_MASK ) |
|
||||
( ( rxFifoSize <<
|
||||
_USB_GNPTXFSIZ_NPTXFSTADDR_SHIFT ) &
|
||||
_USB_GNPTXFSIZ_NPTXFSTADDR_MASK );
|
||||
|
||||
USB->HPTXFSIZ = ( ( ptxFifoSize << _USB_HPTXFSIZ_PTXFSIZE_SHIFT ) &
|
||||
_USB_HPTXFSIZ_PTXFSIZE_MASK ) |
|
||||
( ( ( rxFifoSize + nptxFifoSize )
|
||||
<< _USB_HPTXFSIZ_PTXFSTADDR_SHIFT ) &
|
||||
_USB_HPTXFSIZ_PTXFSTADDR_MASK );
|
||||
|
||||
/* Flush Tx and Rx FIFO's */
|
||||
USBHAL_FlushTxFifo( 0x10 );
|
||||
USBHAL_FlushRxFifo();
|
||||
|
||||
for ( i = 0; i < MAX_NUM_HOSTCHANNELS; i++ )
|
||||
{
|
||||
USB->HC[ i ].CHAR = USB_HC_CHAR_CHDIS; /* Disable channel */
|
||||
USB->HC[ i ].INT = 0xFFFFFFFF; /* Clear pending interrupts */
|
||||
}
|
||||
|
||||
/* Enable and halt all channels */
|
||||
for ( i = 0; i < MAX_NUM_HOSTCHANNELS; i++ )
|
||||
{
|
||||
USB->HC[ i ].CHAR |= USB_HC_CHAR_CHDIS | USB_HC_CHAR_CHENA;
|
||||
do
|
||||
{
|
||||
__NOP(); __NOP(); __NOP(); __NOP(); __NOP(); __NOP();
|
||||
}
|
||||
while ( USB->HC[ i ].CHAR & USB_HC_CHAR_CHENA );
|
||||
}
|
||||
|
||||
/* Disable all interrupts */
|
||||
for ( i = 0; i < MAX_NUM_HOSTCHANNELS; i++ )
|
||||
{
|
||||
USB->HC[ i ].INTMSK = 0;
|
||||
}
|
||||
|
||||
USB->HAINTMSK = 0;
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
void USBHHAL_HCHalt( int hcnum, uint32_t hcchar )
|
||||
{
|
||||
hcchar |= USB_HC_CHAR_CHENA | USB_HC_CHAR_CHDIS;
|
||||
USB->HC[ hcnum ].CHAR = hcchar;
|
||||
}
|
||||
|
||||
void USBHHAL_HCInit( int hcnum )
|
||||
{
|
||||
USBH_Ep_TypeDef *ep;
|
||||
|
||||
ep = hcs[ hcnum ].ep;
|
||||
USB->HC[ hcnum ].INT = 0xFFFFFFFF; /* Clear all interrupt flags */
|
||||
|
||||
switch ( ep->type ) /* Enable host channel int. types */
|
||||
{
|
||||
case USB_EPTYPE_CTRL:
|
||||
case USB_EPTYPE_BULK:
|
||||
case USB_EPTYPE_INTR:
|
||||
USB->HC[ hcnum ].INTMSK = USB_HC_INT_CHHLTD;
|
||||
break;
|
||||
}
|
||||
|
||||
hcs[ hcnum ].errorCnt = 0;
|
||||
|
||||
USB->HAINTMSK |= 1 << hcnum; /* Enable host channel interrupt */
|
||||
|
||||
USB->HC[ hcnum ].CHAR = /* Program HCCHAR register */
|
||||
( ep->parentDevice->addr << _USB_HC_CHAR_DEVADDR_SHIFT ) |
|
||||
( ( ep->addr & USB_EPNUM_MASK ) << _USB_HC_CHAR_EPNUM_SHIFT ) |
|
||||
( ep->type << _USB_HC_CHAR_EPTYPE_SHIFT ) |
|
||||
( ep->packetSize << _USB_HC_CHAR_MPS_SHIFT ) |
|
||||
( ep->in ? USB_HC_CHAR_EPDIR : 0 ) |
|
||||
( ep->parentDevice->speed ==
|
||||
HPRT_L_SPEED >> _USB_HPRT_PRTSPD_SHIFT
|
||||
? USB_HC_CHAR_LSPDDEV : 0 );
|
||||
}
|
||||
|
||||
void USBHHAL_HCStart( int hcnum )
|
||||
{
|
||||
USBH_Hc_TypeDef *hc;
|
||||
uint16_t packets, len;
|
||||
|
||||
hc = &hcs[ hcnum ];
|
||||
hc->status = 0;
|
||||
hc->idle = false;
|
||||
|
||||
if ( hc->remaining > 0 )
|
||||
{
|
||||
packets = ( hc->remaining + hc->ep->packetSize - 1 ) / hc->ep->packetSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
packets = 1;
|
||||
}
|
||||
|
||||
if ( hc->ep->in )
|
||||
{
|
||||
len = packets * hc->ep->packetSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = hc->remaining;
|
||||
}
|
||||
|
||||
/* Initialize the HCTSIZn register */
|
||||
hc->hwXferSize = len;
|
||||
USB->HC[ hcnum ].TSIZ =
|
||||
( ( len << _USB_HC_TSIZ_XFERSIZE_SHIFT ) &
|
||||
_USB_HC_TSIZ_XFERSIZE_MASK ) |
|
||||
( ( packets << _USB_HC_TSIZ_PKTCNT_SHIFT ) &
|
||||
_USB_HC_TSIZ_PKTCNT_MASK ) |
|
||||
( ( hc->ep->toggle << _USB_HC_TSIZ_PID_SHIFT ) &
|
||||
_USB_HC_TSIZ_PID_MASK );
|
||||
|
||||
USB->HC[ hcnum ].DMAADDR = (uint32_t)hc->buf;
|
||||
|
||||
USBHHAL_HCActivate( hcnum,
|
||||
USB->HC[ hcnum ].CHAR,
|
||||
hc->ep->type == USB_EPTYPE_INTR );
|
||||
}
|
||||
#endif /* defined( USB_HOST ) */
|
||||
|
||||
/** @endcond */
|
||||
|
||||
#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
|
||||
#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
|
|
@ -0,0 +1,381 @@
|
|||
/***************************************************************************//**
|
||||
* @file em_usbtimer.c
|
||||
* @brief USB protocol stack library, timer API.
|
||||
* @version 3.20.14
|
||||
*******************************************************************************
|
||||
* @section License
|
||||
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "em_device.h"
|
||||
#if defined( USB_PRESENT ) && ( USB_COUNT == 1 )
|
||||
#include "em_usb.h"
|
||||
#if defined( USB_DEVICE ) || defined( USB_HOST )
|
||||
#include "em_cmu.h"
|
||||
#include "em_timer.h"
|
||||
#include "em_usbtypes.h"
|
||||
#include "em_usbhal.h"
|
||||
|
||||
#include "device_peripherals.h"
|
||||
|
||||
/*
|
||||
* Use one HW timer to serve n software milisecond timers.
|
||||
* A timer is, when running, in a linked list of timers.
|
||||
* A given timers timeout period is the acculmulated timeout
|
||||
* of all timers preceeding it in the queue.
|
||||
* This makes timer start (linked list insertion) computing intensive,
|
||||
* but the checking of the queue at each tick very effective.
|
||||
* ______ ______ ______
|
||||
* | | --->| | --->| |
|
||||
* head --> | | | | | | | |
|
||||
* |______|--- |______|--- |______|---/ NULL
|
||||
*/
|
||||
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
#ifndef USB_TIMER
|
||||
#error HW platform must define the timer to use for USB
|
||||
#endif
|
||||
|
||||
#if ( USB_TIMER == USB_TIMER0 ) && ( TIMER_COUNT >= 1 )
|
||||
#define TIMER TIMER0
|
||||
#define TIMER_CLK cmuClock_TIMER0
|
||||
#define TIMER_IRQ TIMER0_IRQn
|
||||
#define TIMER_IRQHandler TIMER0_IRQHandler
|
||||
|
||||
#elif ( USB_TIMER == USB_TIMER1 ) && ( TIMER_COUNT >= 2 )
|
||||
#define TIMER TIMER1
|
||||
#define TIMER_CLK cmuClock_TIMER1
|
||||
#define TIMER_IRQ TIMER1_IRQn
|
||||
#define TIMER_IRQHandler TIMER1_IRQHandler
|
||||
|
||||
#elif ( USB_TIMER == USB_TIMER2 ) && ( TIMER_COUNT >= 3 )
|
||||
#define TIMER TIMER2
|
||||
#define TIMER_CLK cmuClock_TIMER2
|
||||
#define TIMER_IRQ TIMER2_IRQn
|
||||
#define TIMER_IRQHandler TIMER2_IRQHandler
|
||||
|
||||
#elif ( USB_TIMER == USB_TIMER3 ) && ( TIMER_COUNT == 4 )
|
||||
#define TIMER TIMER3
|
||||
#define TIMER_CLK cmuClock_TIMER3
|
||||
#define TIMER_IRQ TIMER3_IRQn
|
||||
#define TIMER_IRQHandler TIMER3_IRQHandler
|
||||
|
||||
#else
|
||||
#error "Illegal USB TIMER definition"
|
||||
#endif
|
||||
|
||||
typedef struct _timer
|
||||
{
|
||||
uint32_t timeout; /* Delta value relative to prev. timer */
|
||||
struct _timer *next;
|
||||
USBTIMER_Callback_TypeDef callback;
|
||||
bool running;
|
||||
} USBTIMER_Timer_TypeDef;
|
||||
|
||||
#if ( NUM_QTIMERS > 0 )
|
||||
static USBTIMER_Timer_TypeDef timers[ NUM_QTIMERS ];
|
||||
static USBTIMER_Timer_TypeDef *head = NULL;
|
||||
#endif
|
||||
|
||||
static uint32_t ticksPrMs, ticksPr1us, ticksPr10us, ticksPr100us;
|
||||
|
||||
#if ( NUM_QTIMERS > 0 )
|
||||
|
||||
static void TimerTick( void );
|
||||
|
||||
void TIMER_IRQHandler( void )
|
||||
{
|
||||
uint32_t flags;
|
||||
|
||||
flags = TIMER_IntGet( TIMER );
|
||||
|
||||
if ( flags & TIMER_IF_CC0 )
|
||||
{
|
||||
TIMER_IntClear( TIMER, TIMER_IFC_CC0 );
|
||||
TIMER_CompareSet( TIMER, 0, TIMER_CaptureGet( TIMER, 0 ) + ticksPrMs );
|
||||
TimerTick();
|
||||
}
|
||||
}
|
||||
#endif /* ( NUM_QTIMERS > 0 ) */
|
||||
|
||||
static void DelayTicks( uint16_t ticks )
|
||||
{
|
||||
uint16_t startTime;
|
||||
volatile uint16_t now;
|
||||
|
||||
if ( ticks )
|
||||
{
|
||||
startTime = TIMER_CounterGet( TIMER );
|
||||
do
|
||||
{
|
||||
now = TIMER_CounterGet(TIMER);
|
||||
} while ( (uint16_t)( now - startTime ) < ticks );
|
||||
}
|
||||
}
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @addtogroup USB_COMMON
|
||||
* @{*/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Active wait millisecond delay function. Can also be used inside
|
||||
* interrupt handlers.
|
||||
*
|
||||
* @param[in] msec
|
||||
* Number of milliseconds to wait.
|
||||
******************************************************************************/
|
||||
void USBTIMER_DelayMs( uint32_t msec )
|
||||
{
|
||||
uint64_t totalTicks;
|
||||
|
||||
totalTicks = (uint64_t)ticksPrMs * msec;
|
||||
while ( totalTicks > 20000 )
|
||||
{
|
||||
DelayTicks( 20000 );
|
||||
totalTicks -= 20000;
|
||||
}
|
||||
DelayTicks( (uint16_t)totalTicks );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Active wait microsecond delay function. Can also be used inside
|
||||
* interrupt handlers.
|
||||
*
|
||||
* @param[in] usec
|
||||
* Number of microseconds to wait.
|
||||
******************************************************************************/
|
||||
void USBTIMER_DelayUs( uint32_t usec )
|
||||
{
|
||||
uint64_t totalTicks;
|
||||
|
||||
totalTicks = (uint64_t)ticksPr1us * usec;
|
||||
if ( totalTicks == 0 )
|
||||
{
|
||||
usec /= 10;
|
||||
totalTicks = (uint64_t)ticksPr10us * usec;
|
||||
|
||||
if ( totalTicks == 0 )
|
||||
{
|
||||
usec /= 10;
|
||||
totalTicks = (uint64_t)ticksPr100us * usec;
|
||||
}
|
||||
}
|
||||
|
||||
while ( totalTicks > 60000 )
|
||||
{
|
||||
DelayTicks( 60000 );
|
||||
totalTicks -= 60000;
|
||||
}
|
||||
DelayTicks( (uint16_t)totalTicks );
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Activate the hardware timer used to pace the 1 millisecond timer system.
|
||||
*
|
||||
* @details
|
||||
* Call this function whenever the HFPERCLK frequency is changed.
|
||||
* This function is initially called by HOST and DEVICE stack xxxx_Init()
|
||||
* functions.
|
||||
******************************************************************************/
|
||||
void USBTIMER_Init( void )
|
||||
{
|
||||
uint32_t freq;
|
||||
TIMER_Init_TypeDef timerInit = TIMER_INIT_DEFAULT;
|
||||
TIMER_InitCC_TypeDef timerCCInit = TIMER_INITCC_DEFAULT;
|
||||
|
||||
freq = CMU_ClockFreqGet( cmuClock_HFPER );
|
||||
ticksPrMs = ( freq + 500 ) / 1000;
|
||||
ticksPr1us = ( freq + 500000 ) / 1000000;
|
||||
ticksPr10us = ( freq + 50000 ) / 100000;
|
||||
ticksPr100us = ( freq + 5000 ) / 10000;
|
||||
|
||||
timerCCInit.mode = timerCCModeCompare;
|
||||
CMU_ClockEnable( TIMER_CLK, true );
|
||||
TIMER_TopSet( TIMER, 0xFFFF );
|
||||
TIMER_InitCC( TIMER, 0, &timerCCInit );
|
||||
TIMER_Init( TIMER, &timerInit );
|
||||
|
||||
#if ( NUM_QTIMERS > 0 )
|
||||
TIMER_IntClear( TIMER, 0xFFFFFFFF );
|
||||
TIMER_IntEnable( TIMER, TIMER_IEN_CC0 );
|
||||
TIMER_CompareSet( TIMER, 0, TIMER_CounterGet( TIMER ) + ticksPrMs );
|
||||
NVIC_ClearPendingIRQ( TIMER_IRQ );
|
||||
NVIC_EnableIRQ( TIMER_IRQ );
|
||||
#endif /* ( NUM_QTIMERS > 0 ) */
|
||||
}
|
||||
|
||||
#if ( NUM_QTIMERS > 0 ) || defined( DOXY_DOC_ONLY )
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Start a timer.
|
||||
*
|
||||
* @details
|
||||
* If the timer is already running, it will be restarted with new timeout.
|
||||
*
|
||||
* @param[in] id
|
||||
* Timer id (0..).
|
||||
*
|
||||
* @param[in] timeout
|
||||
* Number of milliseconds before timer will elapse.
|
||||
*
|
||||
* @param[in] callback
|
||||
* Function to be called on timer elapse, ref. @ref USBTIMER_Callback_TypeDef.
|
||||
******************************************************************************/
|
||||
void USBTIMER_Start( uint32_t id, uint32_t timeout,
|
||||
USBTIMER_Callback_TypeDef callback )
|
||||
{
|
||||
uint32_t accumulated;
|
||||
USBTIMER_Timer_TypeDef *this, **last;
|
||||
|
||||
INT_Disable();
|
||||
|
||||
if ( timers[ id ].running )
|
||||
{
|
||||
USBTIMER_Stop( id );
|
||||
}
|
||||
|
||||
if ( timeout == 0 )
|
||||
{
|
||||
callback();
|
||||
INT_Enable();
|
||||
return;
|
||||
}
|
||||
|
||||
timers[ id ].running = true;
|
||||
timers[ id ].callback = callback;
|
||||
timers[ id ].next = NULL;
|
||||
|
||||
if ( !head ) /* Queue empty ? */
|
||||
{
|
||||
timers[ id ].timeout = timeout;
|
||||
head = &timers[ id ];
|
||||
}
|
||||
else
|
||||
{
|
||||
this = head;
|
||||
last = &head;
|
||||
accumulated = 0;
|
||||
|
||||
/* Do a sorted insert */
|
||||
while ( this )
|
||||
{
|
||||
if ( timeout < accumulated + this->timeout ) /* Insert before "this" ? */
|
||||
{
|
||||
timers[ id ].timeout = timeout - accumulated;
|
||||
timers[ id ].next = this;
|
||||
*last = &timers[ id ];
|
||||
this->timeout -= timers[ id ].timeout; /* Adjust timeout */
|
||||
break;
|
||||
}
|
||||
else if ( this->next == NULL ) /* At end of queue ? */
|
||||
{
|
||||
timers[ id ].timeout = timeout - accumulated - this->timeout;
|
||||
this->next = &timers[ id ];
|
||||
break;
|
||||
}
|
||||
accumulated += this->timeout;
|
||||
last = &this->next;
|
||||
this = this->next;
|
||||
}
|
||||
}
|
||||
|
||||
INT_Enable();
|
||||
}
|
||||
|
||||
/***************************************************************************//**
|
||||
* @brief
|
||||
* Stop a timer.
|
||||
*
|
||||
* @param[in] id
|
||||
* Timer id (0..).
|
||||
******************************************************************************/
|
||||
void USBTIMER_Stop( uint32_t id )
|
||||
{
|
||||
USBTIMER_Timer_TypeDef *this, **last;
|
||||
|
||||
INT_Disable();
|
||||
|
||||
if ( head ) /* Queue empty ? */
|
||||
{
|
||||
this = head;
|
||||
last = &head;
|
||||
timers[ id ].running = false;
|
||||
|
||||
while ( this )
|
||||
{
|
||||
if ( this == &timers[ id ] ) /* Correct timer ? */
|
||||
{
|
||||
if ( this->next )
|
||||
{
|
||||
this->next->timeout += timers[ id ].timeout; /* Adjust timeout */
|
||||
}
|
||||
*last = this->next;
|
||||
break;
|
||||
}
|
||||
last = &this->next;
|
||||
this = this->next;
|
||||
}
|
||||
}
|
||||
|
||||
INT_Enable();
|
||||
}
|
||||
#endif /* ( NUM_QTIMERS > 0 ) */
|
||||
|
||||
/** @} (end addtogroup USB_COMMON) */
|
||||
|
||||
#if ( NUM_QTIMERS > 0 )
|
||||
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
|
||||
|
||||
static void TimerTick( void )
|
||||
{
|
||||
USBTIMER_Callback_TypeDef cb;
|
||||
|
||||
INT_Disable();
|
||||
|
||||
if ( head )
|
||||
{
|
||||
head->timeout--;
|
||||
|
||||
while ( head )
|
||||
{
|
||||
if ( head->timeout == 0 )
|
||||
{
|
||||
cb = head->callback;
|
||||
head->running = false;
|
||||
head = head->next;
|
||||
/* The callback may place new items in the queue !!! */
|
||||
if ( cb )
|
||||
{
|
||||
(cb)();
|
||||
}
|
||||
continue; /* There might be more than one timeout pr. tick */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
INT_Enable();
|
||||
}
|
||||
/** @endcond */
|
||||
#endif /* ( NUM_QTIMERS > 0 ) */
|
||||
|
||||
#endif /* defined( USB_DEVICE ) || defined( USB_HOST ) */
|
||||
#endif /* defined( USB_PRESENT ) && ( USB_COUNT == 1 ) */
|
|
@ -49,6 +49,8 @@ typedef enum {
|
|||
#include "USBEndpoints_RZ_A1H.h"
|
||||
#elif defined(TARGET_Maxim)
|
||||
#include "USBEndpoints_Maxim.h"
|
||||
#elif defined(TARGET_EFM32GG_STK3700) || defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32WG_STK3800) || defined(TARGET_EFM32HG_STK3400)
|
||||
#include "USBEndpoints_EFM32.h"
|
||||
#else
|
||||
#error "Unknown target type"
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
|
||||
#ifndef TARGET_EFM32HG_STK3400
|
||||
# define NUMBER_OF_LOGICAL_ENDPOINTS (6)
|
||||
#else
|
||||
# define NUMBER_OF_LOGICAL_ENDPOINTS (3)
|
||||
#endif
|
||||
|
||||
#define NUMBER_OF_PHYSICAL_ENDPOINTS (NUMBER_OF_LOGICAL_ENDPOINTS * 2)
|
||||
#define NUMBER_OF_ENDPOINTS (NUMBER_OF_PHYSICAL_ENDPOINTS + 2) /* Includes EP0 */
|
||||
|
||||
#define EP0OUT (0)
|
||||
#define EP0IN (1)
|
||||
#define EP1OUT (2)
|
||||
#define EP1IN (3)
|
||||
#define EP2OUT (4)
|
||||
#define EP2IN (5)
|
||||
#define EP3OUT (6)
|
||||
#define EP3IN (7)
|
||||
#ifndef TARGET_EFM32HG_STK3400
|
||||
# define EP4OUT (8)
|
||||
# define EP4IN (9)
|
||||
# define EP5OUT (10)
|
||||
# define EP5IN (11)
|
||||
# define EP6OUT (12)
|
||||
# define EP6IN (13)
|
||||
#endif
|
||||
|
||||
#define USB_EP_TO_INDEX(ep) (ep)
|
||||
#define USB_EP_TO_ADDR(ep) (((ep)>>1) | (((ep) & 1 ) ? 0x80 : 0x00))
|
||||
#define USB_ADDR_TO_EP(ep) (((ep)<<1) | (((ep) & 0x80) ? 0x01 : 0x00))
|
||||
|
||||
/* Maximum Packet sizes */
|
||||
|
||||
#define MAX_PACKET_SIZE_EP0 64
|
||||
#define MAX_PACKET_SIZE_EP1 64
|
||||
#define MAX_PACKET_SIZE_EP2 64
|
||||
#define MAX_PACKET_SIZE_EP3 64
|
||||
#ifndef TARGET_EFM32HG_STK3400
|
||||
# define MAX_PACKET_SIZE_EP4 64
|
||||
# define MAX_PACKET_SIZE_EP5 64
|
||||
# define MAX_PACKET_SIZE_EP6 64
|
||||
#endif
|
||||
|
||||
/* Generic endpoints - intended to be portable accross devices */
|
||||
/* and be suitable for simple USB devices. */
|
||||
|
||||
/* Bulk endpoints */
|
||||
#define EPBULK_OUT EP2OUT
|
||||
#define EPBULK_IN EP2IN
|
||||
#define EPBULK_OUT_callback EP2_OUT_callback
|
||||
#define EPBULK_IN_callback EP2_IN_callback
|
||||
/* Interrupt endpoints */
|
||||
#define EPINT_OUT EP1OUT
|
||||
#define EPINT_IN EP1IN
|
||||
#define EPINT_OUT_callback EP1_OUT_callback
|
||||
#define EPINT_IN_callback EP1_IN_callback
|
||||
/* Isochronous endpoints */
|
||||
#define EPISO_OUT EP3OUT
|
||||
#define EPISO_IN EP3IN
|
||||
#define EPISO_OUT_callback EP3_OUT_callback
|
||||
#define EPISO_IN_callback EP3_IN_callback
|
||||
|
||||
#define MAX_PACKET_SIZE_EPBULK 64
|
||||
#define MAX_PACKET_SIZE_EPINT 64
|
||||
#define MAX_PACKET_SIZE_EPISO 1023
|
|
@ -0,0 +1,775 @@
|
|||
/* Copyright 2015 Silicon Labs, http://www.silabs.com
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined TARGET_EFM32GG_STK3700 || \
|
||||
defined TARGET_EFM32LG_STK3600 || \
|
||||
defined TARGET_EFM32WG_STK3800 || \
|
||||
defined TARGET_EFM32HG_STK3400
|
||||
|
||||
#include "USBHAL.h"
|
||||
#include "em_usb.h"
|
||||
#include "em_usbtypes.h"
|
||||
#include "em_usbhal.h"
|
||||
#include "em_usbd.h"
|
||||
|
||||
#include "sleepmodes.h"
|
||||
|
||||
enum USBISRCommand {
|
||||
CMD_HANDLED = 0,
|
||||
CMD_EP0SETUP,
|
||||
CMD_EP0IN,
|
||||
CMD_EP0OUT,
|
||||
CMD_EP_XFER_COMPLETED,
|
||||
CMD_SOF,
|
||||
CMD_BUSRESET,
|
||||
CMD_SUSPEND_STATE_CHANGED,
|
||||
CMD_ENUM_END_MARKER
|
||||
};
|
||||
|
||||
enum IEPStatus {
|
||||
NOT_CONFIGURED = 0,
|
||||
IDLE = 1,
|
||||
READ_PENDING = 2,
|
||||
WRITE_PENDING = 3,
|
||||
READ_COMPLETE = 4,
|
||||
WRITE_COMPLETE = 5,
|
||||
FAILED_INVALID = 6,
|
||||
FAILED_STALLED = 7
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
IEPStatus status;
|
||||
uint32_t byte_count;
|
||||
uint32_t max_packet;
|
||||
USB_XferCompleteCb_TypeDef intern_cb;
|
||||
uint8_t *data_buf;
|
||||
} ep_state_t;
|
||||
|
||||
USBHAL * USBHAL::instance;
|
||||
static uint8_t ep0setupdata[8];
|
||||
static ep_state_t ep_state[NUMBER_OF_ENDPOINTS];
|
||||
#ifdef USB_USE_DYNAMIC_MEMORY
|
||||
static uint8_t ep0in_data_buf[MAX_PACKET_SIZE_EP0] __attribute__ ((aligned (4)));
|
||||
static uint8_t ep0out_data_buf[MAX_PACKET_SIZE_EP0]; // FIXME: does this need to be this big?
|
||||
#else
|
||||
static uint8_t ep_data_buf[NUMBER_OF_ENDPOINTS][64] __attribute__ ((aligned (4)));
|
||||
#endif
|
||||
|
||||
static void run_cmd(USBISRCommand cmd, uint32_t param);
|
||||
static void (*isrptr)() = NULL;
|
||||
static USBISRCommand usb_isrcmd = CMD_HANDLED;
|
||||
static uint32_t usb_isrcmd_param = 0;
|
||||
|
||||
extern "C" void usbhal_allow_em2(bool allow_em2);
|
||||
|
||||
#ifdef DEBUG_USB_API
|
||||
#define TRACE(fmt,...) printf("USB: %s: " fmt "\n", __func__, __VA_ARGS__);
|
||||
#define TRACE_FUNC_IN printf("USB: > %s\n",__func__);
|
||||
#define TRACE_FUNC_IN_P(fmt, ...) printf("USB: > %s: " fmt "\n", __func__, __VA_ARGS__);
|
||||
#else
|
||||
#define TRACE(fmt,...)
|
||||
#define TRACE_FUNC_IN
|
||||
#define TRACE_FUNC_IN_P(fmt, ...)
|
||||
#endif
|
||||
|
||||
static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize);
|
||||
|
||||
static int usbhal_xfer_complete_cb(uint8_t epaddr, USB_Status_TypeDef status,
|
||||
uint32_t xferred, uint32_t remaining);
|
||||
static void usbhal_free_buffers(void);
|
||||
|
||||
/* Internal EP transfer complete callbacks */
|
||||
#define EPCB(n) static int usbhal_xfer_complete_cb_##n(USB_Status_TypeDef status, \
|
||||
uint32_t xferred, uint32_t remaining) { \
|
||||
return usbhal_xfer_complete_cb(n, status, xferred, remaining); \
|
||||
}
|
||||
/* ------^ */
|
||||
EPCB(EP0OUT)
|
||||
EPCB(EP0IN)
|
||||
EPCB(EP1OUT)
|
||||
EPCB(EP1IN)
|
||||
EPCB(EP2OUT)
|
||||
EPCB(EP2IN)
|
||||
EPCB(EP3OUT)
|
||||
EPCB(EP3IN)
|
||||
#ifndef TARGET_EFM32HG_STK3400
|
||||
EPCB(EP4OUT)
|
||||
EPCB(EP4IN)
|
||||
EPCB(EP5OUT)
|
||||
EPCB(EP5IN)
|
||||
EPCB(EP6OUT)
|
||||
EPCB(EP6IN)
|
||||
#endif
|
||||
|
||||
static inline bool is_aligned(const void *pointer, size_t byte_count)
|
||||
{
|
||||
return ((uintptr_t)pointer % byte_count == 0);
|
||||
}
|
||||
|
||||
USBHAL::USBHAL(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
|
||||
isrptr = &USBHAL::_usbisr;
|
||||
|
||||
if (instance) {
|
||||
TRACE("Assert self failed! instance=%p", instance);
|
||||
abort();
|
||||
}
|
||||
instance = this;
|
||||
|
||||
// When USB is active, we can't go below EM1. This block may
|
||||
// be dynamically removed/reinstated to allow deeper sleep.
|
||||
usbhal_allow_em2(false);
|
||||
|
||||
// When in suspend / Vbus off we can go to EM2, but never below
|
||||
// that as long as USB is being used. Despite the name the call here
|
||||
// blocks entering modes _below_ EM2, but allows EM2.
|
||||
blockSleepMode(EM2);
|
||||
|
||||
epCallback[EP0OUT] = NULL;
|
||||
epCallback[EP0IN ] = NULL;
|
||||
epCallback[EP1OUT] = &USBHAL::EP1_OUT_callback;
|
||||
epCallback[EP1IN ] = &USBHAL::EP1_IN_callback;
|
||||
epCallback[EP2OUT] = &USBHAL::EP2_OUT_callback;
|
||||
epCallback[EP2IN ] = &USBHAL::EP2_IN_callback;
|
||||
epCallback[EP3OUT] = &USBHAL::EP3_OUT_callback;
|
||||
epCallback[EP3IN ] = &USBHAL::EP3_IN_callback;
|
||||
#ifndef TARGET_EFM32HG_STK3400
|
||||
epCallback[EP4OUT] = &USBHAL::EP4_OUT_callback;
|
||||
epCallback[EP4IN ] = &USBHAL::EP4_IN_callback;
|
||||
epCallback[EP5OUT] = &USBHAL::EP5_OUT_callback;
|
||||
epCallback[EP5IN ] = &USBHAL::EP5_IN_callback;
|
||||
epCallback[EP6OUT] = &USBHAL::EP6_OUT_callback;
|
||||
epCallback[EP6IN ] = &USBHAL::EP6_IN_callback;
|
||||
#endif
|
||||
|
||||
memset(ep_state, 0, sizeof(ep_state));
|
||||
|
||||
ep_state[EP0OUT].intern_cb = usbhal_xfer_complete_cb_EP0OUT;
|
||||
ep_state[EP0IN ].intern_cb = usbhal_xfer_complete_cb_EP0IN;
|
||||
ep_state[EP1OUT].intern_cb = usbhal_xfer_complete_cb_EP1OUT;
|
||||
ep_state[EP1IN ].intern_cb = usbhal_xfer_complete_cb_EP1IN;
|
||||
ep_state[EP2OUT].intern_cb = usbhal_xfer_complete_cb_EP2OUT;
|
||||
ep_state[EP2IN ].intern_cb = usbhal_xfer_complete_cb_EP2IN;
|
||||
ep_state[EP3OUT].intern_cb = usbhal_xfer_complete_cb_EP3OUT;
|
||||
ep_state[EP3IN ].intern_cb = usbhal_xfer_complete_cb_EP3IN;
|
||||
#ifndef TARGET_EFM32HG_STK3400
|
||||
ep_state[EP4OUT].intern_cb = usbhal_xfer_complete_cb_EP4OUT;
|
||||
ep_state[EP4IN ].intern_cb = usbhal_xfer_complete_cb_EP4IN;
|
||||
ep_state[EP5OUT].intern_cb = usbhal_xfer_complete_cb_EP5OUT;
|
||||
ep_state[EP5IN ].intern_cb = usbhal_xfer_complete_cb_EP5IN;
|
||||
ep_state[EP6OUT].intern_cb = usbhal_xfer_complete_cb_EP6OUT;
|
||||
ep_state[EP6IN ].intern_cb = usbhal_xfer_complete_cb_EP6IN;
|
||||
#endif
|
||||
|
||||
#ifdef USB_USE_DYNAMIC_MEMORY
|
||||
ep_state[EP0OUT].data_buf = ep0out_data_buf;
|
||||
ep_state[EP0IN].data_buf = ep0in_data_buf;
|
||||
#else
|
||||
for (int i=0 ; i<NUMBER_OF_ENDPOINTS ; i++) {
|
||||
ep_state[i].data_buf = ep_data_buf[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
USBHAL::~USBHAL(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
USBD_AbortAllTransfers();
|
||||
USBD_Disconnect();
|
||||
usbhal_free_buffers();
|
||||
|
||||
usbhal_allow_em2(true);
|
||||
unblockSleepMode(EM2);
|
||||
}
|
||||
|
||||
extern "C" void usbhal_allow_em2(bool allow_em2)
|
||||
{
|
||||
if (allow_em2) {
|
||||
// unblockSleepMode is safe to call even if we would unblock
|
||||
// an already unblocked mode, so no checks here.
|
||||
unblockSleepMode(EM1);
|
||||
} else {
|
||||
blockSleepMode(EM1);
|
||||
}
|
||||
}
|
||||
|
||||
static void usbhal_reset_cb(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
run_cmd(CMD_BUSRESET, 0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_USB_API
|
||||
static const char *usbstate[] = { "NONE", "ATTACHED", "POWERED", "DEFAULT",
|
||||
"ADDRESSED", "CONFIGURED", "SUSPENDED", "???" };
|
||||
#endif
|
||||
|
||||
static void usbhal_state_change_cb(USBD_State_TypeDef oldState,
|
||||
USBD_State_TypeDef newState)
|
||||
{
|
||||
TRACE("state changed %s -> %s", usbstate[oldState], usbstate[newState]);
|
||||
|
||||
if (oldState == USBD_STATE_SUSPENDED) {
|
||||
run_cmd(CMD_SUSPEND_STATE_CHANGED, 0);
|
||||
}
|
||||
|
||||
if (newState == USBD_STATE_SUSPENDED) {
|
||||
run_cmd(CMD_SUSPEND_STATE_CHANGED, 1);
|
||||
}
|
||||
|
||||
// Should call connectStateChanged from here as well but there is
|
||||
// no documentation on when to actually do so. (And the implementation
|
||||
// in USBDevice.cpp is a stub)
|
||||
|
||||
// HACK! Since connectStateChanged is not used, indicate the loss
|
||||
// off connection by reporting a bus reset. This causes USBDevice
|
||||
// to realise that at least it's not in CONFIGURED anymore, and
|
||||
// stop trying to read/write in a busyloop.
|
||||
if (newState == USBD_STATE_NONE) {
|
||||
run_cmd(CMD_BUSRESET, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int usbhal_setupcmd_cb(const USB_Setup_TypeDef *setup)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
if (!setup) {
|
||||
EFM_ASSERT(false);
|
||||
return USB_STATUS_REQ_ERR;
|
||||
}
|
||||
|
||||
memcpy(ep0setupdata, setup, 8);
|
||||
run_cmd(CMD_EP0SETUP, 0);
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
static void usbhal_sof_cb(uint16_t frameNum)
|
||||
{
|
||||
run_cmd(CMD_SOF, frameNum);
|
||||
}
|
||||
|
||||
static void usbhal_free_buffers(void)
|
||||
{
|
||||
#ifdef USB_USE_DYNAMIC_MEMORY
|
||||
TRACE_FUNC_IN;
|
||||
|
||||
for (int i=EP1OUT ; i<NUMBER_OF_ENDPOINTS ; i++ ) {
|
||||
if (ep_state[i].data_buf) {
|
||||
free(ep_state[i].data_buf);
|
||||
ep_state[i].data_buf = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void USBHAL::connect(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
|
||||
// Init datastructures must be static - driver will use these even after the init function exits!
|
||||
|
||||
static const uint8_t buffer_multiplier[] = { 1 }; // Mult 1 for control EP
|
||||
static const USBD_Callbacks_TypeDef usbd_callbacks = {
|
||||
.usbReset = usbhal_reset_cb,
|
||||
.usbStateChange = usbhal_state_change_cb,
|
||||
.setupCmd = usbhal_setupcmd_cb,
|
||||
.isSelfPowered = NULL,
|
||||
.sofInt = usbhal_sof_cb
|
||||
};
|
||||
|
||||
USBD_Init_TypeDef initdata = {
|
||||
.deviceDescriptor = NULL,
|
||||
.configDescriptor = NULL,
|
||||
.stringDescriptors = NULL,
|
||||
.numberOfStrings = 0,
|
||||
.bufferingMultiplier = buffer_multiplier,
|
||||
.callbacks = &usbd_callbacks,
|
||||
.reserved = 0
|
||||
};
|
||||
|
||||
int ret = USBD_Init(&initdata);
|
||||
|
||||
TRACE("init = %d, devicedesc = %lx, configdesc = %lx", ret,
|
||||
(uint32_t) initdata.deviceDescriptor,
|
||||
(uint32_t) initdata.configDescriptor);
|
||||
|
||||
EFM_ASSERT(ret == USB_STATUS_OK);
|
||||
}
|
||||
|
||||
void USBHAL::disconnect(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
USBD_Disconnect();
|
||||
}
|
||||
|
||||
void USBHAL::configureDevice(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
USBD_SetUsbState(USBD_STATE_CONFIGURED);
|
||||
}
|
||||
|
||||
void USBHAL::unconfigureDevice(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
USBD_SetUsbState(USBD_STATE_DEFAULT);
|
||||
usbhal_free_buffers();
|
||||
}
|
||||
|
||||
void USBHAL::setAddress(uint8_t address)
|
||||
{
|
||||
TRACE_FUNC_IN_P("addr 0x%x", (unsigned)address);
|
||||
USBD_SetAddress(address);
|
||||
}
|
||||
|
||||
void USBHAL::remoteWakeup(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
USBD_RemoteWakeup();
|
||||
}
|
||||
|
||||
void USBHAL::EP0setup(uint8_t *buffer)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
EFM_ASSERT(buffer);
|
||||
if (buffer) {
|
||||
memcpy(buffer, ep0setupdata, 8);
|
||||
}
|
||||
}
|
||||
|
||||
void USBHAL::EP0read(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
(void)internEndpointRead(0, MAX_PACKET_SIZE_EP0);
|
||||
}
|
||||
|
||||
void USBHAL::EP0readStage(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
// Not needed
|
||||
}
|
||||
|
||||
uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
EFM_ASSERT(buffer);
|
||||
|
||||
uint32_t read = 0;
|
||||
endpointReadResult(0, buffer, &read);
|
||||
return read;
|
||||
}
|
||||
|
||||
static int usbhal_xfer_complete_cb(uint8_t ep, USB_Status_TypeDef status,
|
||||
uint32_t xferred, uint32_t remaining)
|
||||
{
|
||||
TRACE_FUNC_IN_P("ep 0x%x, status %u, xferred %lu, rem %lu",
|
||||
ep, status, xferred, remaining);
|
||||
|
||||
if (ep >= NUMBER_OF_ENDPOINTS) {
|
||||
EFM_ASSERT(false);
|
||||
return USB_STATUS_REQ_ERR;
|
||||
}
|
||||
|
||||
switch (ep) {
|
||||
case EP0OUT:
|
||||
if (ep_state[EP0OUT].status == READ_PENDING) {
|
||||
ep_state[EP0OUT].status = READ_COMPLETE;
|
||||
ep_state[EP0OUT].byte_count = xferred;
|
||||
// drop zlp
|
||||
if (xferred == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
run_cmd(CMD_EP0OUT, 0);
|
||||
break;
|
||||
|
||||
case EP0IN:
|
||||
run_cmd(CMD_EP0IN, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
bool write = ep & 1;
|
||||
|
||||
if (status == USB_STATUS_OK) {
|
||||
if (!write && ep_state[ep].status == READ_PENDING) {
|
||||
ep_state[ep].status = READ_COMPLETE;
|
||||
ep_state[ep].byte_count = xferred;
|
||||
} else if (write && ep_state[ep].status == WRITE_PENDING) {
|
||||
ep_state[ep].status = WRITE_COMPLETE;
|
||||
} else {
|
||||
ep_state[ep].status = FAILED_INVALID;
|
||||
}
|
||||
} else {
|
||||
ep_state[ep].status = FAILED_INVALID;
|
||||
}
|
||||
|
||||
if (ep_state[ep].status != FAILED_INVALID) {
|
||||
run_cmd(CMD_EP_XFER_COMPLETED, ep);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return USB_STATUS_OK;
|
||||
}
|
||||
|
||||
void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
|
||||
{
|
||||
//TRACE_FUNC_IN_P("buffer %lx, size %lu", (uint32_t) buffer, size);
|
||||
|
||||
int ret;
|
||||
USB_XferCompleteCb_TypeDef cb = ep_state[EP0IN].intern_cb;
|
||||
|
||||
EFM_ASSERT((buffer != NULL) || (size == 0));
|
||||
EFM_ASSERT(size <= MAX_PACKET_SIZE_EP0);
|
||||
|
||||
if (!buffer || size == 0) {
|
||||
// No callback after writing EP0 ZLP
|
||||
cb = NULL;
|
||||
}
|
||||
|
||||
if (buffer && !is_aligned(buffer,4)) {
|
||||
// Copy unaligned data to write-buffer before USBD_Write
|
||||
memcpy(ep_state[EP0IN].data_buf, buffer, size);
|
||||
ret = USBD_Write(0, ep_state[EP0IN].data_buf, size, cb);
|
||||
} else {
|
||||
ret = USBD_Write(0, buffer, size, cb);
|
||||
}
|
||||
|
||||
if (ret != USB_STATUS_OK) {
|
||||
TRACE("FAILED - ret %d", ret);
|
||||
}
|
||||
}
|
||||
|
||||
void USBHAL::EP0stall(void)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
USBD_StallEp0();
|
||||
}
|
||||
|
||||
static EP_STATUS internEndpointRead(uint8_t ep, uint32_t maxSize)
|
||||
{
|
||||
//TRACE_FUNC_IN_P("endpoint 0x%x, size %ld, cb %d", (unsigned)ep, maxSize, useCallback);
|
||||
|
||||
if (ep >= NUMBER_OF_ENDPOINTS) {
|
||||
EFM_ASSERT(false);
|
||||
return EP_INVALID;
|
||||
}
|
||||
|
||||
ep_state[ep].status = READ_PENDING;
|
||||
|
||||
int ret = USBD_Read(USB_EP_TO_ADDR(ep), ep_state[ep].data_buf, maxSize,
|
||||
ep_state[ep].intern_cb);
|
||||
|
||||
if (ret == USB_STATUS_OK) {
|
||||
return EP_PENDING;
|
||||
} else {
|
||||
TRACE("FAILED - ret %d", ret);
|
||||
|
||||
if (ret == USB_STATUS_EP_STALLED) {
|
||||
return EP_STALLED;
|
||||
} else {
|
||||
return EP_INVALID;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
|
||||
{
|
||||
return internEndpointRead(endpoint, maximumSize);
|
||||
}
|
||||
|
||||
EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
|
||||
if (endpoint >= NUMBER_OF_ENDPOINTS) {
|
||||
EFM_ASSERT(false);
|
||||
return EP_INVALID;
|
||||
}
|
||||
|
||||
EFM_ASSERT(data);
|
||||
EFM_ASSERT(bytesRead);
|
||||
if (!data || !bytesRead) {
|
||||
return EP_INVALID;
|
||||
}
|
||||
|
||||
switch (ep_state[endpoint].status) {
|
||||
case READ_PENDING:
|
||||
return EP_PENDING;
|
||||
|
||||
case READ_COMPLETE:
|
||||
memcpy(data, ep_state[endpoint].data_buf, ep_state[endpoint].byte_count);
|
||||
*bytesRead = ep_state[endpoint].byte_count;
|
||||
ep_state[endpoint].status = IDLE;
|
||||
return EP_COMPLETED;
|
||||
|
||||
case FAILED_STALLED:
|
||||
ep_state[endpoint].status = IDLE;
|
||||
return EP_STALLED;
|
||||
|
||||
default:
|
||||
ep_state[endpoint].status = IDLE;
|
||||
return EP_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
|
||||
{
|
||||
TRACE_FUNC_IN_P("endpoint 0x%x, data 0x%lx, size %lu", (unsigned )endpoint, (uint32_t)data, size);
|
||||
|
||||
EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
|
||||
EFM_ASSERT(endpoint > EP0IN);
|
||||
EFM_ASSERT(size <= ep_state[endpoint].max_packet);
|
||||
EFM_ASSERT(data);
|
||||
|
||||
uint8_t ep = USB_EP_TO_INDEX(endpoint);
|
||||
|
||||
if (endpoint >= NUMBER_OF_ENDPOINTS || endpoint <= EP0IN) {
|
||||
return EP_INVALID;
|
||||
}
|
||||
|
||||
if (size > ep_state[endpoint].max_packet) {
|
||||
return EP_INVALID;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return EP_INVALID;
|
||||
}
|
||||
|
||||
memcpy(ep_state[ep].data_buf, data, size);
|
||||
|
||||
ep_state[ep].status = WRITE_PENDING;
|
||||
int ret = USBD_Write(USB_EP_TO_ADDR(endpoint), ep_state[ep].data_buf, size, ep_state[ep].intern_cb);
|
||||
|
||||
if (ret == USB_STATUS_EP_STALLED) {
|
||||
ep_state[ep].status = IDLE;
|
||||
return EP_STALLED;
|
||||
} else if (ret != USB_STATUS_OK) {
|
||||
ep_state[ep].status = IDLE;
|
||||
return EP_INVALID;
|
||||
}
|
||||
|
||||
return EP_PENDING;
|
||||
}
|
||||
|
||||
EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
|
||||
{
|
||||
if (endpoint >= NUMBER_OF_ENDPOINTS) {
|
||||
EFM_ASSERT(false);
|
||||
return EP_INVALID;
|
||||
}
|
||||
|
||||
switch (ep_state[endpoint].status) {
|
||||
case WRITE_PENDING:
|
||||
return EP_PENDING;
|
||||
|
||||
case WRITE_COMPLETE:
|
||||
ep_state[endpoint].status = IDLE;
|
||||
return EP_COMPLETED;
|
||||
|
||||
case FAILED_STALLED:
|
||||
ep_state[endpoint].status = IDLE;
|
||||
return EP_STALLED;
|
||||
|
||||
default:
|
||||
ep_state[endpoint].status = IDLE;
|
||||
return EP_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
void USBHAL::stallEndpoint(uint8_t endpoint)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
|
||||
EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
|
||||
EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN));
|
||||
|
||||
USBD_StallEp(USB_EP_TO_ADDR(endpoint));
|
||||
}
|
||||
|
||||
void USBHAL::unstallEndpoint(uint8_t endpoint)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
|
||||
EFM_ASSERT(endpoint < NUMBER_OF_ENDPOINTS);
|
||||
EFM_ASSERT((endpoint != EP0OUT) && (endpoint != EP0IN));
|
||||
|
||||
USBD_UnStallEp(USB_EP_TO_ADDR(endpoint));
|
||||
}
|
||||
|
||||
bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options)
|
||||
{
|
||||
TRACE_FUNC_IN_P("endpoint %d, packetsize %ld, options 0x%lx", endpoint,
|
||||
maxPacket, options);
|
||||
|
||||
int mult = 1; // RX/TX buffer size multiplier
|
||||
int type = USB_EPTYPE_INTR;
|
||||
|
||||
if (endpoint >= NUMBER_OF_ENDPOINTS) {
|
||||
EFM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (endpoint == EP0IN || endpoint == EP0OUT) {
|
||||
EFM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
ep_state[endpoint].max_packet = 0;
|
||||
|
||||
if (endpoint == EPISO_OUT || endpoint == EPISO_IN) {
|
||||
if (maxPacket > MAX_PACKET_SIZE_EPISO) {
|
||||
EFM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
} else if ((maxPacket > MAX_PACKET_SIZE_EPBULK) || (maxPacket > MAX_PACKET_SIZE_EPINT)) {
|
||||
EFM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// USBDevice performs a read right after creating the endpoints,
|
||||
// before calling configureDevice. The read will fail since
|
||||
// at that point the device state is still ADDRESSED. Workaround
|
||||
// is to force configured state here.
|
||||
//
|
||||
// This relies on USBDevice to not call realiseEndpoint unless
|
||||
// it is transitioning to the CONFIGURED state.
|
||||
USBD_SetUsbState(USBD_STATE_CONFIGURED);
|
||||
|
||||
// Why doesn't this function have a type param? This is silly...
|
||||
switch (endpoint) {
|
||||
case EPBULK_OUT:
|
||||
case EPBULK_IN:
|
||||
type = USB_EPTYPE_BULK;
|
||||
mult = 2;
|
||||
break;
|
||||
case EPINT_OUT:
|
||||
case EPINT_IN:
|
||||
type = USB_EPTYPE_INTR;
|
||||
mult = 1;
|
||||
break;
|
||||
case EPISO_OUT:
|
||||
case EPISO_IN:
|
||||
type = USB_EPTYPE_ISOC;
|
||||
mult = 2; // ?
|
||||
break;
|
||||
}
|
||||
|
||||
// Some options force the endpoint to a specific type
|
||||
if( options & ISOCHRONOUS ) {
|
||||
type = USB_EPTYPE_ISOC;
|
||||
mult = 2; // ?
|
||||
} else if ( options & RATE_FEEDBACK_MODE ) {
|
||||
// No support for whatever rate feedback is, but for interrupt only
|
||||
type = USB_EPTYPE_INTR;
|
||||
mult = 1;
|
||||
}
|
||||
|
||||
#ifdef USB_USE_DYNAMIC_MEMORY
|
||||
if (ep_state[endpoint].data_buf) {
|
||||
free(ep_state[endpoint].data_buf);
|
||||
}
|
||||
|
||||
ep_state[endpoint].data_buf = (uint8_t *)malloc(maxPacket);
|
||||
|
||||
if (!ep_state[endpoint].data_buf) {
|
||||
EFM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ret = USBD_AddEndpoint(USB_EP_TO_ADDR(endpoint), type, maxPacket, mult);
|
||||
|
||||
if (ret == USB_STATUS_OK) {
|
||||
ep_state[endpoint].status = IDLE;
|
||||
ep_state[endpoint].max_packet = maxPacket;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool USBHAL::getEndpointStallState(unsigned char endpoint)
|
||||
{
|
||||
TRACE_FUNC_IN;
|
||||
if (endpoint >= NUMBER_OF_ENDPOINTS) {
|
||||
EFM_ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
return USBD_EpIsStalled(USB_EP_TO_ADDR(endpoint));
|
||||
}
|
||||
|
||||
static void run_cmd(USBISRCommand cmd, uint32_t param)
|
||||
{
|
||||
if (usb_isrcmd != CMD_HANDLED || cmd >= CMD_ENUM_END_MARKER) {
|
||||
EFM_ASSERT(false);
|
||||
abort();
|
||||
}
|
||||
|
||||
usb_isrcmd = cmd;
|
||||
usb_isrcmd_param = param;
|
||||
isrptr();
|
||||
}
|
||||
|
||||
void USBHAL::_usbisr(void)
|
||||
{
|
||||
EFM_ASSERT(instance);
|
||||
instance->usbisr();
|
||||
}
|
||||
|
||||
void USBHAL::usbisr(void)
|
||||
{
|
||||
//TRACE_FUNC_IN;
|
||||
|
||||
// This "ISR" is used just to route callbacks from SiL USB driver
|
||||
// callback context (which can not call protected/private USBHAL
|
||||
// methods), to the actual USBHAL.
|
||||
|
||||
EFM_ASSERT(usb_isrcmd != CMD_HANDLED);
|
||||
switch (usb_isrcmd) {
|
||||
case CMD_EP0SETUP:
|
||||
this->EP0setupCallback();
|
||||
break;
|
||||
case CMD_EP0IN:
|
||||
this->EP0in();
|
||||
break;
|
||||
case CMD_EP0OUT:
|
||||
this->EP0out();
|
||||
break;
|
||||
case CMD_BUSRESET:
|
||||
this->busReset();
|
||||
break;
|
||||
case CMD_EP_XFER_COMPLETED:
|
||||
if (epCallback[usb_isrcmd_param] && instance) {
|
||||
(instance->*(epCallback[usb_isrcmd_param]))();
|
||||
}
|
||||
break;
|
||||
case CMD_SOF:
|
||||
this->SOF(usb_isrcmd_param);
|
||||
break;
|
||||
case CMD_SUSPEND_STATE_CHANGED:
|
||||
this->suspendStateChanged(usb_isrcmd_param);
|
||||
break;
|
||||
default:
|
||||
EFM_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
usb_isrcmd = CMD_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
// End of file
|
|
@ -26,6 +26,9 @@
|
|||
#define PWM_TIMER_CLOCK cmuClock_TIMER2
|
||||
#define PWM_ROUTE TIMER_ROUTE_LOCATION_LOC1
|
||||
|
||||
/* USB */
|
||||
#define USB_TIMER USB_TIMER1
|
||||
|
||||
/* Clocks */
|
||||
|
||||
/* Clock definitions */
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define PWM_TIMER_CLOCK cmuClock_TIMER0
|
||||
#define PWM_ROUTE TIMER_ROUTE_LOCATION_LOC0
|
||||
|
||||
/* USB */
|
||||
#define USB_TIMER USB_TIMER2
|
||||
|
||||
/* Clocks */
|
||||
|
||||
/* Clock definitions */
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define PWM_TIMER_CLOCK cmuClock_TIMER2
|
||||
#define PWM_ROUTE TIMER_ROUTE_LOCATION_LOC1
|
||||
|
||||
/* USB */
|
||||
#define USB_TIMER USB_TIMER1
|
||||
|
||||
/* Clocks */
|
||||
|
||||
/* Clock definitions */
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define PWM_TIMER_CLOCK cmuClock_TIMER2
|
||||
#define PWM_ROUTE TIMER_ROUTE_LOCATION_LOC1
|
||||
|
||||
/* USB */
|
||||
#define USB_TIMER USB_TIMER1
|
||||
|
||||
/* Clocks */
|
||||
|
||||
/* Clock definitions */
|
||||
|
|
|
@ -27,57 +27,63 @@ import sys
|
|||
# "libs" can contain "dsp", "rtos", "eth", "usb_host", "usb", "ublox", "fat"
|
||||
|
||||
build_list = (
|
||||
{ "target": "LPC1768", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "eth", "usb_host", "usb", "ublox", "fat"] },
|
||||
{ "target": "LPC2368", "toolchains": "GCC_ARM", "libs": ["fat"] },
|
||||
{ "target": "LPC2460", "toolchains": "GCC_ARM", "libs": ["rtos", "usb_host", "usb", "fat"] },
|
||||
{ "target": "LPC11U24", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "OC_MBUINO", "toolchains": "GCC_ARM", "libs": ["fat"] },
|
||||
{ "target": "LPC1768", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "eth", "usb_host", "usb", "ublox", "fat"] },
|
||||
{ "target": "LPC2368", "toolchains": "GCC_ARM", "libs": ["fat"] },
|
||||
{ "target": "LPC2460", "toolchains": "GCC_ARM", "libs": ["rtos", "usb_host", "usb", "fat"] },
|
||||
{ "target": "LPC11U24", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "OC_MBUINO", "toolchains": "GCC_ARM", "libs": ["fat"] },
|
||||
|
||||
{ "target": "LPC11U24_301", "toolchains": "GCC_ARM", "libs": ["fat"] },
|
||||
{ "target": "LPC11U24_301", "toolchains": "GCC_ARM", "libs": ["fat"] },
|
||||
|
||||
{ "target": "NUCLEO_L053R8", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_L152RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F030R8", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "NUCLEO_F070RB", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "NUCLEO_F072RB", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F091RC", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F103RB", "toolchains": "GCC_ARM", "libs": ["rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F302R8", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F303RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F334R8", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F401RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F411RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_L053R8", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_L152RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F030R8", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "NUCLEO_F070RB", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "NUCLEO_F072RB", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F091RC", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F103RB", "toolchains": "GCC_ARM", "libs": ["rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F302R8", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F303RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F334R8", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F401RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NUCLEO_F411RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
|
||||
{ "target": "MTS_MDOT_F405RG", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos"] },
|
||||
{ "target": "MTS_MDOT_F411RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos"] },
|
||||
{ "target": "MTS_MDOT_F405RG", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos"] },
|
||||
{ "target": "MTS_MDOT_F411RE", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos"] },
|
||||
{ "target": "MTS_DRAGONFLY_F411RE", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "ARCH_MAX", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "ARCH_MAX", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
|
||||
{ "target": "DISCO_F051R8", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "DISCO_F334C8", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "DISCO_F401VC", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "DISCO_F407VG", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "DISCO_F429ZI", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "DISCO_F746NG", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "DISCO_F051R8", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "DISCO_F334C8", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "DISCO_F401VC", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "DISCO_F407VG", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "DISCO_F429ZI", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "DISCO_F746NG", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
|
||||
{ "target": "LPC1114", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "LPC11U35_401", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "UBLOX_C027", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "LPC11U35_501", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "LPC11U68", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "LPC11U37H_401", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "LPC1114", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "LPC11U35_401", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "UBLOX_C027", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "LPC11U35_501", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "LPC11U68", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "LPC11U37H_401", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
|
||||
{ "target": "KL05Z", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "KL25Z", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "KL43Z", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "KL46Z", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "K20D50M", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "TEENSY3_1", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "K64F", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "LPC4088", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "ARCH_PRO", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "LPC1549", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NRF51822", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "KL05Z", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "KL25Z", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "KL43Z", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "KL46Z", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "K20D50M", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "TEENSY3_1", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
{ "target": "K64F", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "LPC4088", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "usb", "fat"] },
|
||||
{ "target": "ARCH_PRO", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "LPC1549", "toolchains": "GCC_ARM", "libs": ["dsp", "rtos", "fat"] },
|
||||
{ "target": "NRF51822", "toolchains": "GCC_ARM", "libs": ["dsp", "fat"] },
|
||||
|
||||
{ "target": "EFM32ZG_STK3200", "toolchains": "GCC_ARM", "libs": ["dsp"] },
|
||||
{ "target": "EFM32HG_STK3400", "toolchains": "GCC_ARM", "libs": ["dsp", "usb"] },
|
||||
{ "target": "EFM32LG_STK3600", "toolchains": "GCC_ARM", "libs": ["dsp", "usb"] },
|
||||
{ "target": "EFM32GG_STK3700", "toolchains": "GCC_ARM", "libs": ["dsp", "usb"] },
|
||||
{ "target": "EFM32WG_STK3800", "toolchains": "GCC_ARM", "libs": ["dsp", "usb"] },
|
||||
)
|
||||
|
||||
################################################################################
|
||||
|
|
Loading…
Reference in New Issue