Add branch for the conversion of demos to use standard C header files for configuration, rather than makefile defined macros.
This commit is contained in:
parent
e8570c4a37
commit
359fbfe14d
395 changed files with 9912 additions and 2756 deletions
|
@ -42,6 +42,21 @@
|
|||
uint8_t USB_Device_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE;
|
||||
#endif
|
||||
|
||||
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
|
||||
const uint8_t Entries)
|
||||
{
|
||||
for (uint8_t i = 0; i < Entries; i++)
|
||||
{
|
||||
if (!(Table[i].Address))
|
||||
continue;
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
|
||||
const uint8_t UECFG0XData,
|
||||
const uint8_t UECFG1XData)
|
||||
|
|
|
@ -89,35 +89,6 @@
|
|||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define _ENDPOINT_GET_MAXSIZE(EPIndex) _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## EPIndex)
|
||||
#define _ENDPOINT_GET_MAXSIZE2(EPDetails) _ENDPOINT_GET_MAXSIZE3(EPDetails)
|
||||
#define _ENDPOINT_GET_MAXSIZE3(MaxSize, Banks) (MaxSize)
|
||||
|
||||
#define _ENDPOINT_GET_BANKS(EPIndex) _ENDPOINT_GET_BANKS2(ENDPOINT_DETAILS_EP ## EPIndex)
|
||||
#define _ENDPOINT_GET_BANKS2(EPDetails) _ENDPOINT_GET_BANKS3(EPDetails)
|
||||
#define _ENDPOINT_GET_BANKS3(MaxSize, Banks) (Banks)
|
||||
|
||||
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
|
||||
#define ENDPOINT_DETAILS_MAXEP 7
|
||||
|
||||
#define ENDPOINT_DETAILS_EP0 64, 1
|
||||
#define ENDPOINT_DETAILS_EP1 256, 2
|
||||
#define ENDPOINT_DETAILS_EP2 64, 2
|
||||
#define ENDPOINT_DETAILS_EP3 64, 2
|
||||
#define ENDPOINT_DETAILS_EP4 64, 2
|
||||
#define ENDPOINT_DETAILS_EP5 64, 2
|
||||
#define ENDPOINT_DETAILS_EP6 64, 2
|
||||
#else
|
||||
#define ENDPOINT_DETAILS_MAXEP 5
|
||||
|
||||
#define ENDPOINT_DETAILS_EP0 64, 1
|
||||
#define ENDPOINT_DETAILS_EP1 64, 1
|
||||
#define ENDPOINT_DETAILS_EP2 64, 1
|
||||
#define ENDPOINT_DETAILS_EP3 64, 2
|
||||
#define ENDPOINT_DETAILS_EP4 64, 2
|
||||
#endif
|
||||
|
||||
/* Inline Functions: */
|
||||
static inline uint8_t Endpoint_BytesToEPSizeMask(const uint16_t Bytes) ATTR_WARN_UNUSED_RESULT ATTR_CONST
|
||||
ATTR_ALWAYS_INLINE;
|
||||
|
@ -145,23 +116,6 @@
|
|||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** \name Endpoint Bank Mode Masks */
|
||||
//@{
|
||||
/** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates
|
||||
* that the endpoint should have one single bank, which requires less USB FIFO memory but results
|
||||
* in slower transfers as only one USB device (the AVR or the host) can access the endpoint's
|
||||
* bank at the one time.
|
||||
*/
|
||||
#define ENDPOINT_BANK_SINGLE (0 << EPBK0)
|
||||
|
||||
/** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates
|
||||
* that the endpoint should have two banks, which requires more USB FIFO memory but results
|
||||
* in faster transfers as one USB device (the AVR or the host) can access one bank while the other
|
||||
* accesses the second bank.
|
||||
*/
|
||||
#define ENDPOINT_BANK_DOUBLE (1 << EPBK0)
|
||||
//@}
|
||||
|
||||
#if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
|
||||
/** Default size of the default control endpoint's bank, until altered by the control endpoint bank size
|
||||
* value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined.
|
||||
|
@ -169,30 +123,16 @@
|
|||
#define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8
|
||||
#endif
|
||||
|
||||
/** Retrieves the maximum bank size in bytes of a given endpoint.
|
||||
*
|
||||
* \attention This macro will only work correctly on endpoint indexes that are compile-time constants
|
||||
* defined by the preprocessor.
|
||||
*
|
||||
* \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1)
|
||||
*/
|
||||
#define ENDPOINT_MAX_SIZE(EPIndex) _ENDPOINT_GET_MAXSIZE(EPIndex)
|
||||
|
||||
/** Retrieves the total number of banks supported by the given endpoint.
|
||||
*
|
||||
* \attention This macro will only work correctly on endpoint indexes that are compile-time constants
|
||||
* defined by the preprocessor.
|
||||
*
|
||||
* \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1)
|
||||
*/
|
||||
#define ENDPOINT_BANKS_SUPPORTED(EPIndex) _ENDPOINT_GET_BANKS(EPIndex)
|
||||
|
||||
#if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__)
|
||||
/** Total number of endpoints (including the default control endpoint at address 0) which may
|
||||
* be used in the device. Different USB AVR models support different amounts of endpoints,
|
||||
* this value reflects the maximum number of endpoints for the currently selected AVR model.
|
||||
*/
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS ENDPOINT_DETAILS_MAXEP
|
||||
#if defined(USB_SERIES_4_AVR) || defined(USB_SERIES_6_AVR) || defined(USB_SERIES_7_AVR)
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS 7
|
||||
#else
|
||||
/** Total number of endpoints (including the default control endpoint at address 0) which may
|
||||
* be used in the device. Different USB AVR models support different amounts of endpoints,
|
||||
* this value reflects the maximum number of endpoints for the currently selected AVR model.
|
||||
*/
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS 5
|
||||
#endif
|
||||
#else
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS 1
|
||||
#endif
|
||||
|
@ -222,28 +162,20 @@
|
|||
};
|
||||
|
||||
/* Inline Functions: */
|
||||
/** Configures the specified endpoint number with the given endpoint type, direction, bank size
|
||||
* and banking mode. Once configured, the endpoint may be read from or written to, depending
|
||||
* on its direction.
|
||||
/** Configures the specified endpoint address with the given endpoint type, bank size and number of hardware
|
||||
* banks. Once configured, the endpoint may be read from or written to, depending on its direction.
|
||||
*
|
||||
* \param[in] Number Endpoint number to configure. This must be more than 0 and less than
|
||||
* \ref ENDPOINT_TOTAL_ENDPOINTS.
|
||||
* \param[in] Address Endpoint address to configure.
|
||||
*
|
||||
* \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types
|
||||
* are available on Low Speed USB devices - refer to the USB 2.0 specification.
|
||||
*
|
||||
* \param[in] Direction Endpoint data direction, either \ref ENDPOINT_DIR_OUT or \ref ENDPOINT_DIR_IN.
|
||||
* All endpoints (except Control type) are unidirectional - data may only be read
|
||||
* from or written to the endpoint bank based on its direction, not both.
|
||||
*
|
||||
* \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted
|
||||
* to the USB host, or after they have been received from the USB host (depending on
|
||||
* the endpoint's data direction). The bank size must indicate the maximum packet size
|
||||
* that the endpoint can handle.
|
||||
*
|
||||
* \param[in] Banks Number of banks to use for the endpoint being configured, an \c ENDPOINT_BANK_* mask.
|
||||
* More banks uses more USB DPRAM, but offers better performance. Isochronous type
|
||||
* endpoints <b>must</b> have at least two banks.
|
||||
* \param[in] Banks Number of banks to use for the endpoint being configured.
|
||||
*
|
||||
* \attention When the \c ORDERED_EP_CONFIG compile time option is used, Endpoints <b>must</b> be configured in
|
||||
* ascending order, or bank corruption will occur.
|
||||
|
@ -261,19 +193,18 @@
|
|||
*
|
||||
* \return Boolean \c true if the configuration succeeded, \c false otherwise.
|
||||
*/
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Direction,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks) ATTR_ALWAYS_INLINE;
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Direction,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks)
|
||||
{
|
||||
return Endpoint_ConfigureEndpoint_Prv(Number, ((Type << EPTYPE0) | (Direction ? (1 << EPDIR) : 0)),
|
||||
((1 << ALLOC) | Banks | Endpoint_BytesToEPSizeMask(Size)));
|
||||
return Endpoint_ConfigureEndpoint_Prv((Address & ENDPOINT_EPNUM_MASK),
|
||||
((Type << EPTYPE0) | ((Address & ENDPOINT_DIR_IN) ? (1 << EPDIR) : 0)),
|
||||
((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Endpoint_BytesToEPSizeMask(Size)));
|
||||
}
|
||||
|
||||
/** Indicates the number of bytes currently stored in the current endpoint's selected bank.
|
||||
|
@ -294,9 +225,19 @@
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Determines the currently selected endpoint's direction.
|
||||
*
|
||||
* \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
|
||||
*/
|
||||
static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Endpoint_GetEndpointDirection(void)
|
||||
{
|
||||
return (UECFG0X & (1 << EPDIR)) ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT;
|
||||
}
|
||||
|
||||
/** Get the endpoint address of the currently selected endpoint. This is typically used to save
|
||||
* the currently selected endpoint number so that it can be restored after another endpoint has
|
||||
* been manipulated.
|
||||
* the currently selected endpoint so that it can be restored after another endpoint has been
|
||||
* manipulated.
|
||||
*
|
||||
* \return Index of the currently selected endpoint.
|
||||
*/
|
||||
|
@ -304,38 +245,36 @@
|
|||
static inline uint8_t Endpoint_GetCurrentEndpoint(void)
|
||||
{
|
||||
#if !defined(CONTROL_ONLY_DEVICE)
|
||||
return (UENUM & ENDPOINT_EPNUM_MASK);
|
||||
return ((UENUM & ENDPOINT_EPNUM_MASK) | Endpoint_GetEndpointDirection());
|
||||
#else
|
||||
return ENDPOINT_CONTROLEP;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Selects the given endpoint number. If the address from the device descriptors is used, the
|
||||
* value should be masked with the \ref ENDPOINT_EPNUM_MASK constant to extract only the endpoint
|
||||
* number (and discarding the endpoint direction bit).
|
||||
/** Selects the given endpoint address.
|
||||
*
|
||||
* Any endpoint operations which do not require the endpoint number to be indicated will operate on
|
||||
* Any endpoint operations which do not require the endpoint address to be indicated will operate on
|
||||
* the currently selected endpoint.
|
||||
*
|
||||
* \param[in] EndpointNumber Endpoint number to select.
|
||||
* \param[in] Address Endpoint address to select.
|
||||
*/
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber)
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t Address)
|
||||
{
|
||||
#if !defined(CONTROL_ONLY_DEVICE)
|
||||
UENUM = EndpointNumber;
|
||||
UENUM = (Address & ENDPOINT_EPNUM_MASK);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
|
||||
* data In and Out pointers to the bank's contents.
|
||||
*
|
||||
* \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset.
|
||||
* \param[in] Address Endpoint address whose FIFO buffers are to be reset.
|
||||
*/
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber)
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t Address)
|
||||
{
|
||||
UERST = (1 << EndpointNumber);
|
||||
UERST = (1 << (Address & ENDPOINT_EPNUM_MASK));
|
||||
UERST = 0;
|
||||
}
|
||||
|
||||
|
@ -441,14 +380,14 @@
|
|||
/** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
|
||||
* endpoints).
|
||||
*
|
||||
* \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested.
|
||||
* \param[in] Address Address of the endpoint whose interrupt flag should be tested.
|
||||
*
|
||||
* \return Boolean \c true if the specified endpoint has interrupted, \c false otherwise.
|
||||
*/
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber)
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address)
|
||||
{
|
||||
return ((Endpoint_GetEndpointInterrupts() & (1 << EndpointNumber)) ? true : false);
|
||||
return ((Endpoint_GetEndpointInterrupts() & (1 << (Address & ENDPOINT_EPNUM_MASK))) ? true : false);
|
||||
}
|
||||
|
||||
/** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
|
||||
|
@ -576,16 +515,6 @@
|
|||
UECONX |= (1 << RSTDT);
|
||||
}
|
||||
|
||||
/** Determines the currently selected endpoint's direction.
|
||||
*
|
||||
* \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
|
||||
*/
|
||||
static inline uint8_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Endpoint_GetEndpointDirection(void)
|
||||
{
|
||||
return (UECFG0X & (1 << EPDIR)) ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT;
|
||||
}
|
||||
|
||||
/** Sets the direction of the currently selected endpoint.
|
||||
*
|
||||
* \param[in] DirectionMask New endpoint direction, as a \c ENDPOINT_DIR_* mask.
|
||||
|
@ -841,6 +770,20 @@
|
|||
#endif
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple
|
||||
* endpoints at the same time.
|
||||
*
|
||||
* \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the
|
||||
* control endpoint.
|
||||
*
|
||||
* \param[in] Table Pointer to a table of endpoint descriptions.
|
||||
* \param[in] Entries Number of entries in the endpoint table to configure.
|
||||
*
|
||||
* \return Boolean \c true if all endpoints configured successfully, \c false otherwise.
|
||||
*/
|
||||
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
|
||||
const uint8_t Entries);
|
||||
|
||||
/** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
|
||||
* with respect to the data direction. This is a convenience function which can be used to
|
||||
* simplify user control request handling.
|
||||
|
|
|
@ -114,9 +114,7 @@ void USB_Host_ProcessNextHostState(void)
|
|||
HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe);
|
||||
break;
|
||||
case HOST_STATE_Powered_ConfigPipe:
|
||||
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
|
||||
PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,
|
||||
PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE)))
|
||||
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, PIPE_CONTROLPIPE_DEFAULT_SIZE, 1)))
|
||||
{
|
||||
ErrorCode = HOST_ENUMERROR_PipeConfigError;
|
||||
SubErrorCode = 0;
|
||||
|
@ -151,9 +149,7 @@ void USB_Host_ProcessNextHostState(void)
|
|||
HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset);
|
||||
break;
|
||||
case HOST_STATE_Default_PostReset:
|
||||
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
|
||||
PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,
|
||||
USB_Host_ControlPipeSize, PIPE_BANK_SINGLE)))
|
||||
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, USB_Host_ControlPipeSize, 1)))
|
||||
{
|
||||
ErrorCode = HOST_ENUMERROR_PipeConfigError;
|
||||
SubErrorCode = 0;
|
||||
|
|
|
@ -40,21 +40,43 @@
|
|||
|
||||
uint8_t USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
|
||||
|
||||
bool Pipe_ConfigurePipe(const uint8_t Number,
|
||||
bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
|
||||
const uint8_t Entries)
|
||||
{
|
||||
for (uint8_t i = 0; i < Entries; i++)
|
||||
{
|
||||
if (!(Table[i].Address))
|
||||
continue;
|
||||
|
||||
if (!(Pipe_ConfigurePipe(Table[i].Address, Table[i].Type, Table[i].EndpointAddress, Table[i].Size, Table[i].Banks)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pipe_ConfigurePipe(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Token,
|
||||
const uint8_t EndpointNumber,
|
||||
const uint8_t EndpointAddress,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks)
|
||||
{
|
||||
uint8_t Number = (Address & PIPE_EPNUM_MASK);
|
||||
uint8_t Token = (Address & PIPE_DIR_IN) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT;
|
||||
|
||||
if (Type == EP_TYPE_CONTROL)
|
||||
Token = PIPE_TOKEN_SETUP;
|
||||
|
||||
#if defined(ORDERED_EP_CONFIG)
|
||||
Pipe_SelectPipe(Number);
|
||||
Pipe_EnablePipe();
|
||||
|
||||
UPCFG1X = 0;
|
||||
|
||||
UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointNumber & PIPE_EPNUM_MASK) << PEPNUM0));
|
||||
UPCFG1X = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size));
|
||||
UPCFG0X = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0));
|
||||
UPCFG1X = ((1 << ALLOC) | ((Banks > 1) ? (1 << EPBK0) : 0) | Pipe_BytesToEPSizeMask(Size));
|
||||
|
||||
Pipe_SetInfiniteINRequests();
|
||||
|
||||
|
@ -71,7 +93,7 @@ bool Pipe_ConfigurePipe(const uint8_t Number,
|
|||
|
||||
if (PNum == Number)
|
||||
{
|
||||
UPCFG0XTemp = ((Type << EPTYPE0) | Token | ((EndpointNumber & PIPE_EPNUM_MASK) << PEPNUM0));
|
||||
UPCFG0XTemp = ((Type << EPTYPE0) | Token | ((EndpointAddress & PIPE_EPNUM_MASK) << PEPNUM0));
|
||||
UPCFG1XTemp = ((1 << ALLOC) | Banks | Pipe_BytesToEPSizeMask(Size));
|
||||
UPCFG2XTemp = 0;
|
||||
UPIENXTemp = 0;
|
||||
|
|
|
@ -124,38 +124,22 @@
|
|||
|
||||
/** \name Pipe Token Masks */
|
||||
//@{
|
||||
/** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a SETUP token (for CONTROL type pipes),
|
||||
/** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a SETUP token (for CONTROL type pipes),
|
||||
* which will trigger a control request on the attached device when data is written to the pipe.
|
||||
*/
|
||||
#define PIPE_TOKEN_SETUP (0 << PTOKEN0)
|
||||
|
||||
/** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a IN token (for non-CONTROL type pipes),
|
||||
/** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a IN token (for non-CONTROL type pipes),
|
||||
* indicating that the pipe data will flow from device to host.
|
||||
*/
|
||||
#define PIPE_TOKEN_IN (1 << PTOKEN0)
|
||||
|
||||
/** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a OUT token (for non-CONTROL type pipes),
|
||||
/** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a OUT token (for non-CONTROL type pipes),
|
||||
* indicating that the pipe data will flow from host to device.
|
||||
*/
|
||||
#define PIPE_TOKEN_OUT (2 << PTOKEN0)
|
||||
//@}
|
||||
|
||||
/** \name Pipe Bank Mode Masks */
|
||||
//@{
|
||||
/** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe
|
||||
* should have one single bank, which requires less USB FIFO memory but results in slower transfers as
|
||||
* only one USB device (the AVR or the attached device) can access the pipe's bank at the one time.
|
||||
*/
|
||||
#define PIPE_BANK_SINGLE (0 << EPBK0)
|
||||
|
||||
/** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe
|
||||
* should have two banks, which requires more USB FIFO memory but results in faster transfers as one
|
||||
* USB device (the AVR or the attached device) can access one bank while the other accesses the second
|
||||
* bank.
|
||||
*/
|
||||
#define PIPE_BANK_DOUBLE (1 << EPBK0)
|
||||
//@}
|
||||
|
||||
/** Default size of the default control pipe's bank, until altered by the Endpoint0Size value
|
||||
* in the device descriptor of the attached device.
|
||||
*/
|
||||
|
@ -203,36 +187,46 @@
|
|||
return UPBCX;
|
||||
}
|
||||
|
||||
/** Determines the currently selected pipe's direction.
|
||||
*
|
||||
* \return The currently selected pipe's direction, as a \c PIPE_DIR_* mask.
|
||||
*/
|
||||
static inline uint8_t Pipe_GetPipeDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Pipe_GetPipeDirection(void)
|
||||
{
|
||||
return (UPCFG0X & (1 << EPDIR)) ? PIPE_DIR_IN : PIPE_DIR_OUT;
|
||||
}
|
||||
|
||||
/** Returns the pipe address of the currently selected pipe. This is typically used to save the
|
||||
* currently selected pipe number so that it can be restored after another pipe has been manipulated.
|
||||
* currently selected pipe address so that it can be restored after another pipe has been manipulated.
|
||||
*
|
||||
* \return Index of the currently selected pipe.
|
||||
*/
|
||||
static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Pipe_GetCurrentPipe(void)
|
||||
{
|
||||
return (UPNUM & PIPE_PIPENUM_MASK);
|
||||
return ((UPNUM & PIPE_PIPENUM_MASK) | Pipe_GetPipeDirection());
|
||||
}
|
||||
|
||||
/** Selects the given pipe number. Any pipe operations which do not require the pipe number to be
|
||||
/** Selects the given pipe address. Any pipe operations which do not require the pipe address to be
|
||||
* indicated will operate on the currently selected pipe.
|
||||
*
|
||||
* \param[in] PipeNumber Index of the pipe to select.
|
||||
* \param[in] Address Address of the pipe to select.
|
||||
*/
|
||||
static inline void Pipe_SelectPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
|
||||
static inline void Pipe_SelectPipe(const uint8_t PipeNumber)
|
||||
static inline void Pipe_SelectPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
|
||||
static inline void Pipe_SelectPipe(const uint8_t Address)
|
||||
{
|
||||
UPNUM = PipeNumber;
|
||||
UPNUM = (Address & PIPE_PIPENUM_MASK);
|
||||
}
|
||||
|
||||
/** Resets the desired pipe, including the pipe banks and flags.
|
||||
*
|
||||
* \param[in] PipeNumber Index of the pipe to reset.
|
||||
* \param[in] Address Address of the pipe to reset.
|
||||
*/
|
||||
static inline void Pipe_ResetPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
|
||||
static inline void Pipe_ResetPipe(const uint8_t PipeNumber)
|
||||
static inline void Pipe_ResetPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
|
||||
static inline void Pipe_ResetPipe(const uint8_t Address)
|
||||
{
|
||||
UPRST = (1 << PipeNumber);
|
||||
UPRST = (1 << (Address & PIPE_PIPENUM_MASK));
|
||||
UPRST = 0;
|
||||
}
|
||||
|
||||
|
@ -326,8 +320,9 @@
|
|||
static inline uint8_t Pipe_GetBoundEndpointAddress(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Pipe_GetBoundEndpointAddress(void)
|
||||
{
|
||||
return (((UPCFG0X >> PEPNUM0) & PIPE_EPNUM_MASK) |
|
||||
((Pipe_GetPipeToken() == PIPE_TOKEN_IN) ? PIPE_EPDIR_MASK : 0));
|
||||
uint8_t UPCFG0X_Temp = UPCFG0X;
|
||||
|
||||
return (((UPCFG0X_Temp >> PEPNUM0) & PIPE_EPNUM_MASK) | ((UPCFG0X_Temp & PEPNUM1) ? ENDPOINT_DIR_OUT : ENDPOINT_DIR_IN));
|
||||
}
|
||||
|
||||
/** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds.
|
||||
|
@ -351,17 +346,17 @@
|
|||
return UPINT;
|
||||
}
|
||||
|
||||
/** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type
|
||||
/** Determines if the specified pipe address has interrupted (valid only for INTERRUPT type
|
||||
* pipes).
|
||||
*
|
||||
* \param[in] PipeNumber Index of the pipe whose interrupt flag should be tested.
|
||||
* \param[in] Address Address of the pipe whose interrupt flag should be tested.
|
||||
*
|
||||
* \return Boolean \c true if the specified pipe has interrupted, \c false otherwise.
|
||||
*/
|
||||
static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber)
|
||||
static inline bool Pipe_HasPipeInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Pipe_HasPipeInterrupted(const uint8_t Address)
|
||||
{
|
||||
return ((UPINT & (1 << PipeNumber)) ? true : false);
|
||||
return ((UPINT & (1 << (Address & PIPE_PIPENUM_MASK))) ? true : false);
|
||||
}
|
||||
|
||||
/** Unfreezes the selected pipe, allowing it to communicate with an attached device. */
|
||||
|
@ -810,8 +805,22 @@
|
|||
extern uint8_t USB_Host_ControlPipeSize;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the specified pipe number with the given pipe type, token, target endpoint number in the
|
||||
* attached device, bank size and banking mode.
|
||||
/** Configures a table of pipe descriptions, in sequence. This function can be used to configure multiple
|
||||
* pipes at the same time.
|
||||
*
|
||||
* \note Pipe with a zero address will be ignored, thus this function cannot be used to configure the
|
||||
* control pipe.
|
||||
*
|
||||
* \param[in] Table Pointer to a table of pipe descriptions.
|
||||
* \param[in] Entries Number of entries in the pipe table to configure.
|
||||
*
|
||||
* \return Boolean \c true if all pipes configured successfully, \c false otherwise.
|
||||
*/
|
||||
bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
|
||||
const uint8_t Entries);
|
||||
|
||||
/** Configures the specified pipe address with the given pipe type, endpoint address within the attached device, bank size
|
||||
* and number of hardware banks.
|
||||
*
|
||||
* A newly configured pipe is frozen by default, and must be unfrozen before use via the \ref Pipe_Unfreeze()
|
||||
* before being used. Pipes should be kept frozen unless waiting for data from a device while in IN mode, or
|
||||
|
@ -819,25 +828,19 @@
|
|||
* numbers of IN requests without automatic freezing - this can be overridden by a call to
|
||||
* \ref Pipe_SetFiniteINRequests().
|
||||
*
|
||||
* \param[in] Number Pipe number to configure. This must be more than 0 and less than \ref PIPE_TOTAL_PIPES.
|
||||
* \param[in] Address Pipe address to configure.
|
||||
*
|
||||
* \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low
|
||||
* Speed USB devices - refer to the USB 2.0 specification.
|
||||
* \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low
|
||||
* Speed USB devices - refer to the USB 2.0 specification.
|
||||
*
|
||||
* \param[in] Token Pipe data token, either \ref PIPE_TOKEN_SETUP, \ref PIPE_TOKEN_OUT or \ref PIPE_TOKEN_IN.
|
||||
* All pipes (except Control type) are unidirectional - data may only be read from or
|
||||
* written to the pipe bank based on its direction, not both.
|
||||
* \param[in] EndpointAddress Endpoint address within the attached device that the pipe should interface to.
|
||||
*
|
||||
* \param[in] EndpointNumber Endpoint index within the attached device that the pipe should interface to.
|
||||
* \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to
|
||||
* the USB device, or after they have been received from the USB device (depending on
|
||||
* the pipe's data direction). The bank size must indicate the maximum packet size that
|
||||
* the pipe can handle.
|
||||
*
|
||||
* \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to
|
||||
* the USB device, or after they have been received from the USB device (depending on
|
||||
* the pipe's data direction). The bank size must indicate the maximum packet size that
|
||||
* the pipe can handle.
|
||||
*
|
||||
* \param[in] Banks Number of banks to use for the pipe being configured, a \c PIPE_BANK_* mask. More banks
|
||||
* uses more USB DPRAM, but offers better performance. Isochronous type pipes <b>must</b>
|
||||
* have at least two banks.
|
||||
* \param[in] Banks Number of banks to use for the pipe being configured.
|
||||
*
|
||||
* \attention When the \c ORDERED_EP_CONFIG compile time option is used, Pipes <b>must</b> be configured in ascending order,
|
||||
* or bank corruption will occur.
|
||||
|
@ -855,10 +858,9 @@
|
|||
*
|
||||
* \return Boolean \c true if the configuration succeeded, \c false otherwise.
|
||||
*/
|
||||
bool Pipe_ConfigurePipe(const uint8_t Number,
|
||||
bool Pipe_ConfigurePipe(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Token,
|
||||
const uint8_t EndpointNumber,
|
||||
const uint8_t EndpointAddress,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks);
|
||||
|
||||
|
|
|
@ -232,8 +232,7 @@ static void USB_Init_Device(void)
|
|||
#endif
|
||||
|
||||
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
|
||||
ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
USB_Device_ControlEndpointSize, 1);
|
||||
|
||||
USB_INT_Clear(USB_INT_SUSPI);
|
||||
USB_INT_Enable(USB_INT_SUSPI);
|
||||
|
|
|
@ -171,8 +171,7 @@ ISR(USB_GEN_vect, ISR_BLOCK)
|
|||
USB_INT_Enable(USB_INT_WAKEUPI);
|
||||
|
||||
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
|
||||
ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
USB_Device_ControlEndpointSize, 1);
|
||||
|
||||
#if defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
USB_INT_Enable(USB_INT_RXSTPI);
|
||||
|
|
|
@ -289,7 +289,6 @@ static void USB_Device_GetStatus(void)
|
|||
|
||||
switch (USB_ControlRequest.bmRequestType)
|
||||
{
|
||||
#if !defined(NO_DEVICE_SELF_POWER) || !defined(NO_DEVICE_REMOTE_WAKEUP)
|
||||
case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_DEVICE):
|
||||
#if !defined(NO_DEVICE_SELF_POWER)
|
||||
if (USB_Device_CurrentlySelfPowered)
|
||||
|
@ -301,17 +300,16 @@ static void USB_Device_GetStatus(void)
|
|||
CurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
#if !defined(CONTROL_ONLY_DEVICE)
|
||||
case (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_ENDPOINT):
|
||||
#if !defined(CONTROL_ONLY_DEVICE)
|
||||
Endpoint_SelectEndpoint((uint8_t)USB_ControlRequest.wIndex & ENDPOINT_EPNUM_MASK);
|
||||
|
||||
CurrentStatus = Endpoint_IsStalled();
|
||||
|
||||
Endpoint_SelectEndpoint(ENDPOINT_CONTROLEP);
|
||||
#endif
|
||||
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,18 @@
|
|||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** Type define for a endpoint table entry, used to configure endpoints in groups via
|
||||
* \ref Endpoint_ConfigureEndpointTable().
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Address; /**< Address of the endpoint to configure, or zero if the table entry is to be unused. */
|
||||
uint16_t Size; /**< Size of the endpoint bank, in bytes. */
|
||||
uint8_t Type; /**< Type of the endpoint, a \c EP_TYPE_* mask. */
|
||||
uint8_t Banks; /**< Number of hardware banks to use for the endpoint. */
|
||||
} USB_Endpoint_Table_t;
|
||||
|
||||
/* Macros: */
|
||||
/** Endpoint number mask, for masking against endpoint addresses to retrieve the endpoint's
|
||||
* numerical address in the device.
|
||||
|
|
|
@ -97,6 +97,19 @@
|
|||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Type Defines: */
|
||||
/** Type define for a pipe table entry, used to configure pipes in groups via
|
||||
* \ref Pipe_ConfigurePipeTable().
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Address; /**< Address of the pipe to configure, or zero if the table entry is to be unused. */
|
||||
uint16_t Size; /**< Size of the pipe bank, in bytes. */
|
||||
uint8_t EndpointAddress; /** Address of the endpoint in the connected device. */
|
||||
uint8_t Type; /**< Type of the endpoint, a \c EP_TYPE_* mask. */
|
||||
uint8_t Banks; /**< Number of hardware banks to use for the pipe. */
|
||||
} USB_Pipe_Table_t;
|
||||
|
||||
/* Macros: */
|
||||
/** Pipe address for the default control pipe, which always resides in address 0. This is
|
||||
* defined for convenience to give more readable code when used with the pipe macros.
|
||||
|
@ -113,11 +126,6 @@
|
|||
*/
|
||||
#define PIPE_EPNUM_MASK 0x0F
|
||||
|
||||
/** Endpoint direction mask, for masking against endpoint addresses to retrieve the endpoint's
|
||||
* direction for comparing with the \c ENDPOINT_DIR_* masks.
|
||||
*/
|
||||
#define PIPE_EPDIR_MASK 0x80
|
||||
|
||||
/* Architecture Includes: */
|
||||
#if (ARCH == ARCH_AVR8)
|
||||
#include "AVR8/Pipe_AVR8.h"
|
||||
|
|
|
@ -94,8 +94,8 @@
|
|||
*
|
||||
* \param[in] x Version number to encode as a 16-bit little-endian number, as a floating point number.
|
||||
*/
|
||||
#define VERSION_BCD(x) CPU_TO_LE16((((VERSION_TENS(x) << 4) | VERSION_ONES(x)) << 8) | \
|
||||
((VERSION_TENTHS(x) << 4) | VERSION_HUNDREDTHS(x)))
|
||||
#define VERSION_BCD(x) CPU_TO_LE16((VERSION_TENS(x) << 12) | (VERSION_ONES(x) << 8) | \
|
||||
(VERSION_TENTHS(x) << 4) | (VERSION_HUNDREDTHS(x) << 0) )
|
||||
|
||||
/** String language ID for the English language. Should be used in \ref USB_Descriptor_String_t descriptors
|
||||
* to indicate that the English language is supported by the device in its string descriptors.
|
||||
|
@ -722,10 +722,10 @@
|
|||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define VERSION_TENS(x) (int)((x) / 10)
|
||||
#define VERSION_ONES(x) (int)((x) - (10 * VERSION_TENS(x)))
|
||||
#define VERSION_TENTHS(x) (int)(((x) - (int)(x)) * 10)
|
||||
#define VERSION_HUNDREDTHS(x) (int)((((x) - (int)(x)) * 100) - (10 * VERSION_TENTHS(x)))
|
||||
#define VERSION_TENS(x) (int)((int)(x) / 10)
|
||||
#define VERSION_ONES(x) (int)((int)(x) % 10)
|
||||
#define VERSION_TENTHS(x) (int)(((x * 1) - ((int)(x * 1))) * 10)
|
||||
#define VERSION_HUNDREDTHS(x) (int)(((x * 10) - ((int)(x * 10))) * 10)
|
||||
#endif
|
||||
|
||||
/* Disable C linkage for C++ Compilers: */
|
||||
|
|
|
@ -45,6 +45,23 @@ uint8_t USB_Device_ControlEndpointSize = ENDPOINT_CONTROLEP_DEFAULT_SIZE;
|
|||
volatile uint32_t USB_Endpoint_SelectedEndpoint = ENDPOINT_CONTROLEP;
|
||||
volatile uint8_t* USB_Endpoint_FIFOPos[ENDPOINT_TOTAL_ENDPOINTS];
|
||||
|
||||
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
|
||||
const uint8_t Entries)
|
||||
{
|
||||
for (uint8_t i = 0; i < Entries; i++)
|
||||
{
|
||||
if (!(Table[i].Address))
|
||||
continue;
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Endpoint_ConfigureEndpoint_Prv(const uint8_t Number,
|
||||
const uint32_t UECFG0Data)
|
||||
{
|
||||
|
|
|
@ -90,47 +90,6 @@
|
|||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define _ENDPOINT_GET_MAXSIZE(EPIndex) _ENDPOINT_GET_MAXSIZE2(ENDPOINT_DETAILS_EP ## EPIndex)
|
||||
#define _ENDPOINT_GET_MAXSIZE2(EPDetails) _ENDPOINT_GET_MAXSIZE3(EPDetails)
|
||||
#define _ENDPOINT_GET_MAXSIZE3(MaxSize, Banks) (MaxSize)
|
||||
|
||||
#define _ENDPOINT_GET_BANKS(EPIndex) _ENDPOINT_GET_BANKS2(ENDPOINT_DETAILS_EP ## EPIndex)
|
||||
#define _ENDPOINT_GET_BANKS2(EPDetails) _ENDPOINT_GET_BANKS3(EPDetails)
|
||||
#define _ENDPOINT_GET_BANKS3(MaxSize, Banks) (Banks)
|
||||
|
||||
#if defined(USB_SERIES_UC3A0_AVR32) || defined(USB_SERIES_UC3A1_AVR32)
|
||||
#define ENDPOINT_DETAILS_MAXEP 7
|
||||
|
||||
#define ENDPOINT_DETAILS_EP0 64, 1
|
||||
#define ENDPOINT_DETAILS_EP1 256, 2
|
||||
#define ENDPOINT_DETAILS_EP2 256, 2
|
||||
#define ENDPOINT_DETAILS_EP3 64, 2
|
||||
#define ENDPOINT_DETAILS_EP4 64, 2
|
||||
#define ENDPOINT_DETAILS_EP5 256, 2
|
||||
#define ENDPOINT_DETAILS_EP6 256, 2
|
||||
#elif defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32)
|
||||
#define ENDPOINT_DETAILS_MAXEP 8
|
||||
|
||||
#define ENDPOINT_DETAILS_EP0 64, 1
|
||||
#define ENDPOINT_DETAILS_EP1 512, 3
|
||||
#define ENDPOINT_DETAILS_EP2 512, 3
|
||||
#define ENDPOINT_DETAILS_EP3 512, 3
|
||||
#define ENDPOINT_DETAILS_EP4 512, 3
|
||||
#define ENDPOINT_DETAILS_EP5 512, 3
|
||||
#define ENDPOINT_DETAILS_EP6 512, 3
|
||||
#define ENDPOINT_DETAILS_EP7 512, 3
|
||||
#elif defined(USB_SERIES_UC3B0_AVR32) || defined(USB_SERIES_UC3B1_AVR32)
|
||||
#define ENDPOINT_DETAILS_MAXEP 7
|
||||
|
||||
#define ENDPOINT_DETAILS_EP0 64, 1
|
||||
#define ENDPOINT_DETAILS_EP1 64, 2
|
||||
#define ENDPOINT_DETAILS_EP2 64, 2
|
||||
#define ENDPOINT_DETAILS_EP3 64, 2
|
||||
#define ENDPOINT_DETAILS_EP4 64, 2
|
||||
#define ENDPOINT_DETAILS_EP5 256, 2
|
||||
#define ENDPOINT_DETAILS_EP6 256, 2
|
||||
#endif
|
||||
|
||||
#define ENDPOINT_HSB_ADDRESS_SPACE_SIZE (64 * 1024UL)
|
||||
|
||||
/* Inline Functions: */
|
||||
|
@ -162,34 +121,6 @@
|
|||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** \name Endpoint Bank Mode Masks */
|
||||
//@{
|
||||
/** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates
|
||||
* that the endpoint should have one single bank, which requires less USB FIFO memory but results
|
||||
* in slower transfers as only one USB device (the AVR or the host) can access the endpoint's
|
||||
* bank at the one time.
|
||||
*/
|
||||
#define ENDPOINT_BANK_SINGLE AVR32_USBB_UECFG0_EPBK_SINGLE
|
||||
|
||||
/** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates
|
||||
* that the endpoint should have two banks, which requires more USB FIFO memory but results
|
||||
* in faster transfers as one USB device (the AVR or the host) can access one bank while the other
|
||||
* accesses the second bank.
|
||||
*/
|
||||
#define ENDPOINT_BANK_DOUBLE AVR32_USBB_UECFG0_EPBK_DOUBLE
|
||||
|
||||
#if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || defined(__DOXYGEN__)
|
||||
/** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates
|
||||
* that the endpoint should have three banks, which requires more USB FIFO memory but results
|
||||
* in faster transfers as one USB device (the AVR or the host) can access one bank while the other
|
||||
* accesses the remaining banks.
|
||||
*
|
||||
* \note Not available on all AVR models.
|
||||
*/
|
||||
#define ENDPOINT_BANK_TRIPLE AVR32_USBB_UECFG0_EPBK_TRIPLE
|
||||
#endif
|
||||
//@}
|
||||
|
||||
#if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
|
||||
/** Default size of the default control endpoint's bank, until altered by the control endpoint bank size
|
||||
* value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined.
|
||||
|
@ -197,30 +128,16 @@
|
|||
#define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8
|
||||
#endif
|
||||
|
||||
/** Retrieves the maximum bank size in bytes of a given endpoint.
|
||||
*
|
||||
* \attention This macro will only work correctly on endpoint indexes that are compile-time constants
|
||||
* defined by the preprocessor.
|
||||
*
|
||||
* \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1)
|
||||
*/
|
||||
#define ENDPOINT_MAX_SIZE(EPIndex) _ENDPOINT_GET_MAXSIZE(EPIndex)
|
||||
|
||||
/** Retrieves the total number of banks supported by the given endpoint.
|
||||
*
|
||||
* \attention This macro will only work correctly on endpoint indexes that are compile-time constants
|
||||
* defined by the preprocessor.
|
||||
*
|
||||
* \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1)
|
||||
*/
|
||||
#define ENDPOINT_BANKS_SUPPORTED(EPIndex) _ENDPOINT_GET_BANKS(EPIndex)
|
||||
|
||||
#if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__)
|
||||
/** Total number of endpoints (including the default control endpoint at address 0) which may
|
||||
* be used in the device. Different AVR models support different amounts of endpoints,
|
||||
* this value reflects the maximum number of endpoints for the currently selected AVR model.
|
||||
*/
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS ENDPOINT_DETAILS_MAXEP
|
||||
#if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32)
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS 8
|
||||
#else
|
||||
/** Total number of endpoints (including the default control endpoint at address 0) which may
|
||||
* be used in the device. Different AVR models support different amounts of endpoints,
|
||||
* this value reflects the maximum number of endpoints for the currently selected AVR model.
|
||||
*/
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS 7
|
||||
#endif
|
||||
#else
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS 1
|
||||
#endif
|
||||
|
@ -250,28 +167,21 @@
|
|||
};
|
||||
|
||||
/* Inline Functions: */
|
||||
/** Configures the specified endpoint number with the given endpoint type, direction, bank size
|
||||
/** Configures the specified endpoint address with the given endpoint type, direction, bank size
|
||||
* and banking mode. Once configured, the endpoint may be read from or written to, depending
|
||||
* on its direction.
|
||||
*
|
||||
* \param[in] Number Endpoint number to configure. This must be more than 0 and less than
|
||||
* \ref ENDPOINT_TOTAL_ENDPOINTS.
|
||||
* \param[in] Address Endpoint address to configure.
|
||||
*
|
||||
* \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types
|
||||
* are available on Low Speed USB devices - refer to the USB 2.0 specification.
|
||||
*
|
||||
* \param[in] Direction Endpoint data direction, either \ref ENDPOINT_DIR_OUT or \ref ENDPOINT_DIR_IN.
|
||||
* All endpoints (except Control type) are unidirectional - data may only be read
|
||||
* from or written to the endpoint bank based on its direction, not both.
|
||||
*
|
||||
* \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted
|
||||
* to the USB host, or after they have been received from the USB host (depending on
|
||||
* the endpoint's data direction). The bank size must indicate the maximum packet size
|
||||
* that the endpoint can handle.
|
||||
*
|
||||
* \param[in] Banks Number of banks to use for the endpoint being configured, an \c ENDPOINT_BANK_* mask.
|
||||
* More banks uses more USB DPRAM, but offers better performance. Isochronous type
|
||||
* endpoints <b>must</b> have at least two banks.
|
||||
* \param[in] Banks Number of hardware banks to use for the endpoint being configured.
|
||||
*
|
||||
* \attention When the \c ORDERED_EP_CONFIG compile time option is used, Endpoints <b>must</b> be configured in
|
||||
* ascending order, or bank corruption will occur.
|
||||
|
@ -289,22 +199,21 @@
|
|||
*
|
||||
* \return Boolean \c true if the configuration succeeded, \c false otherwise.
|
||||
*/
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Direction,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks) ATTR_ALWAYS_INLINE;
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Direction,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks)
|
||||
{
|
||||
return Endpoint_ConfigureEndpoint_Prv(Number, (AVR32_USBB_ALLOC_MASK |
|
||||
((uint32_t)Type << AVR32_USBB_EPTYPE_OFFSET) |
|
||||
((uint32_t)(Direction ? AVR32_USBB_UECFG0_EPDIR_MASK : 0) |
|
||||
((uint32_t)Banks << AVR32_USBB_EPBK_OFFSET) |
|
||||
Endpoint_BytesToEPSizeMask(Size))));
|
||||
return Endpoint_ConfigureEndpoint_Prv((Address & ENDPOINT_EPNUM_MASK),
|
||||
(AVR32_USBB_ALLOC_MASK |
|
||||
((uint32_t)Type << AVR32_USBB_EPTYPE_OFFSET) |
|
||||
((uint32_t)(Address & ENDPOINT_DIR_IN) ? AVR32_USBB_UECFG0_EPDIR_MASK : 0) |
|
||||
((uint32_t)Banks << AVR32_USBB_EPBK_OFFSET) |
|
||||
Endpoint_BytesToEPSizeMask(Size)));
|
||||
}
|
||||
|
||||
/** Indicates the number of bytes currently stored in the current endpoint's selected bank.
|
||||
|
@ -319,41 +228,51 @@
|
|||
return (&AVR32_USBB.UESTA0)[USB_Endpoint_SelectedEndpoint].byct;
|
||||
}
|
||||
|
||||
/** Determines the currently selected endpoint's direction.
|
||||
*
|
||||
* \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
|
||||
*/
|
||||
static inline uint32_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint32_t Endpoint_GetEndpointDirection(void)
|
||||
{
|
||||
return ((&AVR32_USBB.UECFG0)[USB_Endpoint_SelectedEndpoint].epdir ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT);
|
||||
}
|
||||
|
||||
/** Get the endpoint address of the currently selected endpoint. This is typically used to save
|
||||
* the currently selected endpoint number so that it can be restored after another endpoint has
|
||||
* been manipulated.
|
||||
* the currently selected endpoint so that it can be restored after another endpoint has been
|
||||
* manipulated.
|
||||
*
|
||||
* \return Index of the currently selected endpoint.
|
||||
*/
|
||||
static inline uint8_t Endpoint_GetCurrentEndpoint(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Endpoint_GetCurrentEndpoint(void)
|
||||
{
|
||||
return USB_Endpoint_SelectedEndpoint;
|
||||
return (USB_Endpoint_SelectedEndpoint | Endpoint_GetEndpointDirection());
|
||||
}
|
||||
|
||||
/** Selects the given endpoint number. If the address from the device descriptors is used, the
|
||||
* value should be masked with the \ref ENDPOINT_EPNUM_MASK constant to extract only the endpoint
|
||||
* number (and discarding the endpoint direction bit).
|
||||
/** Selects the given endpoint address.
|
||||
*
|
||||
* Any endpoint operations which do not require the endpoint number to be indicated will operate on
|
||||
* Any endpoint operations which do not require the endpoint address to be indicated will operate on
|
||||
* the currently selected endpoint.
|
||||
*
|
||||
* \param[in] EndpointNumber Endpoint number to select.
|
||||
* \param[in] Address Endpoint address to select.
|
||||
*/
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber)
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t Address)
|
||||
{
|
||||
USB_Endpoint_SelectedEndpoint = EndpointNumber;
|
||||
USB_Endpoint_SelectedEndpoint = (Address & ENDPOINT_EPNUM_MASK);
|
||||
}
|
||||
|
||||
/** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
|
||||
* data In and Out pointers to the bank's contents.
|
||||
*
|
||||
* \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset.
|
||||
* \param[in] Address Endpoint number whose FIFO buffers are to be reset.
|
||||
*/
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber)
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t Address)
|
||||
{
|
||||
uint32_t EndpointNumber = (Address & ENDPOINT_EPNUM_MASK);
|
||||
|
||||
AVR32_USBB.uerst |= (AVR32_USBB_EPRST0_MASK << EndpointNumber);
|
||||
AVR32_USBB.uerst &= ~(AVR32_USBB_EPRST0_MASK << EndpointNumber);
|
||||
USB_Endpoint_FIFOPos[EndpointNumber] = &AVR32_USBB_SLAVE[EndpointNumber * ENDPOINT_HSB_ADDRESS_SPACE_SIZE];
|
||||
|
@ -452,8 +371,8 @@
|
|||
*
|
||||
* \return Mask whose bits indicate which endpoints have interrupted.
|
||||
*/
|
||||
static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Endpoint_GetEndpointInterrupts(void)
|
||||
static inline uint32_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint32_t Endpoint_GetEndpointInterrupts(void)
|
||||
{
|
||||
return ((AVR32_USBB.udint & (AVR32_USBB_EP6INT_MASK | AVR32_USBB_EP5INT_MASK |
|
||||
AVR32_USBB_EP4INT_MASK | AVR32_USBB_EP3INT_MASK |
|
||||
|
@ -464,14 +383,14 @@
|
|||
/** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
|
||||
* endpoints).
|
||||
*
|
||||
* \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested.
|
||||
* \param[in] Address Address of the endpoint whose interrupt flag should be tested.
|
||||
*
|
||||
* \return Boolean \c true if the specified endpoint has interrupted, \c false otherwise.
|
||||
*/
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber)
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t Address)
|
||||
{
|
||||
return ((Endpoint_GetEndpointInterrupts() & (AVR32_USBB_EP0INT_MASK << EndpointNumber)) ? true : false);
|
||||
return ((Endpoint_GetEndpointInterrupts() & (AVR32_USBB_EP0INT_MASK << (Address & ENDPOINT_EPNUM_MASK))) ? true : false);
|
||||
}
|
||||
|
||||
/** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
|
||||
|
@ -596,16 +515,6 @@
|
|||
(&AVR32_USBB.UECON0SET)[USB_Endpoint_SelectedEndpoint].rstdts = true;
|
||||
}
|
||||
|
||||
/** Determines the currently selected endpoint's direction.
|
||||
*
|
||||
* \return The currently selected endpoint's direction, as a \c ENDPOINT_DIR_* mask.
|
||||
*/
|
||||
static inline uint32_t Endpoint_GetEndpointDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint32_t Endpoint_GetEndpointDirection(void)
|
||||
{
|
||||
return ((&AVR32_USBB.UECFG0)[USB_Endpoint_SelectedEndpoint].epdir ? ENDPOINT_DIR_IN : ENDPOINT_DIR_OUT);
|
||||
}
|
||||
|
||||
/** Sets the direction of the currently selected endpoint.
|
||||
*
|
||||
* \param[in] DirectionMask New endpoint direction, as a \c ENDPOINT_DIR_* mask.
|
||||
|
@ -837,6 +746,20 @@
|
|||
#endif
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple
|
||||
* endpoints at the same time.
|
||||
*
|
||||
* \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the
|
||||
* control endpoint.
|
||||
*
|
||||
* \param[in] Table Pointer to a table of endpoint descriptions.
|
||||
* \param[in] Entries Number of entries in the endpoint table to configure.
|
||||
*
|
||||
* \return Boolean \c true if all endpoints configured successfully, \c false otherwise.
|
||||
*/
|
||||
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
|
||||
const uint8_t Entries);
|
||||
|
||||
/** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
|
||||
* with respect to the data direction. This is a convenience function which can be used to
|
||||
* simplify user control request handling.
|
||||
|
|
|
@ -114,9 +114,7 @@ void USB_Host_ProcessNextHostState(void)
|
|||
HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Powered_ConfigPipe);
|
||||
break;
|
||||
case HOST_STATE_Powered_ConfigPipe:
|
||||
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
|
||||
PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,
|
||||
PIPE_CONTROLPIPE_DEFAULT_SIZE, PIPE_BANK_SINGLE)))
|
||||
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, PIPE_CONTROLPIPE_DEFAULT_SIZE, 1)))
|
||||
{
|
||||
ErrorCode = HOST_ENUMERROR_PipeConfigError;
|
||||
SubErrorCode = 0;
|
||||
|
@ -151,9 +149,7 @@ void USB_Host_ProcessNextHostState(void)
|
|||
HOST_TASK_NONBLOCK_WAIT(200, HOST_STATE_Default_PostReset);
|
||||
break;
|
||||
case HOST_STATE_Default_PostReset:
|
||||
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL,
|
||||
PIPE_TOKEN_SETUP, ENDPOINT_CONTROLEP,
|
||||
USB_Host_ControlPipeSize, PIPE_BANK_SINGLE)))
|
||||
if (!(Pipe_ConfigurePipe(PIPE_CONTROLPIPE, EP_TYPE_CONTROL, ENDPOINT_CONTROLEP, USB_Host_ControlPipeSize, 1)))
|
||||
{
|
||||
ErrorCode = HOST_ENUMERROR_PipeConfigError;
|
||||
SubErrorCode = 0;
|
||||
|
|
|
@ -43,13 +43,35 @@ uint8_t USB_Host_ControlPipeSize = PIPE_CONTROLPIPE_DEFAULT_SIZE;
|
|||
volatile uint32_t USB_Pipe_SelectedPipe = PIPE_CONTROLPIPE;
|
||||
volatile uint8_t* USB_Pipe_FIFOPos[PIPE_TOTAL_PIPES];
|
||||
|
||||
bool Pipe_ConfigurePipe(const uint8_t Number,
|
||||
bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
|
||||
const uint8_t Entries)
|
||||
{
|
||||
for (uint8_t i = 0; i < Entries; i++)
|
||||
{
|
||||
if (!(Table[i].Address))
|
||||
continue;
|
||||
|
||||
if (!(Pipe_ConfigurePipe(Table[i].Address, Table[i].Type, Table[i].EndpointAddress, Table[i].Size, Table[i].Banks)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Pipe_ConfigurePipe(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Token,
|
||||
const uint8_t EndpointNumber,
|
||||
const uint8_t EndpointAddress,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks)
|
||||
{
|
||||
uint8_t Number = (Address & PIPE_EPNUM_MASK);
|
||||
uint8_t Token = (Address & PIPE_DIR_IN) ? PIPE_TOKEN_IN : PIPE_TOKEN_OUT;
|
||||
|
||||
if (Type == EP_TYPE_CONTROL)
|
||||
Token = PIPE_TOKEN_SETUP;
|
||||
|
||||
USB_Pipe_FIFOPos[Number] = &AVR32_USBB_SLAVE[Number * 0x10000];
|
||||
|
||||
#if defined(ORDERED_EP_CONFIG)
|
||||
|
@ -60,7 +82,7 @@ bool Pipe_ConfigurePipe(const uint8_t Number,
|
|||
(&AVR32_USBB.upcfg0)[Number] = (AVR32_USBB_ALLOC_MASK |
|
||||
((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) |
|
||||
((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) |
|
||||
((uint32_t)Banks << AVR32_USBB_PBK_OFFSET) |
|
||||
((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) |
|
||||
Pipe_BytesToEPSizeMask(Size) |
|
||||
((EndpointNumber & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET));
|
||||
|
||||
|
@ -79,9 +101,9 @@ bool Pipe_ConfigurePipe(const uint8_t Number,
|
|||
UPCFG0Temp = (AVR32_USBB_ALLOC_MASK |
|
||||
((uint32_t)Type << AVR32_USBB_PTYPE_OFFSET) |
|
||||
((uint32_t)Token << AVR32_USBB_PTOKEN_OFFSET) |
|
||||
((uint32_t)Banks << AVR32_USBB_PBK_OFFSET) |
|
||||
((Banks > 1) ? AVR32_USBB_PBK_MASK : 0) |
|
||||
Pipe_BytesToEPSizeMask(Size) |
|
||||
((EndpointNumber & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET));
|
||||
((EndpointAddress & PIPE_EPNUM_MASK) << AVR32_USBB_PEPNUM_OFFSET));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -131,49 +131,22 @@
|
|||
|
||||
/** \name Pipe Token Masks */
|
||||
//@{
|
||||
/** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a SETUP token (for CONTROL type pipes),
|
||||
/** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a SETUP token (for CONTROL type pipes),
|
||||
* which will trigger a control request on the attached device when data is written to the pipe.
|
||||
*/
|
||||
#define PIPE_TOKEN_SETUP AVR32_USBB_UPCFG0_PTOKEN_SETUP
|
||||
|
||||
/** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a IN token (for non-CONTROL type pipes),
|
||||
/** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a IN token (for non-CONTROL type pipes),
|
||||
* indicating that the pipe data will flow from device to host.
|
||||
*/
|
||||
#define PIPE_TOKEN_IN AVR32_USBB_UPCFG0_PTOKEN_IN
|
||||
|
||||
/** Token mask for \ref Pipe_ConfigurePipe(). This sets the pipe as a OUT token (for non-CONTROL type pipes),
|
||||
/** Token mask for \ref Pipe_SetPipeToken() and \ref Pipe_GetPipeToken(). This sets the pipe as a OUT token (for non-CONTROL type pipes),
|
||||
* indicating that the pipe data will flow from host to device.
|
||||
*/
|
||||
#define PIPE_TOKEN_OUT AVR32_USBB_UPCFG0_PTOKEN_OUT
|
||||
//@}
|
||||
|
||||
/** \name Pipe Bank Mode Masks */
|
||||
//@{
|
||||
/** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe
|
||||
* should have one single bank, which requires less USB FIFO memory but results in slower transfers as
|
||||
* only one USB device (the AVR or the attached device) can access the pipe's bank at the one time.
|
||||
*/
|
||||
#define PIPE_BANK_SINGLE AVR32_USBB_UPCFG0_PBK_SINGLE
|
||||
|
||||
/** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the pipe
|
||||
* should have two banks, which requires more USB FIFO memory but results in faster transfers as one
|
||||
* USB device (the AVR or the attached device) can access one bank while the other accesses the second
|
||||
* bank.
|
||||
*/
|
||||
#define PIPE_BANK_DOUBLE AVR32_USBB_UPCFG0_PBK_DOUBLE
|
||||
|
||||
#if defined(USB_SERIES_UC3A3_AVR32) || defined(USB_SERIES_UC3A4_AVR32) || defined(__DOXYGEN__)
|
||||
/** Mask for the bank mode selection for the \ref Pipe_ConfigurePipe() macro. This indicates that the
|
||||
* pipe should have three banks, which requires more USB FIFO memory but results in faster transfers
|
||||
* as one USB device (the AVR or the attached device) can access one bank while the other accesses the
|
||||
* remaining banks.
|
||||
*
|
||||
* \note Not available on all AVR models.
|
||||
*/
|
||||
#define PIPE_BANK_TRIPLE AVR32_USBB_UPCFG0_PBK_TRIPLE
|
||||
#endif
|
||||
//@}
|
||||
|
||||
/** Default size of the default control pipe's bank, until altered by the Endpoint0Size value
|
||||
* in the device descriptor of the attached device.
|
||||
*/
|
||||
|
@ -224,6 +197,16 @@
|
|||
return (&AVR32_USBB.UPSTA0)[USB_Pipe_SelectedPipe].pbyct;
|
||||
}
|
||||
|
||||
/** Determines the currently selected pipe's direction.
|
||||
*
|
||||
* \return The currently selected pipe's direction, as a \c PIPE_DIR_* mask.
|
||||
*/
|
||||
static inline uint8_t Pipe_GetPipeDirection(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Pipe_GetPipeDirection(void)
|
||||
{
|
||||
return (((&AVR32_USBB.UPCFG0)[USB_Endpoint_SelectedEndpoint].ptoken == PIPE_TOKEN_OUT) ? PIPE_DIR_OUT : PIPE_DIR_IN);
|
||||
}
|
||||
|
||||
/** Returns the pipe address of the currently selected pipe. This is typically used to save the
|
||||
* currently selected pipe number so that it can be restored after another pipe has been manipulated.
|
||||
*
|
||||
|
@ -232,30 +215,32 @@
|
|||
static inline uint8_t Pipe_GetCurrentPipe(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Pipe_GetCurrentPipe(void)
|
||||
{
|
||||
return USB_Pipe_SelectedPipe;
|
||||
return (USB_Pipe_SelectedPipe | Pipe_GetPipeDirection());
|
||||
}
|
||||
|
||||
/** Selects the given pipe number. Any pipe operations which do not require the pipe number to be
|
||||
/** Selects the given pipe address. Any pipe operations which do not require the pipe address to be
|
||||
* indicated will operate on the currently selected pipe.
|
||||
*
|
||||
* \param[in] PipeNumber Index of the pipe to select.
|
||||
* \param[in] Address Address of the pipe to select.
|
||||
*/
|
||||
static inline void Pipe_SelectPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
|
||||
static inline void Pipe_SelectPipe(const uint8_t PipeNumber)
|
||||
static inline void Pipe_SelectPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
|
||||
static inline void Pipe_SelectPipe(const uint8_t Address)
|
||||
{
|
||||
USB_Pipe_SelectedPipe = PipeNumber;
|
||||
USB_Pipe_SelectedPipe = (Address & PIPE_EPNUM_MASK);
|
||||
}
|
||||
|
||||
/** Resets the desired pipe, including the pipe banks and flags.
|
||||
*
|
||||
* \param[in] PipeNumber Index of the pipe to reset.
|
||||
* \param[in] Address Index of the pipe to reset.
|
||||
*/
|
||||
static inline void Pipe_ResetPipe(const uint8_t PipeNumber) ATTR_ALWAYS_INLINE;
|
||||
static inline void Pipe_ResetPipe(const uint8_t PipeNumber)
|
||||
static inline void Pipe_ResetPipe(const uint8_t Address) ATTR_ALWAYS_INLINE;
|
||||
static inline void Pipe_ResetPipe(const uint8_t Address)
|
||||
{
|
||||
uint32_t PipeNumber = (Address & PIPE_EPNUM_MASK);
|
||||
|
||||
AVR32_USBB.uprst |= (AVR32_USBB_PRST0_MASK << PipeNumber);
|
||||
AVR32_USBB.uprst &= ~(AVR32_USBB_PRST0_MASK << PipeNumber);
|
||||
USB_Pipe_FIFOPos[USB_Pipe_SelectedPipe] = &AVR32_USBB_SLAVE[USB_Pipe_SelectedPipe * PIPE_HSB_ADDRESS_SPACE_SIZE];
|
||||
USB_Pipe_FIFOPos[PipeNumber] = &AVR32_USBB_SLAVE[PipeNumber * PIPE_HSB_ADDRESS_SPACE_SIZE];
|
||||
}
|
||||
|
||||
/** Enables the currently selected pipe so that data can be sent and received through it to and from
|
||||
|
@ -349,7 +334,7 @@
|
|||
static inline uint8_t Pipe_GetBoundEndpointAddress(void)
|
||||
{
|
||||
return ((&AVR32_USBB.UPCFG0)[USB_Pipe_SelectedPipe].pepnum |
|
||||
((Pipe_GetPipeToken() == PIPE_TOKEN_IN) ? PIPE_EPDIR_MASK : 0));
|
||||
((Pipe_GetPipeToken() == PIPE_TOKEN_IN) ? PIPE_DIR_IN : PIPE_DIR_OUT));
|
||||
}
|
||||
|
||||
/** Sets the period between interrupts for an INTERRUPT type pipe to a specified number of milliseconds.
|
||||
|
@ -376,17 +361,17 @@
|
|||
AVR32_USBB_P0INT_MASK)) >> AVR32_USBB_P0INT_OFFSET);
|
||||
}
|
||||
|
||||
/** Determines if the specified pipe number has interrupted (valid only for INTERRUPT type
|
||||
/** Determines if the specified pipe address has interrupted (valid only for INTERRUPT type
|
||||
* pipes).
|
||||
*
|
||||
* \param[in] PipeNumber Index of the pipe whose interrupt flag should be tested.
|
||||
* \param[in] Address Address of the pipe whose interrupt flag should be tested.
|
||||
*
|
||||
* \return Boolean \c true if the specified pipe has interrupted, \c false otherwise.
|
||||
*/
|
||||
static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Pipe_HasPipeInterrupted(const uint8_t PipeNumber)
|
||||
static inline bool Pipe_HasPipeInterrupted(const uint8_t Address) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Pipe_HasPipeInterrupted(const uint8_t Address)
|
||||
{
|
||||
return ((AVR32_USBB.uhint & (AVR32_USBB_P0INTES_MASK << PipeNumber)) ? true : false);
|
||||
return ((AVR32_USBB.uhint & (AVR32_USBB_P0INTES_MASK << (Address & PIPE_EPNUM_MASK))) ? true : false);
|
||||
}
|
||||
|
||||
/** Unfreezes the selected pipe, allowing it to communicate with an attached device. */
|
||||
|
@ -821,8 +806,22 @@
|
|||
extern uint8_t USB_Host_ControlPipeSize;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures the specified pipe number with the given pipe type, token, target endpoint number in the
|
||||
* attached device, bank size and banking mode.
|
||||
/** Configures a table of pipe descriptions, in sequence. This function can be used to configure multiple
|
||||
* pipes at the same time.
|
||||
*
|
||||
* \note Pipe with a zero address will be ignored, thus this function cannot be used to configure the
|
||||
* control pipe.
|
||||
*
|
||||
* \param[in] Table Pointer to a table of pipe descriptions.
|
||||
* \param[in] Entries Number of entries in the pipe table to configure.
|
||||
*
|
||||
* \return Boolean \c true if all pipes configured successfully, \c false otherwise.
|
||||
*/
|
||||
bool Pipe_ConfigurePipeTable(const USB_Pipe_Table_t* const Table,
|
||||
const uint8_t Entries);
|
||||
|
||||
/** Configures the specified pipe address with the given pipe type, endpoint address within the attached device, bank size
|
||||
* and number of hardware banks.
|
||||
*
|
||||
* A newly configured pipe is frozen by default, and must be unfrozen before use via the \ref Pipe_Unfreeze()
|
||||
* before being used. Pipes should be kept frozen unless waiting for data from a device while in IN mode, or
|
||||
|
@ -830,25 +829,19 @@
|
|||
* numbers of IN requests without automatic freezing - this can be overridden by a call to
|
||||
* \ref Pipe_SetFiniteINRequests().
|
||||
*
|
||||
* \param[in] Number Pipe number to configure. This must be more than 0 and less than \ref PIPE_TOTAL_PIPES.
|
||||
* \param[in] Address Pipe address to configure.
|
||||
*
|
||||
* \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low
|
||||
* Speed USB devices - refer to the USB 2.0 specification.
|
||||
* \param[in] Type Type of pipe to configure, an \c EP_TYPE_* mask. Not all pipe types are available on Low
|
||||
* Speed USB devices - refer to the USB 2.0 specification.
|
||||
*
|
||||
* \param[in] Token Pipe data token, either \ref PIPE_TOKEN_SETUP, \ref PIPE_TOKEN_OUT or \ref PIPE_TOKEN_IN.
|
||||
* All pipes (except Control type) are unidirectional - data may only be read from or
|
||||
* written to the pipe bank based on its direction, not both.
|
||||
* \param[in] EndpointAddress Endpoint address within the attached device that the pipe should interface to.
|
||||
*
|
||||
* \param[in] EndpointNumber Endpoint index within the attached device that the pipe should interface to.
|
||||
* \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to
|
||||
* the USB device, or after they have been received from the USB device (depending on
|
||||
* the pipe's data direction). The bank size must indicate the maximum packet size that
|
||||
* the pipe can handle.
|
||||
*
|
||||
* \param[in] Size Size of the pipe's bank, where packets are stored before they are transmitted to
|
||||
* the USB device, or after they have been received from the USB device (depending on
|
||||
* the pipe's data direction). The bank size must indicate the maximum packet size that
|
||||
* the pipe can handle.
|
||||
*
|
||||
* \param[in] Banks Number of banks to use for the pipe being configured, a \c PIPE_BANK_* mask. More banks
|
||||
* uses more USB DPRAM, but offers better performance. Isochronous type pipes <b>must</b>
|
||||
* have at least two banks.
|
||||
* \param[in] Banks Number of banks to use for the pipe being configured.
|
||||
*
|
||||
* \note When the \c ORDERED_EP_CONFIG compile time option is used, Pipes <b>must</b> be configured in ascending order,
|
||||
* or bank corruption will occur.
|
||||
|
@ -867,10 +860,9 @@
|
|||
*
|
||||
* \return Boolean \c true if the configuration succeeded, \c false otherwise.
|
||||
*/
|
||||
bool Pipe_ConfigurePipe(const uint8_t Number,
|
||||
bool Pipe_ConfigurePipe(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Token,
|
||||
const uint8_t EndpointNumber,
|
||||
const uint8_t EndpointAddress,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks);
|
||||
|
||||
|
|
|
@ -191,8 +191,7 @@ static void USB_Init_Device(void)
|
|||
USB_INT_Enable(USB_INT_VBUSTI);
|
||||
|
||||
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
|
||||
ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
USB_Device_ControlEndpointSize, 1);
|
||||
|
||||
USB_INT_Clear(USB_INT_SUSPI);
|
||||
USB_INT_Enable(USB_INT_SUSPI);
|
||||
|
|
|
@ -121,8 +121,7 @@ ISR(USB_GEN_vect)
|
|||
|
||||
USB_Device_SetDeviceAddress(0);
|
||||
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
|
||||
ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
USB_Device_ControlEndpointSize, 1);
|
||||
|
||||
#if defined(INTERRUPT_CONTROL_ENDPOINT)
|
||||
USB_INT_Enable(USB_INT_RXSTPI);
|
||||
|
|
|
@ -81,6 +81,24 @@
|
|||
#define ENDPOINT_DIR_IN 0x80
|
||||
//@}
|
||||
|
||||
/** \name Pipe Direction Masks */
|
||||
//@{
|
||||
/** Pipe direction mask, for masking against pipe addresses to retrieve the pipe's
|
||||
* direction for comparing with the \c PIPE_DIR_* masks.
|
||||
*/
|
||||
#define PIPE_DIR_MASK 0x80
|
||||
|
||||
/** Endpoint address direction mask for an OUT direction (Host to Device) endpoint. This may be ORed with
|
||||
* the index of the address within a device to obtain the full endpoint address.
|
||||
*/
|
||||
#define PIPE_DIR_OUT 0x00
|
||||
|
||||
/** Endpoint address direction mask for an IN direction (Device to Host) endpoint. This may be ORed with
|
||||
* the index of the address within a device to obtain the full endpoint address.
|
||||
*/
|
||||
#define PIPE_DIR_IN 0x80
|
||||
//@}
|
||||
|
||||
/** \name Endpoint/Pipe Type Masks */
|
||||
//@{
|
||||
/** Mask for determining the type of an endpoint from an endpoint descriptor. This should then be compared
|
||||
|
|
|
@ -137,6 +137,16 @@
|
|||
*/
|
||||
#define USB_SERIES_B3_XMEGA
|
||||
|
||||
/** Indicates that the target AVR microcontroller belongs to the XMEGA C3 Series USB controller
|
||||
* (i.e. ATXMEGA*C3) when defined.
|
||||
*/
|
||||
#define USB_SERIES_C3_XMEGA
|
||||
|
||||
/** Indicates that the target AVR microcontroller belongs to the XMEGA C4 Series USB controller
|
||||
* (i.e. ATXMEGA*C4) when defined.
|
||||
*/
|
||||
#define USB_SERIES_C4_XMEGA
|
||||
|
||||
/** Indicates that the target microcontroller and compilation settings allow for the
|
||||
* target to be configured in USB Device mode when defined.
|
||||
*/
|
||||
|
@ -219,6 +229,14 @@
|
|||
#elif (defined(__AVR_ATxmega128B3__) || defined(__AVR_ATxmega64B3__))
|
||||
#define USB_SERIES_B3_XMEGA
|
||||
#define USB_CAN_BE_DEVICE
|
||||
#elif (defined(__AVR_ATxmega128C3__) || defined(__AVR_ATxmega64C3__) || \
|
||||
defined(__AVR_ATxmega192C3__) || defined(__AVR_ATxmega256C3__) || \
|
||||
defined(__AVR_ATxmega384C3__))
|
||||
#define USB_SERIES_C3_XMEGA
|
||||
#define USB_CAN_BE_DEVICE
|
||||
#elif (defined(__AVR_ATxmega16C4__) || defined(__AVR_ATxmega32C4__))
|
||||
#define USB_SERIES_C4_XMEGA
|
||||
#define USB_CAN_BE_DEVICE
|
||||
#endif
|
||||
|
||||
#if (defined(USB_CAN_BE_DEVICE) && defined(USB_CAN_BE_HOST))
|
||||
|
|
|
@ -92,10 +92,12 @@
|
|||
*/
|
||||
#define USB_DEVICE_OPT_LOWSPEED (1 << 0)
|
||||
|
||||
/** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
|
||||
* USB interface should be initialized in full speed (12Mb/s) mode.
|
||||
*/
|
||||
#define USB_DEVICE_OPT_FULLSPEED (0 << 0)
|
||||
#if (F_USB > 6000000)
|
||||
/** Mask for the Options parameter of the \ref USB_Init() function. This indicates that the
|
||||
* USB interface should be initialized in full speed (12Mb/s) mode.
|
||||
*/
|
||||
#define USB_DEVICE_OPT_FULLSPEED (0 << 0)
|
||||
#endif
|
||||
//@}
|
||||
|
||||
#if (!defined(NO_INTERNAL_SERIAL) || defined(__DOXYGEN__))
|
||||
|
@ -157,7 +159,7 @@
|
|||
static inline uint16_t USB_Device_GetFrameNumber(void) ATTR_ALWAYS_INLINE ATTR_WARN_UNUSED_RESULT;
|
||||
static inline uint16_t USB_Device_GetFrameNumber(void)
|
||||
{
|
||||
return USB_EndpointTable.FrameNum;
|
||||
return ((USB_EndpointTable_t*)USB.EPPTR)->FrameNum;
|
||||
}
|
||||
|
||||
#if !defined(NO_SOF_EVENTS)
|
||||
|
|
|
@ -48,20 +48,36 @@ volatile uint8_t USB_Endpoint_SelectedEndpoint;
|
|||
volatile USB_EP_t* USB_Endpoint_SelectedHandle;
|
||||
volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO;
|
||||
|
||||
bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Number,
|
||||
const uint8_t Direction,
|
||||
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
|
||||
const uint8_t Entries)
|
||||
{
|
||||
for (uint8_t i = 0; i < Entries; i++)
|
||||
{
|
||||
if (!(Table[i].Address))
|
||||
continue;
|
||||
|
||||
if (!(Endpoint_ConfigureEndpoint(Table[i].Address, Table[i].Type, Table[i].Size, Table[i].Banks)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address,
|
||||
const uint8_t Config,
|
||||
const uint8_t Size)
|
||||
{
|
||||
Endpoint_SelectEndpoint(Number | Direction);
|
||||
Endpoint_SelectEndpoint(Address);
|
||||
|
||||
USB_Endpoint_SelectedHandle->CTRL = 0;
|
||||
USB_Endpoint_SelectedHandle->STATUS = (Direction == ENDPOINT_DIR_IN) ? USB_EP_BUSNACK0_bm : 0;
|
||||
USB_Endpoint_SelectedHandle->STATUS = (Address & ENDPOINT_DIR_IN) ? USB_EP_BUSNACK0_bm : 0;
|
||||
USB_Endpoint_SelectedHandle->CTRL = Config;
|
||||
USB_Endpoint_SelectedHandle->CNT = 0;
|
||||
USB_Endpoint_SelectedHandle->DATAPTR = (intptr_t)USB_Endpoint_SelectedFIFO->Data;
|
||||
|
||||
USB_Endpoint_SelectedFIFO->Length = (Direction == ENDPOINT_DIR_IN) ? Size : 0;
|
||||
USB_Endpoint_SelectedFIFO->Length = (Address & ENDPOINT_DIR_IN) ? Size : 0;
|
||||
USB_Endpoint_SelectedFIFO->Position = 0;
|
||||
|
||||
return true;
|
||||
|
@ -71,8 +87,8 @@ void Endpoint_ClearEndpoints(void)
|
|||
{
|
||||
for (uint8_t EPNum = 0; EPNum < ENDPOINT_TOTAL_ENDPOINTS; EPNum++)
|
||||
{
|
||||
USB_EndpointTable.Endpoints[EPNum].IN.CTRL = 0;
|
||||
USB_EndpointTable.Endpoints[EPNum].OUT.CTRL = 0;
|
||||
((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].IN.CTRL = 0;
|
||||
((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EPNum].OUT.CTRL = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,14 +88,20 @@
|
|||
#error Do not include this file directly. Include LUFA/Drivers/USB/USB.h instead.
|
||||
#endif
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
#if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__)
|
||||
/** Total number of endpoints (including the default control endpoint at address 0) which may
|
||||
* be used in the device. Different USB AVR models support different amounts of endpoints,
|
||||
* this value reflects the maximum number of endpoints for the currently selected AVR model.
|
||||
*/
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS 16
|
||||
#else
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS 1
|
||||
#endif
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
#if !defined(__DOXYGEN__)
|
||||
/* Macros: */
|
||||
#define _ENDPOINT_GET_MAXSIZE(EPIndex) 1023
|
||||
#define _ENDPOINT_GET_BANKS(EPIndex) 2
|
||||
|
||||
#define ENDPOINT_DETAILS_MAXEP 16
|
||||
|
||||
/* Type Defines: */
|
||||
typedef struct
|
||||
{
|
||||
|
@ -112,7 +118,7 @@
|
|||
} Endpoint_FIFOPair_t;
|
||||
|
||||
/* External Variables: */
|
||||
extern Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_DETAILS_MAXEP];
|
||||
extern Endpoint_FIFOPair_t USB_Endpoint_FIFOs[ENDPOINT_TOTAL_ENDPOINTS];
|
||||
extern volatile uint8_t USB_Endpoint_SelectedEndpoint;
|
||||
extern volatile USB_EP_t* USB_Endpoint_SelectedHandle;
|
||||
extern volatile Endpoint_FIFO_t* USB_Endpoint_SelectedFIFO;
|
||||
|
@ -135,8 +141,7 @@
|
|||
}
|
||||
|
||||
/* Function Prototypes: */
|
||||
bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Number,
|
||||
const uint8_t Direction,
|
||||
bool Endpoint_ConfigureEndpoint_PRV(const uint8_t Address,
|
||||
const uint8_t Config,
|
||||
const uint8_t Size);
|
||||
void Endpoint_ClearEndpoints(void);
|
||||
|
@ -144,23 +149,6 @@
|
|||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Macros: */
|
||||
/** \name Endpoint Bank Mode Masks */
|
||||
//@{
|
||||
/** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates
|
||||
* that the endpoint should have one single bank, which requires less USB FIFO memory but results
|
||||
* in slower transfers as only one USB device (the AVR or the host) can access the endpoint's
|
||||
* bank at the one time.
|
||||
*/
|
||||
#define ENDPOINT_BANK_SINGLE 0
|
||||
|
||||
/** Mask for the bank mode selection for the \ref Endpoint_ConfigureEndpoint() macro. This indicates
|
||||
* that the endpoint should have two banks, which requires more USB FIFO memory but results
|
||||
* in faster transfers as one USB device (the AVR or the host) can access one bank while the other
|
||||
* accesses the second bank.
|
||||
*/
|
||||
#define ENDPOINT_BANK_DOUBLE USB_EP_PINGPONG_bm
|
||||
//@}
|
||||
|
||||
#if (!defined(FIXED_CONTROL_ENDPOINT_SIZE) || defined(__DOXYGEN__))
|
||||
/** Default size of the default control endpoint's bank, until altered by the control endpoint bank size
|
||||
* value in the device descriptor. Not available if the \c FIXED_CONTROL_ENDPOINT_SIZE token is defined.
|
||||
|
@ -168,34 +156,6 @@
|
|||
#define ENDPOINT_CONTROLEP_DEFAULT_SIZE 8
|
||||
#endif
|
||||
|
||||
/** Retrieves the maximum bank size in bytes of a given endpoint.
|
||||
*
|
||||
* \attention This macro will only work correctly on endpoint indexes that are compile-time constants
|
||||
* defined by the preprocessor.
|
||||
*
|
||||
* \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1)
|
||||
*/
|
||||
#define ENDPOINT_MAX_SIZE(EPIndex) _ENDPOINT_GET_MAXSIZE(EPIndex)
|
||||
|
||||
/** Retrieves the total number of banks supported by the given endpoint.
|
||||
*
|
||||
* \attention This macro will only work correctly on endpoint indexes that are compile-time constants
|
||||
* defined by the preprocessor.
|
||||
*
|
||||
* \param[in] EPIndex Endpoint number, a value between 0 and (\ref ENDPOINT_TOTAL_ENDPOINTS - 1)
|
||||
*/
|
||||
#define ENDPOINT_BANKS_SUPPORTED(EPIndex) _ENDPOINT_GET_BANKS(EPIndex)
|
||||
|
||||
#if !defined(CONTROL_ONLY_DEVICE) || defined(__DOXYGEN__)
|
||||
/** Total number of endpoints (including the default control endpoint at address 0) which may
|
||||
* be used in the device. Different USB AVR models support different amounts of endpoints,
|
||||
* this value reflects the maximum number of endpoints for the currently selected AVR model.
|
||||
*/
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS ENDPOINT_DETAILS_MAXEP
|
||||
#else
|
||||
#define ENDPOINT_TOTAL_ENDPOINTS 1
|
||||
#endif
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible error return codes of the \ref Endpoint_WaitUntilReady() function.
|
||||
*
|
||||
|
@ -221,54 +181,47 @@
|
|||
};
|
||||
|
||||
/* Inline Functions: */
|
||||
/** Selects the given endpoint number. If the address from the device descriptors is used, the
|
||||
* value should be masked with the \ref ENDPOINT_EPNUM_MASK constant to extract only the endpoint
|
||||
* number (and discarding the endpoint direction bit).
|
||||
/** Selects the given endpoint address.
|
||||
*
|
||||
* Any endpoint operations which do not require the endpoint number to be indicated will operate on
|
||||
* Any endpoint operations which do not require the endpoint address to be indicated will operate on
|
||||
* the currently selected endpoint.
|
||||
*
|
||||
* \param[in] EndpointNumber Endpoint number to select.
|
||||
* \param[in] Address Endpoint address to select.
|
||||
*/
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber);
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t EndpointNumber)
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t Address);
|
||||
static inline void Endpoint_SelectEndpoint(const uint8_t Address)
|
||||
{
|
||||
USB_Endpoint_SelectedEndpoint = EndpointNumber;
|
||||
uint8_t EndpointNumber = (Address & ENDPOINT_EPNUM_MASK);
|
||||
|
||||
if (EndpointNumber & ENDPOINT_DIR_IN)
|
||||
USB_Endpoint_SelectedEndpoint = Address;
|
||||
|
||||
if (Address & ENDPOINT_DIR_IN)
|
||||
{
|
||||
USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].IN;
|
||||
USB_Endpoint_SelectedHandle = &USB_EndpointTable.Endpoints[EndpointNumber & ENDPOINT_EPNUM_MASK].IN;
|
||||
USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber].IN;
|
||||
USB_Endpoint_SelectedHandle = &((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EndpointNumber].IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].OUT;
|
||||
USB_Endpoint_SelectedHandle = &USB_EndpointTable.Endpoints[EndpointNumber & ENDPOINT_EPNUM_MASK].OUT;
|
||||
USB_Endpoint_SelectedFIFO = &USB_Endpoint_FIFOs[EndpointNumber].OUT;
|
||||
USB_Endpoint_SelectedHandle = &((USB_EndpointTable_t*)USB.EPPTR)->Endpoints[EndpointNumber].OUT;
|
||||
}
|
||||
}
|
||||
|
||||
/** Configures the specified endpoint number with the given endpoint type, direction, bank size
|
||||
/** Configures the specified endpoint address with the given endpoint type, direction, bank size
|
||||
* and banking mode. Once configured, the endpoint may be read from or written to, depending
|
||||
* on its direction.
|
||||
*
|
||||
* \param[in] Number Endpoint number to configure. This must be more than 0 and less than
|
||||
* \ref ENDPOINT_TOTAL_ENDPOINTS.
|
||||
* \param[in] Address Endpoint address to configure.
|
||||
*
|
||||
* \param[in] Type Type of endpoint to configure, a \c EP_TYPE_* mask. Not all endpoint types
|
||||
* are available on Low Speed USB devices - refer to the USB 2.0 specification.
|
||||
*
|
||||
* \param[in] Direction Endpoint data direction, either \ref ENDPOINT_DIR_OUT or \ref ENDPOINT_DIR_IN.
|
||||
* All endpoints (except Control type) are unidirectional - data may only be read
|
||||
* from or written to the endpoint bank based on its direction, not both.
|
||||
*
|
||||
* \param[in] Size Size of the endpoint's bank, where packets are stored before they are transmitted
|
||||
* to the USB host, or after they have been received from the USB host (depending on
|
||||
* the endpoint's data direction). The bank size must indicate the maximum packet size
|
||||
* that the endpoint can handle.
|
||||
*
|
||||
* \param[in] Banks Number of banks to use for the endpoint being configured, an \c ENDPOINT_BANK_* mask.
|
||||
* More banks uses more USB DPRAM, but offers better performance. Isochronous type
|
||||
* endpoints <b>must</b> have at least two banks.
|
||||
* \param[in] Banks Number of hardware banks to use for the endpoint being configured.
|
||||
*
|
||||
* \note The default control endpoint should not be manually configured by the user application, as
|
||||
* it is automatically configured by the library internally.
|
||||
|
@ -278,21 +231,19 @@
|
|||
*
|
||||
* \return Boolean \c true if the configuration succeeded, \c false otherwise.
|
||||
*/
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Direction,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks) ATTR_ALWAYS_INLINE;
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Number,
|
||||
static inline bool Endpoint_ConfigureEndpoint(const uint8_t Address,
|
||||
const uint8_t Type,
|
||||
const uint8_t Direction,
|
||||
const uint16_t Size,
|
||||
const uint8_t Banks)
|
||||
{
|
||||
uint8_t EPConfigMask = (USB_EP_INTDSBL_bm | Banks | Endpoint_BytesToEPSizeMask(Size));
|
||||
uint8_t EPConfigMask = (USB_EP_INTDSBL_bm | ((Banks > 1) ? USB_EP_PINGPONG_bm : 0) | Endpoint_BytesToEPSizeMask(Size));
|
||||
|
||||
// TODO - Fix once limitations are lifted
|
||||
if ((Banks != ENDPOINT_BANK_SINGLE) || (Size > 64))
|
||||
if ((Banks > 1) || (Size > 64))
|
||||
return false;
|
||||
|
||||
switch (Type)
|
||||
|
@ -309,9 +260,9 @@
|
|||
}
|
||||
|
||||
if (Type == EP_TYPE_CONTROL)
|
||||
Endpoint_ConfigureEndpoint_PRV(Number, (Direction ^ ENDPOINT_DIR_IN), EPConfigMask, Size);
|
||||
Endpoint_ConfigureEndpoint_PRV(Address ^ ENDPOINT_DIR_IN, EPConfigMask, Size);
|
||||
|
||||
return Endpoint_ConfigureEndpoint_PRV(Number, Direction, EPConfigMask, Size);
|
||||
return Endpoint_ConfigureEndpoint_PRV(Address, EPConfigMask, Size);
|
||||
}
|
||||
|
||||
/** Indicates the number of bytes currently stored in the current endpoint's selected bank.
|
||||
|
@ -327,8 +278,8 @@
|
|||
}
|
||||
|
||||
/** Get the endpoint address of the currently selected endpoint. This is typically used to save
|
||||
* the currently selected endpoint number so that it can be restored after another endpoint has
|
||||
* been manipulated.
|
||||
* the currently selected endpoint so that it can be restored after another endpoint has been
|
||||
* manipulated.
|
||||
*
|
||||
* \return Index of the currently selected endpoint.
|
||||
*/
|
||||
|
@ -341,15 +292,15 @@
|
|||
/** Resets the endpoint bank FIFO. This clears all the endpoint banks and resets the USB controller's
|
||||
* data In and Out pointers to the bank's contents.
|
||||
*
|
||||
* \param[in] EndpointNumber Endpoint number whose FIFO buffers are to be reset.
|
||||
* \param[in] Address Endpoint address whose FIFO buffers are to be reset.
|
||||
*/
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t EndpointNumber)
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t Address) ATTR_ALWAYS_INLINE;
|
||||
static inline void Endpoint_ResetEndpoint(const uint8_t Address)
|
||||
{
|
||||
if (EndpointNumber & ENDPOINT_DIR_IN)
|
||||
USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].IN.Position = 0;
|
||||
if (Address & ENDPOINT_DIR_IN)
|
||||
USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].IN.Position = 0;
|
||||
else
|
||||
USB_Endpoint_FIFOs[EndpointNumber & ENDPOINT_EPNUM_MASK].OUT.Position = 0;
|
||||
USB_Endpoint_FIFOs[Address & ENDPOINT_EPNUM_MASK].OUT.Position = 0;
|
||||
}
|
||||
|
||||
/** Determines if the currently selected endpoint is enabled, but not necessarily configured.
|
||||
|
@ -388,10 +339,7 @@
|
|||
static inline bool Endpoint_IsReadWriteAllowed(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Endpoint_IsReadWriteAllowed(void)
|
||||
{
|
||||
if (USB_Endpoint_SelectedEndpoint & ENDPOINT_DIR_IN)
|
||||
return (USB_Endpoint_SelectedFIFO->Position < USB_Endpoint_SelectedFIFO->Length);
|
||||
else
|
||||
return (USB_Endpoint_SelectedFIFO->Position > 0);
|
||||
return (USB_Endpoint_SelectedFIFO->Position < USB_Endpoint_SelectedFIFO->Length);
|
||||
}
|
||||
|
||||
/** Determines if the currently selected endpoint is configured.
|
||||
|
@ -404,32 +352,6 @@
|
|||
return ((USB_Endpoint_SelectedHandle->CTRL & USB_EP_TYPE_gm) ? true : false);
|
||||
}
|
||||
|
||||
/** Returns a mask indicating which INTERRUPT type endpoints have interrupted - i.e. their
|
||||
* interrupt duration has elapsed. Which endpoints have interrupted can be determined by
|
||||
* masking the return value against <tt>(1 << <i>{Endpoint Number}</i>)</tt>.
|
||||
*
|
||||
* \return Mask whose bits indicate which endpoints have interrupted.
|
||||
*/
|
||||
static inline uint8_t Endpoint_GetEndpointInterrupts(void) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t Endpoint_GetEndpointInterrupts(void)
|
||||
{
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
/** Determines if the specified endpoint number has interrupted (valid only for INTERRUPT type
|
||||
* endpoints).
|
||||
*
|
||||
* \param[in] EndpointNumber Index of the endpoint whose interrupt flag should be tested.
|
||||
*
|
||||
* \return Boolean \c true if the specified endpoint has interrupted, \c false otherwise.
|
||||
*/
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber) ATTR_WARN_UNUSED_RESULT ATTR_ALWAYS_INLINE;
|
||||
static inline bool Endpoint_HasEndpointInterrupted(const uint8_t EndpointNumber)
|
||||
{
|
||||
(void)EndpointNumber;
|
||||
return 0; // TODO
|
||||
}
|
||||
|
||||
/** Determines if the selected IN endpoint is ready for a new packet to be sent to the host.
|
||||
*
|
||||
* \ingroup Group_EndpointPacketManagement_XMEGA
|
||||
|
@ -800,6 +722,20 @@
|
|||
#endif
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Configures a table of endpoint descriptions, in sequence. This function can be used to configure multiple
|
||||
* endpoints at the same time.
|
||||
*
|
||||
* \note Endpoints with a zero address will be ignored, thus this function cannot be used to configure the
|
||||
* control endpoint.
|
||||
*
|
||||
* \param[in] Table Pointer to a table of endpoint descriptions.
|
||||
* \param[in] Entries Number of entries in the endpoint table to configure.
|
||||
*
|
||||
* \return Boolean \c true if all endpoints configured successfully, \c false otherwise.
|
||||
*/
|
||||
bool Endpoint_ConfigureEndpointTable(const USB_Endpoint_Table_t* const Table,
|
||||
const uint8_t Entries);
|
||||
|
||||
/** Completes the status stage of a control transfer on a CONTROL type endpoint automatically,
|
||||
* with respect to the data direction. This is a convenience function which can be used to
|
||||
* simplify user control request handling.
|
||||
|
|
|
@ -43,7 +43,8 @@ volatile uint8_t USB_CurrentMode = USB_MODE_None;
|
|||
volatile uint8_t USB_Options;
|
||||
#endif
|
||||
|
||||
USB_EndpointTable_t USB_EndpointTable ATTR_ALIGNED(4);
|
||||
/* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for 8-bit AVR-GCC */
|
||||
uint8_t USB_EndpointTable[sizeof(USB_EndpointTable_t) + 1];
|
||||
|
||||
void USB_Init(
|
||||
#if defined(USB_CAN_BE_BOTH)
|
||||
|
@ -75,8 +76,9 @@ void USB_Init(
|
|||
USB.CAL1 = pgm_read_byte(offsetof(NVM_PROD_SIGNATURES_t, USBCAL1));
|
||||
NVM.CMD = 0;
|
||||
|
||||
USB.EPPTR = (intptr_t)&USB_EndpointTable;
|
||||
USB.CTRLA = (USB_STFRNUM_bm | USB_MAXEP_gm);
|
||||
/* Ugly workaround to ensure an aligned table, since __BIGGEST_ALIGNMENT__ == 1 for 8-bit AVR-GCC */
|
||||
USB.EPPTR = ((intptr_t)&USB_EndpointTable[1] & ~(1 << 0));
|
||||
USB.CTRLA = (USB_STFRNUM_bm | ((ENDPOINT_TOTAL_ENDPOINTS - 1) << USB_MAXEP_gp));
|
||||
|
||||
if ((USB_Options & USB_OPT_BUSEVENT_PRIHIGH) == USB_OPT_BUSEVENT_PRIHIGH)
|
||||
USB.INTCTRLA = (3 << USB_INTLVL_gp);
|
||||
|
@ -103,13 +105,17 @@ void USB_Disable(void)
|
|||
|
||||
void USB_ResetInterface(void)
|
||||
{
|
||||
#if defined(USB_DEVICE_OPT_FULLSPEED)
|
||||
if (USB_Options & USB_DEVICE_OPT_LOWSPEED)
|
||||
CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp);
|
||||
else
|
||||
CLK.USBCTRL = (((F_USB / 48000000) - 1) << CLK_USBPSDIV_gp);
|
||||
|
||||
#else
|
||||
CLK.USBCTRL = (((F_USB / 6000000) - 1) << CLK_USBPSDIV_gp);
|
||||
#endif
|
||||
|
||||
if (USB_Options & USB_OPT_PLLCLKSRC)
|
||||
CLK.USBCTRL |= (CLK_USBSRC_PLL_gc | CLK_USBSEN_bm);
|
||||
CLK.USBCTRL |= (CLK_USBSRC_PLL_gc | CLK_USBSEN_bm);
|
||||
else
|
||||
CLK.USBCTRL |= (CLK_USBSRC_RC32M_gc | CLK_USBSEN_bm);
|
||||
|
||||
|
@ -172,8 +178,7 @@ static void USB_Init_Device(void)
|
|||
USB_Device_SetFullSpeed();
|
||||
|
||||
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
|
||||
ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
USB_Device_ControlEndpointSize, 1);
|
||||
|
||||
USB_INT_Enable(USB_INT_BUSEVENTI);
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@
|
|||
} ATTR_PACKED USB_EndpointTable_t;
|
||||
|
||||
/* External Variables: */
|
||||
extern USB_EndpointTable_t USB_EndpointTable;
|
||||
extern uint8_t USB_EndpointTable[];
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -95,7 +95,7 @@
|
|||
#error F_USB is not defined. You must define F_USB to the frequency of the unprescaled USB controller clock in your project makefile.
|
||||
#endif
|
||||
|
||||
#if (F_USB % 6000000)
|
||||
#if ((F_USB % 6000000) || (F_USB < 6000000))
|
||||
#error Invalid F_USB specified. F_USB must be a multiple of 6MHz for USB Low Speed operation, and a multiple of 48MHz for Full Speed operation.
|
||||
#endif
|
||||
|
||||
|
|
|
@ -97,8 +97,7 @@ ISR(USB_BUSEVENT_vect)
|
|||
|
||||
Endpoint_ClearEndpoints();
|
||||
Endpoint_ConfigureEndpoint(ENDPOINT_CONTROLEP, EP_TYPE_CONTROL,
|
||||
ENDPOINT_DIR_OUT, USB_Device_ControlEndpointSize,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
USB_Device_ControlEndpointSize, 1);
|
||||
|
||||
EVENT_USB_Device_Reset();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue