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:
Dean Camera 2012-05-10 19:24:58 +00:00
parent e8570c4a37
commit 359fbfe14d
395 changed files with 9912 additions and 2756 deletions

View file

@ -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)
{

View file

@ -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.

View file

@ -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;

View file

@ -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
{

View file

@ -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);

View file

@ -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);

View file

@ -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);