init
This commit is contained in:
4
lib_xud/lib_xud/api/legacy/usb_defs.h
Normal file
4
lib_xud/lib_xud/api/legacy/usb_defs.h
Normal file
@@ -0,0 +1,4 @@
|
||||
// Copyright 2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include "XUD_USB_Defines.h"
|
||||
|
||||
4
lib_xud/lib_xud/api/legacy/usb_device.h
Normal file
4
lib_xud/lib_xud/api/legacy/usb_device.h
Normal file
@@ -0,0 +1,4 @@
|
||||
// Copyright 2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include "xud_device.h"
|
||||
|
||||
4
lib_xud/lib_xud/api/legacy/usb_std_descriptors.h
Normal file
4
lib_xud/lib_xud/api/legacy/usb_std_descriptors.h
Normal file
@@ -0,0 +1,4 @@
|
||||
// Copyright 2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include "xud_std_descriptors.h"
|
||||
|
||||
4
lib_xud/lib_xud/api/legacy/usb_std_requests.h
Normal file
4
lib_xud/lib_xud/api/legacy/usb_std_requests.h
Normal file
@@ -0,0 +1,4 @@
|
||||
// Copyright 2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include "xud_std_requests.h"
|
||||
|
||||
520
lib_xud/lib_xud/api/xud.h
Normal file
520
lib_xud/lib_xud/api/xud.h
Normal file
@@ -0,0 +1,520 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
/*
|
||||
* \brief User defines and functions for XMOS USB Device library
|
||||
*/
|
||||
|
||||
#ifndef _XUD_H_
|
||||
#define _XUD_H_
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#if !defined(__XS2A__)
|
||||
#define XUD_OPT_SOFTCRC5 (1)
|
||||
#else
|
||||
#define XUD_OPT_SOFTCRC5 (0)
|
||||
#endif
|
||||
|
||||
#ifdef __xud_conf_h_exists__
|
||||
#include "xud_conf.h"
|
||||
#endif
|
||||
|
||||
#ifndef XUD_STARTUP_ADDRESS
|
||||
#define XUD_STARTUP_ADDRESS (0)
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
#include <xs1.h>
|
||||
#include <platform.h>
|
||||
#include <print.h>
|
||||
#include <xccompat.h>
|
||||
|
||||
#ifndef XUD_WEAK_API
|
||||
#define XUD_WEAK_API (0)
|
||||
#endif
|
||||
|
||||
#if defined(__STDC__) && XUD_WEAK_API
|
||||
#define ATTRIB_WEAK __attribute__((weak));
|
||||
#else
|
||||
#define ATTRIB_WEAK
|
||||
#endif
|
||||
|
||||
#if !defined(USB_TILE)
|
||||
#define USB_TILE tile[0]
|
||||
#endif
|
||||
|
||||
#ifndef XUD_CORE_CLOCK
|
||||
#ifdef __XS2A__
|
||||
//#warning XUD_CORE_CLOCK not defined, using default (500MHz)
|
||||
#define XUD_CORE_CLOCK (500)
|
||||
#else
|
||||
//#warning XUD_CORE_CLOCK not defined, using default (600MHz)
|
||||
#define XUD_CORE_CLOCK (600)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(PORT_USB_CLK)
|
||||
/* Ports have not been defined in the .xn file */
|
||||
#define PORT_USB_CLK on USB_TILE: XS1_PORT_1J
|
||||
#define PORT_USB_TXD on USB_TILE: XS1_PORT_8A
|
||||
#define PORT_USB_RXD on USB_TILE: XS1_PORT_8B
|
||||
#define PORT_USB_TX_READYOUT on USB_TILE: XS1_PORT_1K
|
||||
#define PORT_USB_TX_READYIN on USB_TILE: XS1_PORT_1H
|
||||
#define PORT_USB_RX_READY on USB_TILE: XS1_PORT_1I
|
||||
#define PORT_USB_FLAG0 on USB_TILE: XS1_PORT_1E
|
||||
#define PORT_USB_FLAG1 on USB_TILE: XS1_PORT_1F
|
||||
#ifdef __XS2A__
|
||||
/* XS2A has an additional flag port */
|
||||
#define PORT_USB_FLAG2 on USB_TILE: XS1_PORT_1G
|
||||
#endif
|
||||
#endif // PORT_USB_CLK
|
||||
|
||||
/**
|
||||
* \var typedef XUD_EpTransferType
|
||||
* \brief Typedef for endpoint data transfer types. Note: it is important that ISO is 0
|
||||
*/
|
||||
typedef enum XUD_EpTransferType
|
||||
{
|
||||
XUD_EPTYPE_ISO = 0, /**< Isoc */
|
||||
XUD_EPTYPE_INT, /**< Interrupt */
|
||||
XUD_EPTYPE_BUL, /**< Bulk */
|
||||
XUD_EPTYPE_CTL, /**< Control */
|
||||
XUD_EPTYPE_DIS, /**< Disabled */
|
||||
} XUD_EpTransferType;
|
||||
|
||||
/**
|
||||
* \var typedef XUD_EpType
|
||||
* \brief Typedef for endpoint type
|
||||
*/
|
||||
typedef unsigned int XUD_EpType;
|
||||
|
||||
/**
|
||||
* \var typedef XUD_ep
|
||||
* \brief Typedef for endpoint identifiers
|
||||
*/
|
||||
typedef unsigned int XUD_ep;
|
||||
|
||||
/* Value to be or'ed in with EpTransferType to enable bus state notifications */
|
||||
#define XUD_STATUS_ENABLE 0x80000000
|
||||
|
||||
typedef enum XUD_BusSpeed
|
||||
{
|
||||
XUD_SPEED_FS = 1,
|
||||
XUD_SPEED_HS = 2,
|
||||
XUD_SPEED_KILL = 3
|
||||
} XUD_BusSpeed_t;
|
||||
|
||||
typedef enum XUD_PwrConfig
|
||||
{
|
||||
XUD_PWR_BUS,
|
||||
XUD_PWR_SELF
|
||||
} XUD_PwrConfig;
|
||||
|
||||
typedef enum XUD_Result
|
||||
{
|
||||
XUD_RES_RST = -1,
|
||||
XUD_RES_OKAY = 0,
|
||||
//XUD_RES_CTL = 1, /* Received a control trans */
|
||||
XUD_RES_ERR = 2,
|
||||
} XUD_Result_t;
|
||||
|
||||
/** This performs the low-level USB I/O operations. Note that this
|
||||
* needs to run in a thread with at least 80 MIPS worst case execution
|
||||
* speed.
|
||||
*
|
||||
* \param c_epOut An array of channel ends, one channel end per
|
||||
* output endpoint (USB OUT transaction); this includes
|
||||
* a channel to obtain requests on Endpoint 0.
|
||||
* \param noEpOut The number of output endpoints, should be at least 1 (for Endpoint 0).
|
||||
* \param c_epIn An array of channel ends, one channel end per input endpoint (USB IN transaction);
|
||||
* this includes a channel to respond to requests on Endpoint 0.
|
||||
* \param noEpIn The number of input endpoints, should be at least 1 (for Endpoint 0).
|
||||
* \param c_sof A channel to receive SOF tokens on. This channel must be connected to a process that
|
||||
* can receive a token once every 125 ms. If tokens are not read, the USB layer will lock up.
|
||||
* If no SOF tokens are required ``null`` should be used for this parameter.
|
||||
*
|
||||
* \param epTypeTableOut See ``epTypeTableIn``.
|
||||
* \param epTypeTableIn This and ``epTypeTableOut`` are two arrays
|
||||
* indicating the type of the endpoint.
|
||||
* Legal types include:
|
||||
* ``XUD_EPTYPE_CTL`` (Endpoint 0),
|
||||
* ``XUD_EPTYPE_BUL`` (Bulk endpoint),
|
||||
* ``XUD_EPTYPE_ISO`` (Isochronous endpoint),
|
||||
* ``XUD_EPTYPE_INT`` (Interrupt endpoint),
|
||||
* ``XUD_EPTYPE_DIS`` (Endpoint not used).
|
||||
* The first array contains the
|
||||
* endpoint types for each of the OUT
|
||||
* endpoints, the second array contains the
|
||||
* endpoint types for each of the IN
|
||||
* endpoints.
|
||||
* \param desiredSpeed This parameter specifies what speed the device will attempt to run at
|
||||
* i.e. full-speed (ie 12Mbps) or high-speed (480Mbps) if supported
|
||||
* by the host. Pass ``XUD_SPEED_HS`` if high-speed is desired or ``XUD_SPEED_FS``
|
||||
* if not. Low speed USB is not supported by XUD.
|
||||
* \param pwrConfig Specifies whether the device is bus or self-powered. When self-powered the XUD
|
||||
* will monitor the VBUS line for host disconnections. This is required for compliance reasons.
|
||||
* Valid values are XUD_PWR_SELF and XUD_PWR_BUS.
|
||||
*
|
||||
*/
|
||||
int XUD_Main(/*tileref * unsafe usbtileXUD_res_t &xudres, */
|
||||
chanend c_epOut[], int noEpOut,
|
||||
chanend c_epIn[], int noEpIn,
|
||||
NULLABLE_RESOURCE(chanend, c_sof),
|
||||
XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[],
|
||||
XUD_BusSpeed_t desiredSpeed,
|
||||
XUD_PwrConfig pwrConfig);
|
||||
|
||||
/* Legacy API support */
|
||||
int XUD_Manager(chanend c_epOut[], int noEpOut,
|
||||
chanend c_epIn[], int noEpIn,
|
||||
NULLABLE_RESOURCE(chanend, c_sof),
|
||||
XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[],
|
||||
NULLABLE_RESOURCE(port, p_usb_rst),
|
||||
NULLABLE_RESOURCE(xcore_clock_t, clk),
|
||||
unsigned rstMask,
|
||||
XUD_BusSpeed_t desiredSpeed,
|
||||
XUD_PwrConfig pwrConfig);
|
||||
|
||||
/**
|
||||
* \brief This function must be called by a thread that deals with an OUT endpoint.
|
||||
* When the host sends data, the low-level driver will fill the buffer. It
|
||||
* pauses until data is available.
|
||||
* \param ep_out The OUT endpoint identifier (created by ``XUD_InitEP``).
|
||||
* \param buffer The buffer in which to store data received from the host.
|
||||
* The buffer is assumed to be word aligned.
|
||||
* \param length The number of bytes written to the buffer
|
||||
* \return XUD_RES_OKAY on success, for errors see `Status Reporting`_.
|
||||
**/
|
||||
XUD_Result_t XUD_GetBuffer(XUD_ep ep_out, unsigned char buffer[], REFERENCE_PARAM(unsigned, length)) ATTRIB_WEAK;
|
||||
|
||||
/**
|
||||
* \brief Request setup data from usb buffer for a specific endpoint, pauses until data is available.
|
||||
* \param ep_out The OUT endpoint identifier (created by ``XUD_InitEP``).
|
||||
* \param buffer A char buffer passed by ref into which data is returned.
|
||||
* \param length Length of the buffer received (expect 8 bytes)
|
||||
* \return XUD_RES_OKAY on success, for errors see ``Status Reporting``_.
|
||||
**/
|
||||
XUD_Result_t XUD_GetSetupBuffer(XUD_ep ep_out, unsigned char buffer[], REFERENCE_PARAM(unsigned, length)) ATTRIB_WEAK;
|
||||
|
||||
/**
|
||||
* \brief This function must be called by a thread that deals with an IN endpoint.
|
||||
* When the host asks for data, the low-level driver will transmit the buffer
|
||||
* to the host.
|
||||
* \param ep_in The endpoint identifier (created by ``XUD_InitEp``).
|
||||
* \param buffer The buffer of data to transmit to the host.
|
||||
* \param datalength The number of bytes in the buffer.
|
||||
* \return XUD_RES_OKAY on success, for errors see `Status Reporting`_.
|
||||
*/
|
||||
XUD_Result_t XUD_SetBuffer(XUD_ep ep_in, unsigned char buffer[], unsigned datalength) ATTRIB_WEAK;
|
||||
|
||||
/**
|
||||
* \brief Similar to XUD_SetBuffer but breaks up data transfers into smaller packets.
|
||||
* This function must be called by a thread that deals with an IN endpoint.
|
||||
* When the host asks for data, the low-level driver will transmit the buffer
|
||||
* to the host.
|
||||
* \param ep_in The IN endpoint identifier (created by ``XUD_InitEp``).
|
||||
* \param buffer The buffer of data to transmit to the host.
|
||||
* \param datalength The number of bytes in the buffer.
|
||||
* \param epMax The maximum packet size in bytes.
|
||||
* \return XUD_RES_OKAY on success, for errors see `Status Reporting`_.
|
||||
*/
|
||||
XUD_Result_t XUD_SetBuffer_EpMax(XUD_ep ep_in, unsigned char buffer[], unsigned datalength, unsigned epMax) ATTRIB_WEAK;
|
||||
|
||||
/**
|
||||
* \brief Performs a combined ``XUD_SetBuffer`` and ``XUD_GetBuffer``.
|
||||
* It transmits the buffer of the given length over the ``ep_in`` endpoint to
|
||||
* answer an IN request, and then waits for a 0 length Status OUT transaction on ``ep_out``.
|
||||
* This function is normally called to handle Get control requests to Endpoint 0.
|
||||
*
|
||||
* \param ep_out The endpoint identifier that handles Endpoint 0 OUT data in the XUD manager.
|
||||
* \param ep_in The endpoint identifier that handles Endpoint 0 IN data in the XUD manager.
|
||||
* \param buffer The data to send in response to the IN transaction. Note that this data
|
||||
* is chopped up in fragments of at most 64 bytes.
|
||||
* \param length Length of data to be sent.
|
||||
* \param requested The length that the host requested, (Typically pass the value ``wLength``).
|
||||
* \return XUD_RES_OKAY on success, for errors see `Status Reporting`_
|
||||
**/
|
||||
XUD_Result_t XUD_DoGetRequest(XUD_ep ep_out, XUD_ep ep_in, unsigned char buffer[], unsigned length, unsigned requested) ATTRIB_WEAK;
|
||||
|
||||
/**
|
||||
* \brief This function sends an empty packet back on the next IN request with
|
||||
* PID1. It is normally used by Endpoint 0 to acknowledge success of a control transfer.
|
||||
* \param ep_in The Endpoint 0 IN identifier to the XUD manager.
|
||||
* \return XUD_RES_OKAY on success, for errors see `Status Reporting`_.
|
||||
**/
|
||||
XUD_Result_t XUD_DoSetRequestStatus(XUD_ep ep_in) ATTRIB_WEAK;
|
||||
|
||||
/**
|
||||
* \brief This function will complete a reset on an endpoint. Can take
|
||||
* one or two ``XUD_ep`` as parameters (the second parameter can be set to ``null``).
|
||||
* The return value should be inspected to find the new bus-speed.
|
||||
* In Endpoint 0 typically two endpoints are reset (IN and OUT).
|
||||
* In other endpoints ``null`` can be passed as the second parameter.
|
||||
* \param one IN or OUT endpoint identifier to perform the reset on.
|
||||
* \param two Optional second IN or OUT endpoint structure to perform a reset on.
|
||||
* \return Either ``XUD_SPEED_HS`` - the host has accepted that this device can execute
|
||||
* at high speed, ``XUD_SPEED_FS`` - the device is running at full speed,
|
||||
* or ``XUD_SPEED_KILL`` to indicate that the USB stack has been shut down
|
||||
* by another part of the user code (using XUD_Kill). If the last value is
|
||||
* returned, the endpoint code should call XUD_CloseEndpoint and then
|
||||
* terminate.
|
||||
*/
|
||||
XUD_BusSpeed_t XUD_ResetEndpoint(XUD_ep one, NULLABLE_REFERENCE_PARAM(XUD_ep, two));
|
||||
|
||||
/**
|
||||
* \brief This function closes an endpoint. It should be called when the USB stack
|
||||
* is shutting down. It should be called on all endpoints, either in parallel
|
||||
* or in numerical order, first all OUT and then all IN endpoints
|
||||
* \param one endpoint to close.
|
||||
*/
|
||||
void XUD_CloseEndpoint(XUD_ep one);
|
||||
|
||||
/**
|
||||
* \brief Initialises an XUD_ep
|
||||
* \param c_ep Endpoint channel to be connected to the XUD library.
|
||||
* \return Endpoint identifier
|
||||
*/
|
||||
XUD_ep XUD_InitEp(chanend c_ep);
|
||||
|
||||
/**
|
||||
* \brief Mark an endpoint as STALL based on its EP address. Cleared automatically if a SETUP received on the endpoint.
|
||||
* Note: the IN bit of the endpoint address is used.
|
||||
* \param epNum Endpoint number.
|
||||
* \warning Must be run on same tile as XUD core
|
||||
*/
|
||||
void XUD_SetStallByAddr(int epNum);
|
||||
|
||||
/**
|
||||
* \brief Mark an endpoint as NOT STALLed based on its EP address.
|
||||
* Note: the IN bit of the endpoint address is used.
|
||||
* \param epNum Endpoint number.
|
||||
* \warning Must be run on same tile as XUD core
|
||||
*/
|
||||
void XUD_ClearStallByAddr(int epNum);
|
||||
|
||||
/**
|
||||
* \brief Mark an endpoint as STALLed. It is cleared automatically if a SETUP received on the endpoint.
|
||||
* \param ep XUD_ep type.
|
||||
* \warning Must be run on same tile as XUD core
|
||||
*/
|
||||
void XUD_SetStall(XUD_ep ep);
|
||||
|
||||
/**
|
||||
* \brief Mark an endpoint as NOT STALLed
|
||||
* \param ep XUD_ep type.
|
||||
* \warning Must be run on same tile as XUD core
|
||||
*/
|
||||
void XUD_ClearStall(XUD_ep ep);
|
||||
|
||||
/* USB 2.0 Spec 9.1.1.5 states that configuring a device should cause all
|
||||
* the status and configuration values associated with the endpoints in the
|
||||
* affected interfaces to be set to their default values. This includes setting
|
||||
* the data toggle of any endpoint using data toggles to the value DATA0 */
|
||||
/**
|
||||
* \brief Reset an Endpoints state including data PID toggle
|
||||
* Note: the IN bit of the endpoint address is used.
|
||||
* \param epNum Endpoint number (including IN bit)
|
||||
* \warning Must be run on same tile as XUD core
|
||||
*/
|
||||
void XUD_ResetEpStateByAddr(unsigned epNum);
|
||||
|
||||
/**
|
||||
* \brief Enable a specific USB test mode in XUD
|
||||
* \param ep XUD_ep type (must be endpoint 0 in or out)
|
||||
* \param testMode The desired test-mode
|
||||
* \warning Must be run on same tile as XUD core
|
||||
*/
|
||||
void XUD_SetTestMode(XUD_ep ep, unsigned testMode);
|
||||
|
||||
/**
|
||||
* \brief Terminate XUD core
|
||||
* \param ep XUD_ep type (must be endpoint 0 in or out)
|
||||
* \warning Must be run on same tile as XUD core
|
||||
*/
|
||||
void XUD_Kill(XUD_ep ep);
|
||||
|
||||
/***********************************************************************************************/
|
||||
|
||||
/*
|
||||
* Advanced functions for supporting multple Endpoints in a single core
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \brief Marks an OUT endpoint as ready to receive data
|
||||
* \param ep The OUT endpoint identifier (created by ``XUD_InitEp``).
|
||||
* \param addr The address of the buffer in which to store data received from the host.
|
||||
* The buffer is assumed to be word aligned.
|
||||
* \return XUD_RES_OKAY on success, for errors see `Status Reporting`.
|
||||
*/
|
||||
#if (XUD_WEAK_API)
|
||||
XUD_Result_t XUD_SetReady_OutPtr(XUD_ep ep, unsigned addr);
|
||||
#else
|
||||
static inline XUD_Result_t XUD_SetReady_OutPtr(XUD_ep ep, unsigned addr)
|
||||
{
|
||||
int chan_array_ptr;
|
||||
int reset;
|
||||
|
||||
/* Firstly check if we have missed a USB reset - endpoint may would not want receive after a reset */
|
||||
asm volatile("ldw %0, %1[9]":"=r"(reset):"r"(ep));
|
||||
if(reset)
|
||||
{
|
||||
return XUD_RES_RST;
|
||||
}
|
||||
asm volatile("ldw %0, %1[0]":"=r"(chan_array_ptr):"r"(ep));
|
||||
asm volatile("stw %0, %1[3]"::"r"(addr),"r"(ep)); // Store buffer
|
||||
asm volatile("stw %0, %1[0]"::"r"(ep),"r"(chan_array_ptr));
|
||||
|
||||
return XUD_RES_OKAY;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Marks an OUT endpoint as ready to receive data
|
||||
* \param ep The OUT endpoint identifier (created by ``XUD_InitEp``).
|
||||
* \param buffer The buffer in which to store data received from the host.
|
||||
* The buffer is assumed to be word aligned.
|
||||
* \return XUD_RES_OKAY on success, for errors see `Status Reporting`.
|
||||
*/
|
||||
int XUD_SetReady_Out(XUD_ep ep, unsigned char buffer[]) ATTRIB_WEAK;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Marks an IN endpoint as ready to transmit data
|
||||
* \param ep The IN endpoint identifier (created by ``XUD_InitEp``).
|
||||
* \param addr The address of the buffer to transmit to the host.
|
||||
* The buffer is assumed be word aligned.
|
||||
* \param len The length of the data to transmit.
|
||||
* \return XUD_RES_OKAY on success, for errors see `Status Reporting`.
|
||||
*/
|
||||
#if (XUD_WEAK_API)
|
||||
XUD_Result_t XUD_SetReady_InPtr(XUD_ep ep, unsigned addr, int len);
|
||||
#else
|
||||
static inline XUD_Result_t XUD_SetReady_InPtr(XUD_ep ep, unsigned addr, int len)
|
||||
{
|
||||
int chan_array_ptr;
|
||||
int tmp, tmp2;
|
||||
int wordLength;
|
||||
int tailLength;
|
||||
|
||||
int reset;
|
||||
|
||||
/* Firstly check if we have missed a USB reset - endpoint may not want to send out old data after a reset */
|
||||
asm volatile("ldw %0, %1[9]":"=r"(reset):"r"(ep));
|
||||
if(reset)
|
||||
{
|
||||
return XUD_RES_RST;
|
||||
}
|
||||
|
||||
/* Tail length bytes to bits */
|
||||
#ifdef __XC__
|
||||
tailLength = zext((len << 3),5);
|
||||
#else
|
||||
tailLength = (len << 3) & 0x1F;
|
||||
#endif
|
||||
|
||||
/* Datalength (bytes) --> datalength (words) */
|
||||
wordLength = len >> 2;
|
||||
|
||||
/* If tail-length is 0 and word-length not 0. Make tail-length 32 and word-length-- */
|
||||
if ((tailLength == 0) && (wordLength != 0))
|
||||
{
|
||||
wordLength = wordLength - 1;
|
||||
tailLength = 32;
|
||||
}
|
||||
|
||||
/* Get end off buffer address */
|
||||
asm volatile("add %0, %1, %2":"=r"(tmp):"r"(addr),"r"(wordLength << 2));
|
||||
|
||||
/* Produce negative offset from end of buffer */
|
||||
asm volatile("neg %0, %1":"=r"(tmp2):"r"(wordLength));
|
||||
|
||||
/* Store neg index */
|
||||
asm volatile("stw %0, %1[6]"::"r"(tmp2),"r"(ep));
|
||||
|
||||
/* Store buffer pointer */
|
||||
asm volatile("stw %0, %1[3]"::"r"(tmp),"r"(ep));
|
||||
|
||||
/* Store tail len */
|
||||
asm volatile("stw %0, %1[7]"::"r"(tailLength),"r"(ep));
|
||||
|
||||
/* Finally, mark ready */
|
||||
asm volatile("ldw %0, %1[0]":"=r"(chan_array_ptr):"r"(ep));
|
||||
asm volatile("stw %0, %1[0]"::"r"(ep),"r"(chan_array_ptr));
|
||||
|
||||
return XUD_RES_OKAY;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Marks an IN endpoint as ready to transmit data
|
||||
* \param ep The IN endpoint identifier (created by ``XUD_InitEp``).
|
||||
* \param buffer The buffer to transmit to the host.
|
||||
* The buffer is assumed be word aligned.
|
||||
* \param len The length of the data to transmit.
|
||||
* \return XUD_RES_OKAY on success, for errors see `Status Reporting`.
|
||||
*/
|
||||
static inline XUD_Result_t XUD_SetReady_In(XUD_ep ep, unsigned char buffer[], int len)
|
||||
{
|
||||
unsigned addr;
|
||||
|
||||
asm volatile("mov %0, %1":"=r"(addr):"r"(buffer));
|
||||
|
||||
return XUD_SetReady_InPtr(ep, addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Select handler function for receiving OUT endpoint data in a select.
|
||||
* \param c The chanend related to the endpoint
|
||||
* \param ep The OUT endpoint identifier (created by ``XUD_InitEp``).
|
||||
* \param length Passed by reference. The number of bytes written to the buffer (that was passed into
|
||||
* XUD_SetReady_Out())
|
||||
* \param result XUD_Result_t passed by reference. XUD_RES_OKAY on success, for errors see `Status Reporting`.
|
||||
*/
|
||||
#ifdef __XC__
|
||||
#pragma select handler
|
||||
#endif
|
||||
void XUD_GetData_Select(chanend c, XUD_ep ep, REFERENCE_PARAM(unsigned, length), REFERENCE_PARAM(XUD_Result_t, result));
|
||||
|
||||
/**
|
||||
* \brief Select handler function for transmitting IN endpoint data in a select.
|
||||
* \param c The chanend related to the endpoint
|
||||
* \param ep The IN endpoint identifier (created by ``XUD_InitEp``).
|
||||
* \param result Passed by reference. XUD_RES_OKAY on success, for errors see `Status Reporting`.
|
||||
*/
|
||||
#ifdef __XC__
|
||||
#pragma select handler
|
||||
#endif
|
||||
void XUD_SetData_Select(chanend c, XUD_ep ep, REFERENCE_PARAM(XUD_Result_t, result));
|
||||
|
||||
/* Control token defines - used to inform EPs of bus-state types */
|
||||
#define USB_RESET_TOKEN 8 /* Control token value that signals RESET */
|
||||
|
||||
#ifndef XUD_OSC_MHZ
|
||||
#define XUD_OSC_MHZ (24)
|
||||
#endif
|
||||
|
||||
/* TODO pack this to save mem
|
||||
* TODO size of this hardcoded in ResetEpStateByAddr_
|
||||
*/
|
||||
typedef struct XUD_ep_info
|
||||
{
|
||||
unsigned int array_ptr; // 0
|
||||
unsigned int xud_chanend; // 1
|
||||
unsigned int client_chanend; // 2
|
||||
unsigned int buffer; // 3 Pointer to buffer
|
||||
unsigned int pid; // 4 Expected out PID
|
||||
unsigned int epType; // 5 Data
|
||||
unsigned int actualPid; // 6 Actual OUT PID received for OUT, Length (words) for IN.
|
||||
unsigned int tailLength; // 7 "tail" length for IN (bytes)
|
||||
unsigned int epAddress; // 8 EP address assigned by XUD (Used for marking stall etc)
|
||||
unsigned int resetting; // 9 Flag to indicate to EP a bus-reset occured.
|
||||
unsigned int halted; // 10 NAK or STALL
|
||||
unsigned int saved_array_ptr; // 11
|
||||
unsigned int array_ptr_setup; // 12
|
||||
} XUD_ep_info;
|
||||
|
||||
#endif
|
||||
#endif // _XUD_H_
|
||||
11
lib_xud/lib_xud/api/xud_conf_default.h
Normal file
11
lib_xud/lib_xud/api/xud_conf_default.h
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2017-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef __XUD_CONF_DEFAULT_H__
|
||||
#define __XUD_CONF_DEFAULT_H__
|
||||
|
||||
#ifdef __xud_conf_h_exists__
|
||||
#include "xud_conf.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
87
lib_xud/lib_xud/api/xud_device.h
Normal file
87
lib_xud/lib_xud/api/xud_device.h
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2015-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/*
|
||||
* @brief USB Device helper functions
|
||||
*/
|
||||
|
||||
#ifndef _USB_DEVICE_H_
|
||||
#define _USB_DEVICE_H_
|
||||
|
||||
#include <xccompat.h>
|
||||
|
||||
/* Low level XUD API for USB Device */
|
||||
#include "xud.h"
|
||||
|
||||
/* Generic USB defines */
|
||||
#include "XUD_USB_Defines.h"
|
||||
|
||||
/* Generic USB descriptor defines */
|
||||
#include "xud_std_descriptors.h"
|
||||
|
||||
/* Generic USB descriptor defines */
|
||||
#include "xud_std_requests.h"
|
||||
|
||||
/**
|
||||
* \brief This function deals with common requests This includes Standard Device Requests listed
|
||||
* in table 9-3 of the USB 2.0 Spec all devices must respond to these requests, in some
|
||||
* cases a bare minimum implementation is provided and should be extended in the devices EP0 code
|
||||
* It handles the following standard requests appropriately using values passed to it:
|
||||
*
|
||||
* Get Device Descriptor (using devDesc_hs/devDesc_fs arguments)
|
||||
*
|
||||
* Get Configuration Descriptor (using cfgDesc_hs/cfgDesc_fs arguments)
|
||||
*
|
||||
* String requests (using strDesc argument)
|
||||
*
|
||||
* Get Device_Qualifier Descriptor
|
||||
*
|
||||
* Get Other-Speed Configuration Descriptor
|
||||
*
|
||||
* Set/Clear Feature (Endpoint Halt)
|
||||
*
|
||||
* Get/Set Interface
|
||||
*
|
||||
* Set Configuration
|
||||
*
|
||||
* If the request is not recognised the endpoint is marked STALLED
|
||||
*
|
||||
*
|
||||
* \param ep_out Endpoint from XUD (ep 0)
|
||||
* \param ep_in Endpoint from XUD (ep 0)
|
||||
* \param devDesc_hs The Device descriptor to use, encoded according to the USB standard
|
||||
* \param devDescLength_hs Length of device descriptor in bytes
|
||||
* \param cfgDesc_hs Configuration descriptor
|
||||
* \param cfgDescLength_hs Length of config descriptor in bytes
|
||||
* \param devDesc_fs The Device descriptor to use, encoded according to the USB standard
|
||||
* \param devDescLength_fs Length of device descriptor in bytes. If 0 the HS device descriptor is used.
|
||||
* \param cfgDesc_fs Configuration descriptor
|
||||
* \param cfgDescLength_fs Length of config descriptor in bytes. If 0 the HS config descriptor is used.
|
||||
* \param strDescs
|
||||
* \param strDescsLength
|
||||
* \param sp ``USB_SetupPacket_t`` (passed by ref) in which the setup data is returned
|
||||
* \param usbBusSpeed The current bus speed (XUD_SPEED_HS or XUD_SPEED_FS)
|
||||
*
|
||||
* \return Returns XUD_RES_OKAY on success.
|
||||
*/
|
||||
|
||||
XUD_Result_t USB_StandardRequests(XUD_ep ep_out, XUD_ep ep_in,
|
||||
NULLABLE_ARRAY_OF(unsigned char, devDesc_hs), int devDescLength_hs,
|
||||
NULLABLE_ARRAY_OF(unsigned char, cfgDesc_hs), int cfgDescLength_hs,
|
||||
NULLABLE_ARRAY_OF(unsigned char, devDesc_fs), int devDescLength_fs,
|
||||
NULLABLE_ARRAY_OF(unsigned char, cfgDesc_fs), int cfgDescLength_fs,
|
||||
#ifdef __XC__
|
||||
char * unsafe strDescs[],
|
||||
#else
|
||||
char * strDescs[],
|
||||
#endif
|
||||
int strDescsLength, REFERENCE_PARAM(USB_SetupPacket_t, sp), XUD_BusSpeed_t usbBusSpeed);
|
||||
/**
|
||||
* \brief Receives a Setup data packet and parses it into the passed USB_SetupPacket_t structure.
|
||||
* \param ep_out OUT endpint from XUD
|
||||
* \param ep_in IN endpoint to XUD
|
||||
* \param sp SetupPacket structure to be filled in (passed by ref)
|
||||
* \return Returns XUD_RES_OKAY on success, XUD_RES_RST on bus reset
|
||||
*/
|
||||
XUD_Result_t USB_GetSetupPacket(XUD_ep ep_out, XUD_ep ep_in, REFERENCE_PARAM(USB_SetupPacket_t, sp));
|
||||
|
||||
#endif
|
||||
191
lib_xud/lib_xud/api/xud_std_descriptors.h
Normal file
191
lib_xud/lib_xud/api/xud_std_descriptors.h
Normal file
@@ -0,0 +1,191 @@
|
||||
// Copyright 2015-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef _USB_DESCRIPTORS_H_
|
||||
#define _USB_DESCRIPTORS_H_
|
||||
|
||||
#if !defined (__ASSEMBLER__)
|
||||
/* USB Class Codes (from usb.org) */
|
||||
typedef enum
|
||||
{
|
||||
USB_CLASS_USE_CLASS = 0x00, /* Use class information in the interface descriptors */
|
||||
USB_CLASS_AUDIO = 0x01,
|
||||
USB_CLASS_COMMUNICATIONS = 0x02,
|
||||
USB_CLASS_HID = 0x03,
|
||||
USB_CLASS_PHYSICAL = 0x05,
|
||||
USB_CLASS_IMAGE = 0x06,
|
||||
USB_CLASS_PRINTER = 0x07,
|
||||
USB_CLASS_MASS_STORAGE = 0x08,
|
||||
USB_CLASS_HUB = 0x09,
|
||||
USB_CLASS_CDC_DATA = 0x0A,
|
||||
USB_CLASS_SMART_CARD = 0x0B,
|
||||
USB_CLASS_RESERVED = 0x0C,
|
||||
USB_CLASS_CONTENT_SECURITY = 0x0D,
|
||||
USB_CLASS_VIDEO = 0x0E,
|
||||
USB_CLASS_PERSONAL_HEALTHCARE = 0x0F,
|
||||
USB_CLASS_AUDIO_VIDEO = 0x10,
|
||||
//...
|
||||
USB_CLASS_MAPPED_INDEX_END = 17,
|
||||
USB_CLASS_VENDOR_SPECIFIC = 0xFF
|
||||
} USB_ClassCode_t;
|
||||
|
||||
#endif
|
||||
|
||||
/* USB Standard Descriptor types (Section 9.4, table 9-5) */
|
||||
enum USB_DescriptorTypes_t
|
||||
{
|
||||
USB_DESCTYPE_DEVICE = 0x01, /* Device descriptor */
|
||||
USB_DESCTYPE_CONFIGURATION = 0x02, /* Configuration descriptor */
|
||||
USB_DESCTYPE_STRING = 0x03, /* String descriptor */
|
||||
USB_DESCTYPE_INTERFACE = 0x04, /* Interface descriptor */
|
||||
USB_DESCTYPE_ENDPOINT = 0x05, /* Endpoint descriptor */
|
||||
USB_DESCTYPE_DEVICE_QUALIFIER = 0x06, /* Device qualifier descriptor */
|
||||
USB_DESCTYPE_OTHER_SPEED = 0x07,
|
||||
USB_DESCTYPE_INTERFACE_POWER = 0x08, /* Interface power descriptor */
|
||||
USB_DESCTYPE_OTG = 0x09,
|
||||
USB_DESCTYPE_DEBUG = 0x0A,
|
||||
USB_DESCTYPE_INTERFACE_ASSOCIATION = 0x0B, /* Interface association descriptor */
|
||||
};
|
||||
|
||||
#ifdef __STDC__
|
||||
|
||||
/* No current support for __attribute((packed)) in XC */
|
||||
|
||||
/* Generic USB Descriptor Header */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of the descriptor (bytes) */
|
||||
unsigned char bDescriptorType; /* Descriptor type, either a value. See \ref USB_DescriptorTypes_t or
|
||||
* a value given by the specific class */
|
||||
} __attribute__((packed)) USB_Descriptor_Header_t;
|
||||
|
||||
/* USB Standard Device Descriptor (section 9.6.1, table 9-8) */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of the descriptor (bytes) */
|
||||
unsigned char bDescriptorType; /* Descriptor type, either a value in \ref USB_DescriptorTypes_t
|
||||
* or a value given by the specific class */
|
||||
unsigned short bcdUSB; /* Supported USB version */
|
||||
unsigned char bDeviceClass; /* USB device class code */
|
||||
unsigned char bDeviceSubClass; /* USB device subclass code */
|
||||
unsigned char bDeviceProtocol; /* USB device protocol code */
|
||||
unsigned char bMaxPacketSize0; /* Maximum packet size for endpoint 0 (bytes) */
|
||||
unsigned short idVendor; /* Vendor ID */
|
||||
unsigned short idProduct; /* Product ID */
|
||||
unsigned short bcdDevice; /* Device release number in binary-coded decimal */
|
||||
unsigned char iManufacturer; /* Index of string descriptor describing manufacturer */
|
||||
unsigned char iProduct; /* Index of string descriptor describing product */
|
||||
unsigned char iSerialNumber; /* Index of String descriptor describing the devices serial number */
|
||||
unsigned char bNumConfigurations; /* Total number of configurations supported by the device */
|
||||
} __attribute__((packed)) USB_Descriptor_Device_t;
|
||||
|
||||
/* USB Interface Association Descriptor (See IAD Engineering Change Notice) */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of the descriptor (bytes) */
|
||||
unsigned char bDescriptorType; /* Descriptor type, either a value in \ref USB_DescriptorTypes_t
|
||||
or a value given by the specific class */
|
||||
unsigned char bFirstInterface; /* Index of the first associated interface */
|
||||
unsigned char bInterfaceCount; /* Total number of associated interfaces */
|
||||
unsigned char bFunctionClass; /* Interface class ID */
|
||||
unsigned char bFunctionSubClass; /* Interface subclass ID */
|
||||
unsigned char bFunctionProtocol; /* Interface protocol ID */
|
||||
unsigned char iFunction; /* Index of the string descriptor describing the
|
||||
* interface association */
|
||||
} __attribute__((packed)) USB_Descriptor_Interface_Association_t;
|
||||
|
||||
/* USB Standard Interface Descriptor (section 9.6.1 table 9-12) */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of the descriptor (bytes) */
|
||||
unsigned char bDescriptorType; /* Type of the descriptor, either a value in \ref USB_DescriptorTypes_t
|
||||
* or a value given by the specific class */
|
||||
unsigned char bInterfaceNumber; /* Index of the interface in the current config */
|
||||
unsigned char bAlternateSetting; /* Alternate setting for this interface number. Multiple alternatives
|
||||
* are supported per interface (with different EP configs) */
|
||||
unsigned char bNumEndpoints; /* Total endpoint count in this interface */
|
||||
unsigned char bInterfaceClass; /* Interface class code */
|
||||
|
||||
unsigned char bInterfaceSubClass; /* Interface subclass code */
|
||||
unsigned char bInterfaceProtocol; /* Interface protocol code */
|
||||
unsigned char iInterface; /* Index of the string descriptor in the string table */
|
||||
} __attribute__((packed)) USB_Descriptor_Interface_t;
|
||||
|
||||
/* USB Standard Configuration Descriptor (section 9.6.1 table 9-10) */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of the descriptor (bytes) */
|
||||
unsigned char bDescriptorType; /* Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value
|
||||
* given by the specific class */
|
||||
unsigned short wTotalLength; /* Size of the configuration descriptor header and all sub descriptors inside
|
||||
* the configuration */
|
||||
unsigned char bNumInterfaces; /* Total interface count in the configuration */
|
||||
unsigned char bConfigurationValue; /* Value to use as an argument to the SetConfiguration() request to select this
|
||||
* configuration */
|
||||
unsigned char iConfiguration; /* Index of string descriptor describing this configuration */
|
||||
unsigned char bmAttributes; /* Configuration characteristics
|
||||
* D7: Reserved (set to one)
|
||||
* D6: Self-powered
|
||||
* D5: Remote Wakeup
|
||||
* D4...0: Reserved (reset to zero)
|
||||
*/
|
||||
unsigned char bMaxPower; /* Maximum power consumption of the USB device from the bus in this specific
|
||||
* configuration when the device is fully operational. Expressed in 2 mA units
|
||||
* (i.e., 50 = 100 mA) */
|
||||
} __attribute__((packed)) USB_Descriptor_Configuration_Header_t;
|
||||
|
||||
/* USB Standard Endpoint Descriptor (section 9.6.1 table 9-13) */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of the descriptor (bytes) */
|
||||
unsigned char bDescriptorType; /* Descriptor type, either a value. See \ref USB_DescriptorTypes_t or
|
||||
* a value given by the specific class */
|
||||
unsigned char bEndpointAddress; /* Address of the endpoint, includes a direction mask */
|
||||
unsigned char bmAttributes; /* Endpoint attributes, comprised of a mask of the endpoint type
|
||||
* See EP_TYPE_ ad EP_ADDR) */
|
||||
unsigned short wMaxPacketSize; /* Maximum packet size (bytes) that the endpoint can receive */
|
||||
unsigned char bInterval; /* Polling interval in milliseconds for the endpoint.
|
||||
* Relevant to Isochronous and Interrupt endpoints only */
|
||||
} __attribute__((packed)) USB_Descriptor_Endpoint_t;
|
||||
|
||||
/* USB Standard Endpoint Descriptor (Section 9.6.6, table 9-13) */
|
||||
enum USB_Endpoint_TransType_t
|
||||
{
|
||||
USB_ENDPOINT_TRANSTYPE_CTRL = 0x0,
|
||||
USB_ENDPOINT_TRANSTYPE_ISO = 0x1,
|
||||
USB_ENDPOINT_TRANSTYPE_BULK = 0x2,
|
||||
USB_ENDPOINT_TRANSTYPE_INT = 0x3
|
||||
};
|
||||
#define USB_ENDPOINT_TRANSTYPE_SHIFT (0)
|
||||
|
||||
enum USB_Endpoint_SyncType_t
|
||||
{
|
||||
USB_ENDPOINT_SYNCTYPE_NONE = 0x0,
|
||||
USB_ENDPOINT_SYNCTYPE_ASYNC = 0x1,
|
||||
USB_ENDPOINT_SYNCTYPE_ADAPT = 0x2,
|
||||
USB_ENDPOINT_SYNCTYPE_SYNC = 0x3
|
||||
};
|
||||
#define USB_ENDPOINT_SYNCTYPE_SHIFT (2)
|
||||
|
||||
enum USB_Endpoint_UsageType_t
|
||||
{
|
||||
USB_ENDPOINT_USAGETYPE_DATA = 0x0,
|
||||
USB_ENDPOINT_USAGETYPE_FEEDBACK = 0x1,
|
||||
USB_ENDPOINT_USAGETYPE_IMPLICIT = 0x2,
|
||||
USB_ENDPOINT_USAGETYPE_RESERVED = 0x3
|
||||
};
|
||||
#define USB_ENDPOINT_USAGETYPE_SHIFT (4)
|
||||
|
||||
|
||||
|
||||
/* USB String Descriptor (Section 9.6.7 table 9-15) */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of the descriptor (bytes) */
|
||||
unsigned char bDescriptorType; /* Descriptor type, either a value in \ref USB_DescriptorTypes_t
|
||||
* or a value given by the specific class */
|
||||
unsigned short bString[]; /* String data, (as unicode characters) - use array of chars instead of string.
|
||||
* In GCC prefix string with "L" */
|
||||
} __attribute__((packed)) USB_Descriptor_String_t;
|
||||
#endif
|
||||
#endif
|
||||
120
lib_xud/lib_xud/api/xud_std_requests.h
Normal file
120
lib_xud/lib_xud/api/xud_std_requests.h
Normal file
@@ -0,0 +1,120 @@
|
||||
// Copyright 2015-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef _USB_STD_REQUESTS_H_
|
||||
#define _USB_STD_REQUESTS_H_
|
||||
|
||||
#include <xccompat.h>
|
||||
#include "XUD_USB_Defines.h"
|
||||
|
||||
/* 9.3 USB Device Requests: Table 9-2 Format of Setup Data */
|
||||
/* bmRequestType: */
|
||||
#define USB_BM_REQTYPE_DIRECTION_H2D 0 /* Host to device */
|
||||
#define USB_BM_REQTYPE_DIRECTION_D2H 1 /* Device to host */
|
||||
|
||||
#define USB_BM_REQTYPE_TYPE_STANDARD 0x00
|
||||
#define USB_BM_REQTYPE_TYPE_CLASS 0x01
|
||||
#define USB_BM_REQTYPE_TYPE_VENDOR 0x02
|
||||
|
||||
#define USB_BM_REQTYPE_RECIP_DEV 0x00
|
||||
#define USB_BM_REQTYPE_RECIP_INTER 0x01
|
||||
#define USB_BM_REQTYPE_RECIP_EP 0x02
|
||||
#define USB_BM_REQTYPE_RECIP_OTHER 0x03
|
||||
|
||||
#define USB_BMREQ_H2D_STANDARD_DEV ((USB_BM_REQTYPE_DIRECTION_H2D << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_STANDARD << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_DEV))
|
||||
#define USB_BMREQ_D2H_STANDARD_DEV ((USB_BM_REQTYPE_DIRECTION_D2H << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_STANDARD << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_DEV))
|
||||
#define USB_BMREQ_H2D_STANDARD_INT ((USB_BM_REQTYPE_DIRECTION_H2D << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_STANDARD << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_INTER))
|
||||
#define USB_BMREQ_D2H_STANDARD_INT ((USB_BM_REQTYPE_DIRECTION_D2H << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_STANDARD << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_INTER))
|
||||
#define USB_BMREQ_H2D_STANDARD_EP ((USB_BM_REQTYPE_DIRECTION_H2D << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_STANDARD << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_EP))
|
||||
#define USB_BMREQ_D2H_STANDARD_EP ((USB_BM_REQTYPE_DIRECTION_D2H << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_STANDARD << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_EP))
|
||||
|
||||
|
||||
#define USB_BMREQ_H2D_CLASS_INT ((USB_BM_REQTYPE_DIRECTION_H2D << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_CLASS << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_INTER))
|
||||
#define USB_BMREQ_D2H_CLASS_INT ((USB_BM_REQTYPE_DIRECTION_D2H << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_CLASS << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_INTER))
|
||||
#define USB_BMREQ_H2D_CLASS_EP ((USB_BM_REQTYPE_DIRECTION_H2D << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_CLASS << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_EP))
|
||||
#define USB_BMREQ_D2H_CLASS_EP ((USB_BM_REQTYPE_DIRECTION_D2H << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_CLASS << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_EP))
|
||||
|
||||
#define USB_BMREQ_H2D_VENDOR_DEV ((USB_BM_REQTYPE_DIRECTION_H2D << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_VENDOR << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_DEV))
|
||||
#define USB_BMREQ_D2H_VENDOR_DEV ((USB_BM_REQTYPE_DIRECTION_D2H << 7) | \
|
||||
(USB_BM_REQTYPE_TYPE_VENDOR << 5) | \
|
||||
(USB_BM_REQTYPE_RECIP_DEV))
|
||||
|
||||
/* Table 9-4. Standard Request Codes */
|
||||
/* bRequest */
|
||||
#define USB_GET_STATUS 0x00
|
||||
#define USB_CLEAR_FEATURE 0x01
|
||||
#define USB_SET_FEATURE 0x03
|
||||
#define USB_SET_ADDRESS 0x05
|
||||
#define USB_GET_DESCRIPTOR 0x06
|
||||
#define USB_SET_DESCRIPTOR 0x07
|
||||
#define USB_GET_CONFIGURATION 0x08
|
||||
#define USB_SET_CONFIGURATION 0x09
|
||||
#define USB_GET_INTERFACE 0x0A
|
||||
#define USB_SET_INTERFACE 0x0B
|
||||
#define USB_SYNCH_FRAME 0x0C
|
||||
|
||||
/**
|
||||
* \var typedef USB_BmRequestType_t
|
||||
* \brief Defines the Recepient, Type and Direction of a USB request.
|
||||
*/
|
||||
typedef struct USB_BmRequestType
|
||||
{
|
||||
unsigned char Recipient; // [4..0] Request directed to:
|
||||
// 0b00000: Device
|
||||
// 0b00001: Specific interface
|
||||
// 0b00010: Specific endpoint
|
||||
// 0b00011: Other element in device
|
||||
unsigned char Type; // [6..5] 0b00: Standard request
|
||||
// 0b01: Class specific request
|
||||
// 0b10: Request by vendor specific driver
|
||||
unsigned char Direction; // [7] 0 (Host->Dev)
|
||||
// 1 (Dev->Host)
|
||||
} USB_BmRequestType_t;
|
||||
|
||||
/**
|
||||
* \var typedef USB_SetupPacket_t
|
||||
* \brief Typedef for setup packet structure */
|
||||
typedef struct USB_SetupPacket
|
||||
{
|
||||
USB_BmRequestType_t bmRequestType; /* (1 byte) Specifies direction of dataflow,
|
||||
type of rquest and recipient */
|
||||
unsigned char bRequest; /* Specifies the request */
|
||||
unsigned short wValue; /* Host can use this to pass info to the
|
||||
device in its own way */
|
||||
unsigned short wIndex; /* Typically used to pass index/offset such
|
||||
as interface or EP no */
|
||||
unsigned short wLength; /* Number of data bytes in the data stage
|
||||
(for Host -> Device this this is exact
|
||||
count, for Dev->Host is a max. */
|
||||
} USB_SetupPacket_t;
|
||||
|
||||
/**
|
||||
* \brief Prints out passed ``USB_SetupPacket_t`` struct using debug IO
|
||||
*/
|
||||
void USB_PrintSetupPacket(USB_SetupPacket_t sp);
|
||||
|
||||
void USB_ComposeSetupBuffer(USB_SetupPacket_t sp, unsigned char buffer[]);
|
||||
|
||||
void USB_ParseSetupPacket(unsigned char b[], REFERENCE_PARAM(USB_SetupPacket_t, p));
|
||||
#endif
|
||||
33
lib_xud/lib_xud/lib_build_info.cmake
Normal file
33
lib_xud/lib_xud/lib_build_info.cmake
Normal file
@@ -0,0 +1,33 @@
|
||||
set(LIB_NAME lib_xud)
|
||||
set(LIB_VERSION 2.4.0)
|
||||
set(LIB_INCLUDES api src/user api/legacy src/core src/user/class)
|
||||
|
||||
set(LIB_DEPENDENT_MODULES "")
|
||||
|
||||
set(LIB_OPTIONAL_HEADERS xud_conf.h)
|
||||
|
||||
set(LIB_ASM_SRCS src/core/XUD_IoLoop.S
|
||||
src/core/XUD_TestMode.S
|
||||
src/core/XUD_CRC5_Table.S
|
||||
src/core/XUD_USBTile_Support.S
|
||||
src/core/XUD_CRC5_Table_Addr.S
|
||||
src/user/client/XUD_EpFuncs.S)
|
||||
set(LIB_COMPILER_FLAGS -O3
|
||||
-fasm-linenum
|
||||
-fcomment-asm
|
||||
-DXUD_FULL_PIDTABLE=1
|
||||
-g)
|
||||
|
||||
set(LIB_COMPILER_FLAGS_XUD_IoLoop.S ${LIB_COMPILER_FLAGS} -fschedule)
|
||||
|
||||
set(LIB_COMPILER_FLAGS_XUD_Client.xc ${LIB_COMPILER_FLAGS} -mno-dual-issue)
|
||||
set(LIB_COMPILER_FLAGS_XUD_Main.xc ${LIB_COMPILER_FLAGS} -mno-dual-issue)
|
||||
set(LIB_COMPILER_FLAGS_XUD_PhyResetUser.xc ${LIB_COMPILER_FLAGS} -mno-dual-issue)
|
||||
set(LIB_COMPILER_FLAGS_XUD_Support.xc ${LIB_COMPILER_FLAGS} -mno-dual-issue)
|
||||
set(LIB_COMPILER_FLAGS_XUD_IOLoopCall.xc ${LIB_COMPILER_FLAGS} -mno-dual-issue)
|
||||
set(LIB_COMPILER_FLAGS_XUD_Signalling.xc ${LIB_COMPILER_FLAGS} -mno-dual-issue -Wno-return-type)
|
||||
set(LIB_COMPILER_FLAGS_XUD_TestMode.xc ${LIB_COMPILER_FLAGS} -mno-dual-issue)
|
||||
set(LIB_COMPILER_FLAGS_XUD_SetCrcTableAddr.c ${LIB_COMPILER_FLAGS} -mno-dual-issue)
|
||||
set(LIB_COMPILER_FLAGS_XUD_User.c ${LIB_COMPILER_FLAGS} -mno-dual-issue)
|
||||
|
||||
XMOS_REGISTER_MODULE()
|
||||
47
lib_xud/lib_xud/module_build_info
Normal file
47
lib_xud/lib_xud/module_build_info
Normal file
@@ -0,0 +1,47 @@
|
||||
VERSION = 2.4.0
|
||||
|
||||
MODULE_XCC_FLAGS = $(XCC_FLAGS) \
|
||||
-O3 \
|
||||
-fasm-linenum \
|
||||
-fcomment-asm \
|
||||
-DXUD_FULL_PIDTABLE=1 \
|
||||
-g
|
||||
|
||||
XCC_FLAGS_XUD_IoLoop.S = $(MODULE_XCC_FLAGS) -fschedule
|
||||
|
||||
XCC_FLAGS_XUD_Client.xc = $(MODULE_XCC_FLAGS) -mno-dual-issue
|
||||
XCC_FLAGS_XUD_Main.xc = $(MODULE_XCC_FLAGS) -mno-dual-issue
|
||||
XCC_FLAGS_XUD_PhyResetUser.xc = $(MODULE_XCC_FLAGS) -mno-dual-issue
|
||||
XCC_FLAGS_XUD_Support.xc = $(MODULE_XCC_FLAGS) -mno-dual-issue
|
||||
XCC_FLAGS_XUD_IOLoopCall.xc = $(MODULE_XCC_FLAGS) -mno-dual-issue
|
||||
XCC_FLAGS_XUD_Signalling.xc = $(MODULE_XCC_FLAGS) -mno-dual-issue -Wno-return-type
|
||||
XCC_FLAGS_XUD_TestMode.xc = $(MODULE_XCC_FLAGS) -mno-dual-issue
|
||||
XCC_FLAGS_XUD_SetCrcTableAddr.c = $(MODULE_XCC_FLAGS) -mno-dual-issue
|
||||
XCC_FLAGS_XUD_User.c = $(MODULE_XCC_FLAGS) -mno-dual-issue
|
||||
|
||||
OPTIONAL_HEADERS += xud_conf.h
|
||||
|
||||
DEPENDENT_MODULES =
|
||||
|
||||
EXPORT_INCLUDE_DIRS = api \
|
||||
src/user \
|
||||
api/legacy
|
||||
|
||||
INCLUDE_DIRS = $(EXPORT_INCLUDE_DIRS) \
|
||||
src/core \
|
||||
src/user/class
|
||||
|
||||
SOURCE_DIRS = src/core \
|
||||
src/user/client \
|
||||
src/user/control
|
||||
|
||||
EXCLUDE_FILES += XUD_CrcAddrCheck.S \
|
||||
XUD_PidJumpTable.S \
|
||||
XUD_PidJumpTable_RxData.S \
|
||||
XUD_RxData.S \
|
||||
XUD_Token_In_DI.S \
|
||||
XUD_Token_Out_DI.S \
|
||||
XUD_Token_Ping.S \
|
||||
XUD_Token_SOF.S \
|
||||
XUD_Token_Setup_DI.S \
|
||||
XUD_TokenJmp.S
|
||||
23
lib_xud/lib_xud/src/core/XUD_AlignmentDefines.h
Normal file
23
lib_xud/lib_xud/src/core/XUD_AlignmentDefines.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2021-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/* XUD_AlignmentDefines.h
|
||||
* @brief Architecture-specific ASM function alignment
|
||||
*/
|
||||
|
||||
#ifndef _XUD_ALIGNMENT_DEFINES_
|
||||
#define _XUD_ALIGNMENT_DEFINES_
|
||||
#if !defined(__XS2A__)
|
||||
#define IBUFFER_FETCH_CORRECTION 1
|
||||
#else
|
||||
#define IBUFFER_FETCH_CORRECTION 0
|
||||
#endif
|
||||
|
||||
#if IBUFFER_FETCH_CORRECTION == 1
|
||||
#define FUNCTION_ALIGNMENT 16
|
||||
#elif IBUFFER_FETCH_CORRECTION == 0
|
||||
#define FUNCTION_ALIGNMENT 4
|
||||
#else
|
||||
#error IBUFFER_FETCH_CORRECTION not defined
|
||||
#endif
|
||||
|
||||
#endif // _XUD_ALIGNMENT_DEFINES_
|
||||
2063
lib_xud/lib_xud/src/core/XUD_CRC5_Table.S
Normal file
2063
lib_xud/lib_xud/src/core/XUD_CRC5_Table.S
Normal file
File diff suppressed because it is too large
Load Diff
2063
lib_xud/lib_xud/src/core/XUD_CRC5_Table_Addr.S
Normal file
2063
lib_xud/lib_xud/src/core/XUD_CRC5_Table_Addr.S
Normal file
File diff suppressed because it is too large
Load Diff
38
lib_xud/lib_xud/src/core/XUD_CrcAddrCheck.S
Normal file
38
lib_xud/lib_xud/src/core/XUD_CrcAddrCheck.S
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
// On Entry:
|
||||
// r0: rxd port
|
||||
// r8: 16 (XS3 only)
|
||||
|
||||
// Required on exit:
|
||||
// r4: 0
|
||||
// r10: Extracted EP number
|
||||
|
||||
#if !defined(__XS2A__)
|
||||
{in r10, res[RXD]; sub r1, r8, 5} // ldc r1 11
|
||||
{shr r10, r10, 16; mkmsk r11, r1}
|
||||
{and r11, r10, r11; ldw r8, sp[STACK_CRC5TABLE_ADDR]}
|
||||
|
||||
{shr r4, r10, r1 // r4: Received CRC
|
||||
ld8u r8, r8[r11]} // r8: Expected CRC
|
||||
|
||||
// R4 set to 0 in L code with in from valid tok port
|
||||
{eq r4, r4, r8; shr r10, r11, 7} // Extract EP number
|
||||
BRFT_ru6 r4, 5
|
||||
|
||||
ldw r11, sp[STACK_RXA_PORT] // Wait for RXA to gow low (i.e. end of packet)
|
||||
in r10, res[r11]
|
||||
bt r10, waitforRXALow0
|
||||
setc res[RXD], XS1_SETC_RUN_CLRBUF
|
||||
bu Loop_BadPid
|
||||
#else
|
||||
// __XS2A__
|
||||
inpw r10, res[RXD], 8; // Read EP Number
|
||||
shr r10, r10, 24; // Shift off junk
|
||||
|
||||
in r4, res[r1];
|
||||
bt r4, XUD_InvalidToken; // If VALID_TOKEN not high, ignore token - PORT INVERTED! */
|
||||
#endif
|
||||
|
||||
|
||||
9
lib_xud/lib_xud/src/core/XUD_DeviceAttach.h
Normal file
9
lib_xud/lib_xud/src/core/XUD_DeviceAttach.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
|
||||
/** @brief Does high speed device attach
|
||||
* @return non-zero for error
|
||||
**/
|
||||
int XUD_DeviceAttachHS(XUD_PwrConfig p);
|
||||
|
||||
154
lib_xud/lib_xud/src/core/XUD_DeviceAttach.xc
Normal file
154
lib_xud/lib_xud/src/core/XUD_DeviceAttach.xc
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#if !defined(XUD_BYPASS_RESET)
|
||||
#include <xs1.h>
|
||||
#include <platform.h>
|
||||
#include "xud.h"
|
||||
#include "XUD_USB_Defines.h"
|
||||
#include "XUD_TimingDefines.h"
|
||||
#include "XUD_HAL.h"
|
||||
|
||||
extern in port flag0_port;
|
||||
extern in port flag1_port;
|
||||
extern in port flag2_port;
|
||||
extern out buffered port:32 p_usb_txd;
|
||||
|
||||
#define TUCHEND_DELAY_us (1500) // 1.5ms
|
||||
#define TUCHEND_DELAY (TUCHEND_DELAY_us * PLATFORM_REFERENCE_MHZ)
|
||||
|
||||
#ifndef INVALID_DELAY_us
|
||||
#define INVALID_DELAY_us (2500) // 2.5ms
|
||||
#endif
|
||||
|
||||
#define INVALID_DELAY (INVALID_DELAY_us * PLATFORM_REFERENCE_MHZ)
|
||||
|
||||
extern int resetCount;
|
||||
|
||||
/* Assumptions:
|
||||
* - In full speed mode
|
||||
* - No flags sticky
|
||||
* - Flag 0 port inverted
|
||||
*/
|
||||
int XUD_DeviceAttachHS(XUD_PwrConfig pwrConfig)
|
||||
{
|
||||
unsigned tmp;
|
||||
timer t;
|
||||
int start_time;
|
||||
int detecting_k = 1;
|
||||
int tx;
|
||||
unsigned int chirpCount = 0;
|
||||
|
||||
clearbuf(p_usb_txd);
|
||||
|
||||
/* On detecting the SE0 move into chirp mode */
|
||||
XUD_HAL_EnterMode_PeripheralChirp();
|
||||
|
||||
/* output k-chirp for required time */
|
||||
#if defined(XUD_SIM_RTL) || (XUD_SIM_XSIM)
|
||||
for (int i = 0; i < 800; i++)
|
||||
#else
|
||||
for (int i = 0; i < 16000; i++) // 16000 words @ 480 MBit = 1.066 ms
|
||||
#endif
|
||||
{
|
||||
p_usb_txd <: 0;
|
||||
}
|
||||
|
||||
// J, K, SE0 on flag ports 0, 1, 2 respectively (on XS2)
|
||||
// XS3 has raw linestate on flag port 0 and 1
|
||||
// Wait for fs chirp k (i.e. HS chirp j)
|
||||
#if defined(__XS2A__)
|
||||
flag1_port when pinseq(0) :> tmp; // Wait for out k to go
|
||||
#endif
|
||||
|
||||
t :> start_time;
|
||||
while(1)
|
||||
{
|
||||
select
|
||||
{
|
||||
case t when timerafter(start_time + INVALID_DELAY) :> void:
|
||||
|
||||
/* Go into full speed mode: XcvrSelect and Term Select (and suspend) high */
|
||||
XUD_HAL_EnterMode_PeripheralFullSpeed();
|
||||
|
||||
/* Wait for end of SE0 */
|
||||
while(1)
|
||||
{
|
||||
/* TODO Use a timer to save some juice...*/
|
||||
#if !defined(__XS2A__)
|
||||
unsigned dp, dm;
|
||||
flag0_port :> dm;
|
||||
flag1_port :> dp;
|
||||
|
||||
if(dp || dm)
|
||||
{
|
||||
/* SE0 gone, return 0 to indicate FULL SPEED */
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
flag2_port :> tmp;
|
||||
|
||||
if(!tmp)
|
||||
{
|
||||
/* SE0 gone, return 0 to indicate FULL SPEED */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if(pwrConfig == XUD_PWR_SELF)
|
||||
{
|
||||
if(!XUD_HAL_GetVBusState())
|
||||
{
|
||||
XUD_HAL_EnterMode_TristateDrivers();
|
||||
return -1; // VBUS gone, handshake fails completely.
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#if !defined(__XS2A__)
|
||||
// Note, J and K definitions are reversed in XS3A
|
||||
#define j_port flag1_port
|
||||
#define k_port flag0_port
|
||||
#else
|
||||
#define k_port flag1_port
|
||||
#define j_port flag0_port
|
||||
#endif
|
||||
case detecting_k => k_port when pinseq(1):> void @ tx: // K Chirp
|
||||
k_port @ tx + T_FILT_ticks :> tmp;
|
||||
if (tmp)
|
||||
{
|
||||
detecting_k = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case !detecting_k => j_port when pinseq(1) :> void @ tx: // J Chirp
|
||||
j_port @ tx + T_FILT_ticks :> tmp;
|
||||
if (tmp == 1)
|
||||
{
|
||||
chirpCount++; // Seen an extra K-J pair
|
||||
detecting_k = 1;
|
||||
|
||||
if (chirpCount == 3)
|
||||
{
|
||||
/* Three pairs of KJ received. Enter high-speed mode */
|
||||
XUD_HAL_EnterMode_PeripheralHighSpeed();
|
||||
|
||||
// Wait for SE0 (TODO consume other chirps?)
|
||||
#if !defined(__XS2A__)
|
||||
// TODO ideally dont use a polling loop here
|
||||
while (XUD_HAL_GetLineState() != XUD_LINESTATE_SE0);
|
||||
#else
|
||||
flag2_port when pinseq(1) :> tmp;
|
||||
#endif
|
||||
|
||||
/* Return 1 to indicate successful HS handshake*/
|
||||
return 1;
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Unreachable
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
11
lib_xud/lib_xud/src/core/XUD_HAL.c
Normal file
11
lib_xud/lib_xud/src/core/XUD_HAL.c
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2019-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
/* See XUD_HAL.xc */
|
||||
unsigned int XUD_HAL_GetVBusState_(void);
|
||||
unsigned int XUD_HAL_GetVBusState(void) __attribute__((weak));
|
||||
|
||||
unsigned int XUD_HAL_GetVBusState(void)
|
||||
{
|
||||
return XUD_HAL_GetVBusState_();
|
||||
}
|
||||
95
lib_xud/lib_xud/src/core/XUD_HAL.h
Normal file
95
lib_xud/lib_xud/src/core/XUD_HAL.h
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright 2019-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
/**
|
||||
* @file XUD_HAL.h
|
||||
* \brief USB HAL Layer
|
||||
**/
|
||||
|
||||
#include <xccompat.h>
|
||||
#include "xud.h"
|
||||
#include <platform.h>
|
||||
|
||||
#define USB_TILE_REF usb_tile
|
||||
|
||||
#if !defined(__XS2A__)
|
||||
#include <xs1.h>
|
||||
// TODO should be properly in HAL
|
||||
unsigned XtlSelFromMhz(unsigned m);
|
||||
#else
|
||||
#include "XUD_USBTile_Support.h"
|
||||
#include "xs1_to_glx.h"
|
||||
#include "xs2_su_registers.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \enum XUD_LineState_t
|
||||
* \brief USB Line States
|
||||
*/
|
||||
typedef enum XUD_LineState_t
|
||||
{
|
||||
XUD_LINESTATE_SE0 = 0, /**< SE0 State */
|
||||
XUD_LINESTATE_HS_J_FS_K = 1,/**< J/K State */
|
||||
XUD_LINESTATE_HS_K_FS_J = 2,/**< K/J State */
|
||||
XUD_LINESTATE_SE1 = 3 /**< Invalid bus state - both lines high **/
|
||||
} XUD_LineState_t;
|
||||
|
||||
void XUD_HAL_EnterMode_PeripheralChirp();
|
||||
void XUD_HAL_EnterMode_PeripheralFullSpeed();
|
||||
void XUD_HAL_EnterMode_PeripheralHighSpeed();
|
||||
#ifdef __XS2A__
|
||||
/* Special case for __XS2A__ where writing to USB register is relatively slow */
|
||||
void XUD_HAL_EnterMode_PeripheralHighSpeed_Start();
|
||||
void XUD_HAL_EnterMode_PeripheralHighSpeed_Complete();
|
||||
#endif
|
||||
void XUD_HAL_EnterMode_PeripheralTestJTestK();
|
||||
void XUD_HAL_EnterMode_TristateDrivers();
|
||||
|
||||
/**
|
||||
* \brief Get current linestate status
|
||||
* \return XUD_LineState_t representing current line status
|
||||
**/
|
||||
XUD_LineState_t XUD_HAL_GetLineState();
|
||||
|
||||
/**
|
||||
* \brief Wait for a change in linestate and return, or timeout
|
||||
* \param Reference to current linestate (updated with new linestate
|
||||
* \return 1 for timed out, otherwise 0
|
||||
**/
|
||||
unsigned XUD_HAL_WaitForLineStateChange(REFERENCE_PARAM(XUD_LineState_t, currentLs), unsigned timeout);
|
||||
|
||||
/**
|
||||
* \brief HAL function to set xCORE into signalling mode
|
||||
* (as opposed to "data transfer" mode)
|
||||
*
|
||||
* TODO Should this be combined with EnterMode_PeripheralChirp()?
|
||||
**/
|
||||
void XUD_HAL_Mode_Signalling();
|
||||
|
||||
/**
|
||||
* \brief HAL function to set xCORE into data transfer mode
|
||||
* (as opposed to "signalling" mode )
|
||||
*
|
||||
* TODO Should this be combined with EnterMode_PeripheralHigh/FullSpeed()?
|
||||
**/
|
||||
void XUD_HAL_Mode_DataTransfer();
|
||||
|
||||
/**
|
||||
* \brief HAL function to set xCORE to correct USB device address
|
||||
* \param address The new address
|
||||
* \return void
|
||||
**/
|
||||
void XUD_HAL_SetDeviceAddress(unsigned char address);
|
||||
|
||||
/**
|
||||
* \brief Enable USB funtionality in the device
|
||||
**/
|
||||
void XUD_HAL_EnableUsb(unsigned pwrConfig);
|
||||
|
||||
/**
|
||||
* \brief HAL funtion to get state of VBUS line, if any
|
||||
* \param none
|
||||
* \return unsigned int non-zero if VBUS asserted, zero otherwise
|
||||
**/
|
||||
unsigned int XUD_HAL_GetVBusState(void);
|
||||
|
||||
451
lib_xud/lib_xud/src/core/XUD_HAL.xc
Normal file
451
lib_xud/lib_xud/src/core/XUD_HAL.xc
Normal file
@@ -0,0 +1,451 @@
|
||||
// Copyright 2019-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include <xs1.h>
|
||||
#include "xud.h"
|
||||
|
||||
#include "XUD_HAL.h"
|
||||
|
||||
#ifdef __XS2A__
|
||||
#include "xs1_to_glx.h"
|
||||
#include "xs2_su_registers.h"
|
||||
#include "XUD_USBTile_Support.h"
|
||||
extern in port flag0_port;
|
||||
extern in port flag1_port;
|
||||
extern in port flag2_port;
|
||||
extern buffered in port:32 p_usb_clk;
|
||||
#else
|
||||
extern in port flag0_port; /* For XS3: RXA or DP */
|
||||
extern in port flag1_port; /* For XS3: RXE or DM */
|
||||
extern buffered in port:32 p_usb_clk;
|
||||
void XUD_SetCrcTableAddr(unsigned addr);
|
||||
unsigned XtlSelFromMhz(unsigned m)
|
||||
{ // NOCOVER
|
||||
switch(m) //NOCOVER
|
||||
{
|
||||
case 10:
|
||||
return 0b000;
|
||||
case 12:
|
||||
return 0b001;
|
||||
case 25:
|
||||
return 0b010;
|
||||
case 30:
|
||||
return 0b011;
|
||||
case 19: /*.2*/
|
||||
return 0b100;
|
||||
case 24:
|
||||
return 0b101;
|
||||
case 27:
|
||||
return 0b110;
|
||||
case 40:
|
||||
return 0b111;
|
||||
default:
|
||||
/* Panic */
|
||||
while(1); //NOCOVER
|
||||
break;
|
||||
}
|
||||
|
||||
return 0b000;
|
||||
}
|
||||
#endif
|
||||
extern clock rx_usb_clk;
|
||||
|
||||
unsigned int XUD_EnableUsbPortMux();
|
||||
|
||||
void XUD_HAL_EnableUsb(unsigned pwrConfig)
|
||||
{
|
||||
/* For xCORE-200 enable USB port muxing before enabling phy etc */
|
||||
XUD_EnableUsbPortMux(); //setps(XS1_PS_XCORE_CTRL0, UIFM_MODE);
|
||||
|
||||
#ifndef XUD_SIM_XSIM
|
||||
|
||||
#ifdef __XS2A__
|
||||
/* Enable the USB clock */
|
||||
write_sswitch_reg(get_tile_id(USB_TILE_REF), XS1_SU_CFG_RST_MISC_NUM, ( 1 << XS1_SU_CFG_USB_CLK_EN_SHIFT));
|
||||
|
||||
/* Now reset the phy */
|
||||
write_periph_word(USB_TILE_REF, XS1_GLX_PER_UIFM_CHANEND_NUM, XS1_GLX_PER_UIFM_PHY_CONTROL_NUM, 0); //(0<<XS1_UIFM_PHY_CONTROL_FORCERESET));
|
||||
|
||||
/* Keep usb clock active, enter active mode */
|
||||
write_sswitch_reg(get_tile_id(USB_TILE_REF), XS1_SU_CFG_RST_MISC_NUM, (1 << XS1_SU_CFG_USB_CLK_EN_SHIFT) | (1<<XS1_SU_CFG_USB_EN_SHIFT) );
|
||||
|
||||
/* Clear OTG control reg - incase we were running as host previously.. */
|
||||
write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_OTG_CONTROL_NUM, 0);
|
||||
#else
|
||||
unsigned d = 0;
|
||||
|
||||
/* Enable wphy and take out of reset */
|
||||
read_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_PHY_CFG2_NUM, d);
|
||||
d = XS1_USB_PHY_CFG2_PONRST_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG2_UTMI_RESET_SET(d, 0);
|
||||
write_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_PHY_CFG2_NUM, d);
|
||||
|
||||
/* Setup clocking appropriately */
|
||||
read_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_PHY_CFG0_NUM, d);
|
||||
unsigned xtlselVal = XtlSelFromMhz(XUD_OSC_MHZ);
|
||||
d = XS1_USB_PHY_CFG0_XTLSEL_SET(d, xtlselVal);
|
||||
write_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_PHY_CFG0_NUM, d);
|
||||
#endif
|
||||
|
||||
/* Wait for USB clock (typically 1ms after reset) */
|
||||
p_usb_clk when pinseq(1) :> int _;
|
||||
p_usb_clk when pinseq(0) :> int _;
|
||||
p_usb_clk when pinseq(1) :> int _;
|
||||
p_usb_clk when pinseq(0) :> int _;
|
||||
|
||||
#ifdef __XS2A__
|
||||
/* Some extra settings are required for proper operation on XS2A */
|
||||
#define XS1_UIFM_USB_PHY_EXT_CTRL_REG 0x50
|
||||
#define XS1_UIFM_USB_PHY_EXT_CTRL_VBUSVLDEXT_MASK 0x4
|
||||
|
||||
/* Remove requirement for VBUS in bus-powered mode */
|
||||
if(pwrConfig == XUD_PWR_BUS)
|
||||
{
|
||||
write_periph_word(USB_TILE_REF, XS1_GLX_PER_UIFM_CHANEND_NUM, XS1_UIFM_USB_PHY_EXT_CTRL_REG, XS1_UIFM_USB_PHY_EXT_CTRL_VBUSVLDEXTSEL_MASK | XS1_UIFM_USB_PHY_EXT_CTRL_VBUSVLDEXT_MASK);
|
||||
}
|
||||
|
||||
#define PHYTUNEREGVAL 0x0093B264
|
||||
#define XS1_UIFM_USB_PHY_TUNE_REG 0x4c
|
||||
/* Phy Tuning parameters */
|
||||
/* OTG TUNE: 3b'100
|
||||
* TXFSLSTUNE: 4b'1001
|
||||
* TXVREFTUNE:4b'1001 -- +1.25% adjustment in HS DC voltage level
|
||||
* BIASTUNE: 1b'0
|
||||
* COMDISTUNE:3b'011 -- -1.5% adjustment from default (disconnect threshold adjustment)
|
||||
* SQRXTUNE:3b'010 -- +5% adjustment from default (Squelch Threshold)
|
||||
* TXRISETUNE: 1b'0
|
||||
* TXPREEMPHASISTUNE:1b'1 -- enabled (default is disabled)
|
||||
* TXHSXVTUNE: 2b'11
|
||||
*/
|
||||
write_periph_word(USB_TILE_REF, XS1_GLX_PER_UIFM_CHANEND_NUM, XS1_UIFM_USB_PHY_TUNE_REG, PHYTUNEREGVAL);
|
||||
|
||||
write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_CONTROL_NUM, (1<<XS1_SU_UIFM_IFM_CONTROL_DECODELINESTATE_SHIFT));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void XUD_HAL_EnterMode_PeripheralFullSpeed()
|
||||
{
|
||||
#ifdef __XS2A__
|
||||
write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM,
|
||||
(1<<XS1_SU_UIFM_FUNC_CONTROL_XCVRSELECT_SHIFT) | (1<<XS1_SU_UIFM_FUNC_CONTROL_TERMSELECT_SHIFT));
|
||||
#else
|
||||
unsigned d = 0;
|
||||
d = XS1_USB_PHY_CFG0_UTMI_XCVRSELECT_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_UTMI_TERMSELECT_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_UTMI_OPMODE_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_DMPULLDOWN_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_DPPULLDOWN_SET(d, 0);
|
||||
|
||||
d = XS1_USB_PHY_CFG0_UTMI_SUSPENDM_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_TXBITSTUFF_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_PLL_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_LPM_ALIVE_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_IDPAD_EN_SET(d, 0);
|
||||
|
||||
unsigned xtlSelVal = XtlSelFromMhz(XUD_OSC_MHZ);
|
||||
d = XS1_USB_PHY_CFG0_XTLSEL_SET(d, xtlSelVal);
|
||||
|
||||
write_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_PHY_CFG0_NUM, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
void XUD_HAL_EnterMode_PeripheralChirp()
|
||||
{
|
||||
#ifdef __XS2A__
|
||||
write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM, 0b1010);
|
||||
#else
|
||||
unsigned d = 0;
|
||||
d = XS1_USB_PHY_CFG0_UTMI_XCVRSELECT_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_UTMI_TERMSELECT_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_UTMI_OPMODE_SET(d, 0b10);
|
||||
d = XS1_USB_PHY_CFG0_DMPULLDOWN_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_DPPULLDOWN_SET(d, 0);
|
||||
|
||||
d = XS1_USB_PHY_CFG0_UTMI_SUSPENDM_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_TXBITSTUFF_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_PLL_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_LPM_ALIVE_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_IDPAD_EN_SET(d, 0);
|
||||
|
||||
unsigned xtlselVal = XtlSelFromMhz(XUD_OSC_MHZ);
|
||||
d = XS1_USB_PHY_CFG0_XTLSEL_SET(d, xtlselVal);
|
||||
write_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_PHY_CFG0_NUM, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
void XUD_HAL_EnterMode_PeripheralHighSpeed()
|
||||
{
|
||||
#ifdef __XS2A__
|
||||
write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM, 0b0000);
|
||||
#else
|
||||
unsigned d = 0;
|
||||
d = XS1_USB_PHY_CFG0_UTMI_XCVRSELECT_SET(d, 0); // HS
|
||||
d = XS1_USB_PHY_CFG0_UTMI_TERMSELECT_SET(d, 0); // HS
|
||||
d = XS1_USB_PHY_CFG0_UTMI_OPMODE_SET(d, 0b00); // Normal operation
|
||||
d = XS1_USB_PHY_CFG0_DMPULLDOWN_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_DPPULLDOWN_SET(d, 0);
|
||||
|
||||
d = XS1_USB_PHY_CFG0_UTMI_SUSPENDM_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_TXBITSTUFF_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_PLL_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_LPM_ALIVE_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_IDPAD_EN_SET(d, 0);
|
||||
|
||||
unsigned xtlselVal = XtlSelFromMhz(XUD_OSC_MHZ);
|
||||
d = XS1_USB_PHY_CFG0_XTLSEL_SET(d, xtlselVal);
|
||||
write_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_PHY_CFG0_NUM, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __XS2A__
|
||||
/* Special case for XSA when exiting resume back to HS - breaks standard HAL API */
|
||||
unsafe chanend c;
|
||||
void XUD_HAL_EnterMode_PeripheralHighSpeed_Start()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
asm("getr %0, 2" : "=r"(c)); // XS1_RES_TYPE_CHANEND=2 (no inline assembly immediate operands in xC)
|
||||
write_periph_word_two_part_start((chanend)c, USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM, 0);
|
||||
}
|
||||
}
|
||||
void XUD_HAL_EnterMode_PeripheralHighSpeed_Complete()
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
write_periph_word_two_part_end((chanend)c, 0);
|
||||
asm("freer res[%0]" :: "r"(c));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void XUD_HAL_EnterMode_PeripheralTestJTestK()
|
||||
{ // NOCOVER
|
||||
#ifdef __XS2A__
|
||||
write_periph_word(USB_TILE_REF, XS1_GLX_PER_UIFM_CHANEND_NUM, XS1_GLX_PER_UIFM_FUNC_CONTROL_NUM, 0b1000);
|
||||
#else
|
||||
/* From ULPI Specification Revsion 1.1, table 41
|
||||
* XcvrSelect: 00b
|
||||
* TermSelect: 0b
|
||||
* OpMode: 10b
|
||||
* DpPullDown 0b
|
||||
* DmPullDown: 0b
|
||||
*/
|
||||
unsigned d = 0;
|
||||
d = XS1_USB_PHY_CFG0_UTMI_XCVRSELECT_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_UTMI_TERMSELECT_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_UTMI_OPMODE_SET(d, 2);
|
||||
d = XS1_USB_PHY_CFG0_DMPULLDOWN_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_DPPULLDOWN_SET(d, 0);
|
||||
|
||||
d = XS1_USB_PHY_CFG0_UTMI_SUSPENDM_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_TXBITSTUFF_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_PLL_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_LPM_ALIVE_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_IDPAD_EN_SET(d, 0);
|
||||
|
||||
unsigned xtlSelVal = XtlSelFromMhz(XUD_OSC_MHZ);
|
||||
d = XS1_USB_PHY_CFG0_XTLSEL_SET(d, xtlSelVal);
|
||||
|
||||
write_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_PHY_CFG0_NUM, d); // NOCOVER
|
||||
#endif
|
||||
}
|
||||
|
||||
void XUD_HAL_EnterMode_TristateDrivers()
|
||||
{ // NOCOVER
|
||||
#ifdef __XS2A__
|
||||
write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM, 4);
|
||||
#else
|
||||
/* From ULPI Specification Revsion 1.1, table 41
|
||||
* XcvrSelect: XXb
|
||||
* TermSelect: Xb
|
||||
* OpMode: 01b
|
||||
* DpPullDown Xb
|
||||
* DmPullDown: Xb
|
||||
*/
|
||||
unsigned d = 0;
|
||||
d = XS1_USB_PHY_CFG0_UTMI_XCVRSELECT_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_UTMI_TERMSELECT_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_UTMI_OPMODE_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_DMPULLDOWN_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_DPPULLDOWN_SET(d, 0);
|
||||
|
||||
d = XS1_USB_PHY_CFG0_UTMI_SUSPENDM_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_TXBITSTUFF_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_PLL_EN_SET(d, 1);
|
||||
d = XS1_USB_PHY_CFG0_LPM_ALIVE_SET(d, 0);
|
||||
d = XS1_USB_PHY_CFG0_IDPAD_EN_SET(d, 0);
|
||||
|
||||
unsigned xtlSelVal = XtlSelFromMhz(XUD_OSC_MHZ);
|
||||
d = XS1_USB_PHY_CFG0_XTLSEL_SET(d, xtlSelVal);
|
||||
|
||||
write_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_PHY_CFG0_NUM, d); //NOCOVER
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void XUD_HAL_Mode_Signalling()
|
||||
{
|
||||
/* Reset port to use XS1_CLKBLK_REF (from rx_usb_clk) */
|
||||
set_port_use_on(flag1_port);
|
||||
|
||||
#ifdef __XS2A__
|
||||
/* For XS2 we invert VALID_TOKEN port for data-transfer mode, so undo this for signalling */
|
||||
set_port_no_inv(flag2_port);
|
||||
|
||||
write_periph_word(USB_TILE_REF, XS1_GLX_PER_UIFM_CHANEND_NUM, XS1_GLX_PER_UIFM_MASK_NUM,
|
||||
((1<<XS1_UIFM_IFM_FLAGS_SE0_SHIFT)<<16)
|
||||
| ((1<<XS1_UIFM_IFM_FLAGS_K_SHIFT)<<8)
|
||||
| (1 << XS1_UIFM_IFM_FLAGS_J_SHIFT));
|
||||
#else
|
||||
unsigned d = 0;
|
||||
d = XS1_USB_SHIM_CFG_FLAG_MODE_SET(d, 1);
|
||||
write_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_SHIM_CFG_NUM, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
void XUD_HAL_Mode_DataTransfer()
|
||||
{
|
||||
configure_in_port(flag1_port, rx_usb_clk);
|
||||
set_pad_delay(flag1_port, 2);
|
||||
|
||||
#ifdef __XS2A__
|
||||
/* Set UIFM to CHECK TOKENS mode and enable LINESTATE_DECODE
|
||||
* NOTE: Need to do this every iteration since CHKTOK would break power signaling */
|
||||
write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_CONTROL_NUM,
|
||||
(1<<XS1_SU_UIFM_IFM_CONTROL_DOTOKENS_SHIFT)
|
||||
| (1<< XS1_SU_UIFM_IFM_CONTROL_CHECKTOKENS_SHIFT)
|
||||
| (1<< XS1_SU_UIFM_IFM_CONTROL_DECODELINESTATE_SHIFT)
|
||||
| (1<< XS1_SU_UIFM_IFM_CONTROL_SOFISTOKEN_SHIFT));
|
||||
|
||||
write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_MASK_NUM,
|
||||
((1<<XS1_SU_UIFM_IFM_FLAGS_RXERROR_SHIFT)
|
||||
| ((1<<XS1_SU_UIFM_IFM_FLAGS_RXACTIVE_SHIFT)<<8)
|
||||
| ((1<<XS1_SU_UIFM_IFM_FLAGS_NEWTOKEN_SHIFT)<<16)));
|
||||
|
||||
/* Flag 2 (VALID_TOKEN) port is inverted as an optimisation (having a zero is useful) */
|
||||
set_port_inv(flag2_port);
|
||||
#else
|
||||
unsigned d = 0;
|
||||
d = XS1_USB_SHIM_CFG_FLAG_MODE_SET(d, 0);
|
||||
write_sswitch_reg(get_local_tile_id(), XS1_SSWITCH_USB_SHIM_CFG_NUM, d);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* In full-speed and low-speed mode, LineState(0) always reflects DP and LineState(1) reflects DM */
|
||||
/* Note, this port ordering is the opposite of what might be expected - but linestate is swapped in the USB shim */
|
||||
#define dp_port flag0_port // DP: LINESTATE[0]
|
||||
#define dm_port flag1_port // DM: LINESTATE[1]
|
||||
|
||||
{unsigned, unsigned} LineStateToLines(XUD_LineState_t ls)
|
||||
{
|
||||
return {ls & 1, (ls >> 1) & 1};
|
||||
}
|
||||
|
||||
static inline XUD_LineState_t LinesToLineState(unsigned dp, unsigned dm)
|
||||
{
|
||||
return (XUD_LineState_t) (dp & 1) | ((dm & 1)<< 1);
|
||||
}
|
||||
|
||||
/* TODO pass structure */
|
||||
XUD_LineState_t XUD_HAL_GetLineState(/*XUD_HAL_t &xudHal*/)
|
||||
{
|
||||
#ifdef __XS2A__
|
||||
unsigned j, k, se0;
|
||||
flag0_port :> j;
|
||||
flag1_port :> k;
|
||||
flag2_port :> se0;
|
||||
|
||||
if(j)
|
||||
return XUD_LINESTATE_HS_J_FS_K;
|
||||
if(k)
|
||||
return XUD_LINESTATE_HS_K_FS_J;
|
||||
if(se0)
|
||||
return XUD_LINESTATE_SE0;
|
||||
|
||||
return XUD_LINESTATE_SE1;
|
||||
#else
|
||||
unsigned dp, dm;
|
||||
dp_port :> dp;
|
||||
dm_port :> dm;
|
||||
return LinesToLineState(dp, dm);
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO debounce?
|
||||
unsigned XUD_HAL_WaitForLineStateChange(XUD_LineState_t ¤tLs, unsigned timeout)
|
||||
{
|
||||
unsigned time;
|
||||
timer t;
|
||||
|
||||
if (timeout != null)
|
||||
t :> time;
|
||||
|
||||
#ifdef __XS2A__
|
||||
unsigned se0 = currentLs == XUD_LINESTATE_SE0;
|
||||
unsigned j = currentLs == XUD_LINESTATE_HS_J_FS_K;
|
||||
unsigned k = currentLs == XUD_LINESTATE_HS_K_FS_J;
|
||||
|
||||
/* Wait for a change on any flag port */
|
||||
select
|
||||
{
|
||||
case flag0_port when pinsneq(j) :> void:
|
||||
break;
|
||||
case flag1_port when pinsneq(k) :> void:
|
||||
break;
|
||||
case flag2_port when pinsneq(se0) :> void:
|
||||
break;
|
||||
case timeout != null => t when timerafter(time + timeout) :> int _:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Read current line state - two lines may have change e.g k/j to SE0 */
|
||||
currentLs = XUD_HAL_GetLineState();
|
||||
return 0;
|
||||
#else
|
||||
unsigned dp, dm;
|
||||
|
||||
/* Look up line values from linestate */
|
||||
{dp, dm} = LineStateToLines(currentLs);
|
||||
|
||||
/* Wait for change */
|
||||
select
|
||||
{
|
||||
case dp_port when pinsneq(dp) :> dp:
|
||||
dm_port :> dm; //Both might have changed!
|
||||
break;
|
||||
case dm_port when pinsneq(dm) :> dm:
|
||||
dp_port :> dp; //Both might have changed!
|
||||
break;
|
||||
case timeout != null => t when timerafter(time + timeout) :> int _:
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return new linestate */
|
||||
currentLs = LinesToLineState(dp, dm);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void XUD_HAL_SetDeviceAddress(unsigned char address)
|
||||
{
|
||||
#ifdef __XS2A__
|
||||
write_periph_word(USB_TILE_REF, XS1_SU_PER_UIFM_CHANEND_NUM, XS1_SU_PER_UIFM_DEVICE_ADDRESS_NUM, address);
|
||||
#else
|
||||
XUD_SetCrcTableAddr(address);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Note, this is called from XUA_HAL.c (weak symbol) */
|
||||
unsigned int XUD_HAL_GetVBusState_(void)
|
||||
{
|
||||
#ifdef __XS2A__
|
||||
unsigned int x;
|
||||
read_periph_word(USB_TILE_REF, XS1_GLX_PER_UIFM_CHANEND_NUM, XS1_GLX_PER_UIFM_OTG_FLAGS_NUM, x);
|
||||
return x & (1 << XS1_UIFM_OTG_FLAGS_SESSVLDB_SHIFT);
|
||||
#else
|
||||
return 1u;
|
||||
#endif
|
||||
}
|
||||
|
||||
380
lib_xud/lib_xud/src/core/XUD_IoLoop.S
Normal file
380
lib_xud/lib_xud/src/core/XUD_IoLoop.S
Normal file
@@ -0,0 +1,380 @@
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
// XUD_IoLoop.S
|
||||
// Main USB interfacing loop
|
||||
//
|
||||
// XMOS Ltd
|
||||
// Ross Owen
|
||||
//
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
#include <xs1.h>
|
||||
#include "xud.h"
|
||||
#include "XUD_USB_Defines.h"
|
||||
#include "XUD_TimingDefines.h"
|
||||
#include "XUD_AlignmentDefines.h"
|
||||
|
||||
.section .cp.const4,"aMc",@progbits,4
|
||||
.cc_top suspendTimeout.data
|
||||
.align 4
|
||||
suspendTimeout:
|
||||
.long SUSPEND_TIMEOUT_ticks
|
||||
.cc_bottom suspendTimeout.data
|
||||
.text
|
||||
|
||||
.section .cp.const4,"aMc",@progbits,4
|
||||
.cc_top suspend_t_wtwrsths.data
|
||||
.align 4
|
||||
suspend_t_wtwrsths:
|
||||
.long SUSPEND_T_WTWRSTHS_ticks
|
||||
.cc_bottom suspend_t_wtwrsths.data
|
||||
.text
|
||||
|
||||
|
||||
#define STACK_EXTEND 32
|
||||
|
||||
// Stack frame:
|
||||
// 0
|
||||
// 1..7: : Reg save
|
||||
// 8 : Unused
|
||||
#define STACK_OUT_TIMER (9) // Used for out data timeout
|
||||
#define STACK_RXA_PORT (10) // RXA_port
|
||||
// 11 : Unused
|
||||
// 12 : Unused
|
||||
#define STACK_SUSPEND_TIMEOUT (13)
|
||||
#define STACK_SUSPEND_TIMER (14)
|
||||
#define STACK_RXE_PORT (15)
|
||||
#define STACK_RXCRC_TAIL0 (16)
|
||||
#define STACK_RXCRC_TAIL1 (17)
|
||||
#define STACK_RXCRC_TAIL2 (18)
|
||||
#define STACK_RXCRC_TAIL3 (19)
|
||||
#define STACK_TXCRC_INIT (20)
|
||||
#define STACK_RXCRC_INIT (21)
|
||||
#define STACK_PIDJUMPTABLE (22)
|
||||
#define STACK_PIDJUMPTABLE_RXDATA (23)
|
||||
#define STACK_CRC5TABLE_ADDR (24)
|
||||
|
||||
// Params
|
||||
#define STACK_VTOK_PORT (STACK_EXTEND + 1)
|
||||
#define STACK_EPTYPES_OUT (STACK_EXTEND + 2) // STACK_EXTEND + 6 : EP Type table (out)
|
||||
#define STACK_EPTYPES_IN (STACK_EXTEND + 3) // EP Type table (in)
|
||||
#define STACK_EPCHANS (STACK_EXTEND + 4)
|
||||
#define SP_EPCOUNT (STACK_EXTEND + 5)
|
||||
#define STACK_SOFCHAN (STACK_EXTEND + 6)
|
||||
|
||||
#ifndef XUD_TEST_MODE_SUPPORT_DISABLED
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// void UsbTestModeHandler()
|
||||
// Interrupt handler for entering USB Test mode
|
||||
// ASM level for low-level interrupt handling.
|
||||
.globl UsbTestModeHandler_asm.nstackwords
|
||||
.linkset UsbTestModeHandler_asm.nstackwords, 0
|
||||
.globl UsbTestModeHandler_asm
|
||||
.type UsbTestModeHandler_asm, @function
|
||||
.text
|
||||
.cc_top UsbTestModeHandler_asm.func, UsbTestModeHandler_asm
|
||||
.issue_mode single
|
||||
.align FUNCTION_ALIGNMENT
|
||||
UsbTestModeHandler_asm:
|
||||
ENTSP_lu6 0
|
||||
clrsr 0x18
|
||||
clrsr 0x2
|
||||
clre // clear all events
|
||||
get r11, ed
|
||||
chkct res[r11], XS1_CT_END
|
||||
outct res[r11], XS1_CT_END
|
||||
in r0, res[r11]
|
||||
chkct res[r11], XS1_CT_END
|
||||
outct res[r11], XS1_CT_END
|
||||
bf r0, Return // Special case for Exit
|
||||
bl XUD_UsbTestModeHandler
|
||||
retsp 0
|
||||
.cc_bottom UsbTestModeHandler_asm.func
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// void ResetIntHandler()
|
||||
// Interupt handler for reset/suspend timer
|
||||
.globl ResetIntHandler.nstackwords
|
||||
.linkset ResetIntHandler.nstackwords, 0
|
||||
.globl ResetIntHandler
|
||||
.type ResetIntHandler, @function
|
||||
.text
|
||||
.cc_top ResetIntHandler.func, ResetIntHandler
|
||||
.issue_mode dual
|
||||
.align FUNCTION_ALIGNMENT
|
||||
ResetIntHandler:
|
||||
DUALENTSP_lu6 0
|
||||
clrsr 0x18 // Clear InInterrupt bit (and InKernel)
|
||||
clrsr 0x3 // Clear thread events and interrupts
|
||||
|
||||
get r11, ed // Get timer resource ID
|
||||
setc res[r11], XS1_SETC_IE_MODE_EVENT // Set IE mode back to events
|
||||
|
||||
clre // Clear all events
|
||||
|
||||
ldw r10, dp[SavedSp] // Restore stack pointer
|
||||
set sp, r10
|
||||
|
||||
ldc r0, 1 // Load non-zero (zero is kill)
|
||||
bu Return
|
||||
|
||||
.cc_bottom ResetIntHandler.func
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// void XUD_LLD_IoLoop(in port rxd_port, in port rxa_port, out port txd_port, in port rxe_port, in port flag0_port,
|
||||
// chanend c_out, chanend c_in, chanend c_con_io, chanend c_ctl_buf,
|
||||
// XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[], XUD_chan epChans[], epCount, c_sof) ;
|
||||
.globl XUD_LLD_IoLoop.nstackwords
|
||||
.globl XUD_LLD_IoLoop.maxthreads
|
||||
.globl XUD_LLD_IoLoop.maxtimers
|
||||
.globl XUD_LLD_IoLoop.maxchanends
|
||||
|
||||
.linkset XUD_LLD_IoLoop.nstackwords, STACK_EXTEND
|
||||
.linkset XUD_LLD_IoLoop.maxchanends, 0
|
||||
.linkset XUD_LLD_IoLoop.maxtimers, 2
|
||||
.linkset XUD_LLD_IoLoop.maxthreads, 0
|
||||
|
||||
.globl XUD_LLD_IoLoop
|
||||
.type XUD_LLD_IoLoop, @function
|
||||
.text
|
||||
.cc_top XUD_LLD_IoLoop.func, XUD_LLD_IoLoop
|
||||
|
||||
.issue_mode dual
|
||||
// Note, included here so in same elimination blocks to avoid long jumps
|
||||
#include "./included/XUD_Token_In_DI.S"
|
||||
#include "./included/XUD_Token_Setup_DI.S"
|
||||
#include "./included/XUD_Token_Out_DI.S"
|
||||
#include "./included/XUD_RxData.S"
|
||||
#include "./included/XUD_Token_Ping.S"
|
||||
#include "./included/XUD_Token_SOF.S"
|
||||
|
||||
BadCrcAddr:
|
||||
// zext r11, 8
|
||||
// ldc r10, PIDn_SOF
|
||||
// eq r11, r11, r10
|
||||
//ecallt r11
|
||||
//bt r11, Pid_Sof_NoChan // TODO we should really CRC SOFs
|
||||
ldw r11, sp[STACK_RXA_PORT]
|
||||
|
||||
waitforRXALow0:
|
||||
in r10, res[r11]
|
||||
bt r10, waitforRXALow0
|
||||
setc res[RXD], XS1_SETC_RUN_CLRBUF
|
||||
bu Loop_BadPid
|
||||
|
||||
.align FUNCTION_ALIGNMENT
|
||||
XUD_LLD_IoLoop:
|
||||
DUALENTSP_lu6 STACK_EXTEND
|
||||
stw r4, sp[1]
|
||||
stw r5, sp[2]
|
||||
stw r6, sp[3]
|
||||
stw r7, sp[4]
|
||||
stw r8, sp[5]
|
||||
stw r9, sp[6]
|
||||
stw r10, sp[7]
|
||||
PortsOnStack: // Put ports on stack (loads therefore short insts)
|
||||
stw r1, sp[STACK_RXA_PORT]
|
||||
stw r3, sp[STACK_RXE_PORT]
|
||||
|
||||
SaveStackPointer:
|
||||
ldaw r11, sp[0]
|
||||
stw r11, dp[SavedSp]
|
||||
|
||||
|
||||
ldw r11, cp[suspendTimeout]
|
||||
stw r11, sp[STACK_SUSPEND_TIMEOUT]
|
||||
|
||||
ConfigRxDEventVector: // Configure event on RXD port for receiveing a handshake after Tx
|
||||
setc res[RXD], XS1_SETC_IE_MODE_EVENT
|
||||
ldap r11, TxHandShakeReceived
|
||||
setv res[RXD], r11
|
||||
|
||||
ConfigRxA: // Configure a event on RXA going low, used during packet reception
|
||||
setc res[RXA], XS1_SETC_COND_EQ
|
||||
setc res[RXA], XS1_SETC_IE_MODE_EVENT
|
||||
ldc r11, 0
|
||||
setd res[RXA], r11
|
||||
ldap r11, RxALow
|
||||
setv res[RXA], r11
|
||||
eeu res[RXA]
|
||||
|
||||
ConfigValidToken:
|
||||
#ifdef __XS2A__
|
||||
ldw r10, sp[STACK_VTOK_PORT] // ValidToken is used for timing timeout period when expecting an ack after tx
|
||||
#else
|
||||
ldw r10, dp[rx_rdy] // TODO use from stack
|
||||
#endif
|
||||
setc res[r10], XS1_SETC_COND_NONE
|
||||
ldap r11, TxHandshakeTimeOut
|
||||
setv res[r10], r11
|
||||
|
||||
#ifndef XUD_TEST_MODE_SUPPORT_DISABLED
|
||||
SetupUsbTestMode:
|
||||
// Enable test mode interrupt on Endpoint 0 chanends. IN + OUT
|
||||
ldaw r9, dp[epChans0]
|
||||
ldw r10, r9[0] // Load channel 0
|
||||
|
||||
ldap r11, UsbTestModeHandler_asm
|
||||
setc res[r10], XS1_SETC_IE_MODE_INTERRUPT
|
||||
setv res[r10], r11
|
||||
eeu res[r10]
|
||||
|
||||
ldc r10, 16
|
||||
ldw r10, r9[r10] // Load channel for EP 0 in
|
||||
|
||||
setc res[r10], XS1_SETC_IE_MODE_INTERRUPT
|
||||
setv res[r10], r11
|
||||
eeu res[r10]
|
||||
#endif
|
||||
|
||||
CrcRxResidualsOnStack:
|
||||
ldc r11, 0x7000
|
||||
stw r11, sp[STACK_RXCRC_TAIL0]
|
||||
ldc r11, 0x80be
|
||||
stw r11, sp[STACK_RXCRC_TAIL1]
|
||||
ldc r11, 0x3ffe
|
||||
stw r11, sp[STACK_RXCRC_TAIL2]
|
||||
ldc r11, 0x3ffe
|
||||
stw r11, sp[STACK_RXCRC_TAIL3]
|
||||
|
||||
ldc r11, 0xf335 // CRC16 init (in)
|
||||
stw r11, sp[STACK_TXCRC_INIT]
|
||||
|
||||
ldc r11, 0x3334 // CRC16 init (out)
|
||||
stw r11, sp[STACK_RXCRC_INIT]
|
||||
|
||||
ldw r11, sp[STACK_EPCHANS]
|
||||
stw r11, dp[chanArray]
|
||||
|
||||
ConfigSofJump:
|
||||
ldw r11, sp[STACK_SOFCHAN]
|
||||
ldaw r10, dp[PidJumpTable]
|
||||
bt r11, ConfigSofJump_Done
|
||||
ldap r11, Pid_Sof_NoChan
|
||||
#ifdef __XS2A__
|
||||
stw r11, r10[5]
|
||||
#else
|
||||
ldc r9, 0xa5
|
||||
stw r11, r10[r9]
|
||||
#endif
|
||||
ConfigSofJump_Done:
|
||||
stw r10, sp[STACK_PIDJUMPTABLE]
|
||||
|
||||
ldaw r10, dp[PidJumpTable_RxData]
|
||||
stw r10, sp[STACK_PIDJUMPTABLE_RXDATA]
|
||||
|
||||
ldaw r10, dp[crc5Table_Addr]
|
||||
stw r10, sp[STACK_CRC5TABLE_ADDR]
|
||||
|
||||
|
||||
ConfigRxErrEventVector:
|
||||
setc res[r3], XS1_SETC_COND_EQ
|
||||
setc res[r3], XS1_SETC_IE_MODE_INTERRUPT
|
||||
ldap r11, Err_RxErr
|
||||
setv res[r3], r11
|
||||
ldc r11, 1
|
||||
setd res[r3], r11 // Set event cond data to 1
|
||||
eeu res[r3]
|
||||
|
||||
SetupSuspendResetTimer:
|
||||
getr r10, XS1_RES_TYPE_TIMER
|
||||
ecallf r10
|
||||
|
||||
stw r10, sp[STACK_SUSPEND_TIMER]
|
||||
|
||||
ldap r11, ResetIntHandler
|
||||
setv res[r10], r11
|
||||
|
||||
setc res[r10], XS1_SETC_COND_NONE
|
||||
in r11, res[r10] // Get current time
|
||||
ldw r9, cp[suspendTimeout]
|
||||
add r11, r11, r9
|
||||
setd res[r10], r11
|
||||
setc res[r10], XS1_SETC_COND_AFTER
|
||||
setc res[r10], XS1_SETC_IE_MODE_INTERRUPT
|
||||
eeu res[r10] // Enable events/interupts on resource
|
||||
|
||||
setc res[RXD], XS1_SETC_RUN_CLRBUF
|
||||
|
||||
clre
|
||||
setsr 0x2 // Enable thread interrupts
|
||||
bu NextToken
|
||||
|
||||
// Main IO Loop
|
||||
.align FUNCTION_ALIGNMENT
|
||||
.skip 0
|
||||
NextToken:
|
||||
ldc r9, 0xa001 // CRC16 poly, used in doRxData
|
||||
ldw r5, sp[(STACK_EXTEND+4)] // EP structures array - pointers to EP tables or 0
|
||||
|
||||
NextTokenAfterOut:
|
||||
ldc r7, 0xf335 // TX Crc init
|
||||
ldc r6, 0x3334 // CRC16 init (out) - Needs reseting after an out
|
||||
#ifdef __XS2A__
|
||||
ldw r1, sp[STACK_VTOK_PORT]
|
||||
#endif
|
||||
|
||||
Loop_BadPid:
|
||||
NextTokenAfterPing:
|
||||
setsr 1 // Enable thread events
|
||||
|
||||
#include "XUD_TokenJmp.S"
|
||||
|
||||
// Un-implemented PID list
|
||||
Pid_Reserved:
|
||||
Pid_Ack:
|
||||
Pid_NYet:
|
||||
Pid_Nyet:
|
||||
Pid_Data2:
|
||||
Pid_Split:
|
||||
Pid_Nak:
|
||||
Pid_Pre:
|
||||
Pid_Stall:
|
||||
Pid_MData:
|
||||
Pid_Datam:
|
||||
Pid_Data0:
|
||||
Pid_Data1:
|
||||
Pid_Bad: // Bad PID received, ignore
|
||||
|
||||
XUD_InvalidToken:
|
||||
ldw r10, sp[STACK_RXA_PORT] // Load RxA Port ID (r1)
|
||||
XUD_InvalidTok_waitforRXALow:
|
||||
in r11, res[r10]
|
||||
bt r11, XUD_InvalidTok_waitforRXALow
|
||||
setc res[RXD], XS1_SETC_RUN_CLRBUF
|
||||
bu Loop_BadPid // Invalid token received Ignore unknown toks
|
||||
|
||||
.align FUNCTION_ALIGNMENT
|
||||
Return:
|
||||
clre
|
||||
ldw r11, sp[STACK_SUSPEND_TIMER] // Free suspend/reset timer
|
||||
edu res[r11]
|
||||
freer res[r11]
|
||||
|
||||
ldw r11, sp[STACK_RXE_PORT] // Put RxE IE mode back to events..
|
||||
setc res[r11], XS1_SETC_COND_NONE
|
||||
edu res[r11]
|
||||
setc res[r11], XS1_SETC_IE_MODE_EVENT
|
||||
|
||||
ldw r11, sp[STACK_RXA_PORT]
|
||||
edu res[r11]
|
||||
|
||||
ldw r4, sp[1] // Register restore
|
||||
ldw r5, sp[2]
|
||||
ldw r6, sp[3]
|
||||
ldw r7, sp[4]
|
||||
ldw r8, sp[5]
|
||||
ldw r9, sp[6]
|
||||
ldw r10, sp[7]
|
||||
retsp STACK_EXTEND
|
||||
|
||||
|
||||
.cc_bottom XUD_LLD_IoLoop.func
|
||||
|
||||
|
||||
// Tables of tables...
|
||||
#include "./included/XUD_PidJumpTable.S"
|
||||
#include "./included/XUD_PidJumpTable_RxData.S"
|
||||
|
||||
616
lib_xud/lib_xud/src/core/XUD_Main.xc
Normal file
616
lib_xud/lib_xud/src/core/XUD_Main.xc
Normal file
@@ -0,0 +1,616 @@
|
||||
// Copyright 2011-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
/**
|
||||
* @file XUD_Main.xc
|
||||
* @brief XMOS USB Device (XUD) Layer
|
||||
* @author Ross Owen
|
||||
**/
|
||||
#include <xs1.h>
|
||||
#include <print.h>
|
||||
#include <xclib.h>
|
||||
#include <platform.h>
|
||||
|
||||
#include "xud.h" /* External user include file */
|
||||
#include "XUD_USB_Defines.h"
|
||||
#include "XUD_Support.h"
|
||||
|
||||
#include "XUD_DeviceAttach.h"
|
||||
#include "XUD_Signalling.h"
|
||||
#include "XUD_HAL.h"
|
||||
#include "XUD_TimingDefines.h"
|
||||
|
||||
#if (USB_MAX_NUM_EP_IN != 16)
|
||||
#error USB_MAX_NUM_EP_IN must be 16!
|
||||
#endif
|
||||
#if (USB_MAX_NUM_EP_OUT != 16)
|
||||
#error USB_MAX_NUM_EP_OUT must be 16!
|
||||
#endif
|
||||
|
||||
void XUD_UserSuspend();
|
||||
void XUD_UserResume();
|
||||
void XUD_PhyReset_User();
|
||||
|
||||
#define HS_TX_HANDSHAKE_TIMEOUT (167)
|
||||
#define FS_TX_HANDSHAKE_TIMEOUT (5000)
|
||||
|
||||
/* Global vars for current and desired USB speed */
|
||||
unsigned g_curSpeed;
|
||||
unsigned g_desSpeed;
|
||||
unsigned g_txHandshakeTimeout;
|
||||
|
||||
in port flag0_port = PORT_USB_FLAG0; /* For XS3: Mission: RXE, XS2 is configurable and set to RXE in mission mode */
|
||||
in port flag1_port = PORT_USB_FLAG1; /* For XS3: Mission: RXA, XS2 is configuratble and set to RXA in mission mode*/
|
||||
|
||||
/* XS2A has an additonal flag port. In Mission mode this is set to VALID_TOKEN */
|
||||
#ifdef __XS2A__
|
||||
in port flag2_port = PORT_USB_FLAG2;
|
||||
#else
|
||||
#define flag2_port null
|
||||
#endif
|
||||
|
||||
in buffered port:32 p_usb_clk = PORT_USB_CLK;
|
||||
out buffered port:32 p_usb_txd = PORT_USB_TXD;
|
||||
in buffered port:32 p_usb_rxd = PORT_USB_RXD;
|
||||
out port tx_readyout = PORT_USB_TX_READYOUT;
|
||||
in port tx_readyin = PORT_USB_TX_READYIN;
|
||||
in port rx_rdy = PORT_USB_RX_READY;
|
||||
|
||||
on USB_TILE: clock tx_usb_clk = XS1_CLKBLK_4;
|
||||
on USB_TILE: clock rx_usb_clk = XS1_CLKBLK_5;
|
||||
|
||||
// We use a single array instrad of two here and append epAddr_Ready_setup on the end to save some instructions in the Setup
|
||||
// token handling code. i.e. what we really want is the following, but's less efficient.
|
||||
// unsigned epAddr_Ready[USB_MAN_NUM_EP]
|
||||
// unsigned epAddr_Ready[USB_MAX_NUM_EP_OUT]
|
||||
unsigned epAddr[USB_MAX_NUM_EP]; // Used to store the addr of each EP in ep_info array
|
||||
unsigned epAddr_Ready[USB_MAX_NUM_EP + USB_MAX_NUM_EP_OUT]; // Used by the EP to mark itself as ready, essentially same as epAddr with 0 entries.
|
||||
|
||||
XUD_chan epChans0[USB_MAX_NUM_EP];
|
||||
|
||||
XUD_ep_info ep_info[USB_MAX_NUM_EP];
|
||||
|
||||
/* Location to store stack pointer (required for interrupt handler) */
|
||||
unsigned SavedSp;
|
||||
|
||||
/* Tables storing if EP's are signed up to bus state updates */
|
||||
int epStatFlagTableIn[USB_MAX_NUM_EP_IN];
|
||||
int epStatFlagTableOut[USB_MAX_NUM_EP_OUT];
|
||||
|
||||
|
||||
unsigned sentReset = 0;
|
||||
|
||||
unsigned chanArray;
|
||||
|
||||
#define RESET_TIME_us (5)
|
||||
#define RESET_TIME (RESET_TIME_us * PLATFORM_REFERENCE_MHZ)
|
||||
|
||||
extern unsigned XUD_LLD_IoLoop(
|
||||
in buffered port:32 rxd_port,
|
||||
in port rxa_port,
|
||||
out buffered port:32 txd_port,
|
||||
in port rxe_port, in port ?valtok_port,
|
||||
XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[], XUD_chan epAddr_Ready[],
|
||||
int epCount, chanend? c_sof) ;
|
||||
|
||||
|
||||
#if (XUD_OPT_SOFTCRC5 == 1)
|
||||
extern unsigned char crc5Table[2048];
|
||||
extern unsigned char crc5Table_Addr[2048];
|
||||
|
||||
void XUD_SetCrcTableAddr(unsigned addr);
|
||||
#endif
|
||||
|
||||
static int one = 1;
|
||||
|
||||
#pragma unsafe arrays
|
||||
static void SendResetToEps(XUD_chan c[], XUD_chan epAddr_Ready[], XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[], int nOut, int nIn, int token)
|
||||
{
|
||||
for(int i = 0; i < nOut; i++)
|
||||
{
|
||||
if(epTypeTableOut[i] != XUD_EPTYPE_DIS && epStatFlagTableOut[i])
|
||||
{
|
||||
/* Set EP resetting flag. EP uses this to check if it missed a reset before setting ready */
|
||||
ep_info[i].resetting = 1;
|
||||
|
||||
/* Clear EP ready. Note. small race since EP might set ready after XUD sets resetting to 1
|
||||
* but this should be caught in time (EP gets CT) */
|
||||
epAddr_Ready[i] = 0;
|
||||
epAddr_Ready[i+ USB_MAX_NUM_EP] = 0;
|
||||
XUD_Sup_outct(c[i], token);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < nIn; i++)
|
||||
{
|
||||
if(epTypeTableIn[i] != XUD_EPTYPE_DIS && epStatFlagTableIn[i])
|
||||
{
|
||||
ep_info[i + USB_MAX_NUM_EP_OUT].resetting = 1;
|
||||
epAddr_Ready[i + USB_MAX_NUM_EP_OUT] = 0;
|
||||
XUD_Sup_outct(c[i + USB_MAX_NUM_EP_OUT], token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SendSpeed(XUD_chan c[], XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[], int nOut, int nIn, int speed)
|
||||
{
|
||||
for(int i = 0; i < nOut; i++)
|
||||
{
|
||||
if(epTypeTableOut[i] != XUD_EPTYPE_DIS && epStatFlagTableOut[i])
|
||||
{
|
||||
XUD_Sup_outuint(c[i], speed);
|
||||
}
|
||||
}
|
||||
for(int i = 0; i < nIn; i++)
|
||||
{
|
||||
if(epTypeTableIn[i] != XUD_EPTYPE_DIS && epStatFlagTableIn[i])
|
||||
{
|
||||
XUD_Sup_outuint(c[i + USB_MAX_NUM_EP_OUT], speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Main XUD loop
|
||||
static int XUD_Manager_loop(XUD_chan epChans0[], XUD_chan epAddr_Ready[], chanend ?c_sof, XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[], int noEpOut, int noEpIn, XUD_PwrConfig pwrConfig)
|
||||
{
|
||||
int reset = 1; /* Flag for if device is returning from a reset */
|
||||
|
||||
/* Make sure ports are on and reset port states */
|
||||
set_port_use_on(p_usb_clk);
|
||||
set_port_use_on(p_usb_txd);
|
||||
set_port_use_on(p_usb_rxd);
|
||||
set_port_use_on(flag0_port);
|
||||
set_port_use_on(flag1_port);
|
||||
#if defined(__XS2A__)
|
||||
/* Extra flag port in XS2 */
|
||||
set_port_use_on(flag2_port);
|
||||
#endif
|
||||
|
||||
#if !defined(__XS2A__)
|
||||
|
||||
#ifndef XUD_CORE_CLOCK
|
||||
#error XUD_CORE_CLOCK not defined (in MHz)
|
||||
#endif
|
||||
|
||||
#ifdef XUD_SIM_XSIM
|
||||
#if (XUD_CORE_CLOCK >= 700)
|
||||
#define RX_RISE_DELAY 0
|
||||
#define RX_FALL_DELAY 0
|
||||
#define TX_RISE_DELAY 0
|
||||
#define TX_FALL_DELAY 7
|
||||
#elif (XUD_CORE_CLOCK >= 600)
|
||||
#define RX_RISE_DELAY 0
|
||||
#define RX_FALL_DELAY 0
|
||||
#define TX_RISE_DELAY 0
|
||||
#define TX_FALL_DELAY 5
|
||||
#else
|
||||
#error XUD_CORE_CLOCK must be >= 600
|
||||
#endif
|
||||
#else
|
||||
#if (XUD_CORE_CLOCK >= 600)
|
||||
#define RX_RISE_DELAY 1
|
||||
#define RX_FALL_DELAY 1
|
||||
#define TX_RISE_DELAY 1
|
||||
#define TX_FALL_DELAY 1
|
||||
#elif (XUD_CORE_CLOCK >= 500)
|
||||
#define RX_RISE_DELAY 1
|
||||
#define RX_FALL_DELAY 0
|
||||
#define TX_RISE_DELAY 1
|
||||
#define TX_FALL_DELAY 1
|
||||
#else
|
||||
#error XUD_CORE_CLOCK must be >= 500
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define RX_RISE_DELAY 1
|
||||
#define RX_FALL_DELAY 5
|
||||
#define TX_RISE_DELAY 5
|
||||
#define TX_FALL_DELAY 1
|
||||
#endif
|
||||
|
||||
// Handshaken ports need USB clock
|
||||
configure_clock_src(tx_usb_clk, p_usb_clk);
|
||||
configure_clock_src(rx_usb_clk, p_usb_clk);
|
||||
|
||||
// This, along with the following delays, forces the clock
|
||||
// to the ports to be effectively controlled by the
|
||||
// previous usb clock edges
|
||||
set_port_inv(p_usb_clk);
|
||||
set_port_sample_delay(p_usb_clk);
|
||||
|
||||
// This delay controls the capture of rdy
|
||||
set_clock_rise_delay(tx_usb_clk, TX_RISE_DELAY);
|
||||
|
||||
// This delay controls the launch of data.
|
||||
set_clock_fall_delay(tx_usb_clk, TX_FALL_DELAY);
|
||||
|
||||
// This delay the capture of the rdyIn and data.
|
||||
set_clock_rise_delay(rx_usb_clk, RX_RISE_DELAY);
|
||||
set_clock_fall_delay(rx_usb_clk, RX_FALL_DELAY);
|
||||
|
||||
set_pad_delay(flag1_port, 2);
|
||||
|
||||
start_clock(tx_usb_clk);
|
||||
start_clock(rx_usb_clk);
|
||||
|
||||
configure_out_port_handshake(p_usb_txd, tx_readyin, tx_readyout, tx_usb_clk, 0);
|
||||
configure_in_port_strobed_slave(p_usb_rxd, rx_rdy, rx_usb_clk);
|
||||
|
||||
/* Clock RxA port from USB clock - helps fall event */
|
||||
configure_in_port(flag1_port, rx_usb_clk);
|
||||
|
||||
unsigned noExit = 1;
|
||||
|
||||
while(noExit)
|
||||
{
|
||||
unsigned settings[] = {0};
|
||||
|
||||
/* Enable USB funcitonality in the device */
|
||||
XUD_HAL_EnableUsb(pwrConfig);
|
||||
|
||||
while(1)
|
||||
{
|
||||
{
|
||||
/* Wait for VBUS before enabling pull-up. The USB Spec (page 150) allows 100ms
|
||||
* between vbus valid and signalling attach */
|
||||
if(pwrConfig == XUD_PWR_SELF)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
unsigned time;
|
||||
timer t;
|
||||
|
||||
if(XUD_HAL_GetVBusState())
|
||||
{
|
||||
break;
|
||||
}
|
||||
t :> time;
|
||||
time += (200 * PLATFORM_REFERENCE_MHZ); // 200us poll
|
||||
t when timerafter(time):> void;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go into full speed mode: XcvrSelect and Term Select (and suspend) high */
|
||||
XUD_HAL_EnterMode_PeripheralFullSpeed();
|
||||
|
||||
/* Setup flags for power signalling - i.e. J/K/SE0 line state*/
|
||||
XUD_HAL_Mode_Signalling();
|
||||
|
||||
if (one)
|
||||
{
|
||||
#if defined(XUD_BYPASS_CONNECT)
|
||||
reset = 1;
|
||||
#else
|
||||
reset = XUD_Init();
|
||||
#endif
|
||||
one = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer t; unsigned time;
|
||||
t :> time;
|
||||
t when timerafter(time + SUSPEND_T_WTWRSTHS_ticks) :> int _;// T_WTRSTHS: 100-875us
|
||||
|
||||
/* Sample line state and check for reset (or suspend) */
|
||||
XUD_LineState_t ls = XUD_HAL_GetLineState();
|
||||
if(ls == XUD_LINESTATE_SE0)
|
||||
reset = 1;
|
||||
else
|
||||
reset = 0;
|
||||
}
|
||||
/* Inspect for suspend or reset */
|
||||
if(!reset)
|
||||
{
|
||||
/* Run user suspend code */
|
||||
XUD_UserSuspend();
|
||||
|
||||
/* Run suspend code, returns 1 if reset from suspend, 0 for resume, -1 for invalid vbus */
|
||||
reset = XUD_Suspend(pwrConfig);
|
||||
|
||||
if((pwrConfig == XUD_PWR_SELF) && (reset==-1))
|
||||
{
|
||||
/* Lost VBUS */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Run user resume code */
|
||||
XUD_UserResume();
|
||||
}
|
||||
/* Test if coming back from reset or suspend */
|
||||
if(reset == 1)
|
||||
{
|
||||
if(!sentReset)
|
||||
{
|
||||
SendResetToEps(epChans0, epAddr_Ready, epTypeTableOut, epTypeTableIn, noEpOut, noEpIn, USB_RESET_TOKEN);
|
||||
sentReset = 1;
|
||||
}
|
||||
|
||||
/* Reset the OUT ep structures */
|
||||
for(int i = 0; i< noEpOut; i++)
|
||||
{
|
||||
#if !defined(__XS2A__)
|
||||
ep_info[i].pid = USB_PIDn_DATA0;
|
||||
#else
|
||||
ep_info[i].pid = USB_PID_DATA0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Reset in the ep structures */
|
||||
for(int i = 0; i< noEpIn; i++)
|
||||
{
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].pid = USB_PIDn_DATA0;
|
||||
}
|
||||
|
||||
/* Set default device address - note, for normal operation this is 0, but can be other values for testing */
|
||||
XUD_HAL_SetDeviceAddress(XUD_STARTUP_ADDRESS);
|
||||
|
||||
#ifdef XUD_BYPASS_RESET
|
||||
if(XUD_TEST_SPEED == XUD_SPEED_HS)
|
||||
{
|
||||
g_curSpeed = XUD_SPEED_HS;
|
||||
g_txHandshakeTimeout = HS_TX_HANDSHAKE_TIMEOUT;
|
||||
XUD_HAL_EnterMode_PeripheralHighSpeed();
|
||||
}
|
||||
else
|
||||
{
|
||||
g_curSpeed = XUD_SPEED_FS;
|
||||
g_txHandshakeTimeout = FS_TX_HANDSHAKE_TIMEOUT;
|
||||
XUD_HAL_EnterMode_PeripheralFullSpeed(); //Technically not required since we should already be in FS mode..
|
||||
}
|
||||
#else
|
||||
if(g_desSpeed == XUD_SPEED_HS)
|
||||
{
|
||||
unsigned tmp = 0;
|
||||
tmp = XUD_DeviceAttachHS(pwrConfig);
|
||||
|
||||
if(tmp == -1)
|
||||
{
|
||||
XUD_UserSuspend();
|
||||
continue;
|
||||
}
|
||||
else if (!tmp)
|
||||
{
|
||||
/* HS handshake fail, mark as running in FS */
|
||||
g_curSpeed = XUD_SPEED_FS;
|
||||
g_txHandshakeTimeout = FS_TX_HANDSHAKE_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_curSpeed = XUD_SPEED_HS;
|
||||
g_txHandshakeTimeout = HS_TX_HANDSHAKE_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_curSpeed = XUD_SPEED_FS;
|
||||
g_txHandshakeTimeout = FS_TX_HANDSHAKE_TIMEOUT;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Send speed to EPs */
|
||||
SendSpeed(epChans0, epTypeTableOut, epTypeTableIn, noEpOut, noEpIn, g_curSpeed);
|
||||
sentReset=0;
|
||||
}
|
||||
}
|
||||
|
||||
XUD_HAL_Mode_DataTransfer();
|
||||
|
||||
set_thread_fast_mode_on();
|
||||
|
||||
/* Run main IO loop */
|
||||
/* flag0: Rx Error
|
||||
flag1: Rx Active
|
||||
flag2: Null / Valid Token */
|
||||
noExit = XUD_LLD_IoLoop(p_usb_rxd, flag1_port, p_usb_txd, flag0_port, flag2_port, epTypeTableOut, epTypeTableIn, epAddr_Ready, noEpOut, c_sof);
|
||||
|
||||
set_thread_fast_mode_off();
|
||||
|
||||
if(!noExit)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO stop clock blocks */
|
||||
|
||||
/* Turn ports off */
|
||||
set_port_use_off(p_usb_txd);
|
||||
set_port_use_off(p_usb_rxd);
|
||||
set_port_use_off(flag0_port);
|
||||
set_port_use_off(flag1_port);
|
||||
#ifdef __XS2A__
|
||||
set_port_use_off(flag2_port);
|
||||
#endif
|
||||
set_port_use_off(p_usb_clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _userTrapHandleRegister(void);
|
||||
|
||||
#pragma unsafe arrays
|
||||
static void drain(chanend chans[], int n, int op, XUD_EpType epTypeTable[])
|
||||
{
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
if(epTypeTable[i] != XUD_EPTYPE_DIS)
|
||||
{
|
||||
switch(op)
|
||||
{
|
||||
case 0:
|
||||
outct(chans[i], XS1_CT_END);
|
||||
outuint(chans[i], XUD_SPEED_KILL);
|
||||
break;
|
||||
case 1:
|
||||
outct(chans[i], XS1_CT_END);
|
||||
while (!testct(chans[i]))
|
||||
inuchar(chans[i]);
|
||||
chkct(chans[i], XS1_CT_END);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma unsafe arrays
|
||||
void SetupEndpoints(chanend c_ep_out[], int noEpOut, chanend c_ep_in[], int noEpIn, XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[])
|
||||
{
|
||||
|
||||
for(int i = 0; i < USB_MAX_NUM_EP_OUT; i++)
|
||||
{
|
||||
unsigned x;
|
||||
epAddr_Ready[i] = 0;
|
||||
epAddr_Ready[i+USB_MAX_NUM_EP] = 0; //epAddr_Ready_Setup
|
||||
ep_info[i].epAddress = i;
|
||||
ep_info[i].resetting = 0;
|
||||
|
||||
/* Mark all EP's as halted, we might later clear this if the EP is in use */
|
||||
ep_info[i].halted = USB_PIDn_STALL;
|
||||
|
||||
asm("ldaw %0, %1[%2]":"=r"(x):"r"(ep_info),"r"(i*sizeof(XUD_ep_info)/sizeof(unsigned)));
|
||||
epAddr[i] = x;
|
||||
}
|
||||
|
||||
for(int i = 0; i < USB_MAX_NUM_EP_IN; i++)
|
||||
{
|
||||
unsigned x;
|
||||
ep_info[i].epAddress = i;
|
||||
epAddr_Ready[USB_MAX_NUM_EP_OUT+i] = 0;
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].epAddress = (i | 0x80);
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].resetting = 0;
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].halted = USB_PIDn_STALL;
|
||||
|
||||
asm("ldaw %0, %1[%2]":"=r"(x):"r"(ep_info),"r"((USB_MAX_NUM_EP_OUT+i)*sizeof(XUD_ep_info)/sizeof(unsigned)));
|
||||
epAddr[USB_MAX_NUM_EP_OUT+i] = x;
|
||||
}
|
||||
|
||||
/* Populate arrays of channels and status flag tables */
|
||||
/* Note, if the epTypeTables don't match the provided size there could be trouble.. */
|
||||
for(int i = 0; i < noEpOut; i++)
|
||||
{
|
||||
if(epTypeTableOut[i] != XUD_EPTYPE_DIS)
|
||||
{
|
||||
unsigned x;
|
||||
epChans0[i] = XUD_Sup_GetResourceId(c_ep_out[i]);
|
||||
|
||||
asm("ldaw %0, %1[%2]":"=r"(x):"r"(epAddr_Ready),"r"(i));
|
||||
ep_info[i].array_ptr = x;
|
||||
ep_info[i].saved_array_ptr = 0;
|
||||
|
||||
asm("ldaw %0, %1[%2]":"=r"(x):"r"(epAddr_Ready),"r"(i+USB_MAX_NUM_EP)); //epAddr_Ready_Setup
|
||||
ep_info[i].array_ptr_setup = x;
|
||||
|
||||
asm("mov %0, %1":"=r"(x):"r"(c_ep_out[i]));
|
||||
ep_info[i].xud_chanend = x;
|
||||
|
||||
asm("getd %0, res[%1]":"=r"(x):"r"(c_ep_out[i]));
|
||||
ep_info[i].client_chanend = x;
|
||||
|
||||
epStatFlagTableOut[i] = epTypeTableOut[i] & XUD_STATUS_ENABLE;
|
||||
epTypeTableOut[i] = epTypeTableOut[i] & 0x7FFFFFFF;
|
||||
|
||||
ep_info[i].epType = epTypeTableOut[i];
|
||||
ep_info[i].halted = USB_PIDn_NAK; // Mark EP as not halted
|
||||
|
||||
#if !defined(__XS2A__)
|
||||
ep_info[i].pid = USB_PIDn_DATA0;
|
||||
#else
|
||||
ep_info[i].pid = USB_PID_DATA0;
|
||||
#endif
|
||||
asm("ldaw %0, %1[%2]":"=r"(x):"r"(ep_info),"r"(i*sizeof(XUD_ep_info)/sizeof(unsigned)));
|
||||
outuint(c_ep_out[i], x);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i< noEpIn; i++)
|
||||
{
|
||||
if(epTypeTableIn[i] != XUD_EPTYPE_DIS)
|
||||
{
|
||||
int x;
|
||||
epChans0[i+USB_MAX_NUM_EP_OUT] = XUD_Sup_GetResourceId(c_ep_in[i]);
|
||||
|
||||
asm("ldaw %0, %1[%2]":"=r"(x):"r"(epAddr_Ready),"r"(USB_MAX_NUM_EP_OUT+i));
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].array_ptr = x;
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].saved_array_ptr = 0;
|
||||
|
||||
asm("mov %0, %1":"=r"(x):"r"(c_ep_in[i]));
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].xud_chanend = x;
|
||||
|
||||
asm("getd %0, res[%1]":"=r"(x):"r"(c_ep_in[i]));
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].client_chanend = x;
|
||||
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].pid = USB_PIDn_DATA0;
|
||||
|
||||
epStatFlagTableIn[i] = epTypeTableIn[i] & XUD_STATUS_ENABLE;
|
||||
epTypeTableIn[i] = epTypeTableIn[i] & 0x7FFFFFFF;
|
||||
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].epType = epTypeTableIn[i];
|
||||
|
||||
ep_info[USB_MAX_NUM_EP_OUT+i].halted = 0; // Mark EP as not halted
|
||||
|
||||
asm("ldaw %0, %1[%2]":"=r"(x):"r"(ep_info),"r"((USB_MAX_NUM_EP_OUT+i)*sizeof(XUD_ep_info)/sizeof(unsigned)));
|
||||
outuint(c_ep_in[i], x);
|
||||
}
|
||||
}
|
||||
|
||||
/* EpTypeTable Checks. Note, currently this is not too crucial since we only really care if the EP is ISO or not */
|
||||
|
||||
/* Check for control on IN/OUT 0 */
|
||||
if(epTypeTableOut[0] != XUD_EPTYPE_CTL || epTypeTableIn[0] != XUD_EPTYPE_CTL)
|
||||
{
|
||||
__builtin_trap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma unsafe arrays
|
||||
int XUD_Main(chanend c_ep_out[], int noEpOut,
|
||||
chanend c_ep_in[], int noEpIn,
|
||||
chanend ?c_sof,
|
||||
XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[],
|
||||
XUD_BusSpeed_t speed, XUD_PwrConfig pwrConfig)
|
||||
{
|
||||
g_desSpeed = speed;
|
||||
|
||||
SetupEndpoints(c_ep_out, noEpOut, c_ep_in, noEpIn, epTypeTableOut, epTypeTableIn);
|
||||
|
||||
#if 0
|
||||
/* Check that if the required channel has a destination if the EP is marked as in use */
|
||||
for( int i = 0; i < noEpOut + noEpIn; i++ )
|
||||
{
|
||||
if( XUD_Sup_getd( epAddr_Ready[i] ) == 0 && epTypeTableOut[i] != XUD_EPTYPE_DIS )
|
||||
XUD_Error_hex("XUD_Manager: OUT Ep marked as in use but chanend has no dest: ", i);
|
||||
}
|
||||
|
||||
for( int i = 0; i < noEpOut + noEpIn; i++ )
|
||||
{
|
||||
if( XUD_Sup_getd( epAddr_Ready[i + XUD_EP_COUNT ] ) == 0 && epTypeTableIn[i] != XUD_EPTYPE_DIS )
|
||||
XUD_Error_hex("XUD_Manager: IN Ep marked as in use but chanend has no dest: ", i);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Run the main XUD loop */
|
||||
XUD_Manager_loop(epChans0, epAddr_Ready, c_sof, epTypeTableOut, epTypeTableIn, noEpOut, noEpIn, pwrConfig);
|
||||
|
||||
// Need to close, drain, and check - three stages.
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
drain(c_ep_out, noEpOut, i, epTypeTableOut); // On all inputs
|
||||
drain(c_ep_in, noEpIn, i, epTypeTableIn); // On all output
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Legacy API support */
|
||||
int XUD_Manager(chanend c_epOut[], int noEpOut,
|
||||
chanend c_epIn[], int noEpIn,
|
||||
NULLABLE_RESOURCE(chanend, c_sof),
|
||||
XUD_EpType epTypeTableOut[], XUD_EpType epTypeTableIn[],
|
||||
NULLABLE_RESOURCE(port, p_usb_rst),
|
||||
NULLABLE_RESOURCE(clock, clk),
|
||||
unsigned rstMask,
|
||||
XUD_BusSpeed_t desiredSpeed,
|
||||
XUD_PwrConfig pwrConfig)
|
||||
{
|
||||
return XUD_Main(c_epOut, noEpOut, c_epIn, noEpIn, c_sof, epTypeTableOut, epTypeTableIn, desiredSpeed, pwrConfig); //NOCOVER
|
||||
}
|
||||
|
||||
|
||||
33
lib_xud/lib_xud/src/core/XUD_SetCrcTableAddr.c
Normal file
33
lib_xud/lib_xud/src/core/XUD_SetCrcTableAddr.c
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/** @file XUD_SetCrcTableAddr.c
|
||||
* @author Ross Owen, XMOS Limited
|
||||
*/
|
||||
#include <string.h>
|
||||
|
||||
/* Global table used to store complete valid CRC5 table */
|
||||
extern unsigned char crc5Table[2048];
|
||||
|
||||
/* Global table used to store valid CRCs for current address, all other address is this table are invalidated */
|
||||
extern unsigned char crc5Table_Addr[2048];
|
||||
|
||||
/** XUD_SetCrcTableAddress
|
||||
* @brief Copies CRCs from original valid table to the table we use. Invalidates entries
|
||||
* which correspnds to the wrong address
|
||||
* @param addr new device address
|
||||
* @return void
|
||||
*/
|
||||
void XUD_SetCrcTableAddr(unsigned addr)
|
||||
{
|
||||
unsigned index;
|
||||
|
||||
/* Set whole table to invalid CRC */
|
||||
memset(crc5Table_Addr, 0xff, 2048);
|
||||
|
||||
/* Copy over relevant entries */
|
||||
for(unsigned ep = 0; ep <= 0xF; ep++)
|
||||
{
|
||||
index = addr + (ep << 7);
|
||||
crc5Table_Addr[index] = crc5Table[index];
|
||||
}
|
||||
}
|
||||
11
lib_xud/lib_xud/src/core/XUD_Signalling.h
Normal file
11
lib_xud/lib_xud/src/core/XUD_Signalling.h
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef _XUD_PWRSIG_H_
|
||||
#define _XUD_PWRSIG_H_
|
||||
void XUD_PhyReset(out port p_rst, int resetTime, unsigned rstMask);
|
||||
|
||||
int XUD_Init();
|
||||
|
||||
int XUD_Suspend(XUD_PwrConfig pwrConfig);
|
||||
#endif
|
||||
185
lib_xud/lib_xud/src/core/XUD_Signalling.xc
Normal file
185
lib_xud/lib_xud/src/core/XUD_Signalling.xc
Normal file
@@ -0,0 +1,185 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <xs1.h>
|
||||
#include "xud.h"
|
||||
#include "XUD_Support.h"
|
||||
#include "XUD_USB_Defines.h"
|
||||
#include "XUD_HAL.h"
|
||||
|
||||
#define T_WTRSTFS_us 26 // 26us
|
||||
#ifndef T_WTRSTFS
|
||||
#define T_WTRSTFS (T_WTRSTFS_us * PLATFORM_REFERENCE_MHZ)
|
||||
#endif
|
||||
#define STATE_START_TO_us 3000 // 3ms
|
||||
#define STATE_START_TO (STATE_START_TO_us * PLATFORM_REFERENCE_MHZ)
|
||||
#define DELAY_6ms_us 6000
|
||||
#define DELAY_6ms (DELAY_6ms_us * PLATFORM_REFERENCE_MHZ)
|
||||
#define T_FILTSE0 250
|
||||
|
||||
#ifndef SUSPEND_VBUS_POLL_TIMER_TICKS
|
||||
#define SUSPEND_VBUS_POLL_TIMER_TICKS (500000)
|
||||
#endif
|
||||
|
||||
extern unsigned g_curSpeed;
|
||||
|
||||
int XUD_Init()
|
||||
{
|
||||
/* Wait for host */
|
||||
while (1)
|
||||
{
|
||||
XUD_LineState_t currentLs = XUD_HAL_GetLineState();
|
||||
|
||||
switch (currentLs)
|
||||
{
|
||||
/* SE0 State */
|
||||
case XUD_LINESTATE_SE0:
|
||||
|
||||
unsigned timedOut = XUD_HAL_WaitForLineStateChange(currentLs, T_WTRSTFS);
|
||||
|
||||
/* If no change in LS then return 1 for reset */
|
||||
if(timedOut)
|
||||
return 1;
|
||||
|
||||
/* Otherwise SE0 went away.. keep looking */
|
||||
break;
|
||||
|
||||
/* J State */
|
||||
case XUD_LINESTATE_HS_K_FS_J:
|
||||
|
||||
unsigned timedOut = XUD_HAL_WaitForLineStateChange(currentLs, STATE_START_TO);
|
||||
|
||||
/* If no change in LS then return 0 for suspend */
|
||||
if(timedOut)
|
||||
return 0;
|
||||
|
||||
/* Otherwise J went away.. keep looking */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Shouldn't expect to get here, but ignore anyway */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__builtin_trap();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** XUD_Suspend
|
||||
* @brief Function called when device is suspended. This should include any clock down code etc.
|
||||
* @return non-zero if reset detected during resume */
|
||||
int XUD_Suspend(XUD_PwrConfig pwrConfig)
|
||||
{
|
||||
timer t;
|
||||
unsigned time;
|
||||
|
||||
XUD_LineState_t currentLs = XUD_LINESTATE_HS_K_FS_J;
|
||||
|
||||
while(1)
|
||||
{
|
||||
unsigned timeOutTime = 0;
|
||||
|
||||
if(pwrConfig == XUD_PWR_SELF)
|
||||
timeOutTime = SUSPEND_VBUS_POLL_TIMER_TICKS;
|
||||
|
||||
unsigned timedOut = XUD_HAL_WaitForLineStateChange(currentLs, timeOutTime);
|
||||
|
||||
if(timedOut)
|
||||
{
|
||||
if(!XUD_HAL_GetVBusState())
|
||||
{
|
||||
/* VBUS not valid */
|
||||
XUD_HAL_EnterMode_TristateDrivers();
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* VBUS still valid, keep looking for LS change */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch(currentLs)
|
||||
{
|
||||
/* Reset signalliung */
|
||||
case XUD_LINESTATE_SE0:
|
||||
|
||||
timedOut = XUD_HAL_WaitForLineStateChange(currentLs, T_FILTSE0);
|
||||
|
||||
if(timedOut)
|
||||
{
|
||||
/* Consider 2.5ms a complete reset */
|
||||
t :> time;
|
||||
t when timerafter(time + 250000) :> void;
|
||||
|
||||
/* Return 1 for reset */
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* If didnt timeout then keep looping...*/
|
||||
break;
|
||||
|
||||
/* K, start of resume */
|
||||
case XUD_LINESTATE_HS_J_FS_K:
|
||||
#ifdef __XS2A__
|
||||
if (g_curSpeed == XUD_SPEED_HS)
|
||||
{
|
||||
/* Special case for XS2A - start high-speed switch so it is completed as soon as possible after end of resume is seen */
|
||||
XUD_HAL_EnterMode_PeripheralHighSpeed_Start();
|
||||
}
|
||||
#endif
|
||||
while(1)
|
||||
{
|
||||
XUD_HAL_WaitForLineStateChange(currentLs, 0);
|
||||
|
||||
switch(currentLs)
|
||||
{
|
||||
/* J, unexpected, return */
|
||||
case XUD_LINESTATE_HS_K_FS_J:
|
||||
#ifdef __XS2A__
|
||||
/* For XS2 we have to complete the high-speed switch now, since we started it already..
|
||||
we then revert to full speed straight away - causes a blip on the bus, non-ideal */
|
||||
if (g_curSpeed == XUD_SPEED_HS)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
XUD_HAL_EnterMode_PeripheralHighSpeed_Complete();
|
||||
}
|
||||
}
|
||||
|
||||
XUD_HAL_EnterMode_PeripheralFullSpeed();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
/* SE0, end of resume */
|
||||
case XUD_LINESTATE_SE0:
|
||||
if (g_curSpeed == XUD_SPEED_HS)
|
||||
{
|
||||
#ifdef __XS2A__
|
||||
/* For XS2 we now have to complete the switch back to high-speed */
|
||||
XUD_HAL_EnterMode_PeripheralHighSpeed_Complete();
|
||||
#else
|
||||
/* Move back into high-speed mode - Notes, writes to XS3A registers orders of magnitude faster than XS2A */
|
||||
XUD_HAL_EnterMode_PeripheralHighSpeed();
|
||||
#endif
|
||||
}
|
||||
/* Return 0 for resumed */
|
||||
return 0;
|
||||
|
||||
default:
|
||||
// Keep looping
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // unreachable
|
||||
}
|
||||
|
||||
63
lib_xud/lib_xud/src/core/XUD_Support.h
Normal file
63
lib_xud/lib_xud/src/core/XUD_Support.h
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/** @file XUD_Support.h
|
||||
* @brief Various support functions used in XUD
|
||||
* @author Ross Owen, XMOS Limited
|
||||
*/
|
||||
|
||||
#ifndef _XUD_SUPPORT_H_
|
||||
#define _XUD_SUPPORT_H_ 1
|
||||
|
||||
/* Typedefs for resources */
|
||||
typedef unsigned XUD_lock;
|
||||
typedef unsigned XUD_chan;
|
||||
|
||||
// Delay execution (Uses timer)
|
||||
void XUD_Sup_Delay(unsigned x);
|
||||
|
||||
inline unsigned XUD_Sup_GetResourceId(chanend c)
|
||||
{
|
||||
unsigned id;
|
||||
asm ("mov %0, %1" : "=r"(id) : "r"(c));
|
||||
return id;
|
||||
}
|
||||
|
||||
// Channel comms - In
|
||||
inline unsigned char XUD_Sup_inct(XUD_chan c)
|
||||
{
|
||||
unsigned char x;
|
||||
asm volatile("inct %0, res[%1]" : "=r"(x) : "r"(c));
|
||||
return x;
|
||||
}
|
||||
|
||||
inline unsigned char XUD_Sup_int(XUD_chan c)
|
||||
{
|
||||
unsigned char x;
|
||||
asm volatile("int %0, res[%1]" : "=r"(x) : "r"(c));
|
||||
return x;
|
||||
}
|
||||
|
||||
inline unsigned char XUD_Sup_testct(XUD_chan c)
|
||||
{
|
||||
unsigned char x;
|
||||
asm volatile("testct %0, res[%1]" : "=r"(x) : "r"(c));
|
||||
return x;
|
||||
}
|
||||
|
||||
// Channel comms - Out
|
||||
inline void XUD_Sup_outuint(XUD_chan c, unsigned x)
|
||||
{
|
||||
asm volatile("out res[%0], %1" : /* no outputs */ : "r"(c), "r"(x));
|
||||
}
|
||||
|
||||
inline void XUD_Sup_outuchar(XUD_chan c, unsigned char x)
|
||||
{
|
||||
asm volatile("outt res[%0], %1" : /* no outputs */ : "r"(c), "r"(x));
|
||||
}
|
||||
|
||||
inline void XUD_Sup_outct(XUD_chan c, unsigned char x)
|
||||
{
|
||||
asm volatile("outct res[%0], %1" : /* no outputs */ : "r"(c), "r"(x));
|
||||
}
|
||||
|
||||
#endif
|
||||
13
lib_xud/lib_xud/src/core/XUD_Support.xc
Normal file
13
lib_xud/lib_xud/src/core/XUD_Support.xc
Normal file
@@ -0,0 +1,13 @@
|
||||
// Copyright 2013-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include "XUD_Support.h"
|
||||
#include <xs1.h>
|
||||
|
||||
// Force external definitions of inline functions in this file.
|
||||
extern inline unsigned XUD_Sup_GetResourceId(chanend c);
|
||||
extern inline unsigned char XUD_Sup_inct(XUD_chan c);
|
||||
extern inline unsigned char XUD_Sup_int(XUD_chan c);
|
||||
extern inline unsigned char XUD_Sup_testct(XUD_chan c);
|
||||
extern inline void XUD_Sup_outuint(XUD_chan c, unsigned x);
|
||||
extern inline void XUD_Sup_outct(XUD_chan c, unsigned char x);
|
||||
|
||||
78
lib_xud/lib_xud/src/core/XUD_TestMode.S
Normal file
78
lib_xud/lib_xud/src/core/XUD_TestMode.S
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright 2020-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include <xs1.h>
|
||||
#include "XUD_USB_Defines.h"
|
||||
#include "XUD_AlignmentDefines.h"
|
||||
|
||||
.issue_mode dual
|
||||
|
||||
.globl XUD_UsbTestSE0.nstackwords
|
||||
.linkset XUD_UsbTestSE0.nstackwords, 0
|
||||
.globl XUD_UsbTestSE0
|
||||
.text
|
||||
.cc_top XUD_UsbTestSE0.func, XUD_UsbTestSE0
|
||||
|
||||
// NAK every IN token if the CRC is correct.
|
||||
|
||||
.align FUNCTION_ALIGNMENT
|
||||
XUD_UsbTestSE0:
|
||||
DUALENTSP_lu6 0 // Note, don't really need DI here..
|
||||
// TODO ideally don't load these from dp..
|
||||
ldw r0, dp[p_usb_rxd] // Load RXD port
|
||||
ldw r2, dp[p_usb_txd] // Load TXD port
|
||||
ldw r3, dp[flag1_port] // Load RXA port
|
||||
|
||||
XUD_UsbTestSE0_loop:
|
||||
#ifdef __XS2A__
|
||||
ldw r1, dp[flag2_port] // Valid token port
|
||||
|
||||
inpw r11, res[r0], 8 // Read 8 bit PID
|
||||
shr r11, r11, 24 // shift off junk
|
||||
|
||||
inpw r9, res[r0], 8 // Read EP Number (dont care)
|
||||
|
||||
in r9, res[r1]
|
||||
bt r9, InvalidTestToken // If VALID_TOKEN high, ignore token
|
||||
|
||||
eq r10, r11, USB_PID_IN
|
||||
bf r10, XUD_UsbTestSE0_loop
|
||||
#else
|
||||
ldc r8, 16
|
||||
inpw r9, res[r0], 8 // Read 3 byte token from data port | CRC[5] | EP[4] | ADDR[7] | PID[8] | junk
|
||||
{setpsc res[r0], r8; shr r9, r9, 24} // r9: PID
|
||||
// TODO ideally share this with XUD_CrcAddrCheck rather than a duplication here..
|
||||
{in r10, res[r0]; sub r1, r8, 5} // ldc r1, 11
|
||||
{shr r10, r10, 16; mkmsk r11, r1}
|
||||
{and r11, r10, r11; shr r4, r10, r1} // r4: Received CRC
|
||||
|
||||
ldaw r8, dp[crc5Table] // Note, accepting any address
|
||||
ld8u r8, r8[r11] // Correct CRC
|
||||
|
||||
xor r4, r4, r8 // Check received CRC against expected CRC
|
||||
bt r4, InvalidTestToken; // Note, EP number is ignored
|
||||
|
||||
ldc r4, USB_PIDn_IN
|
||||
eq r9, r9, r4 // Check received PID
|
||||
bf r9, XUD_UsbTestSE0_loop
|
||||
#endif
|
||||
|
||||
nop // If all is well respond with a NAK to any IN token..
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
ldc r11, USB_PIDn_NAK
|
||||
outpw res[r2], r11, 8
|
||||
syncr res[r2]
|
||||
bu XUD_UsbTestSE0_loop
|
||||
|
||||
InvalidTestToken:
|
||||
in r11, res[r3]
|
||||
bt r11, InvalidTestToken
|
||||
setc res[r0], XS1_SETC_RUN_CLRBUF // Clear RXD port
|
||||
bu XUD_UsbTestSE0_loop
|
||||
|
||||
|
||||
.cc_bottom XUD_UsbTestSE0.func
|
||||
19
lib_xud/lib_xud/src/core/XUD_TestMode.h
Normal file
19
lib_xud/lib_xud/src/core/XUD_TestMode.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __XUD_TESTMODE_H__
|
||||
#define __XUD_TESTMODE_H__
|
||||
|
||||
#include <xs1.h>
|
||||
|
||||
#include "XUD_HAL.h"
|
||||
#include "XUD_USB_Defines.h"
|
||||
|
||||
unsigned UsbTestModeHandler_asm();
|
||||
unsigned XUD_UsbTestSE0();
|
||||
|
||||
int XUD_TestMode_TestJ () ;
|
||||
int XUD_TestMode_TestK () ;
|
||||
int XUD_TestMode_TestSE0NAK () ;
|
||||
int XUD_TestMode_TestPacket () ;
|
||||
|
||||
#endif
|
||||
117
lib_xud/lib_xud/src/core/XUD_TestMode.xc
Normal file
117
lib_xud/lib_xud/src/core/XUD_TestMode.xc
Normal file
@@ -0,0 +1,117 @@
|
||||
// Copyright 2011-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <xs1.h>
|
||||
|
||||
#include "xud.h"
|
||||
#include "XUD_TestMode.h"
|
||||
|
||||
extern out buffered port:32 p_usb_txd;
|
||||
|
||||
#define T_INTER_TEST_PACKET_us 2
|
||||
#define T_INTER_TEST_PACKET (T_INTER_TEST_PACKET_us * PLATFORM_REFERENCE_MHZ)
|
||||
|
||||
#ifndef XUD_TEST_MODE_SUPPORT_DISABLED
|
||||
unsigned int test_packet[] =
|
||||
{
|
||||
0x000000c3,
|
||||
0x00000000,
|
||||
0xaaaa0000,
|
||||
0xaaaaaaaa,
|
||||
0xeeeeaaaa,
|
||||
0xeeeeeeee,
|
||||
0xfffeeeee,
|
||||
0xffffffff,
|
||||
0xffffffff,
|
||||
0xbf7fffff,
|
||||
0xfbf7efdf,
|
||||
0xbf7efcfd,
|
||||
0xfbf7efdf,
|
||||
0xceb67efd
|
||||
};
|
||||
|
||||
// Runs in XUD thread with interrupt on entering testmode.
|
||||
int XUD_UsbTestModeHandler(unsigned cmd)
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case USB_WINDEX_TEST_J:
|
||||
|
||||
XUD_HAL_EnterMode_PeripheralTestJTestK();
|
||||
|
||||
while(1)
|
||||
{
|
||||
p_usb_txd <: 0xffffffff;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_WINDEX_TEST_K:
|
||||
|
||||
XUD_HAL_EnterMode_PeripheralTestJTestK();
|
||||
|
||||
while(1)
|
||||
{
|
||||
p_usb_txd <: 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_WINDEX_TEST_SE0_NAK:
|
||||
|
||||
XUD_HAL_EnterMode_PeripheralHighSpeed();
|
||||
|
||||
/* Drop into asm to deal with this mode */
|
||||
XUD_UsbTestSE0();
|
||||
break;
|
||||
|
||||
case USB_WINDEX_TEST_PACKET:
|
||||
{
|
||||
XUD_HAL_EnterMode_PeripheralHighSpeed();
|
||||
|
||||
// Repetitively transmit specific test packet forever.
|
||||
// Timings must still meet minimum interpacket gap
|
||||
// Have to relate KJ pairings to data.
|
||||
unsigned i;
|
||||
timer test_packet_timer;
|
||||
|
||||
#pragma unsafe arrays
|
||||
while (1)
|
||||
{
|
||||
#pragma loop unroll
|
||||
for (i=0; i < sizeof(test_packet)/sizeof(test_packet[0]); i++)
|
||||
{
|
||||
p_usb_txd <: test_packet[i];
|
||||
};
|
||||
sync(p_usb_txd);
|
||||
test_packet_timer :> i;
|
||||
test_packet_timer when timerafter (i + T_INTER_TEST_PACKET) :> int _;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_WINDEX_TEST_XMOS_IN_ADDR1:
|
||||
{
|
||||
XUD_HAL_EnterMode_PeripheralHighSpeed();
|
||||
|
||||
// This isn't a USB test mode but useful for internal testing as the
|
||||
// source of IN packets for the receiver sensitivty compliance test.
|
||||
// Repetitively transmit specific IN packet forever. (PID = IN, Address = 1, Endpoint = 0, CRC = 0x1D)
|
||||
// Not to be used in normal use.
|
||||
unsigned i;
|
||||
timer test_packet_timer;
|
||||
|
||||
while (1)
|
||||
{
|
||||
partout(p_usb_txd, 24, 0xE80169);
|
||||
sync(p_usb_txd);
|
||||
test_packet_timer :> i;
|
||||
test_packet_timer when timerafter (i + T_INTER_TEST_PACKET) :> int _;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
while(1);
|
||||
return -1; // Unreachable
|
||||
}
|
||||
#endif
|
||||
33
lib_xud/lib_xud/src/core/XUD_TimingDefines.h
Normal file
33
lib_xud/lib_xud/src/core/XUD_TimingDefines.h
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright 2015-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef _XUD_TIMING_DEFINES_H_
|
||||
#define _XUD_TIMING_DEFINES_H_
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
// Defines relating to USB/ULPI/UTMI/Phy specs
|
||||
#ifndef SUSPEND_TIMEOUT_us
|
||||
#define SUSPEND_TIMEOUT_us (3000)
|
||||
#endif
|
||||
#define SUSPEND_TIMEOUT_ticks (SUSPEND_TIMEOUT_us * PLATFORM_REFERENCE_MHZ)
|
||||
|
||||
// Device attach timing defines
|
||||
#define T_UCHEND_T_UCH_us (1000000) // 1000ms
|
||||
#define T_UCHEND_T_UCH (T_UCHEND_T_UCH_us * PLATFORM_REFERENCE_MHZ)
|
||||
|
||||
#ifndef T_FILT_us
|
||||
#define T_FILT_us (3) // 2.5us
|
||||
#endif
|
||||
#define T_FILT_ticks (T_FILT_us * PLATFORM_REFERENCE_MHZ)
|
||||
|
||||
#ifndef SUSPEND_T_WTWRSTHS_us
|
||||
#define SUSPEND_T_WTWRSTHS_us (200) // 200us Time beforechecking for J after asserting XcvrSelect and Termselect: T_WTRSTHS: 100-875us
|
||||
#endif
|
||||
#define SUSPEND_T_WTWRSTHS_ticks (SUSPEND_T_WTWRSTHS_us * PLATFORM_REFERENCE_MHZ)
|
||||
|
||||
#define OUT_TIMEOUT_us (500) // How long we wait for data after OUT token
|
||||
#define OUT_TIMEOUT_ticks (OUT_TIMEOUT_us * PLATFORM_REFERENCE_MHZ)
|
||||
#define TX_HANDSHAKE_TIMEOUT_us (5) // How long we wait for handshake after sending tx data
|
||||
#define TX_HANDSHAKE_TIMEOUT_ticks (TX_HANDSHAKE_TIMEOUT_us * PLATFORM_REFERENCE_MHZ)
|
||||
|
||||
#endif
|
||||
23
lib_xud/lib_xud/src/core/XUD_TokenJmp.S
Normal file
23
lib_xud/lib_xud/src/core/XUD_TokenJmp.S
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2013-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#if defined(__XS2A__)
|
||||
ldaw r10, dp[PidJumpTable] // TODO Could load from sp here
|
||||
// We receive: | 0000 4-bit EP | 0000 4-bit PID |
|
||||
inpw r11, res[RXD], 8 // Read 8 bit PID
|
||||
shr r11, r11, 24 // Shift off junk
|
||||
|
||||
ldw r10, r10[r11] // Load relevant branch address
|
||||
bau r10
|
||||
#else
|
||||
{ldw r10, sp[STACK_PIDJUMPTABLE]
|
||||
ldc r8, 16}
|
||||
|
||||
inpw r11, res[RXD], 8 // Read 3 byte token from data port | CRC[5] | EP[4] | ADDR[7] | PID[8] | junk
|
||||
{setpsc res[RXD], r8; shr r11, r11, 24}
|
||||
|
||||
ldw r11, r10[r11]
|
||||
bau r11 // Branch to Pid_Out, Pid_Sof, Pid_In, Pid_Setup etc
|
||||
|
||||
#endif
|
||||
|
||||
75
lib_xud/lib_xud/src/core/XUD_USBTile_Support.S
Normal file
75
lib_xud/lib_xud/src/core/XUD_USBTile_Support.S
Normal file
@@ -0,0 +1,75 @@
|
||||
// Copyright 2015-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/** XUD_USBTile_Support.S
|
||||
* @brief Support functions for USB Tile use
|
||||
* @author Ross Owen, XMOS Limited
|
||||
*/
|
||||
|
||||
#ifdef __XS2A__
|
||||
#include <xs2a_registers.h>
|
||||
#endif
|
||||
#if !defined(__XS2A__)
|
||||
#include <xs1.h>
|
||||
#endif
|
||||
#include <XUD_AlignmentDefines.h>
|
||||
|
||||
.text
|
||||
.globl XUD_EnableUsbPortMux, "f{ui}()"
|
||||
.type XUD_EnableUsbPortMux, @function
|
||||
.cc_top XUD_EnableUsbPortMux.function
|
||||
.align FUNCTION_ALIGNMENT
|
||||
// void XUD_EnableUsbPortMux (unsigned mode);
|
||||
XUD_EnableUsbPortMux:
|
||||
.issue_mode single
|
||||
ENTSP_lu6 0
|
||||
ldc r1, XS1_PS_XCORE_CTRL0
|
||||
get r0, ps[r1]
|
||||
ldc r2, 2
|
||||
or r0, r0, r2
|
||||
set ps[r1], r0
|
||||
|
||||
//Sanity check, read back and check
|
||||
//get r1, ps[r1]
|
||||
//eq r1, r0, r1
|
||||
//ecallf r1
|
||||
retsp 0
|
||||
|
||||
.size XUD_EnableUsbPortMux, .-XUD_EnableUsbPortMux
|
||||
.cc_bottom XUD_EnableUsbPortMux.function
|
||||
.globl XUD_EnableUsbPortMux.nstackwords
|
||||
.globl XUD_EnableUsbPortMux.maxchanends
|
||||
.globl XUD_EnableUsbPortMux.maxtimers
|
||||
.globl XUD_EnableUsbPortMux.maxcores
|
||||
.set XUD_EnableUsbPortMux.nstackwords, 0
|
||||
.set XUD_EnableUsbPortMux.maxchanends, 0
|
||||
.set XUD_EnableUsbPortMux.maxtimers, 0
|
||||
.set XUD_EnableUsbPortMux.maxcores, 1
|
||||
.set XUD_EnableUsbPortMux.locnochandec, 1
|
||||
|
||||
.globl XUD_DisableUsbPortMux, "f{ui}()"
|
||||
.type XUD_DisableUsbPortMux, @function
|
||||
.cc_top XUD_DisableUsbPortMux.function
|
||||
.align FUNCTION_ALIGNMENT
|
||||
// void XUD_DisableUsbPortMux (unsigned mode);
|
||||
XUD_DisableUsbPortMux:
|
||||
ldc r1, XS1_PS_XCORE_CTRL0
|
||||
ldc r0, 0
|
||||
set ps[r1], r0
|
||||
|
||||
//Sanity check, read back and check
|
||||
//get r1, ps[r1]
|
||||
//eq r1, r0, r1
|
||||
//ecallf r1
|
||||
retsp 0
|
||||
|
||||
.size XUD_DisableUsbPortMux, .-XUD_DisableUsbPortMux
|
||||
.cc_bottom XUD_DisableUsbPortMux.function
|
||||
.globl XUD_DisableUsbPortMux.nstackwords
|
||||
.globl XUD_DisableUsbPortMux.maxchanends
|
||||
.globl XUD_DisableUsbPortMux.maxtimers
|
||||
.globl XUD_DisableUsbPortMux.maxcores
|
||||
.set XUD_DisableUsbPortMux.nstackwords, 0
|
||||
.set XUD_DisableUsbPortMux.maxchanends, 0
|
||||
.set XUD_DisableUsbPortMux.maxtimers, 0
|
||||
.set XUD_DisableUsbPortMux.maxcores, 1
|
||||
.set XUD_DisableUsbPortMux.locnochandec, 1
|
||||
22
lib_xud/lib_xud/src/core/XUD_USBTile_Support.h
Normal file
22
lib_xud/lib_xud/src/core/XUD_USBTile_Support.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2015-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef _XUD_USBTILE_SUPPORT_H_
|
||||
#define _XUD_USBTILE_SUPPORT_H_ 1
|
||||
|
||||
#include "XUD_Support.h"
|
||||
|
||||
unsigned XUD_EnableUsbPortMux();
|
||||
|
||||
unsigned XUD_DisableUsbPortMux();
|
||||
|
||||
int write_periph_word(tileref tile, unsigned peripheral, unsigned addr, unsigned data);
|
||||
|
||||
int read_periph_word(tileref tile, unsigned peripheral, unsigned addr, unsigned &data);
|
||||
|
||||
unsigned get_tile_id(tileref ref);
|
||||
|
||||
void write_periph_word_two_part_start(chanend tmpchan, tileref tile, unsigned peripheral,
|
||||
unsigned base_address, unsigned data);
|
||||
void write_periph_word_two_part_end(chanend tmpchan, unsigned data);
|
||||
#endif
|
||||
67
lib_xud/lib_xud/src/core/XUD_USBTile_Support.xc
Normal file
67
lib_xud/lib_xud/src/core/XUD_USBTile_Support.xc
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2013-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifdef __XS2A__
|
||||
|
||||
#include <xs1.h>
|
||||
|
||||
#define STRINGIFY0(x) #x
|
||||
#define STRINGIFY(x) STRINGIFY0(x)
|
||||
#define ENABLE_INTERRUPTS() asm("setsr " STRINGIFY(XS1_SR_IEBLE_SET(0, 1)))
|
||||
#define DISABLE_INTERRUPTS() asm("clrsr " STRINGIFY(XS1_SR_IEBLE_SET(0, 1)))
|
||||
|
||||
#define CT_PERIPH_WRITE 0x24
|
||||
#define JUNK_RETURN_ADDRESS 0xFF
|
||||
|
||||
unsigned getsr_int();
|
||||
|
||||
int write_periph_word(tileref tile, unsigned peripheral, unsigned addr, unsigned data)
|
||||
{
|
||||
unsigned tmp[1];
|
||||
tmp[0] = data;
|
||||
return write_periph_32(tile, peripheral, addr, 1, tmp);
|
||||
}
|
||||
|
||||
int read_periph_word(tileref tile, unsigned peripheral, unsigned addr, unsigned &data)
|
||||
{
|
||||
unsigned tmp[1];
|
||||
unsigned prevSr = 0;
|
||||
|
||||
/* Get current interrupt bit from SR */
|
||||
asm volatile("getsr r11, 2; mov %0, r11" :"=r"(prevSr) :: "r11");
|
||||
|
||||
/* Clear the interrupt bit in SR */
|
||||
DISABLE_INTERRUPTS();
|
||||
|
||||
int retval = read_periph_32(tile, peripheral, addr, 1, tmp);
|
||||
|
||||
/* Re-enable interrupts if they were previously enabled */
|
||||
if(prevSr)
|
||||
ENABLE_INTERRUPTS();
|
||||
|
||||
data = tmp[0];
|
||||
return retval;
|
||||
}
|
||||
|
||||
void write_periph_word_two_part_start(chanend tmpchan, tileref tile, unsigned peripheral,
|
||||
unsigned base_address, unsigned data)
|
||||
{
|
||||
asm("setd res[%0], %1" ::
|
||||
"r"(tmpchan),
|
||||
"r"((get_tile_id(tile) << 16) | (peripheral << 8) | XS1_RES_TYPE_CHANEND));
|
||||
|
||||
/* Preload as much as possible, everything up to last byte of data */
|
||||
outct(tmpchan, CT_PERIPH_WRITE);
|
||||
outuint(tmpchan, (JUNK_RETURN_ADDRESS << 8) | (base_address & 0xFF));
|
||||
outuchar(tmpchan, sizeof(unsigned));
|
||||
outuchar(tmpchan, data >> 24);
|
||||
outuchar(tmpchan, data >> 16);
|
||||
outuchar(tmpchan, data >> 8);
|
||||
}
|
||||
|
||||
void write_periph_word_two_part_end(chanend tmpchan, unsigned data)
|
||||
{
|
||||
/* Send last byte of data to bring the write to effect */
|
||||
outuchar(tmpchan, data);
|
||||
outct(tmpchan, XS1_CT_END);
|
||||
}
|
||||
#endif
|
||||
20
lib_xud/lib_xud/src/core/XUD_User.c
Normal file
20
lib_xud/lib_xud/src/core/XUD_User.c
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
/* User functions to be overridden by app */
|
||||
#include "xud.h"
|
||||
|
||||
void XUD_UserSuspend(void) __attribute__ ((weak));
|
||||
void XUD_UserSuspend()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void XUD_UserResume(void) __attribute__ ((weak));
|
||||
void XUD_UserResume()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
558
lib_xud/lib_xud/src/core/included/XUD_PidJumpTable.S
Normal file
558
lib_xud/lib_xud/src/core/included/XUD_PidJumpTable.S
Normal file
@@ -0,0 +1,558 @@
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#if defined (__XS2A__)
|
||||
|
||||
// PID jump table
|
||||
.section .dp.data, "adw", @progbits
|
||||
|
||||
.globl PidJumpTable
|
||||
.type PidJumpTable, @object
|
||||
|
||||
.cc_top PidJumpTable.func, PidJumpTable
|
||||
.align 4
|
||||
PidJumpTable:
|
||||
.word Pid_Reserved // 0 0x00
|
||||
.word Pid_Out // 1 0x01
|
||||
.word Pid_Ack // 2 0x02
|
||||
.word Pid_Data0 // 3 0x03
|
||||
.word Pid_Ping // 4 0x04
|
||||
.word Pid_Sof // 5 0x05
|
||||
.word Pid_Nyet // 6 0x06
|
||||
.word Pid_Data2 // 7 0x07
|
||||
.word Pid_Split // 8 0x08
|
||||
.word Pid_In // 9 0x09
|
||||
.word Pid_Nak // 10 0x0a
|
||||
.word Pid_Data1 // 11 0x0b
|
||||
.word Pid_Pre // 12 0x0c
|
||||
.word Pid_Setup // 13 0x0d
|
||||
.word Pid_Stall // 14 0x0e
|
||||
.word Pid_Datam // 15 0x0f
|
||||
#if defined(XUD_DEBUG_VERSION) || defined(XUD_FULL_PIDTABLE)
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad //31
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
.word Pid_Bad
|
||||
|
||||
#endif
|
||||
|
||||
.size PidJumpTable, .-PidJumpTable
|
||||
.cc_bottom PidJumpTable.func
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(__XS2A__)
|
||||
// Generated using genpidtable.c
|
||||
.section .dp.data, "adw", @progbits
|
||||
.globl PidJumpTable
|
||||
.type PidJumpTable, @function
|
||||
|
||||
//.cc_top PidJumpTable.func, PidJumpTableFull
|
||||
.cc_top PidJumpTable.func, PidJumpTable
|
||||
.align 4
|
||||
|
||||
PidJumpTable:
|
||||
.word Pid_Bad // 0 0x00
|
||||
.word Pid_Bad // 1 0x01
|
||||
.word Pid_Bad // 2 0x02
|
||||
.word Pid_Bad // 3 0x03
|
||||
.word Pid_Bad // 4 0x04
|
||||
.word Pid_Bad // 5 0x05
|
||||
.word Pid_Bad // 6 0x06
|
||||
.word Pid_Bad // 7 0x07
|
||||
.word Pid_Bad // 8 0x08
|
||||
.word Pid_Bad // 9 0x09
|
||||
.word Pid_Bad // 10 0x0a
|
||||
.word Pid_Bad // 11 0x0b
|
||||
.word Pid_Bad // 12 0x0c
|
||||
.word Pid_Bad // 13 0x0d
|
||||
.word Pid_Bad // 14 0x0e
|
||||
.word Pid_MData // 15 0x0f
|
||||
.word Pid_Bad // 16 0x10
|
||||
.word Pid_Bad // 17 0x11
|
||||
.word Pid_Bad // 18 0x12
|
||||
.word Pid_Bad // 19 0x13
|
||||
.word Pid_Bad // 20 0x14
|
||||
.word Pid_Bad // 21 0x15
|
||||
.word Pid_Bad // 22 0x16
|
||||
.word Pid_Bad // 23 0x17
|
||||
.word Pid_Split // 24 0x1
|
||||
.word Pid_Bad // 25 0x19
|
||||
.word Pid_Bad // 26 0x1a
|
||||
.word Pid_Bad // 27 0x1b
|
||||
.word Pid_Bad // 28 0x1c
|
||||
.word Pid_Bad // 29 0x1d
|
||||
.word Pid_Stall // 30 0x1e
|
||||
.word Pid_Bad // 31 0x1f
|
||||
.word Pid_Bad // 32 0x20
|
||||
.word Pid_Bad // 33 0x21
|
||||
.word Pid_Bad // 34 0x22
|
||||
.word Pid_Bad // 35 0x23
|
||||
.word Pid_Bad // 36 0x24
|
||||
.word Pid_Bad // 37 0x25
|
||||
.word Pid_Bad // 38 0x26
|
||||
.word Pid_Bad // 39 0x27
|
||||
.word Pid_Bad // 40 0x28
|
||||
.word Pid_Bad // 41 0x29
|
||||
.word Pid_Bad // 42 0x2a
|
||||
.word Pid_Bad // 43 0x2b
|
||||
.word Pid_Bad // 44 0x2c
|
||||
.word Pid_Setup // 45 0x2d
|
||||
.word Pid_Bad // 46 0x2e
|
||||
.word Pid_Bad // 47 0x2f
|
||||
.word Pid_Bad // 48 0x30
|
||||
.word Pid_Bad // 49 0x31
|
||||
.word Pid_Bad // 50 0x32
|
||||
.word Pid_Bad // 51 0x33
|
||||
.word Pid_Bad // 52 0x34
|
||||
.word Pid_Bad // 53 0x35
|
||||
.word Pid_Bad // 54 0x36
|
||||
.word Pid_Bad // 55 0x37
|
||||
.word Pid_Bad // 56 0x38
|
||||
.word Pid_Bad // 57 0x39
|
||||
.word Pid_Bad // 58 0x3a
|
||||
.word Pid_Bad // 59 0x3b
|
||||
.word Pid_Pre // 60 0x3c
|
||||
.word Pid_Bad // 61 0x3d
|
||||
.word Pid_Bad // 62 0x3e
|
||||
.word Pid_Bad // 63 0x3f
|
||||
.word Pid_Bad // 64 0x40
|
||||
.word Pid_Bad // 65 0x41
|
||||
.word Pid_Bad // 66 0x42
|
||||
.word Pid_Bad // 67 0x43
|
||||
.word Pid_Bad // 68 0x44
|
||||
.word Pid_Bad // 69 0x45
|
||||
.word Pid_Bad // 70 0x46
|
||||
.word Pid_Bad // 71 0x47
|
||||
.word Pid_Bad // 72 0x48
|
||||
.word Pid_Bad // 73 0x49
|
||||
.word Pid_Bad // 74 0x4a
|
||||
.word Pid_Data1 // 75 0x4b
|
||||
.word Pid_Bad // 76 0x4c
|
||||
.word Pid_Bad // 77 0x4d
|
||||
.word Pid_Bad // 78 0x4e
|
||||
.word Pid_Bad // 79 0x4f
|
||||
.word Pid_Bad // 80 0x50
|
||||
.word Pid_Bad // 81 0x51
|
||||
.word Pid_Bad // 82 0x52
|
||||
.word Pid_Bad // 83 0x53
|
||||
.word Pid_Bad // 84 0x54
|
||||
.word Pid_Bad // 85 0x55
|
||||
.word Pid_Bad // 86 0x56
|
||||
.word Pid_Bad // 87 0x57
|
||||
.word Pid_Bad // 88 0x58
|
||||
.word Pid_Bad // 89 0x59
|
||||
.word Pid_Nak // 90 0x5a
|
||||
.word Pid_Bad // 91 0x5b
|
||||
.word Pid_Bad // 92 0x5c
|
||||
.word Pid_Bad // 93 0x5d
|
||||
.word Pid_Bad // 94 0x5e
|
||||
.word Pid_Bad // 95 0x5f
|
||||
.word Pid_Bad // 96 0x60
|
||||
.word Pid_Bad // 97 0x61
|
||||
.word Pid_Bad // 98 0x62
|
||||
.word Pid_Bad // 99 0x63
|
||||
.word Pid_Bad // 100 0x64
|
||||
.word Pid_Bad // 101 0x65
|
||||
.word Pid_Bad // 102 0x66
|
||||
.word Pid_Bad // 103 0x67
|
||||
.word Pid_Bad // 104 0x68
|
||||
.word Pid_In // 105 0x69
|
||||
.word Pid_Bad // 106 0x6a
|
||||
.word Pid_Bad // 107 0x6b
|
||||
.word Pid_Bad // 108 0x6c
|
||||
.word Pid_Bad // 109 0x6d
|
||||
.word Pid_Bad // 110 0x6e
|
||||
.word Pid_Bad // 111 0x6f
|
||||
.word Pid_Bad // 112 0x70
|
||||
.word Pid_Bad // 113 0x71
|
||||
.word Pid_Bad // 114 0x72
|
||||
.word Pid_Bad // 115 0x73
|
||||
.word Pid_Bad // 116 0x74
|
||||
.word Pid_Bad // 117 0x75
|
||||
.word Pid_Bad // 118 0x76
|
||||
.word Pid_Bad // 119 0x77
|
||||
.word Pid_Bad // 120 0x78
|
||||
.word Pid_Bad // 121 0x79
|
||||
.word Pid_Bad // 122 0x7a
|
||||
.word Pid_Bad // 123 0x7b
|
||||
.word Pid_Bad // 124 0x7c
|
||||
.word Pid_Bad // 125 0x7d
|
||||
.word Pid_Bad // 126 0x7e
|
||||
.word Pid_Bad // 127 0x7f
|
||||
.word Pid_Bad // 128 0x80
|
||||
.word Pid_Bad // 129 0x81
|
||||
.word Pid_Bad // 130 0x82
|
||||
.word Pid_Bad // 131 0x83
|
||||
.word Pid_Bad // 132 0x84
|
||||
.word Pid_Bad // 133 0x85
|
||||
.word Pid_Bad // 134 0x86
|
||||
.word Pid_Data2 // 135 0x87
|
||||
.word Pid_Bad // 136 0x88
|
||||
.word Pid_Bad // 137 0x89
|
||||
.word Pid_Bad // 138 0x8a
|
||||
.word Pid_Bad // 139 0x8b
|
||||
.word Pid_Bad // 140 0x8c
|
||||
.word Pid_Bad // 141 0x8d
|
||||
.word Pid_Bad // 142 0x8e
|
||||
.word Pid_Bad // 143 0x8f
|
||||
.word Pid_Bad // 144 0x90
|
||||
.word Pid_Bad // 145 0x91
|
||||
.word Pid_Bad // 146 0x92
|
||||
.word Pid_Bad // 147 0x93
|
||||
.word Pid_Bad // 148 0x94
|
||||
.word Pid_Bad // 149 0x95
|
||||
.word Pid_NYet // 150 0x96
|
||||
.word Pid_Bad // 151 0x97
|
||||
.word Pid_Bad // 152 0x98
|
||||
.word Pid_Bad // 153 0x99
|
||||
.word Pid_Bad // 154 0x9a
|
||||
.word Pid_Bad // 155 0x9b
|
||||
.word Pid_Bad // 156 0x9c
|
||||
.word Pid_Bad // 157 0x9d
|
||||
.word Pid_Bad // 158 0x9e
|
||||
.word Pid_Bad // 159 0x9f
|
||||
.word Pid_Bad // 160 0xa0
|
||||
.word Pid_Bad // 161 0xa1
|
||||
.word Pid_Bad // 162 0xa2
|
||||
.word Pid_Bad // 163 0xa3
|
||||
.word Pid_Bad // 164 0xa4
|
||||
.word Pid_Sof // 165 0xa5
|
||||
.word Pid_Bad // 166 0xa6
|
||||
.word Pid_Bad // 167 0xa7
|
||||
.word Pid_Bad // 168 0xa8
|
||||
.word Pid_Bad // 169 0xa9
|
||||
.word Pid_Bad // 170 0xaa
|
||||
.word Pid_Bad // 171 0xab
|
||||
.word Pid_Bad // 172 0xac
|
||||
.word Pid_Bad // 173 0xad
|
||||
.word Pid_Bad // 174 0xae
|
||||
.word Pid_Bad // 175 0xaf
|
||||
.word Pid_Bad // 176 0xb0
|
||||
.word Pid_Bad // 177 0xb1
|
||||
.word Pid_Bad // 178 0xb2
|
||||
.word Pid_Bad // 179 0xb3
|
||||
.word Pid_Ping // 180 0xb4
|
||||
.word Pid_Bad // 181 0xb5
|
||||
.word Pid_Bad // 182 0xb6
|
||||
.word Pid_Bad // 183 0xb7
|
||||
.word Pid_Bad // 184 0xb8
|
||||
.word Pid_Bad // 185 0xb9
|
||||
.word Pid_Bad // 186 0xba
|
||||
.word Pid_Bad // 187 0xbb
|
||||
.word Pid_Bad // 188 0xbc
|
||||
.word Pid_Bad // 189 0xbd
|
||||
.word Pid_Bad // 190 0xbe
|
||||
.word Pid_Bad // 191 0xbf
|
||||
.word Pid_Bad // 192 0xc0
|
||||
.word Pid_Bad // 193 0xc1
|
||||
.word Pid_Bad // 194 0xc2
|
||||
.word Pid_Data0 // 195 0xc3
|
||||
.word Pid_Bad // 196 0xc4
|
||||
.word Pid_Bad // 197 0xc5
|
||||
.word Pid_Bad // 198 0xc6
|
||||
.word Pid_Bad // 199 0xc7
|
||||
.word Pid_Bad // 200 0xc8
|
||||
.word Pid_Bad // 201 0xc9
|
||||
.word Pid_Bad // 202 0xca
|
||||
.word Pid_Bad // 203 0xcb
|
||||
.word Pid_Bad // 204 0xcc
|
||||
.word Pid_Bad // 205 0xcd
|
||||
.word Pid_Bad // 206 0xce
|
||||
.word Pid_Bad // 207 0xcf
|
||||
.word Pid_Bad // 208 0xd0
|
||||
.word Pid_Bad // 209 0xd1
|
||||
.word Pid_Ack // 210 0xd2
|
||||
.word Pid_Bad // 211 0xd3
|
||||
.word Pid_Bad // 212 0xd4
|
||||
.word Pid_Bad // 213 0xd5
|
||||
.word Pid_Bad // 214 0xd6
|
||||
.word Pid_Bad // 215 0xd7
|
||||
.word Pid_Bad // 216 0xd8
|
||||
.word Pid_Bad // 217 0xd9
|
||||
.word Pid_Bad // 218 0xda
|
||||
.word Pid_Bad // 219 0xdb
|
||||
.word Pid_Bad // 220 0xdc
|
||||
.word Pid_Bad // 221 0xdd
|
||||
.word Pid_Bad // 222 0xde
|
||||
.word Pid_Bad // 223 0xdf
|
||||
.word Pid_Bad // 224 0xe0
|
||||
.word Pid_Out // 225 0xe1
|
||||
.word Pid_Bad // 226 0xe2
|
||||
.word Pid_Bad // 227 0xe3
|
||||
.word Pid_Bad // 228 0xe4
|
||||
.word Pid_Bad // 229 0xe5
|
||||
.word Pid_Bad // 230 0xe6
|
||||
.word Pid_Bad // 231 0xe7
|
||||
.word Pid_Bad // 232 0xe8
|
||||
.word Pid_Bad // 233 0xe9
|
||||
.word Pid_Bad // 234 0xea
|
||||
.word Pid_Bad // 235 0xeb
|
||||
.word Pid_Bad // 236 0xec
|
||||
.word Pid_Bad // 237 0xed
|
||||
.word Pid_Bad // 238 0xee
|
||||
.word Pid_Bad // 239 0xef
|
||||
.word Pid_Bad // 240 0xf0
|
||||
.word Pid_Bad // 241 0xf1
|
||||
.word Pid_Bad // 242 0xf2
|
||||
.word Pid_Bad // 243 0xf3
|
||||
.word Pid_Bad // 244 0xf4
|
||||
.word Pid_Bad // 245 0xf5
|
||||
.word Pid_Bad // 246 0xf6
|
||||
.word Pid_Bad // 247 0xf7
|
||||
.word Pid_Bad // 248 0xf8
|
||||
.word Pid_Bad // 249 0xf9
|
||||
.word Pid_Bad // 250 0xfa
|
||||
.word Pid_Bad // 251 0xfb
|
||||
.word Pid_Bad // 252 0xfc
|
||||
.word Pid_Bad // 253 0xfd
|
||||
.word Pid_Bad // 254 0xfe
|
||||
.word Pid_Bad // 255 0xff
|
||||
|
||||
.size PidJumpTable, .-PidJumpTable
|
||||
.cc_bottom PidJumpTable.func
|
||||
//.cc_bottom PidJumpTableFull.func
|
||||
|
||||
#endif
|
||||
556
lib_xud/lib_xud/src/core/included/XUD_PidJumpTable_RxData.S
Normal file
556
lib_xud/lib_xud/src/core/included/XUD_PidJumpTable_RxData.S
Normal file
@@ -0,0 +1,556 @@
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#if defined (__XS2A__)
|
||||
|
||||
// PID jump table
|
||||
.section .dp.data, "adw", @progbits
|
||||
|
||||
.globl PidJumpTable_RxData
|
||||
.type PidJumpTable_RxData, @object
|
||||
|
||||
.cc_top PidJumpTable_RxData.func, PidJumpTable_RxData
|
||||
.align 4
|
||||
PidJumpTable_RxData:
|
||||
.word Pid_Reserved // 0 0x00
|
||||
.word Pid_Out // 1 0x01
|
||||
.word Pid_Ack // 2 0x02
|
||||
.word Pid_Data0_RxData // 3 0x03
|
||||
.word Pid_Ping // 4 0x04
|
||||
.word Pid_Sof // 5 0x05
|
||||
.word Pid_Nyet // 6 0x06
|
||||
.word Pid_Data2_RxData // 7 0x07
|
||||
.word Pid_Split // 8 0x08
|
||||
.word Pid_In // 9 0x09
|
||||
.word Pid_Nak // 10 0x0a
|
||||
.word Pid_Data1_RxData // 11 0x0b
|
||||
.word Pid_Pre // 12 0x0c
|
||||
.word Pid_Setup // 13 0x0d
|
||||
.word Pid_Stall // 14 0x0e
|
||||
.word Pid_Datam_RxData // 15 0x0f
|
||||
#if defined(XUD_DEBUG_VERSION) || defined(XUD_FULL_PIDTABLE)
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
.word Pid_Bad_RxData
|
||||
|
||||
#endif
|
||||
|
||||
.size PidJumpTable_RxData, .-PidJumpTable_RxData
|
||||
.cc_bottom PidJumpTable_RxData.func
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(__XS2A__)
|
||||
// Generated using genpidtable.c
|
||||
.section .dp.data, "adw", @progbits
|
||||
.globl PidJumpTable_RxData
|
||||
.type PidJumpTable_RxData, @function
|
||||
|
||||
.cc_top PidJumpTable_RxData.func, PidJumpTable_RxData
|
||||
.align 4
|
||||
|
||||
PidJumpTable_RxData:
|
||||
.word Pid_Bad_RxData // 0 0x00
|
||||
.word Pid_Bad_RxData // 1 0x01
|
||||
.word Pid_Bad_RxData // 2 0x02
|
||||
.word Pid_Bad_RxData // 3 0x03
|
||||
.word Pid_Bad_RxData // 4 0x04
|
||||
.word Pid_Bad_RxData // 5 0x05
|
||||
.word Pid_Bad_RxData // 6 0x06
|
||||
.word Pid_Bad_RxData // 7 0x07
|
||||
.word Pid_Bad_RxData // 8 0x08
|
||||
.word Pid_Bad_RxData // 9 0x09
|
||||
.word Pid_Bad_RxData // 10 0x0a
|
||||
.word Pid_Bad_RxData // 11 0x0b
|
||||
.word Pid_Bad_RxData // 12 0x0c
|
||||
.word Pid_Bad_RxData // 13 0x0d
|
||||
.word Pid_Bad_RxData // 14 0x0e
|
||||
.word Pid_MData // 15 0x0f
|
||||
.word Pid_Bad_RxData // 16 0x10
|
||||
.word Pid_Bad_RxData // 17 0x11
|
||||
.word Pid_Bad_RxData // 18 0x12
|
||||
.word Pid_Bad_RxData // 19 0x13
|
||||
.word Pid_Bad_RxData // 20 0x14
|
||||
.word Pid_Bad_RxData // 21 0x15
|
||||
.word Pid_Bad_RxData // 22 0x16
|
||||
.word Pid_Bad_RxData // 23 0x17
|
||||
.word Pid_Bad_RxData // 24 0x1
|
||||
.word Pid_Bad_RxData // 25 0x19
|
||||
.word Pid_Bad_RxData // 26 0x1a
|
||||
.word Pid_Bad_RxData // 27 0x1b
|
||||
.word Pid_Bad_RxData // 28 0x1c
|
||||
.word Pid_Bad_RxData // 29 0x1d
|
||||
.word Pid_Bad_RxData // 30 0x1e
|
||||
.word Pid_Bad_RxData // 31 0x1f
|
||||
.word Pid_Bad_RxData // 32 0x20
|
||||
.word Pid_Bad_RxData // 33 0x21
|
||||
.word Pid_Bad_RxData // 34 0x22
|
||||
.word Pid_Bad_RxData // 35 0x23
|
||||
.word Pid_Bad_RxData // 36 0x24
|
||||
.word Pid_Bad_RxData // 37 0x25
|
||||
.word Pid_Bad_RxData // 38 0x26
|
||||
.word Pid_Bad_RxData // 39 0x27
|
||||
.word Pid_Bad_RxData // 40 0x28
|
||||
.word Pid_Bad_RxData // 41 0x29
|
||||
.word Pid_Bad_RxData // 42 0x2a
|
||||
.word Pid_Bad_RxData // 43 0x2b
|
||||
.word Pid_Bad_RxData // 44 0x2c
|
||||
.word Pid_Bad_RxData // 45 0x2d
|
||||
.word Pid_Bad_RxData // 46 0x2e
|
||||
.word Pid_Bad_RxData // 47 0x2f
|
||||
.word Pid_Bad_RxData // 48 0x30
|
||||
.word Pid_Bad_RxData // 49 0x31
|
||||
.word Pid_Bad_RxData // 50 0x32
|
||||
.word Pid_Bad_RxData // 51 0x33
|
||||
.word Pid_Bad_RxData // 52 0x34
|
||||
.word Pid_Bad_RxData // 53 0x35
|
||||
.word Pid_Bad_RxData // 54 0x36
|
||||
.word Pid_Bad_RxData // 55 0x37
|
||||
.word Pid_Bad_RxData // 56 0x38
|
||||
.word Pid_Bad_RxData // 57 0x39
|
||||
.word Pid_Bad_RxData // 58 0x3a
|
||||
.word Pid_Bad_RxData // 59 0x3b
|
||||
.word Pid_Bad_RxData // 60 0x3c
|
||||
.word Pid_Bad_RxData // 61 0x3d
|
||||
.word Pid_Bad_RxData // 62 0x3e
|
||||
.word Pid_Bad_RxData // 63 0x3f
|
||||
.word Pid_Bad_RxData // 64 0x40
|
||||
.word Pid_Bad_RxData // 65 0x41
|
||||
.word Pid_Bad_RxData // 66 0x42
|
||||
.word Pid_Bad_RxData // 67 0x43
|
||||
.word Pid_Bad_RxData // 68 0x44
|
||||
.word Pid_Bad_RxData // 69 0x45
|
||||
.word Pid_Bad_RxData // 70 0x46
|
||||
.word Pid_Bad_RxData // 71 0x47
|
||||
.word Pid_Bad_RxData // 72 0x48
|
||||
.word Pid_Bad_RxData // 73 0x49
|
||||
.word Pid_Bad_RxData // 74 0x4a
|
||||
.word Pid_Data1_RxData // 75 0x4b
|
||||
.word Pid_Bad_RxData // 76 0x4c
|
||||
.word Pid_Bad_RxData // 77 0x4d
|
||||
.word Pid_Bad_RxData // 78 0x4e
|
||||
.word Pid_Bad_RxData // 79 0x4f
|
||||
.word Pid_Bad_RxData // 80 0x50
|
||||
.word Pid_Bad_RxData // 81 0x51
|
||||
.word Pid_Bad_RxData // 82 0x52
|
||||
.word Pid_Bad_RxData // 83 0x53
|
||||
.word Pid_Bad_RxData // 84 0x54
|
||||
.word Pid_Bad_RxData // 85 0x55
|
||||
.word Pid_Bad_RxData // 86 0x56
|
||||
.word Pid_Bad_RxData // 87 0x57
|
||||
.word Pid_Bad_RxData // 88 0x58
|
||||
.word Pid_Bad_RxData // 89 0x59
|
||||
.word Pid_Bad_RxData // 90 0x5a
|
||||
.word Pid_Bad_RxData // 91 0x5b
|
||||
.word Pid_Bad_RxData // 92 0x5c
|
||||
.word Pid_Bad_RxData // 93 0x5d
|
||||
.word Pid_Bad_RxData // 94 0x5e
|
||||
.word Pid_Bad_RxData // 95 0x5f
|
||||
.word Pid_Bad_RxData // 96 0x60
|
||||
.word Pid_Bad_RxData // 97 0x61
|
||||
.word Pid_Bad_RxData // 98 0x62
|
||||
.word Pid_Bad_RxData // 99 0x63
|
||||
.word Pid_Bad_RxData // 100 0x64
|
||||
.word Pid_Bad_RxData // 101 0x65
|
||||
.word Pid_Bad_RxData // 102 0x66
|
||||
.word Pid_Bad_RxData // 103 0x67
|
||||
.word Pid_Bad_RxData // 104 0x68
|
||||
.word Pid_Bad_RxData // 105 0x69
|
||||
.word Pid_Bad_RxData // 106 0x6a
|
||||
.word Pid_Bad_RxData // 107 0x6b
|
||||
.word Pid_Bad_RxData // 108 0x6c
|
||||
.word Pid_Bad_RxData // 109 0x6d
|
||||
.word Pid_Bad_RxData // 110 0x6e
|
||||
.word Pid_Bad_RxData // 111 0x6f
|
||||
.word Pid_Bad_RxData // 112 0x70
|
||||
.word Pid_Bad_RxData // 113 0x71
|
||||
.word Pid_Bad_RxData // 114 0x72
|
||||
.word Pid_Bad_RxData // 115 0x73
|
||||
.word Pid_Bad_RxData // 116 0x74
|
||||
.word Pid_Bad_RxData // 117 0x75
|
||||
.word Pid_Bad_RxData // 118 0x76
|
||||
.word Pid_Bad_RxData // 119 0x77
|
||||
.word Pid_Bad_RxData // 120 0x78
|
||||
.word Pid_Bad_RxData // 121 0x79
|
||||
.word Pid_Bad_RxData // 122 0x7a
|
||||
.word Pid_Bad_RxData // 123 0x7b
|
||||
.word Pid_Bad_RxData // 124 0x7c
|
||||
.word Pid_Bad_RxData // 125 0x7d
|
||||
.word Pid_Bad_RxData // 126 0x7e
|
||||
.word Pid_Bad_RxData // 127 0x7f
|
||||
.word Pid_Bad_RxData // 128 0x80
|
||||
.word Pid_Bad_RxData // 129 0x81
|
||||
.word Pid_Bad_RxData // 130 0x82
|
||||
.word Pid_Bad_RxData // 131 0x83
|
||||
.word Pid_Bad_RxData // 132 0x84
|
||||
.word Pid_Bad_RxData // 133 0x85
|
||||
.word Pid_Bad_RxData // 134 0x86
|
||||
.word Pid_Data2 // 135 0x87
|
||||
.word Pid_Bad_RxData // 136 0x88
|
||||
.word Pid_Bad_RxData // 137 0x89
|
||||
.word Pid_Bad_RxData // 138 0x8a
|
||||
.word Pid_Bad_RxData // 139 0x8b
|
||||
.word Pid_Bad_RxData // 140 0x8c
|
||||
.word Pid_Bad_RxData // 141 0x8d
|
||||
.word Pid_Bad_RxData // 142 0x8e
|
||||
.word Pid_Bad_RxData // 143 0x8f
|
||||
.word Pid_Bad_RxData // 144 0x90
|
||||
.word Pid_Bad_RxData // 145 0x91
|
||||
.word Pid_Bad_RxData // 146 0x92
|
||||
.word Pid_Bad_RxData // 147 0x93
|
||||
.word Pid_Bad_RxData // 148 0x94
|
||||
.word Pid_Bad_RxData // 149 0x95
|
||||
.word Pid_Bad_RxData // 150 0x96
|
||||
.word Pid_Bad_RxData // 151 0x97
|
||||
.word Pid_Bad_RxData // 152 0x98
|
||||
.word Pid_Bad_RxData // 153 0x99
|
||||
.word Pid_Bad_RxData // 154 0x9a
|
||||
.word Pid_Bad_RxData // 155 0x9b
|
||||
.word Pid_Bad_RxData // 156 0x9c
|
||||
.word Pid_Bad_RxData // 157 0x9d
|
||||
.word Pid_Bad_RxData // 158 0x9e
|
||||
.word Pid_Bad_RxData // 159 0x9f
|
||||
.word Pid_Bad_RxData // 160 0xa0
|
||||
.word Pid_Bad_RxData // 161 0xa1
|
||||
.word Pid_Bad_RxData // 162 0xa2
|
||||
.word Pid_Bad_RxData // 163 0xa3
|
||||
.word Pid_Bad_RxData // 164 0xa4
|
||||
.word Pid_Bad_RxData // 165 0xa5
|
||||
.word Pid_Bad_RxData // 166 0xa6
|
||||
.word Pid_Bad_RxData // 167 0xa7
|
||||
.word Pid_Bad_RxData // 168 0xa8
|
||||
.word Pid_Bad_RxData // 169 0xa9
|
||||
.word Pid_Bad_RxData // 170 0xaa
|
||||
.word Pid_Bad_RxData // 171 0xab
|
||||
.word Pid_Bad_RxData // 172 0xac
|
||||
.word Pid_Bad_RxData // 173 0xad
|
||||
.word Pid_Bad_RxData // 174 0xae
|
||||
.word Pid_Bad_RxData // 175 0xaf
|
||||
.word Pid_Bad_RxData // 176 0xb0
|
||||
.word Pid_Bad_RxData // 177 0xb1
|
||||
.word Pid_Bad_RxData // 178 0xb2
|
||||
.word Pid_Bad_RxData // 179 0xb3
|
||||
.word Pid_Bad_RxData // 180 0xb4
|
||||
.word Pid_Bad_RxData // 181 0xb5
|
||||
.word Pid_Bad_RxData // 182 0xb6
|
||||
.word Pid_Bad_RxData // 183 0xb7
|
||||
.word Pid_Bad_RxData // 184 0xb8
|
||||
.word Pid_Bad_RxData // 185 0xb9
|
||||
.word Pid_Bad_RxData // 186 0xba
|
||||
.word Pid_Bad_RxData // 187 0xbb
|
||||
.word Pid_Bad_RxData // 188 0xbc
|
||||
.word Pid_Bad_RxData // 189 0xbd
|
||||
.word Pid_Bad_RxData // 190 0xbe
|
||||
.word Pid_Bad_RxData // 191 0xbf
|
||||
.word Pid_Bad_RxData // 192 0xc0
|
||||
.word Pid_Bad_RxData // 193 0xc1
|
||||
.word Pid_Bad_RxData // 194 0xc2
|
||||
.word Pid_Data0_RxData // 195 0xc3
|
||||
.word Pid_Bad_RxData // 196 0xc4
|
||||
.word Pid_Bad_RxData // 197 0xc5
|
||||
.word Pid_Bad_RxData // 198 0xc6
|
||||
.word Pid_Bad_RxData // 199 0xc7
|
||||
.word Pid_Bad_RxData // 200 0xc8
|
||||
.word Pid_Bad_RxData // 201 0xc9
|
||||
.word Pid_Bad_RxData // 202 0xca
|
||||
.word Pid_Bad_RxData // 203 0xcb
|
||||
.word Pid_Bad_RxData // 204 0xcc
|
||||
.word Pid_Bad_RxData // 205 0xcd
|
||||
.word Pid_Bad_RxData // 206 0xce
|
||||
.word Pid_Bad_RxData // 207 0xcf
|
||||
.word Pid_Bad_RxData // 208 0xd0
|
||||
.word Pid_Bad_RxData // 209 0xd1
|
||||
.word Pid_Bad_RxData // 210 0xd2
|
||||
.word Pid_Bad_RxData // 211 0xd3
|
||||
.word Pid_Bad_RxData // 212 0xd4
|
||||
.word Pid_Bad_RxData // 213 0xd5
|
||||
.word Pid_Bad_RxData // 214 0xd6
|
||||
.word Pid_Bad_RxData // 215 0xd7
|
||||
.word Pid_Bad_RxData // 216 0xd8
|
||||
.word Pid_Bad_RxData // 217 0xd9
|
||||
.word Pid_Bad_RxData // 218 0xda
|
||||
.word Pid_Bad_RxData // 219 0xdb
|
||||
.word Pid_Bad_RxData // 220 0xdc
|
||||
.word Pid_Bad_RxData // 221 0xdd
|
||||
.word Pid_Bad_RxData // 222 0xde
|
||||
.word Pid_Bad_RxData // 223 0xdf
|
||||
.word Pid_Bad_RxData // 224 0xe0
|
||||
.word Pid_Bad_RxData // 225 0xe1
|
||||
.word Pid_Bad_RxData // 226 0xe2
|
||||
.word Pid_Bad_RxData // 227 0xe3
|
||||
.word Pid_Bad_RxData // 228 0xe4
|
||||
.word Pid_Bad_RxData // 229 0xe5
|
||||
.word Pid_Bad_RxData // 230 0xe6
|
||||
.word Pid_Bad_RxData // 231 0xe7
|
||||
.word Pid_Bad_RxData // 232 0xe8
|
||||
.word Pid_Bad_RxData // 233 0xe9
|
||||
.word Pid_Bad_RxData // 234 0xea
|
||||
.word Pid_Bad_RxData // 235 0xeb
|
||||
.word Pid_Bad_RxData // 236 0xec
|
||||
.word Pid_Bad_RxData // 237 0xed
|
||||
.word Pid_Bad_RxData // 238 0xee
|
||||
.word Pid_Bad_RxData // 239 0xef
|
||||
.word Pid_Bad_RxData // 240 0xf0
|
||||
.word Pid_Bad_RxData // 241 0xf1
|
||||
.word Pid_Bad_RxData // 242 0xf2
|
||||
.word Pid_Bad_RxData // 243 0xf3
|
||||
.word Pid_Bad_RxData // 244 0xf4
|
||||
.word Pid_Bad_RxData // 245 0xf5
|
||||
.word Pid_Bad_RxData // 246 0xf6
|
||||
.word Pid_Bad_RxData // 247 0xf7
|
||||
.word Pid_Bad_RxData // 248 0xf8
|
||||
.word Pid_Bad_RxData // 249 0xf9
|
||||
.word Pid_Bad_RxData // 250 0xfa
|
||||
.word Pid_Bad_RxData // 251 0xfb
|
||||
.word Pid_Bad_RxData // 252 0xfc
|
||||
.word Pid_Bad_RxData // 253 0xfd
|
||||
.word Pid_Bad_RxData // 254 0xfe
|
||||
.word Pid_Bad_RxData // 255 0xff
|
||||
|
||||
.size PidJumpTable_RxData, .-PidJumpTable_RxData
|
||||
.cc_bottom PidJumpTable_RxData.func
|
||||
|
||||
#endif
|
||||
133
lib_xud/lib_xud/src/core/included/XUD_RxData.S
Normal file
133
lib_xud/lib_xud/src/core/included/XUD_RxData.S
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2019-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#define PASTER(x,y) x ## _ ## y
|
||||
#define EVALUATOR(x,y) PASTER(x,y)
|
||||
#define LABEL(fun) fun
|
||||
|
||||
// r0: RXD: Rx Data port
|
||||
// r1: Buffer
|
||||
// r2: Tx Port
|
||||
// r3: Ep structure
|
||||
// r4: Zero (set in XUD_CrcAddCheck.S) then buffer index
|
||||
// r5: EP structures array
|
||||
// r6: CRC Rx init
|
||||
// r7: CRC Tx init
|
||||
// r9: CRC poly
|
||||
// r8: Scratch
|
||||
// r10: EP number
|
||||
// r11: Scratch
|
||||
|
||||
// On exit require:
|
||||
// r4: Datalength (words)
|
||||
// r8: Taillength (bits)
|
||||
// r11: Expected CRC
|
||||
|
||||
Pid_Bad_RxData:
|
||||
ldaw r10, dp[PidJumpTable]
|
||||
{ldw r11, r10[r4]; ldc r8, 16}
|
||||
{bau r11; setpsc res[RXD], r8} // XUD_CrcAddrCheck.S requires 16 in r8
|
||||
|
||||
doRXData:
|
||||
inpw r4, res[r0], 8 // Input PID
|
||||
|
||||
ldw r8, sp[STACK_RXA_PORT]
|
||||
#ifdef __XS2A__
|
||||
// If pid != DATAx then jump and handle as a token. DATA0, DATA1, DATA2 & MDATA all of the form 0bxx11.
|
||||
// This is a fast alternative to a "timeout"
|
||||
// Note, this doesn't check that PID[0:3] = ~PID[4:7] - which is an issue for XS3
|
||||
{mkmsk r11, 2; shr r4, r4, 24}
|
||||
and r11, r11, r4 // Store PID into EP structure,
|
||||
eq r11, r11, 3
|
||||
bf r11, Pid_Bad_RxData
|
||||
#else
|
||||
{shr r4, r4, 24; ldw r11, sp[STACK_PIDJUMPTABLE_RXDATA]}
|
||||
ldw r11, r11[r4]
|
||||
bau r11
|
||||
#endif
|
||||
|
||||
Pid_Datam_RxData:
|
||||
Pid_Data0_RxData:
|
||||
Pid_Data1_RxData:
|
||||
Pid_Data2_RxData:
|
||||
{stw r4, r3[6]; setsr 1} // Store PID into EP structure
|
||||
|
||||
GotRxPid:
|
||||
{eeu res[r8]; mkmsk r4, 32} // Enable events on RxA
|
||||
// Init buffer index to -1
|
||||
|
||||
NextRxWord: // Partially un-rolled to assist with timing
|
||||
in r11, res[r0]
|
||||
crc32_inc r6, r11, r9, r4, 1
|
||||
stw r11, r1[r4]
|
||||
in r11, res[r0]
|
||||
crc32_inc r6, r11, r9, r4, 1
|
||||
stw r11, r1[r4]
|
||||
in r11, res[r0]
|
||||
crc32_inc r6, r11, r9, r4, 1
|
||||
stw r11, r1[r4]
|
||||
in r11, res[r0]
|
||||
crc32_inc r6, r11, r9, r4, 1
|
||||
stw r11, r1[r4]
|
||||
in r11, res[r0]
|
||||
crc32_inc r6, r11, r9, r4, 1
|
||||
stw r11, r1[r4]
|
||||
in r11, res[r0]
|
||||
crc32_inc r6, r11, r9, r4, 1
|
||||
stw r11, r1[r4]
|
||||
in r11, res[r0]
|
||||
crc32_inc r6, r11, r9, r4, 1
|
||||
stw r11, r1[r4]
|
||||
in r11, res[r0]
|
||||
crc32_inc r6, r11, r9, r4, 1
|
||||
stw r11, r1[r4]
|
||||
in r11, res[r0]
|
||||
crc32_inc r6, r11, r9, r4, 1
|
||||
stw r11, r1[r4]
|
||||
bu NextRxWord
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
.align 32
|
||||
.skip 16
|
||||
RxALow:
|
||||
stw r11, r1[r4] // Extra stw, if not enough MIPS STW in loop above may not have chance to run
|
||||
{in r8, res[r8]; add r4, r4, 1} // Clear event data on RXA
|
||||
endin r8, res[r0]
|
||||
LABEL(RxTail):
|
||||
{in r11, res[r0]; bru r8}
|
||||
|
||||
// Word aligned data (0 byte tail)
|
||||
.align 32
|
||||
OutTail0:
|
||||
crc32 r6, r8, r9 // CRC zero step
|
||||
ldw r11, sp[STACK_RXCRC_TAIL0]
|
||||
{RETSP_u6 0; ldc r1, 0}
|
||||
|
||||
// 1 Tail Byte
|
||||
.align 32
|
||||
OutTail1:
|
||||
shr r11, r11, 24 // Shift off junk
|
||||
crc32 r6, r11, r9
|
||||
stw r11, r1[r4] // Store last data
|
||||
LDWSP_ru6 r11, sp[STACK_RXCRC_TAIL1]
|
||||
{RETSP_u6 0; ldc r1, 0}
|
||||
|
||||
// Two Tail Bytes
|
||||
.align 32
|
||||
OutTail2:
|
||||
shr r11, r11, 16
|
||||
crc32 r6, r11, r9
|
||||
stw r11, r1[r4] // Store last data
|
||||
ldw r11, sp[STACK_RXCRC_TAIL2]
|
||||
{RETSP_u6 0; ldc r1, 0}
|
||||
|
||||
// Three Tail Bytes
|
||||
.align 32
|
||||
OutTail3:
|
||||
shr r11, r11, 8
|
||||
stw r11, r1[r4] // Store last data
|
||||
crc32 r6, r11, r9
|
||||
LDWSP_ru6 r11, sp[STACK_RXCRC_TAIL3]
|
||||
crc8 r6, r1, r2, r9 // Use the fact the the bottom byte of port id is 0.. saves us an ldc
|
||||
{RETSP_u6 0; ldc r1, 0}
|
||||
|
||||
221
lib_xud/lib_xud/src/core/included/XUD_Token_In_DI.S
Normal file
221
lib_xud/lib_xud/src/core/included/XUD_Token_In_DI.S
Normal file
@@ -0,0 +1,221 @@
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <xs1.h>
|
||||
#include "XUD_AlignmentDefines.h"
|
||||
|
||||
// Ports
|
||||
#define RXD r0
|
||||
#define RXA r1
|
||||
#define TXD r2
|
||||
|
||||
// On entry:
|
||||
// R11: Branch address (now free)
|
||||
// R10: EP number (used here)
|
||||
// R9 : CRC16 Poly (used here)
|
||||
// R8 :
|
||||
// R7 : Tx CRC init
|
||||
// R6 : ep_pid_sequence_table_IN_A
|
||||
// R5 : EP structures array
|
||||
// R4 :
|
||||
// R3 : 0
|
||||
// R2 : TXD
|
||||
// R1 : XS2: Valid Token Port, XS3: Spare!
|
||||
// R0 : RXD
|
||||
.align FUNCTION_ALIGNMENT
|
||||
XUD_IN_NotReady:
|
||||
ldw r11, sp[STACK_EPTYPES_IN]
|
||||
ldw r11, r11[r10] // Load EP Type
|
||||
bt r11, XUD_IN_TxHandshake
|
||||
ldc r11, 0xc3 // Create 0-length packet
|
||||
outpw res[TXD], r11, 24
|
||||
#include "XUD_TokenJmp.S"
|
||||
|
||||
XUD_IN_TxHandshake: // Non-Iso
|
||||
ldaw r11, dp[epAddr]
|
||||
ldw r11, r11[r3]
|
||||
ldw r11, r11[10]
|
||||
|
||||
bf r11, XUD_IN_TxNak
|
||||
XUD_IN_TxStall:
|
||||
outpw res[TXD], r11, 8 // Output STALL
|
||||
#include "XUD_TokenJmp.S"
|
||||
|
||||
XUD_IN_TxNak:
|
||||
ldc r11, USB_PIDn_NAK
|
||||
outpw res[TXD], r11, 8
|
||||
#include "XUD_TokenJmp.S"
|
||||
|
||||
.align FUNCTION_ALIGNMENT
|
||||
Pid_In:
|
||||
#include "XUD_CrcAddrCheck.S"
|
||||
ldaw r3, r10[4] // R3 = R10 + 16
|
||||
ldw r4, r5[r3] // Load EP structure address
|
||||
bf r4, XUD_IN_NotReady
|
||||
ldw r1, r4[4] // Load PID from structure
|
||||
|
||||
XUD_IN_Ready:
|
||||
ldw r8, r4[3] // Load buffer
|
||||
ldw r6, r4[7] // Load tail length (bytes)
|
||||
ldw r4, r4[6] // Load data length (words)
|
||||
bf r4, XUD_IN_SmallTxPacket // Check for Short packet
|
||||
|
||||
XUD_IN_Tx:
|
||||
ldw r11, r8[r4] // Load first data word
|
||||
crc32_inc r7, r11, r9, r4, 1
|
||||
outpw res[TXD], r1, 8 // Out PID
|
||||
|
||||
XUD_IN_Loop0:
|
||||
{out res[TXD], r11; bf r4, XUD_IN_TxLoopEnd}
|
||||
|
||||
XUD_IN_TxLoop:
|
||||
ldw r11, r8[r4] // Load first data word
|
||||
crc32_inc r7, r11, r9, r4, 1
|
||||
{out res[TXD], r11; bt r4, XUD_IN_TxLoop}
|
||||
|
||||
XUD_IN_TxLoopEnd:
|
||||
ldw r11, r8[r4] // Load tail
|
||||
crcn r7, r11, r9, r6
|
||||
|
||||
XUD_IN_TxLoopEnd_CrcCalc:
|
||||
crc32 r7, r4, r9 // r4: 0 (from bf)
|
||||
outpw res[TXD], r11, r6
|
||||
not r7, r7
|
||||
XUD_IN_TxCrc:
|
||||
outpw res[TXD], r7, 16 // Output 16-bit CRC
|
||||
|
||||
.scheduling default
|
||||
|
||||
// Wait for handshake... or timeout
|
||||
DoneTail:
|
||||
ldw r11, sp[STACK_EPTYPES_IN]
|
||||
ldw r11, r11[r10] // Load EP Type
|
||||
bt r11, SetupReceiveHandShake
|
||||
bu XUD_IN_DoneTx
|
||||
|
||||
SetupReceiveHandShake:
|
||||
ldc r11, 8
|
||||
setpsc res[RXD], r11 // Set port shift count (expect 8 bit handshake)
|
||||
|
||||
SetupTimeout: // Timeout done using another port we dont happen to already be using events on. Cunning.
|
||||
#ifdef __XS2A__
|
||||
ldw r1, sp[STACK_VTOK_PORT] // Load saved ValidToken port. Event vector already set.
|
||||
#else
|
||||
ldw r1, dp[rx_rdy] // TODO load from stack
|
||||
#endif
|
||||
eeu res[RXD] // Events on RXD always enabled - Can't be any more due to using events on channels
|
||||
|
||||
in r11, res[r1] // Do input and get port time/timestamps
|
||||
getts r11, res[r1]
|
||||
ldw r9, dp[g_txHandshakeTimeout]
|
||||
add r11, r11, r9
|
||||
setpt res[r1], r11 // Set port time and enable events
|
||||
eeu res[r1]
|
||||
|
||||
WaitForHandshake: // Wait for timeout or handshake
|
||||
.xtabranch TxHandshakeTimeOut, TxHandShakeReceived
|
||||
waiteu
|
||||
|
||||
// We sent some data but the host didn't handshake in time. Needs a re-send.
|
||||
.align FUNCTION_ALIGNMENT
|
||||
TxHandshakeTimeOut:
|
||||
clre
|
||||
in r11, res[r1] // This will clear port time
|
||||
bu BadHandshake
|
||||
|
||||
// Transmitted data, and got something back within the timeout. Check for valid handshake...
|
||||
.align FUNCTION_ALIGNMENT
|
||||
TxHandShakeReceived:
|
||||
clre
|
||||
in r11, res[RXD] // Input data from RXD port
|
||||
{clrpt res[r1]; // Clear port time on valid token port
|
||||
shr r11, r11, 24} // Shift off junk data to leave ACK
|
||||
#if defined(__XS2A__)
|
||||
ldc r9, USB_PID_ACK // Check for good ACK (L series strips negated bits from PID)
|
||||
#else
|
||||
ldc r9, USB_PIDn_ACK
|
||||
#endif
|
||||
xor r9, r11, r9
|
||||
bt r9, BadHandshake
|
||||
|
||||
XUD_IN_DoneTx:
|
||||
|
||||
ClearInEpReady: // TODO Tidy this up
|
||||
ldc r9, 0 // TODO
|
||||
ldw r10, r5[r3] // Load the EP struct
|
||||
stw r9, r5[r3] // Clear the ready
|
||||
ldw r11, r10[1] // Load channel
|
||||
out res[r11], r11 // Output word to signal packet sent okay
|
||||
bu NextToken
|
||||
|
||||
BadHandshake:
|
||||
bu NextToken
|
||||
|
||||
.align 64
|
||||
.skip 56
|
||||
XUD_IN_SmallTxPacket:
|
||||
ldw r8, r8[r4] // Load first data word
|
||||
bru r6 // Branch on tail-length
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
.align 32
|
||||
.skip 0
|
||||
TxTail0s: // We know this is a < 4 byte packet, so is 0 length packet
|
||||
// So crc = 0. Note our normal crc calculation works for this, it is
|
||||
// Not a special CRC case, but helps with timing.
|
||||
XUD_IN_TxPid_TailS0:
|
||||
outpw res[TXD], r1, 8 // PID
|
||||
XUD_IN_TxCrc_TailS0:
|
||||
outpw res[TXD], r4, 16 // Output CRC
|
||||
bu DoneTail
|
||||
|
||||
.align 32
|
||||
.skip 0
|
||||
TxTail1s: // One tail byte
|
||||
crcn r7, r8, r9, r6
|
||||
crc32 r7, r4, r9 // r4: 0
|
||||
XUD_IN_TxPid_TailS1:
|
||||
not r7, r7
|
||||
outpw res[TXD], r1, 8 // Output PID
|
||||
outpw res[TXD], r8, 8 // Output data[0]
|
||||
XUD_IN_TxCrc_TailS1:
|
||||
outpw res[TXD], r7, 16
|
||||
bu DoneTail
|
||||
|
||||
.align 32
|
||||
.skip 0
|
||||
TxTail2s: // Two tail byte
|
||||
crcn r7, r8, r9, r6
|
||||
crc32 r7, r4, r9 // r4: 0
|
||||
XUD_IN_TxPid_TailS2:
|
||||
outpw res[TXD], r1, 8 // Output PID
|
||||
outpw res[TXD], r8, 16 // Output data[0:1]
|
||||
not r7, r7
|
||||
XUD_IN_TxCrc_TailS2:
|
||||
outpw res[TXD], r7, 16 // Output CRC16
|
||||
bu DoneTail
|
||||
|
||||
.align 32
|
||||
.skip 0
|
||||
TxTail3s: // Three tail byte
|
||||
XUD_IN_TxPid_TailS3:
|
||||
outpw res[TXD], r1, 8 // PID
|
||||
outpw res[TXD], r8, 24
|
||||
crcn r7, r8, r9, r6
|
||||
crc32 r7, r4, r9 // r4: 0
|
||||
not r7, r7
|
||||
XUD_IN_TxCrc_TailS3:
|
||||
outpw res[TXD], r7, 16
|
||||
bu DoneTail
|
||||
|
||||
.align 32
|
||||
.skip 0
|
||||
TxTail4s: // Four tail byte
|
||||
XUD_IN_TxPid_TailS4:
|
||||
outpw res[TXD], r1, 8 // PID
|
||||
out res[TXD], r8
|
||||
crc32 r7, r8, r9
|
||||
crc32 r7, r4, r9 // r4: 0
|
||||
not r7, r7
|
||||
XUD_IN_TxCrc_TailS4:
|
||||
outpw res[TXD], r7, 16
|
||||
bu DoneTail
|
||||
104
lib_xud/lib_xud/src/core/included/XUD_Token_Out_DI.S
Normal file
104
lib_xud/lib_xud/src/core/included/XUD_Token_Out_DI.S
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
// r10: EP number
|
||||
// OUT Token Packet -----------------------------------------------------------------------------
|
||||
#include "XUD_AlignmentDefines.h"
|
||||
|
||||
.align FUNCTION_ALIGNMENT
|
||||
.skip 0
|
||||
Pid_Out:
|
||||
#include "XUD_CrcAddrCheck.S"
|
||||
ldw r3, r5[r10] // Load relevant EP pointer
|
||||
bf r3, XUD_TokenOut_BufferFull
|
||||
ldw r1, r3[3] // Load buffer from EP structure
|
||||
|
||||
CheckEpTypeOut:
|
||||
ldw r11, r3[5] // Load EP type
|
||||
BRFT_ru6 r11, DoOutNonIso // ISO endpoint
|
||||
|
||||
OutReady:
|
||||
BLRF_u10 doRXData // Leaves r1: 0
|
||||
{clre;
|
||||
ldw r11, r3[1]} // Load EP chanend
|
||||
|
||||
InformEP_Iso: // Iso EP - no handshake
|
||||
out res[r11], r4; // Output datalength (words)
|
||||
stw r1, r5[r10] // Clear ready (r1: 0)
|
||||
{outt res[r11], r8; ldw r6, sp[STACK_RXCRC_INIT]} // CRC16 init (out) - Needs reseting after an out & Send tail length
|
||||
#if defined(__XS2A__)
|
||||
ldw r1, sp[STACK_VTOK_PORT]
|
||||
#endif
|
||||
#include "XUD_TokenJmp.S"
|
||||
|
||||
.align FUNCTION_ALIGNMENT
|
||||
.skip 0
|
||||
DoOutNonIso:
|
||||
bl doRXData
|
||||
{clre; eq r11, r6, r11} // Check for good CRC16
|
||||
|
||||
doRXDataReturn_NonIso:
|
||||
bf r11, NextTokenAfterOut // Check for bad crc
|
||||
|
||||
ldc r11, USB_PIDn_ACK // Data CRC good, EP not Iso, and EP not halted: Send Ack
|
||||
outpw res[TXD], r11, 8
|
||||
syncr res[TXD]
|
||||
|
||||
StoreTailDataOut:
|
||||
stw r1, r5[r10] // Clear ready (r1: 0)
|
||||
ldw r11, r3[1] // Load EP chanend
|
||||
|
||||
out res[r11], r4 // Output datalength (words)
|
||||
outt res[r11], r8 // Send tail length
|
||||
|
||||
bu NextTokenAfterOut
|
||||
|
||||
// Various Error handling functions -------------------------------------------------------------------
|
||||
.align FUNCTION_ALIGNMENT
|
||||
Err_RxErr: // RxError signal high during data packet receive:
|
||||
DUALENTSP_lu6 0
|
||||
clrsr 3
|
||||
clre
|
||||
ldw r10, sp[STACK_RXE_PORT] // Read out data from RxE port
|
||||
in r11, res[r10]
|
||||
eeu res[r10]
|
||||
ldw r10, sp[STACK_RXA_PORT]
|
||||
in r11, res[r10] // Wait for rxa low and ignore packet (let transaction timout)
|
||||
setsr 3 // Re-enable thread interrupts
|
||||
bu NextToken
|
||||
|
||||
XUD_TokenOut_BufferFull:
|
||||
ldw r9, sp[STACK_RXA_PORT]
|
||||
setc res[r9], XS1_SETC_RUN_CLRBUF
|
||||
inpw r4, res[r0], 8 // Input PID of next packet.
|
||||
// TODO catch case where PID is not DATA
|
||||
|
||||
XUD_TokenOut_WaitForPacketEnd: // Wait for end of data then send NAK
|
||||
in r11, res[r9]
|
||||
|
||||
#ifndef XUD_NAK_ISO_OUT
|
||||
ldw r4, sp[STACK_EPTYPES_OUT] // Load ep type table
|
||||
ldw r4, r4[r10] // load EP type
|
||||
bf r4, PrimaryBufferFull_NoNak
|
||||
#endif
|
||||
|
||||
// Load handshake (ACK or STALL)
|
||||
XUD_TokenOut_Handshake:
|
||||
ldaw r6, dp[epAddr]
|
||||
ldw r6, r6[r10]
|
||||
ldw r11, r6[10]
|
||||
|
||||
outpw res[TXD], r11, 8
|
||||
syncr res[TXD]
|
||||
|
||||
PrimaryBufferFull_NoNak:
|
||||
setc res[RXD], XS1_SETC_RUN_CLRBUF
|
||||
bu NextToken
|
||||
|
||||
// Timedout waiting for data after OUT... go back to waiting for tokens
|
||||
//OutDataTimeOut:
|
||||
//clre
|
||||
//bl ERR_OutDataTimeout
|
||||
//bu NextToken
|
||||
|
||||
|
||||
|
||||
42
lib_xud/lib_xud/src/core/included/XUD_Token_Ping.S
Normal file
42
lib_xud/lib_xud/src/core/included/XUD_Token_Ping.S
Normal file
@@ -0,0 +1,42 @@
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include "XUD_AlignmentDefines.h"
|
||||
|
||||
.align FUNCTION_ALIGNMENT
|
||||
Pid_Ping:
|
||||
#include "XUD_CrcAddrCheck.S"
|
||||
|
||||
LoadStatTablePing:
|
||||
ldw r11, r5[r10] // Load relevant EP chanend
|
||||
bf r11, PrimaryBufferFull_PING
|
||||
|
||||
.scheduling off
|
||||
PrimaryBufferEmpty_PING: // Send ACK
|
||||
#if (XUD_CORE_CLOCK > 400)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
#endif
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
ldc r11, USB_PIDn_ACK
|
||||
outpw res[TXD], r11, 8
|
||||
bu NextTokenAfterPing
|
||||
|
||||
PrimaryBufferFull_PING: // Send NAK (or STALL)
|
||||
#if (XUD_CORE_CLOCK > 400)
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
#endif
|
||||
|
||||
ldaw r11, dp[epAddr]
|
||||
ldw r11, r11[r10]
|
||||
ldw r11, r11[10]
|
||||
|
||||
outpw res[TXD], r11, 8
|
||||
bu NextTokenAfterPing
|
||||
.scheduling default
|
||||
|
||||
69
lib_xud/lib_xud/src/core/included/XUD_Token_SOF.S
Normal file
69
lib_xud/lib_xud/src/core/included/XUD_Token_SOF.S
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright 2011-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include "XUD_AlignmentDefines.h"
|
||||
|
||||
// Received SOF token: Reset suspend/reset detection timer
|
||||
.align FUNCTION_ALIGNMENT
|
||||
Pid_Sof:
|
||||
#ifdef __XS2A__
|
||||
inpw r10, res[RXD], 8 // Read EP Number
|
||||
shr r10, r10, 24; // Shift off junk
|
||||
|
||||
in r11, res[r1];
|
||||
bt r11, XUD_InvalidToken; // If VALID_TOKEN not high, ignore token
|
||||
|
||||
#else
|
||||
// NOTE: we are not CRC checking SOF's
|
||||
in r10, res[RXD] // Input Frame number
|
||||
shr r10 , r10, 16 // Shift off port junk
|
||||
ldc r11, 0x7ff // Remove CRC5
|
||||
and r10, r10, r11
|
||||
|
||||
#endif
|
||||
clrsr 0x3
|
||||
ldw r11, sp[STACK_SOFCHAN]
|
||||
|
||||
out res[r11], r10
|
||||
|
||||
ldw r10, sp[STACK_SUSPEND_TIMER] // Load timer from stack
|
||||
setc res[r10], XS1_SETC_COND_NONE // Read current time
|
||||
|
||||
ldw r8, sp[STACK_SUSPEND_TIMEOUT] // Add suspend timeout to current time
|
||||
in r11, res[r10]
|
||||
add r11, r11, r8
|
||||
setd res[r10], r11
|
||||
|
||||
setc res[r10], XS1_SETC_COND_AFTER // Re-enable thread interrupts
|
||||
setsr 0x3
|
||||
|
||||
bu Loop_BadPid
|
||||
|
||||
// Received SOF token: Reset suspend/reset detection timer
|
||||
.align FUNCTION_ALIGNMENT
|
||||
Pid_Sof_NoChan:
|
||||
#ifdef __XS2A__
|
||||
inpw r10, res[RXD], 8; /* Read EP Number */
|
||||
shr r10, r10, 24; /* Shift off junk */
|
||||
|
||||
in r11, res[r1];
|
||||
bt r11, XUD_InvalidToken; /* If VALID_TOKEN not high, ignore token */
|
||||
|
||||
#else
|
||||
in r10, res[RXD] // Input Frame number
|
||||
#endif
|
||||
clrsr 0x3
|
||||
ldw r10, sp[STACK_SUSPEND_TIMER] // Load timer from stack
|
||||
setc res[r10], XS1_SETC_COND_NONE // Read current time
|
||||
ldw r8, sp[STACK_SUSPEND_TIMEOUT]
|
||||
in r11, res[r10]
|
||||
add r11, r11, r8
|
||||
setd res[r10], r11
|
||||
ldw r8, sp[STACK_SUSPEND_TIMEOUT]
|
||||
setc res[r10], XS1_SETC_COND_AFTER // Re-enable thread interrupts
|
||||
setsr 0x3
|
||||
bu Loop_BadPid
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
59
lib_xud/lib_xud/src/core/included/XUD_Token_Setup_DI.S
Normal file
59
lib_xud/lib_xud/src/core/included/XUD_Token_Setup_DI.S
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include "XUD_AlignmentDefines.h"
|
||||
|
||||
// We received a setup token. This is much the same as out token, apart from:
|
||||
// - Can't NAK a setup
|
||||
// - Data PID will always be DATA0
|
||||
// - Payload will always be 8 bytes
|
||||
.align FUNCTION_ALIGNMENT
|
||||
Pid_Setup:
|
||||
#include "XUD_CrcAddrCheck.S"
|
||||
ldaw r7, r10[8] // R3 = R10 + 32. Read Past end of epAddr to epAddr_Setup
|
||||
ldw r3, r5[r7] // Load relevant EP pointer
|
||||
bf r3, XUD_Setup_BuffFull
|
||||
ldw r1, r3[3] // Load buffer
|
||||
|
||||
XUD_Setup_LoadBuffer:
|
||||
bl doRXData // RXData writes available data to buffer and does crc check.
|
||||
// r8: Data tail size (bytes)
|
||||
xor r1, r6, r11 // Check for good CRC16
|
||||
{clre;
|
||||
bt r1, XUD_Setup_NotReady} // Branch based on CRC good/bad
|
||||
|
||||
XUD_Setup_ClearStall: // CRC OK
|
||||
// Have received a Setup so clear any STALL condition on IN/OUT endpoint.
|
||||
// Note, we can speed this up by assuming Setup only received on EP 0
|
||||
ldaw r6, dp[epAddr]
|
||||
|
||||
ldaw r11, r10[4] // R11 = R10 + 16
|
||||
ldw r11, r6[r11]
|
||||
stw r1, r11[10] // r1: 0
|
||||
|
||||
ldw r11, r6[r10]
|
||||
ldc r6, USB_PIDn_NAK
|
||||
stw r6, r11[10]
|
||||
|
||||
XUD_Setup_SendSetupAck:
|
||||
ldc r11, USB_PIDn_ACK
|
||||
outpw res[TXD], r11, 8
|
||||
|
||||
XUD_Setup_StoreTailData: // TODO: don't assume setups are 8 bytes + crc
|
||||
stw r1, r5[r7] // Clear ready
|
||||
ldw r11, r3[1] // Load chanend
|
||||
|
||||
out res[r11], r4
|
||||
outct res[r11], 0 // Send zero control token for Setup. Tail ignored since always expect 8 bytes
|
||||
bu NextTokenAfterOut // Go to next wait for next token
|
||||
|
||||
XUD_Setup_BuffFull:
|
||||
ldw r10, sp[STACK_RXA_PORT] // Load RxA Port ID (r1)
|
||||
in r11, res[r10] // RXA event cond = 0 TODO: Wait for RXA high first?
|
||||
endin r11, res[RXD]
|
||||
in r11, res[RXD]
|
||||
bu NextTokenAfterOut
|
||||
|
||||
|
||||
.align FUNCTION_ALIGNMENT
|
||||
XUD_Setup_NotReady:
|
||||
bu NextTokenAfterOut
|
||||
43
lib_xud/lib_xud/src/core/xs1_to_glx.h
Normal file
43
lib_xud/lib_xud/src/core/xs1_to_glx.h
Normal file
@@ -0,0 +1,43 @@
|
||||
// Copyright 2017-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef _XS1_TO_GLX_H_
|
||||
#define _XS1_TO_GLX_H_
|
||||
/* Workaround for tools issue #17048 */
|
||||
|
||||
#define XS1_SU_PER_UIFM_CHANEND_NUM XS1_GLX_PER_UIFM_CHANEND_NUM
|
||||
#define XS1_SU_PER_UIFM_CONTROL_NUM XS1_GLX_PER_UIFM_CONTROL_NUM
|
||||
|
||||
#define XS1_SU_CFG_RST_MISC_NUM XS1_GLX_CFG_RST_MISC_NUM
|
||||
#define XS1_SU_CFG_USB_CLK_EN_SHIFT XS1_GLX_CFG_USB_CLK_EN_SHIFT
|
||||
|
||||
#define XS1_SU_CFG_USB_CLK_EN_SHIFT XS1_GLX_CFG_USB_CLK_EN_SHIFT
|
||||
|
||||
#define XS1_SU_CFG_USB_EN_SHIFT XS1_GLX_CFG_USB_EN_SHIFT
|
||||
|
||||
#define XS1_SU_PER_UIFM_OTG_CONTROL_NUM XS1_GLX_PER_UIFM_OTG_CONTROL_NUM
|
||||
#define XS1_SU_UIFM_IFM_CONTROL_DECODELINESTATE_SHIFT XS1_UIFM_IFM_CONTROL_DECODELINESTATE_SHIFT
|
||||
|
||||
#define XS1_SU_PER_UIFM_FUNC_CONTROL_NUM XS1_GLX_PER_UIFM_FUNC_CONTROL_NUM
|
||||
|
||||
#define XS1_SU_UIFM_FUNC_CONTROL_XCVRSELECT_SHIFT XS1_UIFM_FUNC_CONTROL_XCVRSELECT_SHIFT
|
||||
#define XS1_SU_UIFM_FUNC_CONTROL_TERMSELECT_SHIFT XS1_UIFM_FUNC_CONTROL_TERMSELECT_SHIFT
|
||||
|
||||
#define XS1_SU_PER_UIFM_DEVICE_ADDRESS_NUM XS1_GLX_PER_UIFM_DEVICE_ADDRESS_NUM
|
||||
|
||||
|
||||
#define XS1_SU_UIFM_IFM_CONTROL_DOTOKENS_SHIFT XS1_UIFM_IFM_CONTROL_DOTOKENS_SHIFT
|
||||
#define XS1_SU_UIFM_IFM_CONTROL_CHECKTOKENS_SHIFT XS1_UIFM_IFM_CONTROL_CHECKTOKENS_SHIFT
|
||||
#define XS1_SU_UIFM_IFM_CONTROL_DECODELINESTATE_SHIFT XS1_UIFM_IFM_CONTROL_DECODELINESTATE_SHIFT
|
||||
#define XS1_SU_UIFM_IFM_CONTROL_SOFISTOKEN_SHIFT XS1_UIFM_IFM_CONTROL_SOFISTOKEN_SHIFT
|
||||
|
||||
#define XS1_SU_PER_UIFM_MASK_NUM XS1_GLX_PER_UIFM_MASK_NUM
|
||||
|
||||
#define XS1_SU_UIFM_IFM_FLAGS_NEWTOKEN_SHIFT XS1_UIFM_IFM_FLAGS_NEWTOKEN_SHIFT
|
||||
#define XS1_SU_UIFM_IFM_FLAGS_RXACTIVE_SHIFT XS1_UIFM_IFM_FLAGS_RXACTIVE_SHIFT
|
||||
#define XS1_SU_UIFM_IFM_FLAGS_RXERROR_SHIFT XS1_UIFM_IFM_FLAGS_RXERROR_SHIFT
|
||||
|
||||
#define XS1_SU_PER_UIFM_OTG_FLAGS_NUM XS1_GLX_PER_UIFM_OTG_FLAGS_NUM
|
||||
#define XS1_SU_UIFM_OTG_FLAGS_SESSVLDB_SHIFT XS1_UIFM_OTG_FLAGS_SESSVLDB_SHIFT
|
||||
|
||||
#endif
|
||||
71
lib_xud/lib_xud/src/user/XUD_USB_Defines.h
Normal file
71
lib_xud/lib_xud/src/user/XUD_USB_Defines.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright 2015-2024 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/**
|
||||
* @brief Defines from the Universal Serial Bus Specification Revision 2.0
|
||||
**/
|
||||
|
||||
#ifndef _USB_DEFS_H_
|
||||
#define _USB_DEFS_H_
|
||||
|
||||
/* Table 8-1. PID Types */
|
||||
#define USB_PID_OUT 0x1 /* Tokens */
|
||||
#define USB_PID_IN 0x9
|
||||
#define USB_PID_SOF 0x5
|
||||
#define USB_PID_SETUP 0xD
|
||||
#define USB_PID_DATA0 0x3 /* Data packet PID even */
|
||||
#define USB_PID_DATA1 0xB /* Data packet PID odd */
|
||||
#define USB_PID_DATA2 0x7 /* Data packet PID high-speed, high bandwidth isoc transaction in a microframe */
|
||||
#define USB_PID_MDATA 0xF /* Data packet PID high-speed and high bandwidth isoc transactions */
|
||||
#define USB_PID_ACK 0x2 /* Receiver accepts error-free data packet */
|
||||
#define USB_PID_NAK 0xA /* Receiving device cannot accept data of transmitting device cannot send data */
|
||||
#define USB_PID_STALL 0xE /* Endpoint is halted or a control pipe request is not supported */
|
||||
#define USB_PID_PRE 0xC
|
||||
#define USB_PID_ERR 0xC
|
||||
#define USB_PID_SPLIT 0x8
|
||||
#define USB_PID_PING 0x4 /* Hign-speed flow control probe for bulk/control endpoint */
|
||||
|
||||
/* PID with error check */
|
||||
#define USB_PID_NEGATE(PID) ((PID) | (((~PID) & 0xf) << 4))
|
||||
#define USB_PIDn_OUT 0xe1
|
||||
#define USB_PIDn_IN 0x69
|
||||
#define USB_PIDn_SOF 0xa5
|
||||
#define USB_PIDn_SETUP 0x2d
|
||||
#define USB_PIDn_DATA0 0xc3
|
||||
#define USB_PIDn_DATA1 USB_PID_NEGATE(USB_PID_DATA1)
|
||||
#define USB_PIDn_DATA2 USB_PID_NEGATE(USB_PID_DATA2)
|
||||
#define USB_PIDn_ACK 0xd2
|
||||
#define USB_PIDn_NAK 0x5a
|
||||
#define USB_PIDn_STALL 0x1e
|
||||
|
||||
/* Table 9-6. Standard Feature Selectors (wValue) */
|
||||
#define USB_DEVICE_REMOTE_WAKEUP 0x01 /* Recipient: Device */
|
||||
#define USB_ENDPOINT_HALT 0x00 /* Recipient: Endpoint */
|
||||
#define USB_TEST_MODE 0x02 /* Recipient: Device */
|
||||
|
||||
#define USB_STANDARD_DEVICE_REQUEST 0x00
|
||||
#define USB_STANDARD_INTERFACE_REQUEST 0x01
|
||||
#define USB_STANDARD_ENDPOINT_REQUEST 0x02
|
||||
#define USB_VENDOR_DEVICE_REQUEST 0x40
|
||||
#define USB_VENDOR_ENDPOINT_REQUEST 0x42
|
||||
#define USB_CLASS_INTERFACE_REQUEST 0x21
|
||||
#define USB_CLASS_ENDPOINT_REQUEST 0x22
|
||||
|
||||
#define USB_WVAL_EP_HALT 0
|
||||
|
||||
// Low byte values:
|
||||
//#define USB_WVALUE_GETDESC_STRING_LANGIDS 0x0
|
||||
//#define USB_WVALUE_GETDESC_STRING_IPRODUCT 0x2
|
||||
|
||||
// Test selector defines for Test mode
|
||||
#define USB_WINDEX_TEST_J (0x1<<8)
|
||||
#define USB_WINDEX_TEST_K (0x2<<8)
|
||||
#define USB_WINDEX_TEST_SE0_NAK (0x3<<8)
|
||||
#define USB_WINDEX_TEST_PACKET (0x4<<8)
|
||||
#define USB_WINDEX_TEST_FORCE_ENABLE (0x5<<8)
|
||||
#define USB_WINDEX_TEST_XMOS_IN_ADDR1 (0x6<<8)
|
||||
|
||||
#define USB_MAX_NUM_EP_OUT (16)
|
||||
#define USB_MAX_NUM_EP_IN (16)
|
||||
#define USB_MAX_NUM_EP (32)
|
||||
|
||||
#endif
|
||||
23
lib_xud/lib_xud/src/user/class/hid.h
Normal file
23
lib_xud/lib_xud/src/user/class/hid.h
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright 2015-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/*
|
||||
* @brief Defines from USB Device Class Definition for Human Interface Devices Specification
|
||||
*/
|
||||
|
||||
/* 7. Requests */
|
||||
|
||||
/* 7.1 Standard Requests - Class Descriptor Types - High byte of wValue
|
||||
* The following defines valid types of Class descriptors */
|
||||
#define HID_HID 0x2100
|
||||
#define HID_REPORT 0x2200
|
||||
#define HID_PHYSICAL_DESCRIPTOR 0x2300
|
||||
/*0x24 - 0x2F: Reserved */
|
||||
|
||||
/* 7.2 Class-Specific Requests - bRequest values */
|
||||
#define HID_GET_REPORT 0x01 /* Mandatory */
|
||||
#define HID_GET_IDLE 0x02
|
||||
#define HID_GET_PROTOCOL 0x03 /* Required only for boot devices */
|
||||
/* Ox04 - 0x08 reserved */
|
||||
#define HID_SET_REPORT 0x09
|
||||
#define HID_SET_IDLE 0x0A
|
||||
#define HID_SET_PROTOCOL 0x0B /* Required only for boot devices */
|
||||
30
lib_xud/lib_xud/src/user/class/usbaudio10.h
Normal file
30
lib_xud/lib_xud/src/user/class/usbaudio10.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright 2017-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef _AUDIO10_H_
|
||||
#define _AUDIO10_H_ 1
|
||||
/**
|
||||
* @brief Defines from the USB Audio 1.0 Specifications
|
||||
* @author Ross Owen, XMOS Limited
|
||||
*/
|
||||
|
||||
/* A.9. Audio Class-Specific Request Codes */
|
||||
#define UAC_B_REQ_SET_CUR 0x01
|
||||
#define UAC_B_REQ_GET_CUR 0x81
|
||||
#define UAC_B_REQ_SET_MIN 0x02
|
||||
#define UAC_B_REQ_GET_MIN 0x82
|
||||
#define UAC_B_REQ_SET_MAX 0x03
|
||||
#define UAC_B_REQ_GET_MAX 0x83
|
||||
#define UAC_B_REQ_SET_RES 0x04
|
||||
#define UAC_B_REQ_GET_RES 0x84
|
||||
#define UAC_B_REQ_SET_MEM 0x05
|
||||
#define UAC_B_REQ_GET_MEM 0x85
|
||||
#define UAC_B_REQ_GET_STAT 0xFF
|
||||
|
||||
/* A.10.5 Endpoint Control Selectors: Table A-19 */
|
||||
#define EP_CONTROL_UNDEFINED 0x00
|
||||
#define SAMPLING_FREQ_CONTROL 0x01
|
||||
#define PITCH_CONTROL 0x02
|
||||
|
||||
#endif
|
||||
|
||||
357
lib_xud/lib_xud/src/user/class/usbaudio20.h
Normal file
357
lib_xud/lib_xud/src/user/class/usbaudio20.h
Normal file
@@ -0,0 +1,357 @@
|
||||
// Copyright 2017-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/**
|
||||
* @brief Defines from the USB Audio 2.0 Specifications
|
||||
* @author Ross Owen, XMOS Limited
|
||||
*/
|
||||
#ifndef _USBAUDIO20_H_
|
||||
#define _USBAUDIO20_H_
|
||||
|
||||
#include "usbaudiocommon.h"
|
||||
|
||||
/***********************************************************************/
|
||||
/* USB Audio 2.0 Class Specification */
|
||||
|
||||
/* A.1 Audio Function Class Code */
|
||||
#define AUDIO_FUNCTION AUDIO
|
||||
|
||||
/* A.2 Audio Function Subclass Codes */
|
||||
#define FUNCTION_SUBCLASS_UNDEFINED 0x00
|
||||
|
||||
/* A.3 Audio Function Protocol Codes */
|
||||
enum USB_Audio_FuncProtocolCodes_t
|
||||
{
|
||||
UAC_FUNC_PROTOCOL_UNDEFINED = 0x00,
|
||||
UAC_FUNC_PROTOCOL_AF_VERSION_02_00 = 0x20
|
||||
};
|
||||
|
||||
/* A.4 Audio Interface Class Code */
|
||||
#define AUDIO 0x01
|
||||
|
||||
/* A.5 Audio Interface Subclass Codes */
|
||||
enum UAC_IntSubclassCodes_t
|
||||
{
|
||||
UAC_INT_SUBCLASS_AUDIOCONTROL = 0x01,
|
||||
UAC_INT_SUBCLASS_AUDIOSTREAMING = 0x02,
|
||||
UAC_INT_SUBCLASS_MIDISTREAMING = 0x03
|
||||
};
|
||||
|
||||
/* A.6 Audio Interface Protocol Codes */
|
||||
enum UAC_IntProtocolCodes_t
|
||||
{
|
||||
UAC_INT_PROTOCOL_UNDEFINED = 0x00,
|
||||
UAC_INT_PROTOCOL_IP_VERSION_02_00 = 0x20
|
||||
};
|
||||
|
||||
/* A.7 Audio Function Category Codes */
|
||||
enum UAC_AudioFunctionCategory_t
|
||||
{
|
||||
UAC_FUNCTION_SUBCLASS_UNDEFINED = 0x00,
|
||||
UAC_FUNCTION_DESKTOP_SPEAKER = 0x01,
|
||||
UAC_FUNCITON_HOME_THEATER = 0x02,
|
||||
UAC_FUNCTION_MICROPHONE = 0x03,
|
||||
UAC_FUNCITON_HEADSET = 0x04,
|
||||
UAC_FUNCTION_TELEPHONE = 0x05,
|
||||
UAC_FUNCTION_CONVERTER = 0x06,
|
||||
UAC_FUNCTION_VOICE_SOUND_RECORDER = 0x07,
|
||||
UAC_FUNCTION_IO_BOX = 0x08,
|
||||
UAC_FUNCTION_MUSICAL_INTRUMENT = 0x09,
|
||||
UAC_FUNCTION_PRO_AUDIO = 0x0A,
|
||||
UAC_FUNCTION_AUDIO_VIDEO = 0x0B,
|
||||
UAC_FUNCTION_CONTROL_PANEL = 0x0C,
|
||||
UAC_FUNCITON_OTHER = 0xFF
|
||||
};
|
||||
|
||||
/* A.8 Audio Class-Specific Descriptor Types */
|
||||
/* Shared with Audio Class 1.0 */
|
||||
enum UAC_CSDescriptorTypes_t
|
||||
{
|
||||
UAC_CS_DESCTYPE_UNDEFINED = 0x20,
|
||||
UAC_CS_DESCTYPE_DEVICE = 0x21,
|
||||
UAC_CS_DESCTYPE_CONFIGURATION = 0x22,
|
||||
UAC_CS_DESCTYPE_STRING = 0x23,
|
||||
UAC_CS_DESCTYPE_INTERFACE = 0x24,
|
||||
UAC_CS_DESCTYPE_ENDPOINT = 0x25,
|
||||
};
|
||||
|
||||
/* A.9 Audio Class-Specific AC Interface Descriptor Subtypes */
|
||||
enum UAC_CS_AC_InterfaceDescriptorSubtype_t
|
||||
{
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_AC_DESCRIPTOR_UNDEFINED = 0x00,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_HEADER = 0x01,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_INPUT_TERMINAL = 0x02,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_OUTPUT_TERMINAL = 0x03,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_MIXER_UNIT = 0x04,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_SELECTOR_UNIT = 0x05,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_FEATURE_UNIT = 0x06,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_EFFECT_UNIT = 0x07,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_PROCESSING_UNIT = 0x08,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_EXTENSION_UNIT = 0x09,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_CLOCK_SOURCE = 0x0A,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_CLOCK_SELECTOR = 0x0B,
|
||||
UAC_CS_AC_INTERFACE_SUBSYPE_CLOCK_MULTIPLIER = 0x0C,
|
||||
UAC_CS_AC_INTERFACE_SUBTYPE_SAMPLE_RATE_CONVERTER = 0x0D
|
||||
};
|
||||
|
||||
/* A.10 Audio Class Specific AS Interface Descriptor Subtypes */
|
||||
enum UAC_CS_AS_InterfaceDescriptorSubtype_t
|
||||
{
|
||||
UAC_CS_AS_INTERFACE_SUBTYPE_UNDEFINED = 0x00,
|
||||
UAC_CS_AS_INTERFACE_SUBTYPE_AS_GENERAL = 0x01,
|
||||
UAC_CS_AS_INTERFACE_SUBTYPE_FORMAT_TYPE = 0x02,
|
||||
UAC_CS_AS_INTERFACE_SUBTYPE_ENCODER = 0x03,
|
||||
UAC_CS_AS_INTERFACE_SUBTYPE_DECODER = 0x04
|
||||
};
|
||||
|
||||
/* A.11 Effect Unit Effect Types */
|
||||
#define EFFECT_UNDEFINED 0x00
|
||||
#define PARAM_EQ_SECTION_EFFECT 0x01
|
||||
#define REVERBERATION_EFFECT 0x02
|
||||
#define MOD_DELAY_EFFECT 0x03
|
||||
#define DYN_RANGE_COMP_EFFECT 0x04
|
||||
|
||||
/* A.12 Processing Unit Process Types */
|
||||
#define PROCESS_UNDEFINED 0x00
|
||||
#define UP_DOWNMIX_PROCESS 0x01
|
||||
#define DOLBY_PROLOGIC_PROCESS 0x02
|
||||
#define STEREO_EXTENDER_PROCESS 0x03
|
||||
|
||||
/* A.13 Audio Class-Specific Endpoint Descriptor Subtypes */
|
||||
enum UAC_CS_EndpointDescriptorSubtype_t
|
||||
{
|
||||
UAC_CS_ENDPOINT_SUBTYPE_UNDEFINED = 0x00,
|
||||
UAC_CS_ENDPOINT_SUBTYPE_EP_GENERAL = 0x01
|
||||
};
|
||||
|
||||
/* A.14 Audio Class-Specific Request Codes */
|
||||
#define REQUEST_CODE_UNDEFINED 0x00
|
||||
#define CUR 0x01
|
||||
#define RANGE 0x02
|
||||
#define MEM 0x03
|
||||
|
||||
/* A.15 Encoder Type Codes */
|
||||
#define ENCODER_UNDEFINED 0x00
|
||||
#define OTHER_ENCODER 0x01
|
||||
#define MPEG_ENCODER 0x02
|
||||
#define AC_3_ENCODER 0x03
|
||||
#define WMA_ENCODER 0x04
|
||||
#define DTS_ENCODER 0x05
|
||||
|
||||
/* A.17 Control Selector Codes */
|
||||
/* A.17.1 Clock Source Control Selectors */
|
||||
#define CS_CONTROL_UNDEFINED 0x00
|
||||
#define CS_SAM_FREQ_CONTROL 0x01
|
||||
#define CS_CLOCK_VALID_CONTROL 0x02
|
||||
|
||||
/* A.17.2 Clock Selector Control Selectors */
|
||||
#define CX_CONTROL_UNDEFINED 0x00
|
||||
#define CX_CLOCK_SELECTOR_CONTROL 0x01
|
||||
|
||||
/* A.17.7 Feature Unit Control Selectors */
|
||||
#define FU_CONTROL_UNDEFINED 0x00
|
||||
#define FU_MUTE_CONTROL 0x01
|
||||
#define FU_VOLUME_CONTROL 0x02
|
||||
|
||||
/* A.17.11 Audio Streaming Interface Control Selectors */
|
||||
#define AS_CONTROL_UNDEFINED 0x00
|
||||
#define AS_ACT_ALT_SETTING_CONTROL 0x01
|
||||
#define AS_VAL_ALT_SETTINGS_CONTROL 0x02
|
||||
#define AS_AUDIO_DATA_FORMAT_CONTROL 0x03
|
||||
|
||||
#ifdef __STDC__
|
||||
/* Clock Source Descriptor (Table 4-6) */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubType;
|
||||
unsigned char bClockID;
|
||||
unsigned char bmAttributes;
|
||||
unsigned char bmControls;
|
||||
unsigned char bAssocTerminal;
|
||||
unsigned char iClockSource;
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_ClockSource_t;
|
||||
|
||||
/* Clock Selector Descriptor (Table 4-7) */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubType;
|
||||
unsigned char bClockID;
|
||||
unsigned char bNrPins;
|
||||
unsigned char baCSourceId[1];
|
||||
unsigned char bmControl; /* bmControls
|
||||
* D[1:0] : Clock Selector Control
|
||||
* D[7:4] : Reserved (0) */
|
||||
unsigned char iClockSelector;
|
||||
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_ClockSelector_1_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubType;
|
||||
unsigned char bClockID;
|
||||
unsigned char bNrPins;
|
||||
unsigned char baCSourceId[2];
|
||||
unsigned char bmControl; /* bmControls
|
||||
* D[1:0] : Clock Selector Control
|
||||
* D[7:4] : Reserved (0) */
|
||||
unsigned char iClockSelector;
|
||||
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_ClockSelector_2_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubType;
|
||||
unsigned char bClockID;
|
||||
unsigned char bNrPins;
|
||||
unsigned char baCSourceId[3];
|
||||
unsigned char bmControl; /* bmControls
|
||||
* D[1:0] : Clock Selector Control
|
||||
* D[7:4] : Reserved (0) */
|
||||
unsigned char iClockSelector;
|
||||
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_ClockSelector_3_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bFormatType; /* Format of the audio stream, see Audio Device Formats specification */
|
||||
unsigned char bSubslotSize; /* Number of bytes for each channels subslot */
|
||||
unsigned char bBitResolution; /* Number of bits used in the above slot for sample */
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_Format_Type1_t;
|
||||
|
||||
/* Table 4-11: Mixer Unit Descriptor */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bUnitID;
|
||||
unsigned char bNrInPins;
|
||||
unsigned char baSourceID;
|
||||
unsigned char bNrChannels;
|
||||
unsigned bmChannelConfig;
|
||||
unsigned char iChannelNames;
|
||||
unsigned char bmMixerControls[18]; /* FIXME */
|
||||
unsigned char bmControls;
|
||||
unsigned char iMixer;
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_MixerUnit_t;
|
||||
|
||||
/* Table 4-24: Extension Unit Descriptor */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bUnitID;
|
||||
unsigned short wExtensionCode;
|
||||
unsigned char bNrInPins;
|
||||
unsigned char baSourceID[1];
|
||||
unsigned char bNrChannels;
|
||||
unsigned bmChannelConfig;
|
||||
unsigned char iChannelNames;
|
||||
unsigned char bmControls;
|
||||
unsigned char iExtension;
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_ExtensionUnit_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bUnitID;
|
||||
unsigned short wExtensionCode;
|
||||
unsigned char bNrInPins;
|
||||
unsigned char baSourceID[2];
|
||||
unsigned char bNrChannels;
|
||||
unsigned bmChannelConfig;
|
||||
unsigned char iChannelNames;
|
||||
unsigned char bmControls;
|
||||
unsigned char iExtension;
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_ExtensionUnit2_t;
|
||||
#endif
|
||||
|
||||
/***********************************************************************/
|
||||
/** USB Device Class Definition for Audio Data Formats **/
|
||||
|
||||
/* A.1 Format Type Codes */
|
||||
enum USB_audio_Fmt_FormatType_t
|
||||
{
|
||||
UAC_FORMAT_TYPE_UNDEFINED = 0x00,
|
||||
UAC_FORMAT_TYPE_I = 0x01,
|
||||
UAC_FORMAT_TYPE_II = 0x02,
|
||||
UAC_FORMAT_TYPE_III = 0x03,
|
||||
UAC_FORMAT_TYPE_IV = 0x04,
|
||||
UAC_EXT_FORMAT_TYPE_I = 0x81,
|
||||
UAC_EXT_FORMAT_TYPE_II = 0x82,
|
||||
UAC_EXT_FORMAT_TYPE_III = 0x83
|
||||
};
|
||||
|
||||
/* A.2 AudioData Format Bit Allocation in the bmFormats field */
|
||||
/* A.2.1 Audio Data Format Type I Bit Allocations */
|
||||
enum USB_Audio_Fmt_DataFormat_TypeI_t
|
||||
{
|
||||
UAC_FORMAT_TYPEI_PCM = 0x00000001,
|
||||
UAC_FORMAT_TYPEI_PCM8 = 0x00000002,
|
||||
UAC_FORMAT_TYPEI_IEEE_FLOAT = 0x00000004,
|
||||
UAC_FORMAT_TYPEI_RAW_DATA = 0x80000000,
|
||||
};
|
||||
|
||||
/* A.2.2 Audio Data Format Type II Bit Allocations */
|
||||
enum USB_Audio_Fmt_DataFormat_TypeII_t
|
||||
{
|
||||
UAC_FORMAT_TYPEII_MPEG = 0x00000001,
|
||||
UAC_FORMAT_TYPEII_AC3 = 0x00000002,
|
||||
UAC_FORMAT_TYPEII_WMA = 0x00000004,
|
||||
UAC_FORMAT_TYPEII_DTS = 0x00000008,
|
||||
UAC_FORMAT_TYPEII_RAW_DATA = 0x80000000
|
||||
};
|
||||
|
||||
/* A.3 Side Band Protocol Codes */
|
||||
#define PROTOCOL_UNDEFINED 0x00
|
||||
#define PRESS_TIMESTAMP_PROTOCOL 0x01
|
||||
|
||||
/***********************************************************************/
|
||||
/* Univeral Serial Bus Device Class Definition for Terminal Types */
|
||||
|
||||
/* 2.1 USB Terminal Types */
|
||||
/* Terminal Types that describe Terminals that handle signals carried over USB */
|
||||
#define USB_TERMTYPE_UNDEFINED 0x0100
|
||||
#define USB_TERMTYPE_USB_STREAMING 0x0101
|
||||
#define USB_TERMTYPE_VENDOR_SPECIFIC 0x01FF
|
||||
|
||||
/* 2.2 Input Terminal Types */
|
||||
/* Terminal Types that describe Terminals that are designed to record sounds */
|
||||
enum USB_Audio_TT_InputTermType_t
|
||||
{
|
||||
UAC_TT_INPUT_TERMTYPE_INPUT_UNDEFINED = 0x0200,
|
||||
UAC_TT_INPUT_TERMTYPE_MICROPHONE = 0x0201,
|
||||
UAC_TT_INPUT_TERMTYPE_DESKTOP_MICROPHONE = 0x0202,
|
||||
UAC_TT_INPUT_TERMTYPE_PERSONAL_MICROPHONE = 0x0203,
|
||||
UAC_TT_INPUT_TERMTYPE_OMNIDIRECTIONAL_MICROPHONE = 0x0204,
|
||||
UAC_TT_INPUT_TERMTYPE_MICROPHONE_ARRAY = 0x0205,
|
||||
UAC_TT_INPUT_TERMTYPE_PROCESSING_MICROPHONE_ARRAY = 0x0206
|
||||
};
|
||||
|
||||
/* 2.3 Output Terminal Types */
|
||||
/* These Terminal Types describe Terminals that produce audible signals that are intended to
|
||||
* be heard by the user of the audio function */
|
||||
enum USB_Audio_TT_OutputTermType_t
|
||||
{
|
||||
UAC_TT_OUTPUT_TERMTYPE_SPEAKER = 0x0301,
|
||||
UAC_TT_OUTPUT_TERMTYPE_HEADPHONES = 0x0302,
|
||||
UAC_TT_OUTPUT_TERMTYPE_HEAD_MOUNTED_DISPLAY = 0x0303,
|
||||
UAC_TT_OUTPUT_TERMTYPE_DESKTOP_SPEAKER = 0x0304,
|
||||
UAC_TT_OUTPUT_TERMTYPE_ROOM_SPEAKER = 0x0305,
|
||||
UAC_TT_OUTPUT_TERMTYPE_COMMUNICATION_SPEAKER = 0x0306,
|
||||
UAC_TT_OUTPUT_TERMTYPE_LOW_FREQ_EFFECTS_SPEAKER = 0x0307
|
||||
};
|
||||
#endif
|
||||
168
lib_xud/lib_xud/src/user/class/usbaudiocommon.h
Normal file
168
lib_xud/lib_xud/src/user/class/usbaudiocommon.h
Normal file
@@ -0,0 +1,168 @@
|
||||
// Copyright 2017-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef _USBAUDIOCOMMON_H_
|
||||
#define _USBAUDIOCOMMON_H_
|
||||
|
||||
#include "xud_conf_default.h"
|
||||
|
||||
#ifdef __STDC__
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of descriptor (bytes) */
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned short bcdADC; /* Binary coded decimal indicating the supported Audio Class version */
|
||||
unsigned char bCatagory; /* Primary use of this audio function. See Audio Function Category Codes */
|
||||
unsigned short wTotalLength; /* Total length of the Audio class-specific descriptors, including this descriptor */
|
||||
unsigned char bmControls; /* D[1:0]: Latency control. D[7:2]: Reserved. Must be set to 0 */
|
||||
} __attribute__((packed)) UAC_Descriptor_Interface_AC_t;
|
||||
|
||||
/* Table 4-9: Input Terminal Descriptor */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of the descriptor (bytes) */
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bTerminalID; /* Unique ID of this terminal unit */
|
||||
unsigned short wTerminalType;
|
||||
unsigned char bAssocTerminal; /* ID of associated output terminal, for physically grouped terminals
|
||||
* such as the speaker and microphone of a phone handset */
|
||||
unsigned char bCSourceID; /* ID of the clock entity to which this Input Terminal is connected */
|
||||
unsigned char bNrChannels; /* Number of logicial output channels in the Terminal's
|
||||
output audio channel cluster */
|
||||
unsigned bmChannelConfig; /* Channel layout supported by this terminal */
|
||||
unsigned char iChannelNames; /* Index in string table describing channels (points to first channel) */
|
||||
unsigned short bmControls; /* Bitmap */
|
||||
unsigned char iTerminal; /* Index of string descriptor describing this terminal */
|
||||
} __attribute__((packed))USB_Descriptor_Audio_InputTerminal_t;
|
||||
|
||||
#if 0
|
||||
//UAC 1.0 version
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength; /* Size of the descriptor (bytes) */
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bTerminalID; /* Unique ID of this terminal unit */
|
||||
unsigned short wTerminalType;
|
||||
unsigned char bAssocTerminal; /* ID of associated output terminal, for physically grouped terminals
|
||||
* such as the speaker and microphone of a phone handset */
|
||||
unsigned char bNrChannels; /* Total number of separate audio channels within this interface */
|
||||
unsigned short wChannelConfig; /* Channel layout supported by this terminal */
|
||||
unsigned char iChannelNames; /* Index in string table describing channels (points to first channel */
|
||||
unsigned char iTerminal; /* Index of string descriptor describing this terminal */
|
||||
} USB_Descriptor_Audio_InputTerminal_t;
|
||||
#endif
|
||||
|
||||
/* Table 4-10: Output Terminal Descriptor */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bTerminalID;
|
||||
unsigned short wTerminalType;
|
||||
unsigned char bAssocTerminal;
|
||||
unsigned char bSourceID;
|
||||
unsigned char bCSourceID;
|
||||
unsigned short bmControls;
|
||||
unsigned char iTerminal;
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_OutputTerminal_t;
|
||||
|
||||
#if 0
|
||||
/* UAC 1.0 Version */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bTerminalID;
|
||||
unsigned short wTerminalType;
|
||||
unsigned char bAssocTerminal;
|
||||
unsigned char bSourceID;
|
||||
unsigned char iTerminal;
|
||||
} USB_Descriptor_Audio_OutputTerminal_t;
|
||||
#endif
|
||||
|
||||
/* Note, we need seperate _out and _in structs due to varying channel count */
|
||||
/* Table 4-13: Feature Unit Descriptor */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bUnitID; /* Unique ID for this feature unit */
|
||||
unsigned char bSourceID; /* Source ID value of the audio source input into this feature unit */
|
||||
unsigned bmaControls[NUM_USB_CHAN_OUT+1]; /* Feature masks for the control channel, and each separate audio channel */
|
||||
unsigned char iFeature; /* String table index describing this feature unit */
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_FeatureUnit_Out_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bUnitID; /* Unique ID for this feature unit */
|
||||
unsigned char bSourceID; /* Source ID value of the audio source input into this feature unit */
|
||||
unsigned bmaControls[NUM_USB_CHAN_IN+1]; /* Feature masks for the control channel, and each separate audio channel */
|
||||
unsigned char iFeature; /* String table index describing this feature unit */
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_FeatureUnit_In_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubType;
|
||||
unsigned char bTerminalLink;
|
||||
unsigned char bmControls;
|
||||
unsigned char bFormatType;
|
||||
unsigned bmFormats;
|
||||
unsigned char bNrChannels;
|
||||
unsigned bmChannelConfig;
|
||||
unsigned char iChannelNames;
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_Interface_AS_t;
|
||||
|
||||
#if 0
|
||||
/* UAC1 Version */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubType;
|
||||
unsigned char bTerminalLink;
|
||||
unsigned char bmControls;
|
||||
unsigned char bFormatType;
|
||||
unsigned bmFormats;
|
||||
unsigned char bNrChannels;
|
||||
unsigned char bmChannelConfig;
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_Interface_AS_t;
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bmAttributes;
|
||||
unsigned char bmControls;
|
||||
unsigned char bLockDelayUnits;
|
||||
unsigned short wLockDelay;
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_Class_AS_Endpoint_t;
|
||||
|
||||
#if 0
|
||||
/* UAC1.0 Version */
|
||||
typedef struct
|
||||
{
|
||||
unsigned char bLength;
|
||||
unsigned char bDescriptorType;
|
||||
unsigned char bDescriptorSubtype;
|
||||
unsigned char bmAttributes;
|
||||
unsigned char bLockDelayUnits;
|
||||
unsigned short wLockDelay;
|
||||
} __attribute__((packed)) USB_Descriptor_Audio_Class_AS_Endpoint_t;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
50
lib_xud/lib_xud/src/user/client/XUD_EpFuncs.S
Normal file
50
lib_xud/lib_xud/src/user/client/XUD_EpFuncs.S
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright 2011-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/** XUD_EpFuncs.S
|
||||
* @brief ASM functions for data transfer to/from XUD
|
||||
* @author Ross Owen, XMOS Limited
|
||||
*/
|
||||
#include "XUD_USB_Defines.h"
|
||||
#include "XUD_AlignmentDefines.h"
|
||||
|
||||
#if defined __XS2A__
|
||||
.set too_many_cores, main.maxcores > 6
|
||||
.assert 0, too_many_cores, "Warning: More than 6 cores used on a tile. Ensure this is not the case on tile running XUD."
|
||||
#endif
|
||||
|
||||
//void XUD_SetTestMode(XUD_ep ep, unsigned testMode);
|
||||
.globl XUD_SetTestMode
|
||||
.type XUD_SetTestMode, @function
|
||||
|
||||
.cc_top XUD_SetTestMode.func
|
||||
.align FUNCTION_ALIGNMENT
|
||||
XUD_SetTestMode:
|
||||
.issue_mode single
|
||||
ENTSP_lu6 0
|
||||
ldw r0, r0[2] // Load our chanend ID to use
|
||||
outct res[r0], 1
|
||||
chkct res[r0], 1
|
||||
out res[r0], r1 // Output test mode
|
||||
outct res[r0], 1
|
||||
chkct res[r0], 1
|
||||
retsp 0
|
||||
.size XUD_SetTestMode, .-XUD_SetTestMode
|
||||
.cc_bottom XUD_SetTestMode.func
|
||||
.globl XUD_SetTestMode.nstackwords
|
||||
.globl XUD_SetTestMode.maxchanends
|
||||
.globl XUD_SetTestMode.maxtimers
|
||||
.globl XUD_SetTestMode.maxcores
|
||||
.set XUD_SetTestMode.nstackwords, 0
|
||||
.set XUD_SetTestMode.maxchanends, 0
|
||||
.set XUD_SetTestMode.maxtimers, 0
|
||||
.set XUD_SetTestMode.maxcores, 1
|
||||
.globl XUD_SetTestMode.locnoside
|
||||
.globl XUD_SetTestMode.locnochandec
|
||||
.globl XUD_SetTestMode.locnoglobalaccess
|
||||
.globl XUD_SetTestMode.locnointerfaceaccess
|
||||
.globl XUD_SetTestMode.locnonotificationselect
|
||||
.set XUD_SetTestMode.locnoside, 1
|
||||
.set XUD_SetTestMode.locnochandec, 1
|
||||
.set XUD_SetTestMode.locnoglobalaccess, 1
|
||||
.set XUD_SetTestMode.locnointerfaceaccess, 1
|
||||
.set XUD_SetTestMode.locnonotificationselect, 1
|
||||
406
lib_xud/lib_xud/src/user/client/XUD_EpFunctions.c
Normal file
406
lib_xud/lib_xud/src/user/client/XUD_EpFunctions.c
Normal file
@@ -0,0 +1,406 @@
|
||||
// Copyright 2021-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include "xud.h"
|
||||
#include "XUD_USB_Defines.h"
|
||||
|
||||
extern XUD_ep_info ep_info[USB_MAX_NUM_EP];
|
||||
|
||||
void XUD_ResetEpStateByAddr(unsigned epAddr)
|
||||
{
|
||||
unsigned pid = USB_PIDn_DATA0;
|
||||
|
||||
#if defined(__XS2A__)
|
||||
/* Check IN bit of address */
|
||||
if((epAddr & 0x80) == 0)
|
||||
{
|
||||
pid = USB_PID_DATA0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(epAddr & 0x80)
|
||||
{
|
||||
epAddr &= 0x7F;
|
||||
epAddr += USB_MAX_NUM_EP_OUT;
|
||||
}
|
||||
|
||||
XUD_ep_info *ep = &ep_info[epAddr];
|
||||
ep->pid = pid;
|
||||
}
|
||||
|
||||
void XUD_SetStallByAddr(int epNum)
|
||||
{
|
||||
if(epNum & 0x80)
|
||||
{
|
||||
epNum &= 0x7f;
|
||||
epNum += 16;
|
||||
}
|
||||
|
||||
XUD_ep_info *ep = &ep_info[epNum];
|
||||
|
||||
unsigned *epReadyEntry = (unsigned *)ep->array_ptr;
|
||||
|
||||
if(*epReadyEntry != 0)
|
||||
{
|
||||
/* Mark EP as not ready (and save that it was ready at Halting */
|
||||
ep->saved_array_ptr = *epReadyEntry;
|
||||
*epReadyEntry = 0;
|
||||
}
|
||||
ep->halted = USB_PIDn_STALL;
|
||||
}
|
||||
|
||||
void XUD_SetStall(XUD_ep e)
|
||||
{
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
|
||||
XUD_SetStallByAddr(ep->epAddress);
|
||||
}
|
||||
|
||||
void XUD_ClearStallByAddr(int epNum)
|
||||
{
|
||||
unsigned handshake = USB_PIDn_NAK;
|
||||
|
||||
/* Reset data PID */
|
||||
XUD_ResetEpStateByAddr(epNum);
|
||||
|
||||
if(epNum & 0x80)
|
||||
{
|
||||
epNum &= 0x7F;
|
||||
epNum += USB_MAX_NUM_EP_OUT;
|
||||
handshake = 0;
|
||||
}
|
||||
|
||||
XUD_ep_info *ep = &ep_info[epNum];
|
||||
|
||||
/* Re-mark as ready if was ready before halting */
|
||||
if(ep->saved_array_ptr != 0)
|
||||
{
|
||||
unsigned *epReadyEntry = (unsigned *)ep->array_ptr;
|
||||
*epReadyEntry = ep->saved_array_ptr;
|
||||
ep->saved_array_ptr = 0;
|
||||
}
|
||||
|
||||
/* Mark EP as un-halted */
|
||||
ep->halted = handshake;
|
||||
}
|
||||
|
||||
void XUD_ClearStall(XUD_ep e)
|
||||
{
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
|
||||
XUD_ClearStallByAddr(ep->epAddress);
|
||||
}
|
||||
|
||||
/* ignoreHalted should only be used for Setup data */
|
||||
static inline XUD_Result_t XUD_GetBuffer_Start(volatile XUD_ep_info *ep, unsigned char buffer[])
|
||||
{
|
||||
/* If EP is marked as halted do not mark as ready.. */
|
||||
do
|
||||
{
|
||||
/* Check if we missed a reset */
|
||||
if(ep->resetting)
|
||||
{
|
||||
return XUD_RES_RST;
|
||||
}
|
||||
}
|
||||
while(ep->halted == USB_PIDn_STALL);
|
||||
|
||||
/* Store buffer address in EP structure */
|
||||
ep->buffer = (unsigned) &buffer[0];
|
||||
|
||||
/* Mark EP as ready */
|
||||
unsigned * array_ptr = (unsigned *)ep->array_ptr;
|
||||
*array_ptr = (unsigned) ep;
|
||||
|
||||
return XUD_RES_OKAY;
|
||||
}
|
||||
|
||||
XUD_Result_t XUD_GetBuffer_Finish(chanend c, XUD_ep e, unsigned *datalength)
|
||||
{ // NOCOVER
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
|
||||
unsigned length;
|
||||
unsigned lengthTail;
|
||||
unsigned isReset;
|
||||
|
||||
/* Wait for XUD response */
|
||||
asm volatile("testct %0, res[%1]" : "=r"(isReset) : "r"(c));
|
||||
|
||||
if(isReset)
|
||||
{
|
||||
return XUD_RES_RST;
|
||||
}
|
||||
|
||||
/* Input packet length (words) */
|
||||
asm volatile("in %0, res[%1]" : "=r"(length) : "r"(c));
|
||||
|
||||
/* Input tail length (bytes) */
|
||||
asm volatile("int %0, res[%1]" : "=r"(lengthTail) : "r"(c));
|
||||
|
||||
/* Bits to bytes */
|
||||
lengthTail >>= 3;
|
||||
|
||||
/* Words to bytes */
|
||||
length <<= 2;
|
||||
|
||||
/* -2 length correction for CRC */
|
||||
*datalength = length + lengthTail - 2;
|
||||
|
||||
/* Load received PID */
|
||||
unsigned receivedPid = ep->actualPid;
|
||||
|
||||
/* Check received PID vs expected PID */
|
||||
if(receivedPid != ep->pid)
|
||||
{
|
||||
*datalength = 0; /* Extra safety measure */
|
||||
return XUD_RES_ERR;
|
||||
}
|
||||
|
||||
/* ISO == 0 */
|
||||
if(ep->epType != XUD_EPTYPE_ISO)
|
||||
{
|
||||
#ifdef __XS2A__
|
||||
ep->pid ^= 0x8;
|
||||
#else
|
||||
ep->pid ^= 0x88;
|
||||
#endif
|
||||
}
|
||||
|
||||
return XUD_RES_OKAY;
|
||||
} // NOCOVER
|
||||
|
||||
XUD_Result_t XUD_DoSetRequestStatus(XUD_ep ep_in)
|
||||
{
|
||||
unsigned char tmp[8];
|
||||
|
||||
/* Send 0 length packet */
|
||||
return XUD_SetBuffer(ep_in, tmp, 0);
|
||||
}
|
||||
|
||||
XUD_Result_t XUD_GetBuffer(XUD_ep e, unsigned char buffer[], unsigned *datalength)
|
||||
{
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
|
||||
while(1)
|
||||
{
|
||||
XUD_Result_t result = XUD_GetBuffer_Start(ep, buffer);
|
||||
|
||||
if(result == XUD_RES_RST)
|
||||
{
|
||||
return XUD_RES_RST;
|
||||
}
|
||||
|
||||
result = XUD_GetBuffer_Finish(ep->client_chanend, e, datalength);
|
||||
|
||||
/* If error (e.g. bad PID seq) try again */
|
||||
if(result != XUD_RES_ERR)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int XUD_SetReady_Out(XUD_ep e, unsigned char buffer[])
|
||||
{
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
|
||||
return XUD_GetBuffer_Start(ep, buffer);
|
||||
}
|
||||
|
||||
void XUD_GetData_Select(chanend c, XUD_ep e, unsigned *datalength, XUD_Result_t *result)
|
||||
{
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
|
||||
*result = XUD_GetBuffer_Finish(ep->client_chanend, e, datalength);
|
||||
}
|
||||
|
||||
XUD_Result_t XUD_GetSetupBuffer(XUD_ep e, unsigned char buffer[], unsigned *datalength)
|
||||
{
|
||||
volatile XUD_ep_info *ep = (XUD_ep_info*) e;
|
||||
unsigned isReset;
|
||||
unsigned length;
|
||||
unsigned lengthTail;
|
||||
|
||||
/* Check if we missed a reset */
|
||||
if(ep->resetting)
|
||||
{
|
||||
return XUD_RES_RST;
|
||||
}
|
||||
|
||||
/* Store buffer address in EP structure */
|
||||
ep->buffer = (unsigned) &buffer[0];
|
||||
|
||||
/* Mark EP as ready for SETUP data */
|
||||
unsigned * array_ptr_setup = (unsigned *)ep->array_ptr_setup;
|
||||
*array_ptr_setup = (unsigned) ep;
|
||||
|
||||
/* Wait for XUD response */
|
||||
asm volatile("testct %0, res[%1]" : "=r"(isReset) : "r"(ep->client_chanend));
|
||||
|
||||
if(isReset)
|
||||
{
|
||||
return XUD_RES_RST;
|
||||
}
|
||||
|
||||
/* Input packet length (words) */
|
||||
asm volatile("in %0, res[%1]" : "=r"(length) : "r"(ep->client_chanend));
|
||||
|
||||
/* Input tail length (bytes) */
|
||||
/* TODO Check CT vs T */
|
||||
asm volatile("inct %0, res[%1]" : "=r"(lengthTail) : "r"(ep->client_chanend));
|
||||
|
||||
/* Reset PID toggling on receipt of SETUP (both IN and OUT) */
|
||||
#ifdef __XS2A__
|
||||
ep->pid = USB_PID_DATA1;
|
||||
#else
|
||||
ep->pid = USB_PIDn_DATA1;
|
||||
#endif
|
||||
|
||||
/* Reset IN EP PID */
|
||||
XUD_ep_info *ep_in = (XUD_ep_info*) ((unsigned)ep + (USB_MAX_NUM_EP_OUT * sizeof(XUD_ep_info)));
|
||||
ep_in->pid = USB_PIDn_DATA1;
|
||||
|
||||
/* TODO check that this is the case */
|
||||
*datalength = 8;
|
||||
|
||||
return XUD_RES_OKAY;
|
||||
}
|
||||
|
||||
XUD_Result_t XUD_SetBuffer_Start(XUD_ep e, unsigned char buffer[], unsigned datalength)
|
||||
{ // NOCOVER
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
|
||||
while(1)
|
||||
{
|
||||
/* Check if we missed a reset */
|
||||
if(ep->resetting)
|
||||
{
|
||||
return XUD_RES_RST;
|
||||
}
|
||||
|
||||
/* If EP is marked as halted do not mark as ready.. */
|
||||
if(ep->halted != USB_PIDn_STALL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int lengthWords = datalength >> 2;
|
||||
unsigned lengthTail = (datalength << 3) & 0x1f; // zext(5)?
|
||||
|
||||
if((lengthTail == 0) && (lengthWords != 0))
|
||||
{
|
||||
lengthWords -= 1;
|
||||
lengthTail = 32;
|
||||
}
|
||||
|
||||
/* Store end of buffer address in EP structure */
|
||||
ep->buffer = (unsigned) &buffer[0] + (lengthWords * 4);
|
||||
|
||||
/* XUD uses negative index */
|
||||
lengthWords *= -1;
|
||||
ep->actualPid = lengthWords; /* Re-use of actualPid entry - TODO rename */
|
||||
ep->tailLength = lengthTail;
|
||||
|
||||
unsigned * array_ptr = (unsigned *)ep->array_ptr;
|
||||
*array_ptr = (unsigned) ep;
|
||||
|
||||
return XUD_RES_OKAY;
|
||||
}
|
||||
|
||||
XUD_Result_t XUD_SetBuffer_Finish(chanend c, XUD_ep e)
|
||||
{ // NOCOVER
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
unsigned isReset;
|
||||
unsigned tmp;
|
||||
|
||||
/* Wait for XUD response */
|
||||
asm volatile("testct %0, res[%1]" : "=r"(isReset) : "r"(ep->client_chanend));
|
||||
|
||||
if(isReset)
|
||||
{
|
||||
return XUD_RES_RST;
|
||||
}
|
||||
|
||||
/* Data sent okay */
|
||||
asm volatile("in %0, res[%1]" : "=r"(tmp) : "r"(ep->client_chanend));
|
||||
|
||||
/* Don't do any PID toggling for Iso EP's */
|
||||
if(ep->epType != XUD_EPTYPE_ISO)
|
||||
{
|
||||
ep->pid ^= 0x88;
|
||||
}
|
||||
|
||||
return XUD_RES_OKAY;
|
||||
} // NOCOVER
|
||||
|
||||
XUD_Result_t XUD_SetBuffer(XUD_ep e, unsigned char buffer[], unsigned datalength)
|
||||
{
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
|
||||
XUD_Result_t result = XUD_SetBuffer_Start(e, buffer, datalength);
|
||||
|
||||
if(result == XUD_RES_RST)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return XUD_SetBuffer_Finish(ep->client_chanend, e);
|
||||
}
|
||||
|
||||
void XUD_SetData_Select(chanend c, XUD_ep e, XUD_Result_t *result)
|
||||
{
|
||||
volatile XUD_ep_info * ep = (XUD_ep_info*) e;
|
||||
|
||||
*result = XUD_SetBuffer_Finish(ep->client_chanend, e);
|
||||
}
|
||||
|
||||
XUD_Result_t XUD_SetBuffer_EpMax(XUD_ep ep_in, unsigned char buffer[], unsigned datalength, unsigned epMax)
|
||||
{
|
||||
int i = 0;
|
||||
XUD_Result_t result;
|
||||
|
||||
/* Note: We could encompass this in the SetData function */
|
||||
if (datalength <= epMax)
|
||||
{
|
||||
/* Datalength is less than the maximum per transaction of the EP, so just send */
|
||||
result = XUD_SetBuffer(ep_in, buffer, datalength);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send first packet out and reset PID */
|
||||
if((result = XUD_SetBuffer(ep_in, buffer, epMax)) != XUD_RES_OKAY)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
i += epMax;
|
||||
datalength -= epMax;
|
||||
|
||||
while (1)
|
||||
{
|
||||
unsigned char *bufferPtr = &buffer[i];
|
||||
|
||||
if (datalength > epMax)
|
||||
{
|
||||
/* PID Automatically toggled */
|
||||
if ((result = XUD_SetBuffer(ep_in, bufferPtr, epMax)) != XUD_RES_OKAY)
|
||||
return result;
|
||||
|
||||
datalength -= epMax;
|
||||
i += epMax;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* PID automatically toggled */
|
||||
if ((result = XUD_SetBuffer(ep_in, bufferPtr, datalength)) != XUD_RES_OKAY)
|
||||
return result;
|
||||
|
||||
break; //out of while loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return XUD_RES_OKAY;
|
||||
}
|
||||
112
lib_xud/lib_xud/src/user/client/XUD_EpFunctions.xc
Normal file
112
lib_xud/lib_xud/src/user/client/XUD_EpFunctions.xc
Normal file
@@ -0,0 +1,112 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/** @file XUD_EPFunctions.xc
|
||||
* @brief Implementation of user API functions. See xud.h for documentation.
|
||||
* @author Ross Owen, XMOS Limited
|
||||
**/
|
||||
|
||||
#include <xs1.h>
|
||||
#include "xud.h"
|
||||
#include "XUD_USB_Defines.h"
|
||||
|
||||
static inline int min(int x, int y)
|
||||
{
|
||||
if (x < y)
|
||||
return x;
|
||||
return y;
|
||||
}
|
||||
|
||||
void XUD_Kill(XUD_ep ep)
|
||||
{
|
||||
XUD_SetTestMode(ep, 0);
|
||||
}
|
||||
|
||||
#ifndef EP0_MAX_PACKET_SIZE
|
||||
#define EP0_MAX_PACKET_SIZE (64)
|
||||
#endif
|
||||
|
||||
/* TODO Should take ep max length as a param - currently hardcoded as 64 (#11384) */
|
||||
XUD_Result_t XUD_DoGetRequest(XUD_ep ep_out, XUD_ep ep_in, unsigned char buffer[], unsigned length, unsigned requested)
|
||||
{
|
||||
unsigned char tmpBuffer[1024];
|
||||
unsigned rxlength;
|
||||
unsigned sendLength = min(length, requested);
|
||||
XUD_Result_t result;
|
||||
|
||||
if ((result = XUD_SetBuffer_EpMax(ep_in, buffer, sendLength, EP0_MAX_PACKET_SIZE)) != XUD_RES_OKAY)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* USB 2.0 8.5.3.2: Send < 0 length packet when data-length % 64 is 0
|
||||
* Note, we also don't want to try and send 2 zero-length packets i.e. if sendLength = 0 */
|
||||
if ((requested > length) && ((length % EP0_MAX_PACKET_SIZE) == 0))
|
||||
{
|
||||
XUD_SetBuffer(ep_in, tmpBuffer, 0);
|
||||
}
|
||||
|
||||
/* Status stage - this should return -1 for reset or 0 for 0 length status stage packet */
|
||||
return XUD_GetBuffer(ep_out, tmpBuffer, rxlength);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void XUD_CloseEndpoint(XUD_ep one)
|
||||
{
|
||||
unsigned c1;
|
||||
|
||||
/* Input rst control token */
|
||||
asm volatile("ldw %0, %1[2]":"=r"(c1):"r"(one)); // Load our chanend
|
||||
asm volatile ("outct res[%0], 1":: "r"(c1)); // Close channel to other side
|
||||
asm volatile ("chkct res[%0], 1":: "r"(c1)); // Close channel to this side
|
||||
}
|
||||
|
||||
XUD_BusSpeed_t XUD_ResetEndpoint(XUD_ep one, XUD_ep &?two)
|
||||
{
|
||||
int busStateCt;
|
||||
int busSpeed;
|
||||
|
||||
unsigned c1, c2, tmp;
|
||||
|
||||
/* Input rst control token */
|
||||
asm volatile("ldw %0, %1[2]":"=r"(c1):"r"(one)); // Load our chanend
|
||||
asm volatile ("inct %0, res[%1]": "=r"(busStateCt):"r"(c1)); // busStateCt = inct(one);
|
||||
|
||||
if (!isnull(two))
|
||||
{
|
||||
asm volatile("ldw %0, %1[2]":"=r"(c2):"r"(two));
|
||||
asm volatile ("inct %0, res[%1]": "=r"(busStateCt):"r"(c2));
|
||||
}
|
||||
|
||||
/* Clear ready flag (tidies small race where EP marked ready just after XUD clears ready due to reset */
|
||||
asm volatile("ldw %0, %1[0]":"=r"(tmp):"r"(one)); // Load address of ep in XUD rdy table
|
||||
asm volatile ("stw %0, %1[0]"::"r"(0), "r"(tmp));
|
||||
|
||||
/* Clear resetting flag */
|
||||
asm volatile ("stw %0, %1[9]"::"r"(0), "r"(one));
|
||||
|
||||
if(!isnull(two))
|
||||
{
|
||||
asm volatile("ldw %0, %1[0]":"=r"(tmp):"r"(two)); // Load address of ep in XUD rdy table
|
||||
asm volatile ("stw %0, %1[0]"::"r"(0), "r"(tmp));
|
||||
|
||||
/* Reset reseting flag */
|
||||
asm volatile ("stw %0, %1[9]"::"r"(0), "r"(two));
|
||||
}
|
||||
|
||||
/* Expect a word with speed */
|
||||
asm volatile ("in %0, res[%1]": "=r"(busSpeed):"r"(c1));
|
||||
|
||||
if (!isnull(two))
|
||||
{
|
||||
asm volatile ("in %0, res[%1]": "=r"(busSpeed):"r"(c2));
|
||||
}
|
||||
return (XUD_BusSpeed_t) busSpeed;
|
||||
}
|
||||
|
||||
XUD_ep XUD_InitEp(chanend c)
|
||||
{
|
||||
XUD_ep ep = inuint(c);
|
||||
return ep;
|
||||
}
|
||||
|
||||
637
lib_xud/lib_xud/src/user/control/xud_device.xc
Normal file
637
lib_xud/lib_xud/src/user/control/xud_device.xc
Normal file
@@ -0,0 +1,637 @@
|
||||
// Copyright 2015-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
/**
|
||||
* @brief Implements USB Device standard requests
|
||||
* @author Ross Owen, XMOS Limited
|
||||
*/
|
||||
|
||||
#include "xud_device.h" /* Defines related to the USB 2.0 Spec */
|
||||
#include "XUD_HAL.h"
|
||||
#include <string.h>
|
||||
#include <xs1.h>
|
||||
#include <print.h>
|
||||
|
||||
#ifndef WINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
#define WINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
#endif
|
||||
|
||||
#ifndef MAX_INTS
|
||||
/* Maximum number of interfaces supported */
|
||||
#define MAX_INTS 16
|
||||
#endif
|
||||
|
||||
#ifndef MAX_EPS
|
||||
/* Maximum number of EP's supported */
|
||||
#define MAX_EPS USB_MAX_NUM_EP
|
||||
#endif
|
||||
|
||||
unsigned char g_currentConfig = 0;
|
||||
unsigned char g_interfaceAlt[MAX_INTS]; /* Global endpoint status arrays */
|
||||
|
||||
unsigned short g_epStatusOut[MAX_EPS];
|
||||
unsigned short g_epStatusIn[MAX_EPS];
|
||||
|
||||
#pragma unsafe arrays
|
||||
XUD_Result_t USB_GetSetupPacket(XUD_ep ep_out, XUD_ep ep_in, USB_SetupPacket_t &sp)
|
||||
{
|
||||
unsigned char sbuffer[120];
|
||||
unsigned length;
|
||||
|
||||
XUD_Result_t result;
|
||||
|
||||
if((result = XUD_GetSetupBuffer(ep_out, sbuffer, length)) != XUD_RES_OKAY)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Parse data buffer end populate SetupPacket struct */
|
||||
USB_ParseSetupPacket(sbuffer, sp);
|
||||
|
||||
/* Return 0 for success */
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Used when setting/clearing EP halt */
|
||||
int SetEndpointHalt(unsigned epNum, unsigned halt)
|
||||
{
|
||||
/* Inspect for IN bit */
|
||||
if(epNum & 0x80)
|
||||
{
|
||||
/* Range check */
|
||||
if((epNum&0x7F) < MAX_EPS)
|
||||
{
|
||||
g_epStatusIn[epNum & 0x7F] = halt;
|
||||
if(halt)
|
||||
XUD_SetStallByAddr(epNum);
|
||||
else
|
||||
XUD_ClearStallByAddr(epNum);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(epNum < MAX_EPS)
|
||||
{
|
||||
g_epStatusOut[epNum] = halt;
|
||||
if(halt)
|
||||
XUD_SetStallByAddr(epNum);
|
||||
else
|
||||
XUD_ClearStallByAddr(epNum);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#pragma unsafe arrays
|
||||
XUD_Result_t USB_StandardRequests(XUD_ep ep_out, XUD_ep ep_in,
|
||||
NULLABLE_ARRAY_OF(unsigned char, devDesc_hs), int devDescLength_hs,
|
||||
NULLABLE_ARRAY_OF(unsigned char, cfgDesc_hs), int cfgDescLength_hs,
|
||||
NULLABLE_ARRAY_OF(unsigned char, devDesc_fs), int devDescLength_fs,
|
||||
NULLABLE_ARRAY_OF(unsigned char, cfgDesc_fs), int cfgDescLength_fs,
|
||||
char * unsafe strDescs[], int strDescsLength,
|
||||
USB_SetupPacket_t &sp, XUD_BusSpeed_t usbBusSpeed)
|
||||
{
|
||||
/* Return value */
|
||||
int datalength;
|
||||
int stringID = 0;
|
||||
|
||||
/* Buffer for Setup data */
|
||||
unsigned char buffer[120];
|
||||
|
||||
/* Stick bmRequest type back together for an easier parse... */
|
||||
unsigned bmRequestType = (sp.bmRequestType.Direction<<7) | (sp.bmRequestType.Type<<5) | (sp.bmRequestType.Recipient);
|
||||
|
||||
switch(bmRequestType)
|
||||
{
|
||||
/* Standard Device Requests - To Device */
|
||||
case USB_BMREQ_H2D_STANDARD_DEV:
|
||||
|
||||
/* Inspect for actual request */
|
||||
switch(sp.bRequest)
|
||||
{
|
||||
/* Standard Device Request: ClearFeature (USB Spec 9.4.1) */
|
||||
case USB_CLEAR_FEATURE:
|
||||
|
||||
/* Device Features than could potenially be cleared are as follows (See Figure 9-4)
|
||||
* Self Powered: Cannot be changed by SetFeature() or ClearFeature()
|
||||
* Remote Wakeup: Indicates if the device is currently enabled to request remote wakeup.
|
||||
by default not implemented
|
||||
*/
|
||||
break;
|
||||
|
||||
/* Standard Device Request: Set Address (USB spec 9.6.4) */
|
||||
/* This is a unique request since the operation is not completed until after the status stage */
|
||||
case USB_SET_ADDRESS:
|
||||
|
||||
if((sp.wValue < 128) && (sp.wIndex == 0) && (sp.wLength == 0))
|
||||
{
|
||||
XUD_Result_t result;
|
||||
|
||||
/* Status stage: Send a zero length packet */
|
||||
if((result = XUD_DoSetRequestStatus(ep_in)) != XUD_RES_OKAY)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Note: Really we should wait until ACK is received for status stage before changing address
|
||||
* We will just wait some time... */
|
||||
{
|
||||
timer t;
|
||||
unsigned time;
|
||||
t :> time;
|
||||
t when timerafter(time+50000) :> void;
|
||||
}
|
||||
|
||||
/* Set the device address in XUD */
|
||||
XUD_HAL_SetDeviceAddress(sp.wValue);
|
||||
return XUD_RES_OKAY;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
/* Standard Device Request: SetConfiguration (USB Spec 9.4.7) */
|
||||
case USB_SET_CONFIGURATION:
|
||||
|
||||
if((sp.wLength == 0) && (sp.wIndex == 0))
|
||||
{
|
||||
/* We can ignore sp.Direction if sp.wLength is 0. See USB Spec 9.3.1 */
|
||||
|
||||
/* USB 2.0 Spec 9.1.1.5 states that configuring a device should cause all
|
||||
* the status and configuration values associated with the endpoints in the
|
||||
* affected interfaces to be set to their default values. This includes setting
|
||||
* the data toggle of any endpoint using data toggles to the value DATA0 */
|
||||
|
||||
/* Note: currently assume all EP's related to config (apart from 0) */
|
||||
for(unsigned i = 1; i < USB_MAX_NUM_EP_IN; i++)
|
||||
{
|
||||
XUD_ResetEpStateByAddr(i | 0x80 );
|
||||
}
|
||||
|
||||
for(unsigned i = 1; i < USB_MAX_NUM_EP_OUT; i++)
|
||||
{
|
||||
XUD_ResetEpStateByAddr(i);
|
||||
}
|
||||
|
||||
/* Update global configuration value
|
||||
* Note alot of devices maye wish to implement features here since this
|
||||
* request indicates the device being placed into its "Configured" state
|
||||
* i.e. the host has accepted the device */
|
||||
g_currentConfig = sp.wValue;
|
||||
|
||||
/* No data stage for this request, just do status stage */
|
||||
return XUD_DoSetRequestStatus(ep_in);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Standard Device Request: SetDescriptor (USB Spec 9.4.8) */
|
||||
case USB_SET_DESCRIPTOR:
|
||||
|
||||
/* Optional request for updating or adding new descriptors */
|
||||
/* Not implemented by default */
|
||||
|
||||
break;
|
||||
|
||||
/* Standard Device Request: SetFeature (USB Spec 9.4.9) */
|
||||
/* TODO only accept these requests in HS? */
|
||||
case USB_SET_FEATURE:
|
||||
|
||||
if((sp.wValue == USB_TEST_MODE) && (sp.wLength == 0))
|
||||
{
|
||||
/* Inspect for Test Selector (high byte of wIndex, lower byte must be zero) */
|
||||
switch(sp.wIndex)
|
||||
{
|
||||
case USB_WINDEX_TEST_J:
|
||||
case USB_WINDEX_TEST_K:
|
||||
case USB_WINDEX_TEST_SE0_NAK:
|
||||
case USB_WINDEX_TEST_PACKET:
|
||||
{
|
||||
XUD_Result_t result;
|
||||
if((result = XUD_DoSetRequestStatus(ep_in)) != XUD_RES_OKAY)
|
||||
return result;
|
||||
|
||||
XUD_SetTestMode(ep_out, sp.wIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Standard Device Requests - To Host */
|
||||
case USB_BMREQ_D2H_STANDARD_DEV:
|
||||
|
||||
switch(sp.bRequest)
|
||||
{
|
||||
/* Standard Device Request: GetStatus (USB Spec 9.4.5)*/
|
||||
case USB_GET_STATUS:
|
||||
|
||||
/* Remote wakeup not supported (bit 1) */
|
||||
buffer[1] = 0;
|
||||
|
||||
/* Pull self/bus powered bit from the config descriptor */
|
||||
unsigned char self_powered = 0;
|
||||
if((usbBusSpeed == XUD_SPEED_FS) && (cfgDescLength_fs != 0))
|
||||
{
|
||||
self_powered = (cfgDesc_fs[7] & 0x40) != 0;
|
||||
}
|
||||
else if(cfgDescLength_hs != 0)
|
||||
{
|
||||
self_powered = (cfgDesc_hs[7] & 0x40) != 0;
|
||||
}
|
||||
buffer[0] = self_powered;
|
||||
|
||||
return XUD_DoGetRequest(ep_out, ep_in, buffer, 2, sp.wLength);
|
||||
|
||||
/* Standard Device Request: GetConfiguration (USB Spec 9.4.2) */
|
||||
case USB_GET_CONFIGURATION:
|
||||
|
||||
/* Return the current configuration of the device */
|
||||
if((sp.wValue == 0) && (sp.wIndex == 0) && (sp.wLength == 1))
|
||||
{
|
||||
buffer[0] = (char)g_currentConfig;
|
||||
return XUD_DoGetRequest(ep_out, ep_in, buffer, 1, sp.wLength);
|
||||
}
|
||||
break;
|
||||
|
||||
/* Standard Device Request: GetDescriptor (USB Spec 9.4.3)*/
|
||||
case USB_GET_DESCRIPTOR:
|
||||
|
||||
/* Inspect for which Type of descriptor is required (high byte of wValue) */
|
||||
switch(sp.wValue & 0xff00)
|
||||
{
|
||||
/* Device descriptor */
|
||||
case (USB_DESCTYPE_DEVICE << 8):
|
||||
|
||||
/* Currently only 1 device descriptor supported */
|
||||
if((sp.wValue & 0xff) == 0)
|
||||
{
|
||||
if((usbBusSpeed == XUD_SPEED_FS) && (devDescLength_fs != 0))
|
||||
{
|
||||
/* Return full-speed device descriptor */
|
||||
return XUD_DoGetRequest(ep_out, ep_in, devDesc_fs, devDescLength_fs, sp.wLength);
|
||||
}
|
||||
else if(devDescLength_hs != 0)
|
||||
{
|
||||
/* Return high-speed device descriptor, if no FS desc, send the HS desc */
|
||||
/* Do get request (send descriptor then 0 length status stage) */
|
||||
return XUD_DoGetRequest(ep_out, ep_in, devDesc_hs, devDescLength_hs, sp.wLength);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Configuration Descriptor */
|
||||
case (USB_DESCTYPE_CONFIGURATION << 8):
|
||||
|
||||
/* Currently only 1 configuration descriptor supported */
|
||||
/* TODO We currently return the same for all configs */
|
||||
//if((sp.wValue & 0xff) == 0)
|
||||
{
|
||||
if((usbBusSpeed == XUD_SPEED_FS) && (cfgDescLength_fs != 0))
|
||||
{
|
||||
/* Return full-speed configuration descriptor */
|
||||
cfgDesc_fs[1] = USB_DESCTYPE_CONFIGURATION;
|
||||
return XUD_DoGetRequest(ep_out, ep_in, cfgDesc_fs, cfgDescLength_fs, sp.wLength);
|
||||
}
|
||||
else if(cfgDescLength_hs != 0)
|
||||
{
|
||||
/* Do get request (send descriptor then 0 length status stage) */
|
||||
cfgDesc_hs[1] = USB_DESCTYPE_CONFIGURATION;
|
||||
return XUD_DoGetRequest(ep_out, ep_in, cfgDesc_hs, cfgDescLength_hs, sp.wLength);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Device qualifier descriptor */
|
||||
case (USB_DESCTYPE_DEVICE_QUALIFIER << 8):
|
||||
|
||||
if((sp.wValue & 0xff) == 0)
|
||||
{
|
||||
/* Build a device qualifer descriptor from the device descriptor */
|
||||
unsigned char devQualDesc[10];
|
||||
|
||||
if((usbBusSpeed == XUD_SPEED_HS) && (devDescLength_fs != 0))
|
||||
{
|
||||
/* Create devQual from FS Device Descriptor*/
|
||||
devQualDesc[0] = 10; /* 0 bLength */
|
||||
devQualDesc[1] = USB_DESCTYPE_DEVICE_QUALIFIER; /* 1 bDescriptorType */
|
||||
devQualDesc[2] = devDesc_fs[2];
|
||||
devQualDesc[3] = devDesc_fs[3];
|
||||
devQualDesc[4] = devDesc_fs[4];
|
||||
devQualDesc[5] = devDesc_fs[5];
|
||||
devQualDesc[6] = devDesc_fs[6];
|
||||
devQualDesc[7] = devDesc_fs[7];
|
||||
devQualDesc[8] = devDesc_fs[17]; /* 8 bNumConfigurations */
|
||||
devQualDesc[9] = 0;
|
||||
|
||||
/* Do get request (send descriptor then 0 length status stage) */
|
||||
return XUD_DoGetRequest(ep_out, ep_in, devQualDesc, 10, sp.wLength);
|
||||
}
|
||||
else if(devDescLength_hs != 0)
|
||||
{
|
||||
/* Running in FS so create devQual from HS Device Descriptor */
|
||||
devQualDesc[0] = 10; /* 0 bLength */
|
||||
devQualDesc[1] = USB_DESCTYPE_DEVICE_QUALIFIER; /* 1 bDescriptorType */
|
||||
devQualDesc[2] = devDesc_hs[2];
|
||||
devQualDesc[3] = devDesc_hs[3];
|
||||
devQualDesc[4] = devDesc_hs[4];
|
||||
devQualDesc[5] = devDesc_hs[5];
|
||||
devQualDesc[6] = devDesc_hs[6];
|
||||
devQualDesc[7] = devDesc_hs[7];
|
||||
devQualDesc[8] = devDesc_hs[17]; /* 8 bNumConfigurations */
|
||||
devQualDesc[9] = 0;
|
||||
|
||||
/* Do get request (send descriptor then 0 length status stage) */
|
||||
return XUD_DoGetRequest(ep_out, ep_in, devQualDesc, 10, sp.wLength);
|
||||
}
|
||||
|
||||
/* Not handled if devDescLength_hs == 0 and running in full-speed.
|
||||
* This should result in a STALL as per USB spec */
|
||||
}
|
||||
break;
|
||||
|
||||
/* Other Speed Configuration Descriptor */
|
||||
case (USB_DESCTYPE_OTHER_SPEED << 8):
|
||||
|
||||
/* Accepts any configuration number */
|
||||
//if((sp.wValue & 0xff) == 0)
|
||||
{
|
||||
if((usbBusSpeed == XUD_SPEED_HS) && (cfgDescLength_fs != 0))
|
||||
{
|
||||
cfgDesc_fs[1] = USB_DESCTYPE_OTHER_SPEED;
|
||||
return XUD_DoGetRequest(ep_out, ep_in, cfgDesc_fs, cfgDescLength_fs, sp.wLength);
|
||||
}
|
||||
else if(cfgDescLength_hs != 0)
|
||||
{
|
||||
cfgDesc_hs[1] = USB_DESCTYPE_OTHER_SPEED;
|
||||
return XUD_DoGetRequest(ep_out, ep_in, cfgDesc_hs, cfgDescLength_hs, sp.wLength);
|
||||
}
|
||||
|
||||
/* Not handled if cfgDescLength_hs == 0 and running in full-speed.
|
||||
* This should result in a STALL as per USB spec */
|
||||
}
|
||||
break;
|
||||
|
||||
/* String Descriptor */
|
||||
case (USB_DESCTYPE_STRING << 8):
|
||||
|
||||
/* Set descriptor type */
|
||||
buffer[1] = USB_DESCTYPE_STRING;
|
||||
|
||||
/* Send the string that was requested (low byte of wValue) */
|
||||
/* First, generate valid descriptor from string */
|
||||
stringID = sp.wValue & 0xff;
|
||||
|
||||
#ifdef WINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
unsigned OS_STR_DESC[8] = {'M','S','F','T','1','0','0',0x01}; // GET_MS_DESCRIPTOR will use the same value as the OS_STR_DESC last byte in bRequest later.
|
||||
#endif
|
||||
|
||||
/* String table bounds check */
|
||||
#ifdef WINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
if((stringID < strDescsLength) || (stringID == 0xEE))
|
||||
#else
|
||||
if(stringID < strDescsLength)
|
||||
#endif
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
#ifdef WINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
datalength = (stringID == 0xEE) ? 8 : strlen((char*)strDescs[stringID]);
|
||||
#else
|
||||
datalength = strlen((char*)strDescs[stringID]);
|
||||
#endif
|
||||
|
||||
/* String 0 (LangIDs) is a special case*/
|
||||
if( stringID == 0 )
|
||||
{
|
||||
buffer[0] = datalength + 2;
|
||||
if( sp.wLength < datalength + 2 )
|
||||
{
|
||||
datalength = sp.wLength - 2;
|
||||
}
|
||||
for(int i = 0; i < datalength; i += 1 )
|
||||
{
|
||||
buffer[i+2] = strDescs[stringID][i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Datalength *= 2 due to unicode */
|
||||
datalength <<= 1;
|
||||
|
||||
/* Set data length in descriptor (+2 due to 2 byte datalength)*/
|
||||
buffer[0] = datalength + 2;
|
||||
|
||||
if(sp.wLength < datalength + 2)
|
||||
{
|
||||
datalength = sp.wLength - 2;
|
||||
}
|
||||
/* Add zero bytes for unicode.. */
|
||||
for(int i = 0; i < datalength; i+=2)
|
||||
{
|
||||
#ifdef WINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
buffer[i+2] = (stringID == 0xEE) ? OS_STR_DESC[i>>1] : strDescs[ stringID ][i>>1];
|
||||
#else
|
||||
buffer[i+2] = strDescs[ stringID ][i>>1];
|
||||
#endif
|
||||
buffer[i+3] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Send back string */
|
||||
return XUD_DoGetRequest(ep_out, ep_in, buffer, datalength + 2, sp.wLength);
|
||||
} /* if(stringID < stringDescs_length) */
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
} //switch(sp.bRequest)
|
||||
break;
|
||||
|
||||
/* Direction: Host-to-device
|
||||
* Type: Standard
|
||||
* Recipient: Interface
|
||||
*/
|
||||
case USB_BMREQ_H2D_STANDARD_INT:
|
||||
|
||||
switch(sp.bRequest)
|
||||
{
|
||||
/* Standard Interface Request: SetInterface (USB Spec 9.4.10) */
|
||||
case USB_SET_INTERFACE:
|
||||
/* Note it is likely that a lot of devices will over-ride this request in their endpoint 0 code
|
||||
* For example, in an audio device this request would show the intent of the host to start streaming
|
||||
*/
|
||||
|
||||
if(sp.wLength == 0)
|
||||
{
|
||||
int numInterfaces = 0;
|
||||
|
||||
/* Pull number of interfaces from the Configuration Descriptor */
|
||||
if((usbBusSpeed == XUD_SPEED_FS) && (cfgDescLength_fs != 0))
|
||||
{
|
||||
numInterfaces = cfgDesc_fs[4];
|
||||
}
|
||||
else if(cfgDescLength_hs != 0)
|
||||
{
|
||||
numInterfaces = cfgDesc_hs[4];
|
||||
}
|
||||
|
||||
/* Record interface change */
|
||||
if((sp.wIndex < numInterfaces) && (sp.wIndex < MAX_INTS))
|
||||
{
|
||||
/* Note here we assume the host has given us a valid Alternate setting
|
||||
* It is hard for use to have a generic check for this here (without parsing the descriptors)
|
||||
* If more robust checking is required this should be done in the endpoint 0 implementation
|
||||
*/
|
||||
g_interfaceAlt[sp.wIndex] = sp.wValue;
|
||||
}
|
||||
|
||||
/* No data stage for this request, just do data stage */
|
||||
return XUD_DoSetRequestStatus(ep_in);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Direction: Device-to-host
|
||||
* Type: Standard
|
||||
* Recipient: Interface
|
||||
*/
|
||||
case USB_BMREQ_D2H_STANDARD_INT:
|
||||
|
||||
switch(sp.bRequest)
|
||||
{
|
||||
case USB_GET_INTERFACE:
|
||||
|
||||
if((sp.wValue == 0) && (sp.wLength == 1))
|
||||
{
|
||||
int numInterfaces = 0;
|
||||
|
||||
/* Pull number of interfaces from the Configuration Descriptor */
|
||||
if((usbBusSpeed == XUD_SPEED_FS) && (cfgDescLength_fs != 0))
|
||||
{
|
||||
numInterfaces = cfgDesc_fs[4];
|
||||
}
|
||||
else if(cfgDescLength_hs != 0)
|
||||
{
|
||||
numInterfaces = cfgDesc_hs[4];
|
||||
}
|
||||
|
||||
if((sp.wIndex < numInterfaces) && (sp.wIndex < MAX_INTS))
|
||||
{
|
||||
buffer[0] = g_interfaceAlt[sp.wIndex];
|
||||
|
||||
return XUD_DoGetRequest(ep_out, ep_in, buffer, 1, sp.wLength);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Direction: Host-to-device
|
||||
* Type: Standard
|
||||
* Recipient: Endpoint
|
||||
*/
|
||||
case USB_BMREQ_H2D_STANDARD_EP:
|
||||
|
||||
switch(sp.bRequest)
|
||||
{
|
||||
/* Standard Endpoint Request: SetFeature (USB Spec 9.4.9) */
|
||||
case USB_SET_FEATURE:
|
||||
|
||||
if(sp.wLength == 0)
|
||||
{
|
||||
/* The only Endpoint feature selector is HALT (bit 0) see figure 9-6 */
|
||||
if(sp.wValue == USB_ENDPOINT_HALT)
|
||||
{
|
||||
/* Returns 0 on non-error */
|
||||
if(!SetEndpointHalt(sp.wIndex, 1))
|
||||
{
|
||||
return XUD_DoSetRequestStatus(ep_in);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Standard Endpoint Request: ClearFeature (USB Spec 9.4.1) */
|
||||
case USB_CLEAR_FEATURE:
|
||||
|
||||
if(sp.wLength == 0)
|
||||
{
|
||||
/* The only feature selector for Endpoint is ENDPOINT_HALT */
|
||||
if(sp.wValue == USB_ENDPOINT_HALT)
|
||||
{
|
||||
/* Returns 0 on non-error */
|
||||
if(!SetEndpointHalt(sp.wIndex, 0))
|
||||
{
|
||||
return XUD_DoSetRequestStatus(ep_in);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Direction: Host-to-device
|
||||
* Type: Standard
|
||||
* Recipient: Endpoint
|
||||
*/
|
||||
case USB_BMREQ_D2H_STANDARD_EP:
|
||||
|
||||
switch(sp.bRequest)
|
||||
{
|
||||
/* Standard Endpoint Request: GetStatus (USB Spec 9.4.5) */
|
||||
case USB_GET_STATUS:
|
||||
|
||||
/* Note: The only status for an EP is Halt (bit 0) */
|
||||
/* Note: Without parsing the descriptors we don't know how many endpoints the device has... */
|
||||
if((sp.wValue == 0) && (sp.wLength == 2))
|
||||
{
|
||||
buffer[0] = 0;
|
||||
buffer[1] = 0;
|
||||
|
||||
if( sp.wIndex & 0x80 )
|
||||
{
|
||||
/* IN Endpoint */
|
||||
if((sp.wIndex&0x7f) < MAX_EPS)
|
||||
{
|
||||
buffer[0] = ( g_epStatusIn[ sp.wIndex & 0x7F ] & 0xff );
|
||||
buffer[1] = ( g_epStatusIn[ sp.wIndex & 0x7F ] >> 8 );
|
||||
return XUD_DoGetRequest(ep_out, ep_in, buffer, 2, sp.wLength);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* OUT Endpoint */
|
||||
if(sp.wIndex < MAX_EPS)
|
||||
{
|
||||
buffer[0] = ( g_epStatusOut[ sp.wIndex ] & 0xff );
|
||||
buffer[1] = ( g_epStatusOut[ sp.wIndex ] >> 8 );
|
||||
return XUD_DoGetRequest(ep_out, ep_in, buffer, 2, sp.wLength);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
} //switch(bmRequestType)
|
||||
|
||||
|
||||
/* If we get this far we did not handle request - Protocol Stall Secion 8.4.5 of USB 2.0 spec
|
||||
* Detailed in Section 8.5.3. Protocol stall is unique to control pipes.
|
||||
* Protocol stall differs from functional stall in meaning and duration.
|
||||
* A protocol STALL is returned during the Data or Status stage of a control
|
||||
* transfer, and the STALL condition terminates at the beginning of the
|
||||
* next control transfer (Setup). The remainder of this section refers to
|
||||
* the general case of a functional stall */
|
||||
XUD_SetStall(ep_out);
|
||||
XUD_SetStall(ep_in);
|
||||
return XUD_RES_ERR;
|
||||
}
|
||||
63
lib_xud/lib_xud/src/user/control/xud_std_requests.xc
Normal file
63
lib_xud/lib_xud/src/user/control/xud_std_requests.xc
Normal file
@@ -0,0 +1,63 @@
|
||||
// Copyright 2015-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#include <print.h>
|
||||
|
||||
#include "xud_std_requests.h"
|
||||
|
||||
void USB_ParseSetupPacket(unsigned char b[], USB_SetupPacket_t &p)
|
||||
{
|
||||
// Byte 0: bmRequestType.
|
||||
p.bmRequestType.Recipient = b[0] & 0x1f;
|
||||
p.bmRequestType.Type = (b[0] & 0x60) >> 5;
|
||||
p.bmRequestType.Direction = b[0] >> 7;
|
||||
|
||||
// Byte 1: bRequest
|
||||
p.bRequest = b[1];
|
||||
|
||||
// Bytes [2:3] wValue
|
||||
p.wValue = (b[3] << 8) | (b[2]);
|
||||
|
||||
// Bytes [4:5] wIndex
|
||||
p.wIndex = (b[5] << 8) | (b[4]);
|
||||
|
||||
// Bytes [6:7] wLength
|
||||
p.wLength = (b[7] << 8) | (b[6]);
|
||||
}
|
||||
|
||||
void USB_ComposeSetupBuffer(USB_SetupPacket_t sp, unsigned char buffer[])
|
||||
{
|
||||
buffer[0] = sp.bmRequestType.Recipient
|
||||
| (sp.bmRequestType.Type << 5)
|
||||
| (sp.bmRequestType.Direction << 7);
|
||||
|
||||
buffer[1] = sp.bRequest;
|
||||
|
||||
buffer[2] = sp.wValue & 0xff;
|
||||
buffer[3] = (sp.wValue & 0xff00)>>8;
|
||||
|
||||
buffer[4] = sp.wIndex & 0xff;
|
||||
buffer[5] = (sp.wIndex & 0xff00)>>8;
|
||||
|
||||
buffer[6] = sp.wLength & 0xff;
|
||||
buffer[7] = (sp.wLength & 0xff00)>>8;
|
||||
}
|
||||
|
||||
void USB_PrintSetupPacket(USB_SetupPacket_t sp)
|
||||
{
|
||||
printstr("Setup data\n"); //NOCOVER
|
||||
printstr("bmRequestType.Recipient: "); //NOCOVER
|
||||
printhexln(sp.bmRequestType.Recipient); //NOCOVER
|
||||
printstr("bmRequestType.Type: "); //NOCOVER
|
||||
printhexln(sp.bmRequestType.Type); //NOCOVER
|
||||
printstr("bmRequestType.Direction: "); //NOCOVER
|
||||
printhexln(sp.bmRequestType.Direction); //NOCOVER
|
||||
printstr("bRequest: "); //NOCOVER
|
||||
printhexln(sp.bRequest); //NOCOVER
|
||||
printstr("bmRequestType.wValue: "); //NOCOVER
|
||||
printhexln(sp.wValue); //NOCOVER
|
||||
printstr("bmRequestType.wIndex: "); //NOCOVER
|
||||
printhexln(sp.wIndex); //NOCOVER
|
||||
printstr("bmRequestType.wLength: "); //NOCOVER
|
||||
printhexln(sp.wLength); //NOCOVER
|
||||
}
|
||||
9
lib_xud/lib_xud/xud_conf_example.h
Normal file
9
lib_xud/lib_xud/xud_conf_example.h
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2013-2022 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __xud_config_h__
|
||||
#define __xud_config_h__
|
||||
|
||||
#define XUD_EP_COUNT_OUT 1
|
||||
#define XUD_EP_COUNT_IN 1
|
||||
|
||||
#endif // __xud_config_h__
|
||||
Reference in New Issue
Block a user